mirror of
https://github.com/nushell/nushell
synced 2024-12-28 14:03:09 +00:00
commit
f2d54f201d
10 changed files with 183 additions and 72 deletions
|
@ -258,7 +258,6 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
|||
whole_stream_command(Next),
|
||||
whole_stream_command(Previous),
|
||||
whole_stream_command(Debug),
|
||||
whole_stream_command(Lines),
|
||||
whole_stream_command(Shells),
|
||||
whole_stream_command(SplitColumn),
|
||||
whole_stream_command(SplitRow),
|
||||
|
@ -277,6 +276,7 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
|||
whole_stream_command(ToYAML),
|
||||
whole_stream_command(SortBy),
|
||||
whole_stream_command(Tags),
|
||||
whole_stream_command(Count),
|
||||
whole_stream_command(First),
|
||||
whole_stream_command(Last),
|
||||
whole_stream_command(Env),
|
||||
|
|
|
@ -8,6 +8,7 @@ pub(crate) mod classified;
|
|||
pub(crate) mod clip;
|
||||
pub(crate) mod command;
|
||||
pub(crate) mod config;
|
||||
pub(crate) mod count;
|
||||
pub(crate) mod cp;
|
||||
pub(crate) mod date;
|
||||
pub(crate) mod debug;
|
||||
|
@ -78,6 +79,7 @@ pub(crate) use command::{
|
|||
|
||||
pub(crate) use classified::ClassifiedCommand;
|
||||
pub(crate) use config::Config;
|
||||
pub(crate) use count::Count;
|
||||
pub(crate) use cp::Cpy;
|
||||
pub(crate) use date::Date;
|
||||
pub(crate) use debug::Debug;
|
||||
|
|
|
@ -251,7 +251,7 @@ impl ExternalCommand {
|
|||
)
|
||||
} else {
|
||||
ShellError::labeled_error(
|
||||
"Error: $it needs string data",
|
||||
"$it needs string data",
|
||||
"given something else",
|
||||
self.name_tag.clone(),
|
||||
)
|
||||
|
|
|
@ -70,9 +70,9 @@ pub fn config(
|
|||
|
||||
if let Some(v) = get {
|
||||
let key = v.to_string();
|
||||
let value = result.get(&key).ok_or_else(|| {
|
||||
ShellError::labeled_error(&format!("Missing key in config"), "key", v.tag())
|
||||
})?;
|
||||
let value = result
|
||||
.get(&key)
|
||||
.ok_or_else(|| ShellError::labeled_error("Missing key in config", "key", v.tag()))?;
|
||||
|
||||
let mut results = VecDeque::new();
|
||||
|
||||
|
@ -121,7 +121,7 @@ pub fn config(
|
|||
config::write(&result, &configuration)?;
|
||||
} else {
|
||||
return Err(ShellError::labeled_error(
|
||||
"{} does not exist in config",
|
||||
"Key does not exist in config",
|
||||
"key",
|
||||
v.tag(),
|
||||
));
|
||||
|
|
46
src/commands/count.rs
Normal file
46
src/commands/count.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::Value;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::CommandRegistry;
|
||||
use crate::prelude::*;
|
||||
use futures::stream::StreamExt;
|
||||
|
||||
pub struct Count;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct CountArgs {}
|
||||
|
||||
impl WholeStreamCommand for Count {
|
||||
fn name(&self) -> &str {
|
||||
"count"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("count")
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Show the total number of rows."
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
args.process(registry, count)?.run()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn count(
|
||||
CountArgs {}: CountArgs,
|
||||
RunnableContext { input, name, .. }: RunnableContext,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let stream = async_stream! {
|
||||
let rows: Vec<Tagged<Value>> = input.values.collect().await;
|
||||
|
||||
yield ReturnSuccess::value(Value::int(rows.len()).tagged(name))
|
||||
};
|
||||
|
||||
Ok(stream.to_output_stream())
|
||||
}
|
|
@ -7,7 +7,7 @@ pub struct First;
|
|||
|
||||
#[derive(Deserialize)]
|
||||
pub struct FirstArgs {
|
||||
amount: Tagged<u64>,
|
||||
rows: Option<Tagged<u64>>,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for First {
|
||||
|
@ -16,7 +16,7 @@ impl WholeStreamCommand for First {
|
|||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("first").required("amount", SyntaxShape::Int)
|
||||
Signature::build("first").optional("rows", SyntaxShape::Int)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
|
@ -33,8 +33,16 @@ impl WholeStreamCommand for First {
|
|||
}
|
||||
|
||||
fn first(
|
||||
FirstArgs { amount }: FirstArgs,
|
||||
FirstArgs { rows }: FirstArgs,
|
||||
context: RunnableContext,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
Ok(OutputStream::from_input(context.input.values.take(*amount)))
|
||||
let rows_desired = if let Some(quantity) = rows {
|
||||
*quantity
|
||||
} else {
|
||||
1
|
||||
};
|
||||
|
||||
Ok(OutputStream::from_input(
|
||||
context.input.values.take(rows_desired),
|
||||
))
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ pub struct Last;
|
|||
|
||||
#[derive(Deserialize)]
|
||||
pub struct LastArgs {
|
||||
amount: Tagged<u64>,
|
||||
rows: Option<Tagged<u64>>,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for Last {
|
||||
|
@ -16,7 +16,7 @@ impl WholeStreamCommand for Last {
|
|||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("last").required("amount", SyntaxShape::Number)
|
||||
Signature::build("last").optional("rows", SyntaxShape::Number)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
|
@ -32,13 +32,17 @@ impl WholeStreamCommand for Last {
|
|||
}
|
||||
}
|
||||
|
||||
fn last(
|
||||
LastArgs { amount }: LastArgs,
|
||||
context: RunnableContext,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
fn last(LastArgs { rows }: LastArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {
|
||||
let stream = async_stream! {
|
||||
let v: Vec<_> = context.input.into_vec().await;
|
||||
let count = (*amount as usize);
|
||||
|
||||
let rows_desired = if let Some(quantity) = rows {
|
||||
*quantity
|
||||
} else {
|
||||
1
|
||||
};
|
||||
|
||||
let count = (rows_desired as usize);
|
||||
if count < v.len() {
|
||||
let k = v.len() - count;
|
||||
for x in v[k..].iter() {
|
||||
|
|
|
@ -21,8 +21,8 @@ async fn docker(sub_command: &String, name: Tag) -> Result<Vec<Tagged<Value>>, S
|
|||
"images" => docker_images(name),
|
||||
_ => Err(ShellError::labeled_error(
|
||||
"Unsupported Docker command",
|
||||
format!("'{}'?", sub_command),
|
||||
name.span,
|
||||
"unknown docker command",
|
||||
name,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ fn process_docker_output(cmd_output: &str, tag: Tag) -> Result<Vec<Tagged<Value>
|
|||
.filter(|s| s.trim() != "")
|
||||
.collect();
|
||||
|
||||
let mut dict = TaggedDictBuilder::new(tag);
|
||||
let mut dict = TaggedDictBuilder::new(&tag);
|
||||
for (i, v) in values.iter().enumerate() {
|
||||
dict.insert(header[i].to_string(), Value::string(v.trim().to_string()));
|
||||
}
|
||||
|
@ -92,18 +92,13 @@ impl Plugin for Docker {
|
|||
if let Some(args) = callinfo.args.positional {
|
||||
match &args[0] {
|
||||
Tagged {
|
||||
item: Value::Primitive(Primitive::String(s)),
|
||||
item: Value::Primitive(Primitive::String(command)),
|
||||
..
|
||||
} => match block_on(docker(&s, callinfo.name_tag)) {
|
||||
} => match block_on(docker(&command, args[0].tag())) {
|
||||
Ok(v) => return Ok(v.into_iter().map(ReturnSuccess::value).collect()),
|
||||
Err(e) => return Err(e),
|
||||
},
|
||||
_ => {
|
||||
return Err(ShellError::string(format!(
|
||||
"Unrecognized type in params: {:?}",
|
||||
args[0]
|
||||
)))
|
||||
}
|
||||
_ => return Err(ShellError::type_error("string", args[0].tagged_type_name())),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,26 +7,21 @@ use helpers::{Playground, Stub::*};
|
|||
fn ls_lists_regular_files() {
|
||||
Playground::setup("ls_test_1", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![
|
||||
EmptyFile("yehuda.10.txt"),
|
||||
EmptyFile("jonathan.10.txt"),
|
||||
EmptyFile("andres.10.txt"),
|
||||
EmptyFile("yehuda.txt"),
|
||||
EmptyFile("jonathan.txt"),
|
||||
EmptyFile("andres.txt"),
|
||||
]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), h::pipeline(
|
||||
r#"
|
||||
ls
|
||||
| get name
|
||||
| lines
|
||||
| split-column "."
|
||||
| get Column2
|
||||
| str --to-int
|
||||
| sum
|
||||
| count
|
||||
| echo $it
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual, "30");
|
||||
assert_eq!(actual, "3");
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -34,22 +29,17 @@ fn ls_lists_regular_files() {
|
|||
fn ls_lists_regular_files_using_asterisk_wildcard() {
|
||||
Playground::setup("ls_test_2", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![
|
||||
EmptyFile("los.1.txt"),
|
||||
EmptyFile("tres.1.txt"),
|
||||
EmptyFile("amigos.1.txt"),
|
||||
EmptyFile("arepas.1.clu"),
|
||||
EmptyFile("los.txt"),
|
||||
EmptyFile("tres.txt"),
|
||||
EmptyFile("amigos.txt"),
|
||||
EmptyFile("arepas.clu"),
|
||||
]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), h::pipeline(
|
||||
r#"
|
||||
ls *.txt
|
||||
| get name
|
||||
| lines
|
||||
| split-column "."
|
||||
| get Column2
|
||||
| str --to-int
|
||||
| sum
|
||||
| count
|
||||
| echo $it
|
||||
"#
|
||||
));
|
||||
|
@ -72,16 +62,11 @@ fn ls_lists_regular_files_using_question_mark_wildcard() {
|
|||
cwd: dirs.test(), h::pipeline(
|
||||
r#"
|
||||
ls *.??.txt
|
||||
| get name
|
||||
| lines
|
||||
| split-column "."
|
||||
| get Column2
|
||||
| str --to-int
|
||||
| sum
|
||||
| count
|
||||
| echo $it
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual, "30");
|
||||
assert_eq!(actual, "3");
|
||||
})
|
||||
}
|
||||
|
|
|
@ -7,38 +7,109 @@ use helpers::{Playground, Stub::*};
|
|||
fn first_gets_first_rows_by_amount() {
|
||||
Playground::setup("first_test_1", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![
|
||||
EmptyFile("los.1.txt"),
|
||||
EmptyFile("tres.1.txt"),
|
||||
EmptyFile("amigos.1.txt"),
|
||||
EmptyFile("arepas.1.clu"),
|
||||
EmptyFile("los.txt"),
|
||||
EmptyFile("tres.txt"),
|
||||
EmptyFile("amigos.txt"),
|
||||
EmptyFile("arepas.clu"),
|
||||
]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), h::pipeline(
|
||||
r#"
|
||||
ls
|
||||
| get name
|
||||
| first 2
|
||||
| split-column "."
|
||||
| get Column2
|
||||
| str --to-int
|
||||
| sum
|
||||
| first 3
|
||||
| count
|
||||
| echo $it
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual, "2");
|
||||
assert_eq!(actual, "3");
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn first_requires_an_amount() {
|
||||
Playground::setup("first_test_2", |dirs, _| {
|
||||
let actual = nu_error!(
|
||||
cwd: dirs.test(), "ls | first"
|
||||
);
|
||||
fn first_gets_all_rows_if_amount_higher_than_all_rows() {
|
||||
Playground::setup("first_test_2", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![
|
||||
EmptyFile("los.txt"),
|
||||
EmptyFile("tres.txt"),
|
||||
EmptyFile("amigos.txt"),
|
||||
EmptyFile("arepas.clu"),
|
||||
]);
|
||||
|
||||
assert!(actual.contains("requires amount parameter"));
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), h::pipeline(
|
||||
r#"
|
||||
ls
|
||||
| first 99
|
||||
| count
|
||||
| echo $it
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual, "4");
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn first_gets_first_row_when_no_amount_given() {
|
||||
Playground::setup("first_test_3", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![EmptyFile("caballeros.txt"), EmptyFile("arepas.clu")]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), h::pipeline(
|
||||
r#"
|
||||
ls
|
||||
| first
|
||||
| count
|
||||
| echo $it
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual, "1");
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn last_gets_last_rows_by_amount() {
|
||||
Playground::setup("last_test_1", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![
|
||||
EmptyFile("los.txt"),
|
||||
EmptyFile("tres.txt"),
|
||||
EmptyFile("amigos.txt"),
|
||||
EmptyFile("arepas.clu"),
|
||||
]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), h::pipeline(
|
||||
r#"
|
||||
ls
|
||||
| last 3
|
||||
| count
|
||||
| echo $it
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual, "3");
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn last_gets_last_row_when_no_amount_given() {
|
||||
Playground::setup("last_test_2", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![EmptyFile("caballeros.txt"), EmptyFile("arepas.clu")]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), h::pipeline(
|
||||
r#"
|
||||
ls
|
||||
| last
|
||||
| count
|
||||
| echo $it
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual, "1");
|
||||
})
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue