ls command #9

This commit is contained in:
sagie gur ari 2020-01-03 11:38:45 +00:00
parent 5fc5a934e0
commit 768a50b502
8 changed files with 347 additions and 2 deletions

View file

@ -2,6 +2,7 @@
### v0.1.2
* New **ls** command #9
* New **cp** command #7
* New **man** command #16
* New **calc** command #10

View file

@ -25,6 +25,7 @@
* [sdk::fs::GetCanonicalPath (canonicalize)](#sdk__fs__GetCanonicalPath)
* [sdk::fs::GetFileName (basename)](#sdk__fs__GetFileName)
* [sdk::fs::GetParentDirectory (dirname)](#sdk__fs__GetParentDirectory)
* [sdk::fs::List (ls)](#sdk__fs__List)
* [sdk::fs::MovePath (mv)](#sdk__fs__MovePath)
* [sdk::fs::Print (cat)](#sdk__fs__Print)
* [sdk::fs::Read (readfile)](#sdk__fs__Read)
@ -973,6 +974,56 @@ directory = dirname ./dir/file.txt
#### Aliases:
dirname
<a name="sdk__fs__List"></a>
## sdk::fs::List
```sh
var = ls [flags] [path]
```
Lists the file/directory contents.<br>
If no path is provided, the current working directory will be used.<br>
The supported flags are:
* -l - Shows extended information
#### Parameters
* Optional flags (currently only -l is supported)
* Optional path (if not provided, current working directory is used)
#### Return Value
**true** is operation was successful.
#### Examples
```sh
# prints current directory content
ls
# prints current directory content
ls .
# prints examples directory content
ls ./examples
# prints examples directory content with extended info
ls -l ./examples
# prints current directory content with extended info
ls -l
# prints file name
ls ./examples/ls.ds
# prints file name with extended info
ls -l ./examples/ls.ds
```
#### Aliases:
ls
<a name="sdk__fs__MovePath"></a>
## sdk::fs::MovePath
```sh

View file

@ -0,0 +1,43 @@
```sh
var = ls [flags] [path]
```
Lists the file/directory contents.<br>
If no path is provided, the current working directory will be used.<br>
The supported flags are:
* -l - Shows extended information
#### Parameters
* Optional flags (currently only -l is supported)
* Optional path (if not provided, current working directory is used)
#### Return Value
**true** is operation was successful.
#### Examples
```sh
# prints current directory content
ls
# prints current directory content
ls .
# prints examples directory content
ls ./examples
# prints examples directory content with extended info
ls -l ./examples
# prints current directory content with extended info
ls -l
# prints file name
ls ./examples/ls.ds
# prints file name with extended info
ls -l ./examples/ls.ds
```

View file

@ -0,0 +1,157 @@
use crate::utils::{flags, io, pckg};
use duckscript::types::command::{Command, CommandResult};
use fs_extra::dir::{ls, DirEntryAttr, DirEntryValue};
use std::collections::{HashMap, HashSet};
use std::path::Path;
#[cfg(test)]
#[path = "./mod_test.rs"]
mod mod_test;
fn get_string_value(
key: DirEntryAttr,
attributes: &HashMap<DirEntryAttr, DirEntryValue>,
) -> String {
match attributes.get(&key) {
Some(ref entry_value) => match entry_value {
DirEntryValue::String(value) => value.to_string(),
_ => "".to_string(),
},
None => "".to_string(),
}
}
fn get_u64_value(key: DirEntryAttr, attributes: &HashMap<DirEntryAttr, DirEntryValue>) -> String {
match attributes.get(&key) {
Some(ref entry_value) => match entry_value {
DirEntryValue::U64(value) => value.to_string(),
_ => "".to_string(),
},
None => "".to_string(),
}
}
fn get_boolean_value(key: DirEntryAttr, attributes: &HashMap<DirEntryAttr, DirEntryValue>) -> bool {
match attributes.get(&key) {
Some(ref entry_value) => match entry_value {
DirEntryValue::Boolean(value) => *value,
_ => false,
},
None => false,
}
}
fn print_entry(item: &HashMap<DirEntryAttr, DirEntryValue>, extended_details: bool) {
if extended_details {
let directory_flag = if get_boolean_value(DirEntryAttr::IsDir, &item) {
"<DIR>"
} else {
""
};
println!(
"{}\t{}\t{}",
get_u64_value(DirEntryAttr::FileSize, &item),
directory_flag,
get_string_value(DirEntryAttr::FullName, &item)
);
} else {
println!("{} ", get_string_value(DirEntryAttr::FullName, &item));
}
}
struct CommandImpl {
package: String,
}
impl Command for CommandImpl {
fn name(&self) -> String {
pckg::concat(&self.package, "List")
}
fn aliases(&self) -> Vec<String> {
vec!["ls".to_string()]
}
fn help(&self) -> String {
include_str!("help.md").to_string()
}
fn run(&self, arguments: Vec<String>) -> CommandResult {
let (path_str, flags) = if arguments.is_empty() {
(".", "")
} else if arguments.len() == 1 {
if flags::is_unix_flags_argument(&arguments[0]) {
(".", arguments[0].as_str())
} else {
(arguments[0].as_str(), "")
}
} else if flags::is_unix_flags_argument(&arguments[0]) {
(arguments[1].as_str(), arguments[0].as_str())
} else {
(arguments[0].as_str(), "")
};
let path = Path::new(path_str);
if !path.exists() {
CommandResult::Continue(Some("false".to_string()))
} else {
let extended_details = flags::is_unix_flag_exists('l', flags);
let mut config = HashSet::new();
config.insert(DirEntryAttr::FullName);
if extended_details {
config.insert(DirEntryAttr::FileSize);
config.insert(DirEntryAttr::IsDir);
}
let (is_file, query_path) = if path.is_file() {
match io::get_parent_directory_name(path_str) {
Some(value) => (true, value),
None => return CommandResult::Continue(Some("false".to_string())),
}
} else {
(false, path_str.to_string())
};
let result = ls(&query_path, &config);
match result {
Ok(ls_result) => {
let items = ls_result.items;
if is_file {
let file_name = match io::get_base_name(path_str) {
Some(value) => value,
None => path_str.to_string(),
};
for item in items {
let item_name = get_string_value(DirEntryAttr::FullName, &item);
if item_name == file_name {
print_entry(&item, extended_details);
break;
}
}
} else {
for item in items {
print_entry(&item, extended_details);
}
}
CommandResult::Continue(Some("true".to_string()))
}
Err(_) => CommandResult::Continue(Some("false".to_string())),
}
}
}
}
pub(crate) fn create(package: &str) -> Box<dyn Command> {
Box::new(CommandImpl {
package: package.to_string(),
})
}

View file

@ -0,0 +1,71 @@
use super::*;
use crate::test;
use crate::test::CommandValidation;
#[test]
fn common_functions() {
test::test_common_command_functions(create(""));
}
#[test]
fn run_no_args() {
test::run_script_and_validate(
vec![create("")],
"out = ls",
CommandValidation::Match("out".to_string(), "true".to_string()),
);
}
#[test]
fn run_flag_only() {
test::run_script_and_validate(
vec![create("")],
"out = ls -l",
CommandValidation::Match("out".to_string(), "true".to_string()),
);
}
#[test]
fn run_current_directory() {
test::run_script_and_validate(
vec![create("")],
"out = ls .",
CommandValidation::Match("out".to_string(), "true".to_string()),
);
}
#[test]
fn run_current_directory_and_flags() {
test::run_script_and_validate(
vec![create("")],
"out = ls -l .",
CommandValidation::Match("out".to_string(), "true".to_string()),
);
}
#[test]
fn run_current_directory_does_not_exist() {
test::run_script_and_validate(
vec![create("")],
"out = ls ./baddirname",
CommandValidation::Match("out".to_string(), "false".to_string()),
);
}
#[test]
fn run_file() {
test::run_script_and_validate(
vec![create("")],
"out = ls ./Cargo.toml",
CommandValidation::Match("out".to_string(), "true".to_string()),
);
}
#[test]
fn run_file_with_flags() {
test::run_script_and_validate(
vec![create("")],
"out = ls -l ./Cargo.toml",
CommandValidation::Match("out".to_string(), "true".to_string()),
);
}

View file

@ -2,6 +2,7 @@ mod basename;
mod canonical;
mod cp;
mod dirname;
mod list;
mod mkdir;
mod mv;
mod print;
@ -24,6 +25,7 @@ pub(crate) fn load(commands: &mut Commands, parent: &str) -> Result<(), ScriptEr
commands.set(canonical::create(&package))?;
commands.set(cp::create(&package))?;
commands.set(dirname::create(&package))?;
commands.set(list::create(&package))?;
commands.set(mkdir::create(&package))?;
commands.set(mv::create(&package))?;
commands.set(print::create(&package))?;

View file

@ -1,5 +1,4 @@
use crate::utils::io;
use crate::utils::pckg;
use crate::utils::{io, pckg};
use duckscript::types::command::{Command, CommandResult};
#[cfg(test)]

21
examples/ls.ds Normal file
View file

@ -0,0 +1,21 @@
# prints current directory content
ls
# prints current directory content
ls .
# prints examples directory content
ls ./examples
# prints examples directory content with extended info
ls -l ./examples
# prints current directory content with extended info
ls -l
# prints file name
ls ./examples/ls.ds
# prints file name with extended info
ls -l ./examples/ls.ds