Port help and start porting split

This commit is contained in:
JT
2021-10-09 14:02:01 +13:00
parent b654415494
commit 4ddc953e38
14 changed files with 633 additions and 50 deletions

View File

@ -15,7 +15,7 @@ impl Command for Do {
}
fn signature(&self) -> nu_protocol::Signature {
Signature::build("do").required(
Signature::build("do").desc(self.usage()).required(
"block",
SyntaxShape::Block(Some(vec![])),
"the block to run",

View File

@ -1,10 +1,10 @@
use nu_protocol::{
ast::Call,
engine::{Command, EvaluationContext},
Example, ShellError, Signature, Spanned, SyntaxShape, Value,
span, Example, ShellError, Signature, Spanned, SyntaxShape, Value,
};
use nu_engine::CallExt;
use nu_engine::{get_full_help, CallExt};
pub struct Help;
@ -73,11 +73,11 @@ impl Command for Help {
}
fn help(context: &EvaluationContext, call: &Call) -> Result<Value, ShellError> {
let span = call.head;
let head = call.head;
let find: Option<Spanned<String>> = call.get_flag(context, "find")?;
let rest: Vec<Spanned<String>> = call.rest(context, 0)?;
let full_commands = context.get_commands_info();
let full_commands = context.get_signatures_with_examples();
if let Some(f) = find {
let search_string = f.item;
@ -87,29 +87,36 @@ fn help(context: &EvaluationContext, call: &Call) -> Result<Value, ShellError> {
let mut cols = vec![];
let mut vals = vec![];
let key = cmd.name.clone();
let c = cmd.usage.clone();
let e = cmd.extra_usage.clone();
let key = cmd.0.name.clone();
let c = cmd.0.usage.clone();
let e = cmd.0.extra_usage.clone();
if key.to_lowercase().contains(&search_string)
|| c.to_lowercase().contains(&search_string)
|| e.to_lowercase().contains(&search_string)
{
cols.push("name".into());
vals.push(Value::String { val: key, span });
vals.push(Value::String {
val: key,
span: head,
});
cols.push("usage".into());
vals.push(Value::String { val: c, span });
vals.push(Value::String { val: c, span: head });
cols.push("extra_usage".into());
vals.push(Value::String { val: e, span });
vals.push(Value::String { val: e, span: head });
found_cmds_vec.push(Value::Record { cols, vals, span });
found_cmds_vec.push(Value::Record {
cols,
vals,
span: head,
});
}
}
return Ok(Value::List {
vals: found_cmds_vec,
span,
span: head,
});
}
@ -121,25 +128,38 @@ fn help(context: &EvaluationContext, call: &Call) -> Result<Value, ShellError> {
let mut cols = vec![];
let mut vals = vec![];
let key = cmd.name.clone();
let c = cmd.usage.clone();
let e = cmd.extra_usage.clone();
let key = cmd.0.name.clone();
let c = cmd.0.usage.clone();
let e = cmd.0.extra_usage.clone();
cols.push("name".into());
vals.push(Value::String { val: key, span });
vals.push(Value::String {
val: key,
span: head,
});
cols.push("usage".into());
vals.push(Value::String { val: c, span });
vals.push(Value::String { val: c, span: head });
cols.push("extra_usage".into());
vals.push(Value::String { val: e, span });
vals.push(Value::String { val: e, span: head });
found_cmds_vec.push(Value::Record { cols, vals, span });
found_cmds_vec.push(Value::Record {
cols,
vals,
span: head,
});
}
Ok(Value::List {
vals: found_cmds_vec,
span: head,
})
} else {
let mut name = String::new();
let mut output = String::new();
for r in rest {
for r in &rest {
if !name.is_empty() {
name.push(' ');
}
@ -147,31 +167,24 @@ fn help(context: &EvaluationContext, call: &Call) -> Result<Value, ShellError> {
}
for cmd in full_commands {
let mut cols = vec![];
let mut vals = vec![];
let key = cmd.name.clone();
let c = cmd.usage.clone();
let e = cmd.extra_usage.clone();
if key.starts_with(&name) {
cols.push("name".into());
vals.push(Value::String { val: key, span });
cols.push("usage".into());
vals.push(Value::String { val: c, span });
cols.push("extra_usage".into());
vals.push(Value::String { val: e, span });
found_cmds_vec.push(Value::Record { cols, vals, span });
if cmd.0.name == name {
let help = get_full_help(&cmd.0, &cmd.1, context);
output.push_str(&help);
}
}
if !output.is_empty() {
Ok(Value::String {
val: output,
span: call.head,
})
} else {
Err(ShellError::CommandNotFound(span(&[
rest[0].span,
rest[rest.len() - 1].span,
])))
}
}
Ok(Value::List {
vals: found_cmds_vec,
span,
})
// FIXME: the fancy help stuff needs to be reimplemented
/*
@ -341,7 +354,7 @@ You can also learn more at https://www.nushell.sh/book/"#;
Ok(Value::String {
val: msg.into(),
span,
span: head,
})
}
}

View File

@ -41,6 +41,8 @@ pub fn create_default_context() -> Rc<RefCell<EngineState>> {
working_set.add_decl(Box::new(Mv));
working_set.add_decl(Box::new(Ps));
working_set.add_decl(Box::new(Select));
working_set.add_decl(Box::new(Split));
working_set.add_decl(Box::new(SplitChars));
working_set.add_decl(Box::new(Sys));
working_set.add_decl(Box::new(Table));
working_set.add_decl(Box::new(Touch));

View File

@ -1,3 +1,5 @@
mod build_string;
mod split;
pub use build_string::BuildString;
pub use split::*;

View File

@ -0,0 +1,157 @@
use nu_protocol::{
ast::Call,
engine::{Command, EvaluationContext},
Example, IntoValueStream, ShellError, Signature, Span, Type, Value,
};
pub struct SubCommand;
impl Command for SubCommand {
fn name(&self) -> &str {
"split chars"
}
fn signature(&self) -> Signature {
Signature::build("split chars")
}
fn usage(&self) -> &str {
"splits a string's characters into separate rows"
}
fn run(
&self,
_context: &EvaluationContext,
call: &Call,
input: Value,
) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
split_chars(call, input)
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Split the string's characters into separate rows",
example: "echo 'hello' | split chars",
result: Some(vec![
Value::String {
val: "h".into(),
span: Span::unknown(),
},
Value::String {
val: "e".into(),
span: Span::unknown(),
},
Value::String {
val: "l".into(),
span: Span::unknown(),
},
Value::String {
val: "l".into(),
span: Span::unknown(),
},
Value::String {
val: "o".into(),
span: Span::unknown(),
},
]),
}]
}
}
fn split_chars(call: &Call, input: Value) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
let name = call.head;
Ok(match input {
Value::List { vals, span } => Value::List {
vals: vals
.iter()
.flat_map(move |v| {
if let Ok(s) = v.as_string() {
let v_span = v.span();
s.chars()
.collect::<Vec<_>>()
.into_iter()
.map(move |x| Value::String {
val: x.to_string(),
span: v_span,
})
.collect()
} else {
vec![Value::Error {
error: ShellError::PipelineMismatch {
expected: Type::String,
expected_span: name,
origin: v.span(),
},
}]
}
})
.collect(),
span,
},
Value::Stream { stream, span } => Value::Stream {
stream: stream
.flat_map(move |v| {
if let Ok(s) = v.as_string() {
let v_span = v.span();
s.chars()
.collect::<Vec<_>>()
.into_iter()
.map(move |x| Value::String {
val: x.to_string(),
span: v_span,
})
.collect()
} else {
vec![Value::Error {
error: ShellError::PipelineMismatch {
expected: Type::String,
expected_span: name,
origin: v.span(),
},
}]
}
})
.into_value_stream(),
span,
},
v => {
let v_span = v.span();
if let Ok(s) = v.as_string() {
Value::List {
vals: s
.chars()
.collect::<Vec<_>>()
.into_iter()
.map(move |x| Value::String {
val: x.to_string(),
span: v_span,
})
.collect(),
span: v_span,
}
} else {
Value::Error {
error: ShellError::PipelineMismatch {
expected: Type::String,
expected_span: name,
origin: v.span(),
},
}
}
}
})
}
// #[cfg(test)]
// mod tests {
// use super::ShellError;
// use super::SubCommand;
// #[test]
// fn examples_work_as_expected() -> Result<(), ShellError> {
// use crate::examples::test as test_examples;
// test_examples(SubCommand {})
// }
// }

View File

@ -0,0 +1,48 @@
use nu_engine::get_full_help;
use nu_protocol::{
ast::Call,
engine::{Command, EvaluationContext},
Signature, Value,
};
#[derive(Clone)]
pub struct SplitCommand;
impl Command for SplitCommand {
fn name(&self) -> &str {
"split"
}
fn signature(&self) -> Signature {
Signature::build("split")
}
fn usage(&self) -> &str {
"Split contents across desired subcommand (like row, column) via the separator."
}
fn run(
&self,
context: &EvaluationContext,
call: &Call,
_input: Value,
) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
Ok(Value::String {
val: get_full_help(&SplitCommand.signature(), &SplitCommand.examples(), context),
span: call.head,
})
}
}
// #[cfg(test)]
// mod tests {
// use super::Command;
// use super::ShellError;
// #[test]
// fn examples_work_as_expected() -> Result<(), ShellError> {
// use crate::examples::test as test_examples;
// test_examples(Command {})
// }
// }

View File

@ -0,0 +1,9 @@
pub mod chars;
// pub mod column;
pub mod command;
// pub mod row;
pub use chars::SubCommand as SplitChars;
// pub use column::SubCommand as SplitColumn;
pub use command::SplitCommand as Split;
// pub use row::SubCommand as SplitRow;