This commit introduces a basic help feature. We can go to it

with the `help` command to explore and list all commands available.

Enter will also try to see if the location to be entered is an existing
Nu command, if it is it will let you inspect the command under `help`.

This provides baseline needed so we can iterate on it.
This commit is contained in:
Andrés N. Robalino 2019-08-29 17:52:32 -05:00
parent ce2d247367
commit ca0c6eaf58
86 changed files with 1180 additions and 453 deletions

View file

@ -209,6 +209,7 @@ Nu adheres closely to a set of goals that make up its design philosophy. As feat
| date (--utc) | Get the current datetime | | date (--utc) | Get the current datetime |
| ps | View current processes | | ps | View current processes |
| sys | View information about the current system | | sys | View information about the current system |
| which filename | Finds a program file. |
| open {filename or url} | Load a file into a cell, convert to table if possible (avoid by appending '--raw') | | open {filename or url} | Load a file into a cell, convert to table if possible (avoid by appending '--raw') |
| post url body (--user <user>) (--password <password>) | Post content to a url and retrieve data as a table if possible | | post url body (--user <user>) (--password <password>) | Post content to a url and retrieve data as a table if possible |
| rm {file or directory} | Remove a file, (for removing directory append '--recursive') | | rm {file or directory} | Remove a file, (for removing directory append '--recursive') |
@ -217,6 +218,8 @@ Nu adheres closely to a set of goals that make up its design philosophy. As feat
| p | Go to previous shell | | p | Go to previous shell |
| n | Go to next shell | | n | Go to next shell |
| shells | Display the list of current shells | | shells | Display the list of current shells |
| help | Display help information about commands |
| version | Display Nu version |
## Filters on tables (structured data) ## Filters on tables (structured data)
| command | description | | command | description |
@ -230,8 +233,11 @@ Nu adheres closely to a set of goals that make up its design philosophy. As feat
| add field value | Add a new field to the table | | add field value | Add a new field to the table |
| sum | Sum a column of values | | sum | Sum a column of values |
| edit field value | Edit an existing field to have a new value | | edit field value | Edit an existing field to have a new value |
| reverse | Reverses the table. |
| skip amount | Skip a number of rows | | skip amount | Skip a number of rows |
| skip-while condition | Skips rows while the condition matches. |
| first amount | Show only the first number of rows | | first amount | Show only the first number of rows |
| last amount | Show only the last number of rows |
| nth row-number | Return only the selected row | | nth row-number | Return only the selected row |
| str (field) | Apply string function. Optional use the field of a table | | str (field) | Apply string function. Optional use the field of a table |
| tags | Read the tags (metadata) for values | | tags | Read the tags (metadata) for values |
@ -240,13 +246,13 @@ Nu adheres closely to a set of goals that make up its design philosophy. As feat
| to-json | Convert table into .json text | | to-json | Convert table into .json text |
| to-toml | Convert table into .toml text | | to-toml | Convert table into .toml text |
| to-yaml | Convert table into .yaml text | | to-yaml | Convert table into .yaml text |
| to-bson | Convert table into .bson text |
| to-csv | Convert table into .csv text | | to-csv | Convert table into .csv text |
| to-bson | Convert table into .bson binary data | | to-bson | Convert table into .bson binary data |
| to-tsv | Convert table into .tsv text | | to-tsv | Convert table into .tsv text |
| to-sqlite | Convert table to sqlite .db binary data | | to-sqlite | Convert table to sqlite .db binary data |
| reverse | Reverse the rows of a table | | reverse | Reverse the rows of a table |
## Filters on text (unstructured data) ## Filters on text (unstructured data)
| command | description | | command | description |
| ------------- | ------------- | | ------------- | ------------- |

View file

@ -212,6 +212,7 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
whole_stream_command(Config), whole_stream_command(Config),
whole_stream_command(SkipWhile), whole_stream_command(SkipWhile),
per_item_command(Enter), per_item_command(Enter),
per_item_command(Help),
whole_stream_command(Exit), whole_stream_command(Exit),
whole_stream_command(Autoview), whole_stream_command(Autoview),
per_item_command(Cpy), per_item_command(Cpy),

View file

@ -25,6 +25,7 @@ pub(crate) mod from_tsv;
pub(crate) mod from_xml; pub(crate) mod from_xml;
pub(crate) mod from_yaml; pub(crate) mod from_yaml;
pub(crate) mod get; pub(crate) mod get;
pub(crate) mod help;
pub(crate) mod last; pub(crate) mod last;
pub(crate) mod lines; pub(crate) mod lines;
pub(crate) mod ls; pub(crate) mod ls;
@ -91,6 +92,7 @@ pub(crate) use from_xml::FromXML;
pub(crate) use from_yaml::FromYAML; pub(crate) use from_yaml::FromYAML;
pub(crate) use from_yaml::FromYML; pub(crate) use from_yaml::FromYML;
pub(crate) use get::Get; pub(crate) use get::Get;
pub(crate) use help::Help;
pub(crate) use last::Last; pub(crate) use last::Last;
pub(crate) use lines::Lines; pub(crate) use lines::Lines;
pub(crate) use ls::LS; pub(crate) use ls::LS;

View file

@ -12,6 +12,14 @@ impl WholeStreamCommand for Autoview {
"autoview" "autoview"
} }
fn signature(&self) -> Signature {
Signature::build("autoview")
}
fn usage(&self) -> &str {
"View the contents of the pipeline as a table or list."
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,
@ -19,10 +27,6 @@ impl WholeStreamCommand for Autoview {
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
Ok(args.process_raw(registry, autoview)?.run()) Ok(args.process_raw(registry, autoview)?.run())
} }
fn signature(&self) -> Signature {
Signature::build("autoview")
}
} }
pub fn autoview( pub fn autoview(

View file

@ -5,6 +5,19 @@ use crate::prelude::*;
pub struct CD; pub struct CD;
impl WholeStreamCommand for CD { impl WholeStreamCommand for CD {
fn name(&self) -> &str {
"cd"
}
fn signature(&self) -> Signature {
Signature::build("cd")
.optional("directory", SyntaxType::Path)
}
fn usage(&self) -> &str {
"Change to a new path."
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,
@ -12,14 +25,6 @@ impl WholeStreamCommand for CD {
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
cd(args, registry) cd(args, registry)
} }
fn name(&self) -> &str {
"cd"
}
fn signature(&self) -> Signature {
Signature::build("cd").optional("directory", SyntaxType::Path)
}
} }
fn cd(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn cd(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {

View file

@ -140,6 +140,29 @@ impl InternalCommand {
context.add_span_source(uuid, span_source); context.add_span_source(uuid, span_source);
} }
CommandAction::Exit => std::process::exit(0), CommandAction::Exit => std::process::exit(0),
CommandAction::EnterHelpShell(value) => {
match value {
Tagged {
item: Value::Primitive(Primitive::String(cmd)),
..
} => {
context.shell_manager.insert_at_current(Box::new(
HelpShell::for_command(
Tagged::from_simple_spanned_item(
Value::string(cmd),
Span::unknown(),
),
&context.registry().clone(),
)?,
));
}
_ => {
context.shell_manager.insert_at_current(Box::new(
HelpShell::index(&context.registry().clone())?,
));
}
}
}
CommandAction::EnterValueShell(value) => { CommandAction::EnterValueShell(value) => {
context context
.shell_manager .shell_manager

View file

@ -18,6 +18,15 @@ pub mod clipboard {
fn name(&self) -> &str { fn name(&self) -> &str {
"clip" "clip"
} }
fn signature(&self) -> Signature {
Signature::build("clip")
}
fn usage(&self) -> &str {
"Copy the contents of the pipeline to the copy/paste buffer"
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,
@ -25,10 +34,6 @@ pub mod clipboard {
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
args.process(registry, clip)?.run() args.process(registry, clip)?.run()
} }
fn signature(&self) -> Signature {
Signature::build("clip")
}
} }
pub fn clip( pub fn clip(

View file

@ -417,6 +417,7 @@ pub enum CommandAction {
Exit, Exit,
EnterShell(String), EnterShell(String),
EnterValueShell(Tagged<Value>), EnterValueShell(Tagged<Value>),
EnterHelpShell(Tagged<Value>),
PreviousShell, PreviousShell,
NextShell, NextShell,
LeaveShell, LeaveShell,
@ -434,6 +435,9 @@ impl ToDebug for CommandAction {
CommandAction::EnterValueShell(t) => { CommandAction::EnterValueShell(t) => {
write!(f, "action:enter-value-shell={:?}", t.debug()) write!(f, "action:enter-value-shell={:?}", t.debug())
} }
CommandAction::EnterHelpShell(t) => {
write!(f, "action:enter-help-shell={:?}", t.debug())
}
CommandAction::PreviousShell => write!(f, "action:previous-shell"), CommandAction::PreviousShell => write!(f, "action:previous-shell"),
CommandAction::NextShell => write!(f, "action:next-shell"), CommandAction::NextShell => write!(f, "action:next-shell"),
CommandAction::LeaveShell => write!(f, "action:leave-shell"), CommandAction::LeaveShell => write!(f, "action:leave-shell"),
@ -488,26 +492,42 @@ impl ReturnSuccess {
pub trait WholeStreamCommand: Send + Sync { pub trait WholeStreamCommand: Send + Sync {
fn name(&self) -> &str; fn name(&self) -> &str;
fn run(
&self,
args: CommandArgs,
registry: &registry::CommandRegistry,
) -> Result<OutputStream, ShellError>;
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature { Signature {
name: self.name().to_string(), name: self.name().to_string(),
usage: self.usage().to_string(),
positional: vec![], positional: vec![],
rest_positional: None, rest_positional: None,
named: indexmap::IndexMap::new(), named: indexmap::IndexMap::new(),
is_filter: true, is_filter: true,
} }
} }
fn usage(&self) -> &str;
fn run(
&self,
args: CommandArgs,
registry: &registry::CommandRegistry,
) -> Result<OutputStream, ShellError>;
} }
pub trait PerItemCommand: Send + Sync { pub trait PerItemCommand: Send + Sync {
fn name(&self) -> &str; fn name(&self) -> &str;
fn signature(&self) -> Signature {
Signature {
name: self.name().to_string(),
usage: self.usage().to_string(),
positional: vec![],
rest_positional: None,
named: indexmap::IndexMap::new(),
is_filter: true,
}
}
fn usage(&self) -> &str;
fn run( fn run(
&self, &self,
call_info: &CallInfo, call_info: &CallInfo,
@ -515,16 +535,6 @@ pub trait PerItemCommand: Send + Sync {
raw_args: &RawCommandArgs, raw_args: &RawCommandArgs,
input: Tagged<Value>, input: Tagged<Value>,
) -> Result<OutputStream, ShellError>; ) -> Result<OutputStream, ShellError>;
fn signature(&self) -> Signature {
Signature {
name: self.name().to_string(),
positional: vec![],
rest_positional: None,
named: indexmap::IndexMap::new(),
is_filter: true,
}
}
} }
pub enum Command { pub enum Command {
@ -547,6 +557,13 @@ impl Command {
} }
} }
pub fn usage(&self) -> &str {
match self {
Command::WholeStream(command) => command.usage(),
Command::PerItem(command) => command.usage(),
}
}
pub fn run(&self, args: CommandArgs, registry: &registry::CommandRegistry) -> OutputStream { pub fn run(&self, args: CommandArgs, registry: &registry::CommandRegistry) -> OutputStream {
match self { match self {
Command::WholeStream(command) => match command.run(args, registry) { Command::WholeStream(command) => match command.run(args, registry) {
@ -618,6 +635,10 @@ impl WholeStreamCommand for FnFilterCommand {
&self.name &self.name
} }
fn usage(&self) -> &str {
"usage"
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,

View file

@ -32,6 +32,10 @@ impl WholeStreamCommand for Config {
.switch("path") .switch("path")
} }
fn usage(&self) -> &str {
"Configuration management."
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,

View file

@ -15,16 +15,6 @@ pub struct CopyArgs {
} }
impl PerItemCommand for Cpy { impl PerItemCommand for Cpy {
fn run(
&self,
call_info: &CallInfo,
_registry: &CommandRegistry,
raw_args: &RawCommandArgs,
_input: Tagged<Value>,
) -> Result<OutputStream, ShellError> {
call_info.process(&raw_args.shell_manager, cp)?.run()
}
fn name(&self) -> &str { fn name(&self) -> &str {
"cp" "cp"
} }
@ -36,6 +26,20 @@ impl PerItemCommand for Cpy {
.named("file", SyntaxType::Any) .named("file", SyntaxType::Any)
.switch("recursive") .switch("recursive")
} }
fn usage(&self) -> &str {
"Copy files."
}
fn run(
&self,
call_info: &CallInfo,
_registry: &CommandRegistry,
raw_args: &RawCommandArgs,
_input: Tagged<Value>,
) -> Result<OutputStream, ShellError> {
call_info.process(&raw_args.shell_manager, cp)?.run()
}
} }
fn cp(args: CopyArgs, context: &RunnablePerItemContext) -> Result<OutputStream, ShellError> { fn cp(args: CopyArgs, context: &RunnablePerItemContext) -> Result<OutputStream, ShellError> {

View file

@ -12,6 +12,20 @@ use indexmap::IndexMap;
pub struct Date; pub struct Date;
impl WholeStreamCommand for Date { impl WholeStreamCommand for Date {
fn name(&self) -> &str {
"date"
}
fn signature(&self) -> Signature {
Signature::build("date")
.switch("utc")
.switch("local")
}
fn usage(&self) -> &str {
"Get the current datetime."
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,
@ -19,13 +33,6 @@ impl WholeStreamCommand for Date {
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
date(args, registry) date(args, registry)
} }
fn name(&self) -> &str {
"date"
}
fn signature(&self) -> Signature {
Signature::build("date").switch("utc").switch("local")
}
} }
pub fn date_to_value<T: TimeZone>(dt: DateTime<T>, span: Span) -> Tagged<Value> pub fn date_to_value<T: TimeZone>(dt: DateTime<T>, span: Span) -> Tagged<Value>

View file

@ -5,14 +5,6 @@ use crate::prelude::*;
pub struct Debug; pub struct Debug;
impl WholeStreamCommand for Debug { impl WholeStreamCommand for Debug {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
debug(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"debug" "debug"
} }
@ -20,6 +12,18 @@ impl WholeStreamCommand for Debug {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("debug") Signature::build("debug")
} }
fn usage(&self) -> &str {
"Debug input fed."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
debug(args, registry)
}
} }
pub fn debug(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> { pub fn debug(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {

View file

@ -17,6 +17,10 @@ impl PerItemCommand for Enter {
Signature::build("enter").required("location", SyntaxType::Block) Signature::build("enter").required("location", SyntaxType::Block)
} }
fn usage(&self) -> &str {
"Create a new shell and begin at this path."
}
fn run( fn run(
&self, &self,
call_info: &CallInfo, call_info: &CallInfo,
@ -33,7 +37,13 @@ impl PerItemCommand for Enter {
} => { } => {
let location = location.to_string(); let location = location.to_string();
let location_clone = location.to_string(); let location_clone = location.to_string();
if PathBuf::from(location).is_dir() {
if registry.has(&location) {
Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell(
Value::string(location_clone).tagged(Tag::unknown()),
)))]
.into())
} else if PathBuf::from(location).is_dir() {
Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterShell( Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterShell(
location_clone, location_clone,
)))] )))]

View file

@ -6,6 +6,19 @@ use crate::prelude::*;
pub struct Exit; pub struct Exit;
impl WholeStreamCommand for Exit { impl WholeStreamCommand for Exit {
fn name(&self) -> &str {
"exit"
}
fn signature(&self) -> Signature {
Signature::build("exit")
.switch("now")
}
fn usage(&self) -> &str {
"Exit the current shell (or all shells)"
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,
@ -13,14 +26,6 @@ impl WholeStreamCommand for Exit {
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
exit(args, registry) exit(args, registry)
} }
fn name(&self) -> &str {
"exit"
}
fn signature(&self) -> Signature {
Signature::build("exit").switch("now")
}
} }
pub fn exit(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { pub fn exit(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {

View file

@ -6,6 +6,19 @@ use crate::prelude::*;
pub struct First; pub struct First;
impl WholeStreamCommand for First { impl WholeStreamCommand for First {
fn name(&self) -> &str {
"first"
}
fn signature(&self) -> Signature {
Signature::build("first")
.required("amount", SyntaxType::Literal)
}
fn usage(&self) -> &str {
"Show only the first number of rows."
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,
@ -13,14 +26,6 @@ impl WholeStreamCommand for First {
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
first(args, registry) first(args, registry)
} }
fn name(&self) -> &str {
"first"
}
fn signature(&self) -> Signature {
Signature::build("first").required("amount", SyntaxType::Literal)
}
} }
fn first(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn first(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {

View file

@ -5,14 +5,6 @@ use crate::prelude::*;
pub struct FromArray; pub struct FromArray;
impl WholeStreamCommand for FromArray { impl WholeStreamCommand for FromArray {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
from_array(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"from-array" "from-array"
} }
@ -20,6 +12,18 @@ impl WholeStreamCommand for FromArray {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("from-array") Signature::build("from-array")
} }
fn usage(&self) -> &str {
"Expand an array/list into rows"
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
from_array(args, registry)
}
} }
fn from_array(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn from_array(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {

View file

@ -7,14 +7,6 @@ use std::str::FromStr;
pub struct FromBSON; pub struct FromBSON;
impl WholeStreamCommand for FromBSON { impl WholeStreamCommand for FromBSON {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
from_bson(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"from-bson" "from-bson"
} }
@ -22,6 +14,18 @@ impl WholeStreamCommand for FromBSON {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("from-bson") Signature::build("from-bson")
} }
fn usage(&self) -> &str {
"Parse text as .bson and create table."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
from_bson(args, registry)
}
} }
fn convert_bson_value_to_nu_value(v: &Bson, tag: impl Into<Tag>) -> Tagged<Value> { fn convert_bson_value_to_nu_value(v: &Bson, tag: impl Into<Tag>) -> Tagged<Value> {

View file

@ -16,7 +16,12 @@ impl WholeStreamCommand for FromCSV {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("from-csv").switch("headerless") Signature::build("from-csv")
.switch("headerless")
}
fn usage(&self) -> &str {
"Parse text as .csv and create table"
} }
fn run( fn run(

View file

@ -6,14 +6,6 @@ use std::collections::HashMap;
pub struct FromINI; pub struct FromINI;
impl WholeStreamCommand for FromINI { impl WholeStreamCommand for FromINI {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
from_ini(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"from-ini" "from-ini"
} }
@ -21,6 +13,18 @@ impl WholeStreamCommand for FromINI {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("from-ini") Signature::build("from-ini")
} }
fn usage(&self) -> &str {
"Parse text as .ini and create table"
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
from_ini(args, registry)
}
} }
fn convert_ini_second_to_nu_value( fn convert_ini_second_to_nu_value(

View file

@ -15,7 +15,12 @@ impl WholeStreamCommand for FromJSON {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("from-json").switch("objects") Signature::build("from-json")
.switch("objects")
}
fn usage(&self) -> &str {
"Parse text as .json and create table."
} }
fn run( fn run(

View file

@ -9,14 +9,6 @@ use std::path::Path;
pub struct FromSQLite; pub struct FromSQLite;
impl WholeStreamCommand for FromSQLite { impl WholeStreamCommand for FromSQLite {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
from_sqlite(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"from-sqlite" "from-sqlite"
} }
@ -24,11 +16,11 @@ impl WholeStreamCommand for FromSQLite {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("from-sqlite") Signature::build("from-sqlite")
} }
}
pub struct FromDB; fn usage(&self) -> &str {
"Parse binary data as sqlite .db and create table."
}
impl WholeStreamCommand for FromDB {
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,
@ -36,7 +28,11 @@ impl WholeStreamCommand for FromDB {
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
from_sqlite(args, registry) from_sqlite(args, registry)
} }
}
pub struct FromDB;
impl WholeStreamCommand for FromDB {
fn name(&self) -> &str { fn name(&self) -> &str {
"from-db" "from-db"
} }
@ -44,6 +40,18 @@ impl WholeStreamCommand for FromDB {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("from-db") Signature::build("from-db")
} }
fn usage(&self) -> &str {
"Parse binary data as db and create table."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
from_sqlite(args, registry)
}
} }
pub fn convert_sqlite_file_to_nu_value( pub fn convert_sqlite_file_to_nu_value(

View file

@ -5,14 +5,6 @@ use crate::prelude::*;
pub struct FromTOML; pub struct FromTOML;
impl WholeStreamCommand for FromTOML { impl WholeStreamCommand for FromTOML {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
from_toml(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"from-toml" "from-toml"
} }
@ -20,6 +12,18 @@ impl WholeStreamCommand for FromTOML {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("from-toml") Signature::build("from-toml")
} }
fn usage(&self) -> &str {
"Parse text as .toml and create table."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
from_toml(args, registry)
}
} }
pub fn convert_toml_value_to_nu_value(v: &toml::Value, tag: impl Into<Tag>) -> Tagged<Value> { pub fn convert_toml_value_to_nu_value(v: &toml::Value, tag: impl Into<Tag>) -> Tagged<Value> {

View file

@ -19,6 +19,10 @@ impl WholeStreamCommand for FromTSV {
Signature::build("from-tsv").switch("headerless") Signature::build("from-tsv").switch("headerless")
} }
fn usage(&self) -> &str {
"Parse text as .tsv and create table."
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,

View file

@ -5,14 +5,6 @@ use crate::prelude::*;
pub struct FromXML; pub struct FromXML;
impl WholeStreamCommand for FromXML { impl WholeStreamCommand for FromXML {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
from_xml(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"from-xml" "from-xml"
} }
@ -20,6 +12,18 @@ impl WholeStreamCommand for FromXML {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("from-xml") Signature::build("from-xml")
} }
fn usage(&self) -> &str {
"Parse text as .xml and create table."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
from_xml(args, registry)
}
} }
fn from_node_to_value<'a, 'd>(n: &roxmltree::Node<'a, 'd>, tag: impl Into<Tag>) -> Tagged<Value> { fn from_node_to_value<'a, 'd>(n: &roxmltree::Node<'a, 'd>, tag: impl Into<Tag>) -> Tagged<Value> {

View file

@ -5,14 +5,6 @@ use crate::prelude::*;
pub struct FromYAML; pub struct FromYAML;
impl WholeStreamCommand for FromYAML { impl WholeStreamCommand for FromYAML {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
from_yaml(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"from-yaml" "from-yaml"
} }
@ -20,11 +12,11 @@ impl WholeStreamCommand for FromYAML {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("from-yaml") Signature::build("from-yaml")
} }
}
pub struct FromYML; fn usage(&self) -> &str {
"Parse text as .yaml/.yml and create table."
}
impl WholeStreamCommand for FromYML {
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,
@ -32,7 +24,11 @@ impl WholeStreamCommand for FromYML {
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
from_yaml(args, registry) from_yaml(args, registry)
} }
}
pub struct FromYML;
impl WholeStreamCommand for FromYML {
fn name(&self) -> &str { fn name(&self) -> &str {
"from-yml" "from-yml"
} }
@ -40,6 +36,18 @@ impl WholeStreamCommand for FromYML {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("from-yml") Signature::build("from-yml")
} }
fn usage(&self) -> &str {
"Parse text as .yaml/.yml and create table."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
from_yaml(args, registry)
}
} }
fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value, tag: impl Into<Tag>) -> Tagged<Value> { fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value, tag: impl Into<Tag>) -> Tagged<Value> {

View file

@ -15,6 +15,14 @@ impl WholeStreamCommand for Get {
"get" "get"
} }
fn signature(&self) -> Signature {
Signature::build("get").rest(SyntaxType::Member)
}
fn usage(&self) -> &str {
"Open given cells as text."
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,
@ -22,10 +30,6 @@ impl WholeStreamCommand for Get {
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
args.process(registry, get)?.run() args.process(registry, get)?.run()
} }
fn signature(&self) -> Signature {
Signature::build("get").rest(SyntaxType::Member)
}
} }
fn get_member(path: &Tagged<String>, obj: &Tagged<Value>) -> Result<Tagged<Value>, ShellError> { fn get_member(path: &Tagged<String>, obj: &Tagged<Value>) -> Result<Tagged<Value>, ShellError> {

55
src/commands/help.rs Normal file
View file

@ -0,0 +1,55 @@
use crate::commands::command::CommandAction;
use crate::commands::PerItemCommand;
use crate::errors::ShellError;
use crate::parser::registry;
use crate::prelude::*;
pub struct Help;
impl PerItemCommand for Help {
fn name(&self) -> &str {
"help"
}
fn signature(&self) -> registry::Signature {
Signature::build("help").rest(SyntaxType::Any)
}
fn usage(&self) -> &str {
"Display help information about commands."
}
fn run(
&self,
call_info: &CallInfo,
_registry: &CommandRegistry,
_raw_args: &RawCommandArgs,
_input: Tagged<Value>,
) -> Result<OutputStream, ShellError> {
let span = call_info.name_span;
if call_info.args.len() == 0 {
return Ok(
vec![
Ok(ReturnSuccess::Action(
CommandAction::EnterHelpShell(
Tagged::from_simple_spanned_item(Value::nothing(), span)
)))].into()
)
}
match call_info.args.expect_nth(0)? {
Tagged {
item: Value::Primitive(Primitive::String(document)),
..
} => Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell(
Tagged::from_simple_spanned_item(Value::string(document), span)
)))]
.into()),
x => Ok(
vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell(x.clone())))]
.into(),
),
}
}
}

View file

@ -6,6 +6,19 @@ use crate::prelude::*;
pub struct Last; pub struct Last;
impl WholeStreamCommand for Last { impl WholeStreamCommand for Last {
fn name(&self) -> &str {
"last"
}
fn signature(&self) -> Signature {
Signature::build("last")
.required("amount", SyntaxType::Number)
}
fn usage(&self) -> &str {
"Show only the last number of rows."
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,
@ -13,14 +26,6 @@ impl WholeStreamCommand for Last {
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
last(args, registry) last(args, registry)
} }
fn name(&self) -> &str {
"last"
}
fn signature(&self) -> Signature {
Signature::build("last").required("amount", SyntaxType::Literal)
}
} }
fn last(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn last(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {

View file

@ -7,14 +7,6 @@ use log::trace;
pub struct Lines; pub struct Lines;
impl WholeStreamCommand for Lines { impl WholeStreamCommand for Lines {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
lines(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"lines" "lines"
} }
@ -22,6 +14,18 @@ impl WholeStreamCommand for Lines {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("lines") Signature::build("lines")
} }
fn usage(&self) -> &str {
"Split single string into rows, one per line."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
lines(args, registry)
}
} }
// TODO: "Amount remaining" wrapper // TODO: "Amount remaining" wrapper

View file

@ -5,14 +5,6 @@ use crate::prelude::*;
pub struct LS; pub struct LS;
impl WholeStreamCommand for LS { impl WholeStreamCommand for LS {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
ls(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"ls" "ls"
} }
@ -20,6 +12,18 @@ impl WholeStreamCommand for LS {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("ls").optional("path", SyntaxType::Path) Signature::build("ls").optional("path", SyntaxType::Path)
} }
fn usage(&self) -> &str {
"View the contents of the current or given path."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
ls(args, registry)
}
} }
fn ls(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn ls(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {

View file

@ -12,6 +12,18 @@ pub struct MkdirArgs {
} }
impl PerItemCommand for Mkdir { impl PerItemCommand for Mkdir {
fn name(&self) -> &str {
"mkdir"
}
fn signature(&self) -> Signature {
Signature::build("mkdir").rest(SyntaxType::Path)
}
fn usage(&self) -> &str {
"Make directories, creates intermediary directories as required."
}
fn run( fn run(
&self, &self,
call_info: &CallInfo, call_info: &CallInfo,
@ -21,14 +33,6 @@ impl PerItemCommand for Mkdir {
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
call_info.process(&raw_args.shell_manager, mkdir)?.run() call_info.process(&raw_args.shell_manager, mkdir)?.run()
} }
fn name(&self) -> &str {
"mkdir"
}
fn signature(&self) -> Signature {
Signature::build("mkdir").rest(SyntaxType::Path)
}
} }
fn mkdir(args: MkdirArgs, context: &RunnablePerItemContext) -> Result<OutputStream, ShellError> { fn mkdir(args: MkdirArgs, context: &RunnablePerItemContext) -> Result<OutputStream, ShellError> {

View file

@ -25,6 +25,10 @@ impl PerItemCommand for Move {
.named("file", SyntaxType::Any) .named("file", SyntaxType::Any)
} }
fn usage(&self) -> &str {
"Move files or directories."
}
fn run( fn run(
&self, &self,
call_info: &CallInfo, call_info: &CallInfo,

View file

@ -6,14 +6,6 @@ use crate::prelude::*;
pub struct Next; pub struct Next;
impl WholeStreamCommand for Next { impl WholeStreamCommand for Next {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
next(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"n" "n"
} }
@ -21,6 +13,18 @@ impl WholeStreamCommand for Next {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("n") Signature::build("n")
} }
fn usage(&self) -> &str {
"Go to next shell."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
next(args, registry)
}
} }
fn next(_args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn next(_args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {

View file

@ -11,14 +11,6 @@ struct NthArgs {
pub struct Nth; pub struct Nth;
impl WholeStreamCommand for Nth { impl WholeStreamCommand for Nth {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, nth)?.run()
}
fn name(&self) -> &str { fn name(&self) -> &str {
"nth" "nth"
} }
@ -26,6 +18,18 @@ impl WholeStreamCommand for Nth {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("nth").required("amount", SyntaxType::Any) Signature::build("nth").required("amount", SyntaxType::Any)
} }
fn usage(&self) -> &str {
"Return only the selected row"
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, nth)?.run()
}
} }
fn nth( fn nth(

View file

@ -23,6 +23,10 @@ impl PerItemCommand for Open {
.switch("raw") .switch("raw")
} }
fn usage(&self) -> &str {
"Load a file into a cell, convert to table if possible (avoid by appending '--raw')"
}
fn run( fn run(
&self, &self,
call_info: &CallInfo, call_info: &CallInfo,

View file

@ -20,6 +20,10 @@ impl WholeStreamCommand for Pick {
Signature::build("pick").rest(SyntaxType::Any) Signature::build("pick").rest(SyntaxType::Any)
} }
fn usage(&self) -> &str {
"Down-select table to only these columns."
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,

View file

@ -51,6 +51,10 @@ impl WholeStreamCommand for PluginCommand {
self.config.clone() self.config.clone()
} }
fn usage(&self) -> &str {
&self.config.usage
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,
@ -270,6 +274,10 @@ impl WholeStreamCommand for PluginSink {
self.config.clone() self.config.clone()
} }
fn usage(&self) -> &str {
&self.config.usage
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,

View file

@ -27,6 +27,10 @@ impl PerItemCommand for Post {
.switch("raw") .switch("raw")
} }
fn usage(&self) -> &str {
"Post content to a url and retrieve data as a table if possible."
}
fn run( fn run(
&self, &self,
call_info: &CallInfo, call_info: &CallInfo,

View file

@ -7,14 +7,6 @@ use crate::commands::WholeStreamCommand;
pub struct Previous; pub struct Previous;
impl WholeStreamCommand for Previous { impl WholeStreamCommand for Previous {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
previous(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"p" "p"
} }
@ -22,6 +14,18 @@ impl WholeStreamCommand for Previous {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("p") Signature::build("p")
} }
fn usage(&self) -> &str {
"Go to previous shell."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
previous(args, registry)
}
} }
fn previous(_args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn previous(_args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {

View file

@ -12,14 +12,6 @@ use heim::units::{ratio, Ratio};
pub struct PS; pub struct PS;
impl WholeStreamCommand for PS { impl WholeStreamCommand for PS {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
ps(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"ps" "ps"
} }
@ -27,6 +19,18 @@ impl WholeStreamCommand for PS {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("ps") Signature::build("ps")
} }
fn usage(&self) -> &str {
"View current processes."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
ps(args, registry)
}
} }
async fn usage(process: Process) -> ProcessResult<(process::Process, Ratio)> { async fn usage(process: Process) -> ProcessResult<(process::Process, Ratio)> {

View file

@ -11,14 +11,6 @@ pub struct RejectArgs {
pub struct Reject; pub struct Reject;
impl WholeStreamCommand for Reject { impl WholeStreamCommand for Reject {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, reject)?.run()
}
fn name(&self) -> &str { fn name(&self) -> &str {
"reject" "reject"
} }
@ -26,6 +18,18 @@ impl WholeStreamCommand for Reject {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("reject").rest(SyntaxType::Member) Signature::build("reject").rest(SyntaxType::Member)
} }
fn usage(&self) -> &str {
"Remove the given columns from the table."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, reject)?.run()
}
} }
fn reject( fn reject(

View file

@ -6,14 +6,6 @@ use crate::prelude::*;
pub struct Reverse; pub struct Reverse;
impl WholeStreamCommand for Reverse { impl WholeStreamCommand for Reverse {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
reverse(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"reverse" "reverse"
} }
@ -21,6 +13,18 @@ impl WholeStreamCommand for Reverse {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("reverse") Signature::build("reverse")
} }
fn usage(&self) -> &str {
"Reverses the table."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
reverse(args, registry)
}
} }
fn reverse(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn reverse(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {

View file

@ -24,6 +24,10 @@ impl PerItemCommand for Remove {
.switch("recursive") .switch("recursive")
} }
fn usage(&self) -> &str {
"Remove a file, (for removing directory append '--recursive')"
}
fn run( fn run(
&self, &self,
call_info: &CallInfo, call_info: &CallInfo,

View file

@ -23,6 +23,10 @@ impl WholeStreamCommand for Save {
.switch("raw") .switch("raw")
} }
fn usage(&self) -> &str {
"Save the contents of the pipeline to a file."
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,

View file

@ -6,14 +6,6 @@ use crate::prelude::*;
pub struct Shells; pub struct Shells;
impl WholeStreamCommand for Shells { impl WholeStreamCommand for Shells {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
shells(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"shells" "shells"
} }
@ -21,6 +13,18 @@ impl WholeStreamCommand for Shells {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("shells") Signature::build("shells")
} }
fn usage(&self) -> &str {
"Display the list of current shells."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
shells(args, registry)
}
} }
fn shells(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn shells(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {

View file

@ -6,14 +6,6 @@ use crate::prelude::*;
pub struct Size; pub struct Size;
impl WholeStreamCommand for Size { impl WholeStreamCommand for Size {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
size(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"size" "size"
} }
@ -21,6 +13,18 @@ impl WholeStreamCommand for Size {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("size") Signature::build("size")
} }
fn usage(&self) -> &str {
"Gather word count statistics on the text."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
size(args, registry)
}
} }
fn size(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn size(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {

View file

@ -20,6 +20,10 @@ impl WholeStreamCommand for SkipWhile {
.filter() .filter()
} }
fn usage(&self) -> &str {
"Skips rows while the condition matches."
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,

View file

@ -10,14 +10,6 @@ pub struct SortByArgs {
} }
impl WholeStreamCommand for SortBy { impl WholeStreamCommand for SortBy {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, sort_by)?.run()
}
fn name(&self) -> &str { fn name(&self) -> &str {
"sort-by" "sort-by"
} }
@ -25,6 +17,18 @@ impl WholeStreamCommand for SortBy {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("sort-by").rest(SyntaxType::String) Signature::build("sort-by").rest(SyntaxType::String)
} }
fn usage(&self) -> &str {
"Sort by the given columns."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, sort_by)?.run()
}
} }
fn sort_by( fn sort_by(

View file

@ -15,14 +15,6 @@ struct SplitColumnArgs {
pub struct SplitColumn; pub struct SplitColumn;
impl WholeStreamCommand for SplitColumn { impl WholeStreamCommand for SplitColumn {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, split_column)?.run()
}
fn name(&self) -> &str { fn name(&self) -> &str {
"split-column" "split-column"
} }
@ -33,6 +25,18 @@ impl WholeStreamCommand for SplitColumn {
.switch("collapse-empty") .switch("collapse-empty")
.rest(SyntaxType::Member) .rest(SyntaxType::Member)
} }
fn usage(&self) -> &str {
"Split row contents across multiple columns via the separator."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, split_column)?.run()
}
} }
fn split_column( fn split_column(

View file

@ -12,6 +12,19 @@ struct SplitRowArgs {
pub struct SplitRow; pub struct SplitRow;
impl WholeStreamCommand for SplitRow { impl WholeStreamCommand for SplitRow {
fn name(&self) -> &str {
"split-row"
}
fn signature(&self) -> Signature {
Signature::build("split-row")
.required("separator", SyntaxType::Any)
}
fn usage(&self) -> &str {
"Split row contents over multiple rows via the separator."
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,
@ -19,14 +32,6 @@ impl WholeStreamCommand for SplitRow {
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
args.process(registry, split_row)?.run() args.process(registry, split_row)?.run()
} }
fn name(&self) -> &str {
"split-row"
}
fn signature(&self) -> Signature {
Signature::build("split-row").required("separator", SyntaxType::Any)
}
} }
fn split_row( fn split_row(

View file

@ -13,6 +13,15 @@ impl WholeStreamCommand for Table {
fn name(&self) -> &str { fn name(&self) -> &str {
"table" "table"
} }
fn signature(&self) -> Signature {
Signature::build("table")
}
fn usage(&self) -> &str {
"View the contents of the pipeline as a table."
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,
@ -20,9 +29,6 @@ impl WholeStreamCommand for Table {
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
args.process(registry, table)?.run() args.process(registry, table)?.run()
} }
fn signature(&self) -> Signature {
Signature::build("table")
}
} }
pub fn table(_args: TableArgs, context: RunnableContext) -> Result<OutputStream, ShellError> { pub fn table(_args: TableArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {

View file

@ -6,14 +6,6 @@ use crate::prelude::*;
pub struct Tags; pub struct Tags;
impl WholeStreamCommand for Tags { impl WholeStreamCommand for Tags {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
tags(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"tags" "tags"
} }
@ -21,6 +13,18 @@ impl WholeStreamCommand for Tags {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("tags") Signature::build("tags")
} }
fn usage(&self) -> &str {
"Read the tags (metadata) for values."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
tags(args, registry)
}
} }
fn tags(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn tags(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {

View file

@ -5,14 +5,6 @@ use crate::prelude::*;
pub struct ToArray; pub struct ToArray;
impl WholeStreamCommand for ToArray { impl WholeStreamCommand for ToArray {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
to_array(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"to-array" "to-array"
} }
@ -20,6 +12,18 @@ impl WholeStreamCommand for ToArray {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("to-array") Signature::build("to-array")
} }
fn usage(&self) -> &str {
"Collapse rows into a single list."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
to_array(args, registry)
}
} }
fn to_array(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn to_array(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {

View file

@ -7,14 +7,6 @@ use std::convert::TryInto;
pub struct ToBSON; pub struct ToBSON;
impl WholeStreamCommand for ToBSON { impl WholeStreamCommand for ToBSON {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
to_bson(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"to-bson" "to-bson"
} }
@ -22,6 +14,18 @@ impl WholeStreamCommand for ToBSON {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("to-bson") Signature::build("to-bson")
} }
fn usage(&self) -> &str {
"Convert table into .bson text."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
to_bson(args, registry)
}
} }
pub fn value_to_bson_value(v: &Value) -> Bson { pub fn value_to_bson_value(v: &Value) -> Bson {

View file

@ -16,7 +16,12 @@ impl WholeStreamCommand for ToCSV {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("to-csv").switch("headerless") Signature::build("to-csv")
.switch("headerless")
}
fn usage(&self) -> &str {
"Convert table into .csv text "
} }
fn run( fn run(

View file

@ -5,14 +5,6 @@ use crate::prelude::*;
pub struct ToJSON; pub struct ToJSON;
impl WholeStreamCommand for ToJSON { impl WholeStreamCommand for ToJSON {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
to_json(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"to-json" "to-json"
} }
@ -20,6 +12,18 @@ impl WholeStreamCommand for ToJSON {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("to-json") Signature::build("to-json")
} }
fn usage(&self) -> &str {
"Convert table into .json text"
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
to_json(args, registry)
}
} }
pub fn value_to_json_value(v: &Value) -> serde_json::Value { pub fn value_to_json_value(v: &Value) -> serde_json::Value {

View file

@ -8,14 +8,6 @@ use std::io::Read;
pub struct ToSQLite; pub struct ToSQLite;
impl WholeStreamCommand for ToSQLite { impl WholeStreamCommand for ToSQLite {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
to_sqlite(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"to-sqlite" "to-sqlite"
} }
@ -23,11 +15,11 @@ impl WholeStreamCommand for ToSQLite {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("to-sqlite") Signature::build("to-sqlite")
} }
}
pub struct ToDB; fn usage(&self) -> &str {
"Convert table to sqlite .db binary data"
}
impl WholeStreamCommand for ToDB {
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,
@ -35,7 +27,11 @@ impl WholeStreamCommand for ToDB {
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
to_sqlite(args, registry) to_sqlite(args, registry)
} }
}
pub struct ToDB;
impl WholeStreamCommand for ToDB {
fn name(&self) -> &str { fn name(&self) -> &str {
"to-db" "to-db"
} }
@ -43,6 +39,18 @@ impl WholeStreamCommand for ToDB {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("to-db") Signature::build("to-db")
} }
fn usage(&self) -> &str {
"Convert table to db data"
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
to_sqlite(args, registry)
}
} }
fn comma_concat(acc: String, current: String) -> String { fn comma_concat(acc: String, current: String) -> String {

View file

@ -6,14 +6,6 @@ use crate::prelude::*;
pub struct ToTOML; pub struct ToTOML;
impl WholeStreamCommand for ToTOML { impl WholeStreamCommand for ToTOML {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
to_toml(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"to-toml" "to-toml"
} }
@ -21,6 +13,18 @@ impl WholeStreamCommand for ToTOML {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("to-toml") Signature::build("to-toml")
} }
fn usage(&self) -> &str {
"Convert table into .toml text"
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
to_toml(args, registry)
}
} }
pub fn value_to_toml_value(v: &Value) -> Result<toml::Value, ShellError> { pub fn value_to_toml_value(v: &Value) -> Result<toml::Value, ShellError> {

View file

@ -16,7 +16,12 @@ impl WholeStreamCommand for ToTSV {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("to-tsv").switch("headerless") Signature::build("to-tsv")
.switch("headerless")
}
fn usage(&self) -> &str {
"Convert table into .tsv text"
} }
fn run( fn run(

View file

@ -5,14 +5,6 @@ use crate::prelude::*;
pub struct ToYAML; pub struct ToYAML;
impl WholeStreamCommand for ToYAML { impl WholeStreamCommand for ToYAML {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
to_yaml(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"to-yaml" "to-yaml"
} }
@ -20,6 +12,18 @@ impl WholeStreamCommand for ToYAML {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("to-yaml") Signature::build("to-yaml")
} }
fn usage(&self) -> &str {
"Convert table into .yaml/.yml text"
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
to_yaml(args, registry)
}
} }
pub fn value_to_yaml_value(v: &Value) -> serde_yaml::Value { pub fn value_to_yaml_value(v: &Value) -> serde_yaml::Value {

View file

@ -6,14 +6,6 @@ use crate::prelude::*;
pub struct Trim; pub struct Trim;
impl WholeStreamCommand for Trim { impl WholeStreamCommand for Trim {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
trim(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"trim" "trim"
} }
@ -21,6 +13,18 @@ impl WholeStreamCommand for Trim {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("trim") Signature::build("trim")
} }
fn usage(&self) -> &str {
"Trim leading and following whitespace from text data."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
trim(args, registry)
}
} }
fn trim(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> { fn trim(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {

View file

@ -8,14 +8,6 @@ use indexmap::IndexMap;
pub struct Version; pub struct Version;
impl WholeStreamCommand for Version { impl WholeStreamCommand for Version {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
date(args, registry)
}
fn name(&self) -> &str { fn name(&self) -> &str {
"version" "version"
} }
@ -23,6 +15,18 @@ impl WholeStreamCommand for Version {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("version") Signature::build("version")
} }
fn usage(&self) -> &str {
"Display Nu version"
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
date(args, registry)
}
} }
pub fn date(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { pub fn date(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {

View file

@ -12,6 +12,15 @@ impl WholeStreamCommand for VTable {
fn name(&self) -> &str { fn name(&self) -> &str {
"vtable" "vtable"
} }
fn signature(&self) -> Signature {
Signature::build("vtable")
}
fn usage(&self) -> &str {
"View the contents of the pipeline as a vertical (rotated) table."
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,
@ -19,9 +28,6 @@ impl WholeStreamCommand for VTable {
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
args.process(registry, vtable)?.run() args.process(registry, vtable)?.run()
} }
fn signature(&self) -> Signature {
Signature::build("vtable")
}
} }
pub fn vtable(_args: VTableArgs, context: RunnableContext) -> Result<OutputStream, ShellError> { pub fn vtable(_args: VTableArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {

View file

@ -12,7 +12,12 @@ impl PerItemCommand for Where {
} }
fn signature(&self) -> registry::Signature { fn signature(&self) -> registry::Signature {
Signature::build("where").required("condition", SyntaxType::Block) Signature::build("where")
.required("condition", SyntaxType::Block)
}
fn usage(&self) -> &str {
"Filter table to match the condition."
} }
fn run( fn run(

View file

@ -8,6 +8,19 @@ use crate::parser::registry::Signature;
pub struct Which; pub struct Which;
impl WholeStreamCommand for Which { impl WholeStreamCommand for Which {
fn name(&self) -> &str {
"which"
}
fn signature(&self) -> Signature {
Signature::build("which")
.required("name", SyntaxType::Any)
}
fn usage(&self) -> &str {
"Finds a program file."
}
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,
@ -15,13 +28,6 @@ impl WholeStreamCommand for Which {
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
which(args, registry) which(args, registry)
} }
fn name(&self) -> &str {
"which"
}
fn signature(&self) -> Signature {
Signature::build("which").required("name", SyntaxType::Any)
}
} }
pub fn which(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { pub fn which(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {

View file

@ -53,7 +53,7 @@ impl CommandRegistry {
registry.get(name).map(|c| c.clone()) registry.get(name).map(|c| c.clone())
} }
fn has(&self, name: &str) -> bool { pub(crate) fn has(&self, name: &str) -> bool {
let registry = self.registry.lock().unwrap(); let registry = self.registry.lock().unwrap();
registry.contains_key(name) registry.contains_key(name)

View file

@ -1,4 +1,5 @@
pub(crate) mod base; pub(crate) mod base;
pub(crate) mod command;
pub(crate) mod config; pub(crate) mod config;
pub(crate) mod dict; pub(crate) mod dict;
pub(crate) mod files; pub(crate) mod files;
@ -8,5 +9,6 @@ pub(crate) mod types;
#[allow(unused)] #[allow(unused)]
pub(crate) use base::{Block, Primitive, Switch, Value}; pub(crate) use base::{Block, Primitive, Switch, Value};
pub(crate) use dict::{Dictionary, TaggedDictBuilder}; pub(crate) use dict::{Dictionary, TaggedListBuilder, TaggedDictBuilder};
pub(crate) use files::dir_entry_dict; pub(crate) use files::dir_entry_dict;
pub(crate) use command::command_dict;

67
src/object/command.rs Normal file
View file

@ -0,0 +1,67 @@
use crate::commands::command::Command;
use crate::object::{TaggedDictBuilder, TaggedListBuilder, Value};
use crate::parser::registry::{NamedType, PositionalType, Signature};
use crate::prelude::*;
use std::ops::Deref;
pub(crate) fn command_dict(command: Arc<Command>, tag: impl Into<Tag>) -> Tagged<Value> {
let tag = tag.into();
let mut cmd_dict = TaggedDictBuilder::new(tag);
cmd_dict.insert("name", Value::string(command.name()));
cmd_dict.insert(
"type",
Value::string(match command.deref() {
Command::WholeStream(_) => "Command",
Command::PerItem(_) => "Filter",
}),
);
cmd_dict.insert_tagged("signature", signature_dict(command.signature(), tag));
cmd_dict.insert("usage", Value::string(command.usage()));
cmd_dict.into_tagged_value()
}
fn for_spec(name: &str, ty: &str, required: bool, tag: impl Into<Tag>) -> Tagged<Value> {
let tag = tag.into();
let mut spec = TaggedDictBuilder::new(tag);
spec.insert("name", Value::string(name));
spec.insert("type", Value::string(ty));
spec.insert("required", Value::string(if required { "yes" } else { "no" }));
spec.into_tagged_value()
}
fn signature_dict(signature: Signature, tag: impl Into<Tag>) -> Tagged<Value> {
let tag = tag.into();
let mut sig = TaggedListBuilder::new(tag);
for arg in signature.positional.iter() {
let is_required = match arg {
PositionalType::Mandatory(_,_) => true,
PositionalType::Optional(_,_) => false,
};
sig.insert_tagged(for_spec(arg.name(), "argument", is_required, tag));
}
if let Some(_) = signature.rest_positional {
let is_required = false;
sig.insert_tagged(for_spec("rest", "argument", is_required, tag));
}
for (name, ty) in signature.named.iter() {
match ty {
NamedType::Mandatory(_) => sig.insert_tagged(for_spec(name, "flag", true, tag)),
NamedType::Optional(_) => sig.insert_tagged(for_spec(name, "flag", false, tag)),
NamedType::Switch => sig.insert_tagged(for_spec(name, "switch", false, tag)),
}
}
sig.into_tagged_value()
}

View file

@ -1,5 +1,4 @@
use crate::prelude::*; use crate::prelude::*;
use crate::object::{Primitive, Value}; use crate::object::{Primitive, Value};
use derive_new::new; use derive_new::new;
use indexmap::IndexMap; use indexmap::IndexMap;

View file

@ -49,6 +49,24 @@ pub enum SyntaxType {
Boolean, Boolean,
} }
impl std::fmt::Display for SyntaxType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
SyntaxType::Any => write!(f, "Any"),
SyntaxType::List => write!(f, "List"),
SyntaxType::Literal => write!(f, "Literal"),
SyntaxType::String => write!(f, "String"),
SyntaxType::Member => write!(f, "Member"),
SyntaxType::Variable => write!(f, "Variable"),
SyntaxType::Number => write!(f, "Number"),
SyntaxType::Path => write!(f, "Path"),
SyntaxType::Binary => write!(f, "Binary"),
SyntaxType::Block => write!(f, "Block"),
SyntaxType::Boolean => write!(f, "Boolean")
}
}
}
pub fn baseline_parse_next_expr( pub fn baseline_parse_next_expr(
tokens: &mut TokensIterator, tokens: &mut TokensIterator,
context: &Context, context: &Context,

View file

@ -73,6 +73,8 @@ impl PositionalType {
pub struct Signature { pub struct Signature {
pub name: String, pub name: String,
#[new(default)] #[new(default)]
pub usage: String,
#[new(default)]
pub positional: Vec<PositionalType>, pub positional: Vec<PositionalType>,
#[new(value = "None")] #[new(value = "None")]
pub rest_positional: Option<SyntaxType>, pub rest_positional: Option<SyntaxType>,
@ -87,6 +89,11 @@ impl Signature {
Signature::new(name.into()) Signature::new(name.into())
} }
pub fn desc(mut self, usage: impl Into<String>) -> Signature {
self.usage = usage.into();
self
}
pub fn required(mut self, name: impl Into<String>, ty: impl Into<SyntaxType>) -> Signature { pub fn required(mut self, name: impl Into<String>, ty: impl Into<SyntaxType>) -> Signature {
self.positional self.positional
.push(PositionalType::Mandatory(name.into(), ty.into())); .push(PositionalType::Mandatory(name.into(), ty.into()));

View file

@ -43,6 +43,7 @@ impl Add {
impl Plugin for Add { impl Plugin for Add {
fn config(&mut self) -> Result<Signature, ShellError> { fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature::build("add") Ok(Signature::build("add")
.desc("Add a new field to the table.")
.required("Field", SyntaxType::String) .required("Field", SyntaxType::String)
.required("Value", SyntaxType::String) .required("Value", SyntaxType::String)
.rest(SyntaxType::String).filter()) .rest(SyntaxType::String).filter())

View file

@ -12,7 +12,9 @@ impl BinaryView {
impl Plugin for BinaryView { impl Plugin for BinaryView {
fn config(&mut self) -> Result<Signature, ShellError> { fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature::build("binaryview").switch("lores")) Ok(Signature::build("binaryview")
.desc("Autoview of binary data.")
.switch("lores"))
} }
fn sink(&mut self, call_info: CallInfo, input: Vec<Tagged<Value>>) { fn sink(&mut self, call_info: CallInfo, input: Vec<Tagged<Value>>) {

View file

@ -42,6 +42,7 @@ impl Edit {
impl Plugin for Edit { impl Plugin for Edit {
fn config(&mut self) -> Result<Signature, ShellError> { fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature::build("edit") Ok(Signature::build("edit")
.desc("Edit an existing field to have a new value.")
.required("Field", SyntaxType::String) .required("Field", SyntaxType::String)
.required("Value", SyntaxType::String) .required("Value", SyntaxType::String)
.filter()) .filter())

View file

@ -70,7 +70,7 @@ impl Inc {
self.error = Some(message.to_string()); self.error = Some(message.to_string());
} }
fn usage(&self) -> &'static str { pub fn usage() -> &'static str {
"Usage: inc field [--major|--minor|--patch]" "Usage: inc field [--major|--minor|--patch]"
} }
@ -116,6 +116,7 @@ impl Inc {
impl Plugin for Inc { impl Plugin for Inc {
fn config(&mut self) -> Result<Signature, ShellError> { fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature::build("inc") Ok(Signature::build("inc")
.desc("Increment a value or version. Optional use the field of a table.")
.switch("major") .switch("major")
.switch("minor") .switch("minor")
.switch("patch") .switch("patch")
@ -159,7 +160,7 @@ impl Plugin for Inc {
match &self.error { match &self.error {
Some(reason) => { Some(reason) => {
return Err(ShellError::string(format!("{}: {}", reason, self.usage()))) return Err(ShellError::string(format!("{}: {}", reason, Inc::usage())))
} }
None => Ok(vec![]), None => Ok(vec![]),
} }

View file

@ -1,4 +1,3 @@
use indexmap::IndexMap;
use nu::{ use nu::{
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
SyntaxType, Tagged, Value, SyntaxType, Tagged, Value,
@ -15,13 +14,10 @@ impl Skip {
impl Plugin for Skip { impl Plugin for Skip {
fn config(&mut self) -> Result<Signature, ShellError> { fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature { Ok(Signature::build("skip")
name: "skip".to_string(), .desc("Skip a number of rows")
positional: vec![], .rest(SyntaxType::Number)
is_filter: true, .filter())
named: IndexMap::new(),
rest_positional: Some(SyntaxType::Number),
})
} }
fn begin_filter(&mut self, call_info: CallInfo) -> Result<Vec<ReturnValue>, ShellError> { fn begin_filter(&mut self, call_info: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
if let Some(args) = call_info.args.positional { if let Some(args) = call_info.args.positional {

View file

@ -124,7 +124,7 @@ impl Str {
} }
} }
fn usage(&self) -> &'static str { pub fn usage() -> &'static str {
"Usage: str field [--downcase|--upcase|--to-int|--replace|--find-replace]" "Usage: str field [--downcase|--upcase|--to-int|--replace|--find-replace]"
} }
} }
@ -154,7 +154,7 @@ impl Str {
None => Err(ShellError::string(format!( None => Err(ShellError::string(format!(
"{}: {}", "{}: {}",
"str needs a field when applying it to a value in an object", "str needs a field when applying it to a value in an object",
self.usage() Str::usage()
))), ))),
}, },
x => Err(ShellError::string(format!( x => Err(ShellError::string(format!(
@ -168,6 +168,7 @@ impl Str {
impl Plugin for Str { impl Plugin for Str {
fn config(&mut self) -> Result<Signature, ShellError> { fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature::build("str") Ok(Signature::build("str")
.desc("Apply string function. Optional use the field of a table")
.switch("downcase") .switch("downcase")
.switch("upcase") .switch("upcase")
.switch("to-int") .switch("to-int")
@ -240,7 +241,7 @@ impl Plugin for Str {
match &self.error { match &self.error {
Some(reason) => { Some(reason) => {
return Err(ShellError::string(format!("{}: {}", reason, self.usage()))) return Err(ShellError::string(format!("{}: {}", reason, Str::usage())))
} }
None => Ok(vec![]), None => Ok(vec![]),
} }

View file

@ -64,7 +64,9 @@ impl Sum {
impl Plugin for Sum { impl Plugin for Sum {
fn config(&mut self) -> Result<Signature, ShellError> { fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature::build("sum").filter()) Ok(Signature::build("sum")
.desc("Sum a column of values.")
.filter())
} }
fn begin_filter(&mut self, _: CallInfo) -> Result<Vec<ReturnValue>, ShellError> { fn begin_filter(&mut self, _: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {

View file

@ -309,7 +309,9 @@ async fn sysinfo(tag: Tag) -> Vec<Tagged<Value>> {
impl Plugin for Sys { impl Plugin for Sys {
fn config(&mut self) -> Result<Signature, ShellError> { fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature::build("sys").filter()) Ok(Signature::build("sys")
.desc("View information about the current system.")
.filter())
} }
fn begin_filter(&mut self, callinfo: CallInfo) -> Result<Vec<ReturnValue>, ShellError> { fn begin_filter(&mut self, callinfo: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {

View file

@ -26,7 +26,8 @@ impl TextView {
impl Plugin for TextView { impl Plugin for TextView {
fn config(&mut self) -> Result<Signature, ShellError> { fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature::build("textview")) Ok(Signature::build("textview")
.desc("Autoview of text data."))
} }
fn sink(&mut self, call_info: CallInfo, input: Vec<Tagged<Value>>) { fn sink(&mut self, call_info: CallInfo, input: Vec<Tagged<Value>>) {

View file

@ -80,7 +80,8 @@ struct TreeViewer;
impl Plugin for TreeViewer { impl Plugin for TreeViewer {
fn config(&mut self) -> Result<Signature, ShellError> { fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature::build("tree")) Ok(Signature::build("tree")
.desc("View the contents of the pipeline as a tree."))
} }
fn sink(&mut self, _call_info: CallInfo, input: Vec<Tagged<Value>>) { fn sink(&mut self, _call_info: CallInfo, input: Vec<Tagged<Value>>) {

View file

@ -68,6 +68,7 @@ pub(crate) use crate::parser::registry::Signature;
pub(crate) use crate::shell::filesystem_shell::FilesystemShell; pub(crate) use crate::shell::filesystem_shell::FilesystemShell;
pub(crate) use crate::shell::shell_manager::ShellManager; pub(crate) use crate::shell::shell_manager::ShellManager;
pub(crate) use crate::shell::value_shell::ValueShell; pub(crate) use crate::shell::value_shell::ValueShell;
pub(crate) use crate::shell::help_shell::HelpShell;
pub(crate) use crate::stream::{InputStream, OutputStream}; pub(crate) use crate::stream::{InputStream, OutputStream};
pub(crate) use crate::traits::{HasSpan, ToDebug}; pub(crate) use crate::traits::{HasSpan, ToDebug};
pub(crate) use crate::Span; pub(crate) use crate::Span;

View file

@ -4,5 +4,6 @@ pub(crate) mod helper;
pub(crate) mod shell; pub(crate) mod shell;
pub(crate) mod shell_manager; pub(crate) mod shell_manager;
pub(crate) mod value_shell; pub(crate) mod value_shell;
pub(crate) mod help_shell;
pub(crate) use helper::Helper; pub(crate) use helper::Helper;

234
src/shell/help_shell.rs Normal file
View file

@ -0,0 +1,234 @@
use crate::commands::command::EvaluatedWholeStreamCommandArgs;
use crate::commands::cp::CopyArgs;
use crate::commands::mkdir::MkdirArgs;
use crate::commands::mv::MoveArgs;
use crate::commands::rm::RemoveArgs;
use crate::context::SourceMap;
use crate::object::{TaggedDictBuilder, command_dict};
use crate::prelude::*;
use crate::shell::shell::Shell;
use std::ffi::OsStr;
use std::path::PathBuf;
#[derive(Clone, Debug)]
pub struct HelpShell {
pub(crate) path: String,
pub(crate) value: Tagged<Value>,
}
impl HelpShell {
pub fn index(registry: &CommandRegistry) -> Result<HelpShell, std::io::Error> {
let mut cmds = TaggedDictBuilder::new(Tag::unknown());
let mut specs = Vec::new();
for cmd in registry.names() {
let mut spec = TaggedDictBuilder::new(Tag::unknown());
let value = command_dict(registry.get_command(&cmd).unwrap(), Tag::unknown());
spec.insert("name", cmd);
spec.insert("description", value.get_data_by_key("usage").unwrap().as_string().unwrap());
spec.insert_tagged("details", value);
specs.push(spec.into_tagged_value());
}
cmds.insert("help", Value::List(specs));
Ok(HelpShell {
path: "/help".to_string(),
value: cmds.into_tagged_value(),
})
}
pub fn for_command(
cmd: Tagged<Value>,
registry: &CommandRegistry,
) -> Result<HelpShell, std::io::Error> {
let mut sh = HelpShell::index(&registry)?;
if let Tagged {
item: Value::Primitive(Primitive::String(name)), ..
} = cmd {
sh.set_path(format!("/help/{:}/details", name));
}
Ok(sh)
}
fn commands(&self) -> VecDeque<Tagged<Value>> {
let mut cmds = VecDeque::new();
let full_path = PathBuf::from(&self.path);
let mut viewed = self.value.clone();
let sep_string = std::path::MAIN_SEPARATOR.to_string();
let sep = OsStr::new(&sep_string);
for p in full_path.iter() {
match p {
x if x == sep => {}
step => match viewed.get_data_by_key(step.to_str().unwrap()) {
Some(v) => {
viewed = v.clone();
}
_ => {}
},
}
}
match viewed {
Tagged {
item: Value::List(l),
..
} => {
for item in l {
cmds.push_back(item.clone());
}
}
x => {
cmds.push_back(x.clone());
}
}
cmds
}
}
impl Shell for HelpShell {
fn name(&self, source_map: &SourceMap) -> String {
let origin_name = self.value.origin_name(source_map);
format!(
"{}",
match origin_name {
Some(x) => format!("{{{}}}", x),
None => format!("<{}>", self.value.item.type_name(),),
}
)
}
fn homedir(&self) -> Option<PathBuf> {
dirs::home_dir()
}
fn path(&self) -> String {
self.path.clone()
}
fn set_path(&mut self, path: String) {
let _ = std::env::set_current_dir(&path);
self.path = path.clone();
}
fn ls(&self, _args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> {
Ok(self
.commands()
.map(|x| ReturnSuccess::value(x))
.to_output_stream())
}
fn cd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> {
let path = match args.nth(0) {
None => "/".to_string(),
Some(v) => {
let target = v.as_path()?;
let mut cwd = PathBuf::from(&self.path);
if target == PathBuf::from("..") {
cwd.pop();
} else {
match target.to_str() {
Some(target) => match target.chars().nth(0) {
Some(x) if x == '/' => cwd = PathBuf::from(target),
_ => cwd.push(target),
},
None => cwd.push(target),
}
}
cwd.to_string_lossy().to_string()
}
};
let mut stream = VecDeque::new();
stream.push_back(ReturnSuccess::change_cwd(path));
Ok(stream.into())
}
fn cp(&self, _args: CopyArgs, _name: Span, _path: &str) -> Result<OutputStream, ShellError> {
Ok(OutputStream::empty())
}
fn mv(&self, _args: MoveArgs, _name: Span, _path: &str) -> Result<OutputStream, ShellError> {
Ok(OutputStream::empty())
}
fn mkdir(
&self,
_args: MkdirArgs,
_name: Span,
_path: &str,
) -> Result<OutputStream, ShellError> {
Ok(OutputStream::empty())
}
fn rm(&self, _args: RemoveArgs, _name: Span, _path: &str) -> Result<OutputStream, ShellError> {
Ok(OutputStream::empty())
}
fn complete(
&self,
line: &str,
pos: usize,
_ctx: &rustyline::Context<'_>,
) -> Result<(usize, Vec<rustyline::completion::Pair>), rustyline::error::ReadlineError> {
let mut completions = vec![];
let mut possible_completion = vec![];
let commands = self.commands();
for cmd in commands {
match cmd {
Tagged { item, .. } => {
for desc in item.data_descriptors() {
possible_completion.push(desc);
}
}
}
}
let line_chars: Vec<_> = line.chars().collect();
let mut replace_pos = pos;
while replace_pos > 0 {
if line_chars[replace_pos - 1] == ' ' {
break;
}
replace_pos -= 1;
}
for command in possible_completion.iter() {
let mut pos = replace_pos;
let mut matched = true;
if pos < line_chars.len() {
for chr in command.chars() {
if line_chars[pos] != chr {
matched = false;
break;
}
pos += 1;
if pos == line_chars.len() {
break;
}
}
}
if matched {
completions.push(rustyline::completion::Pair {
display: command.to_string(),
replacement: command.to_string(),
});
}
}
Ok((replace_pos, completions))
}
fn hint(&self, _line: &str, _pos: usize, _ctx: &rustyline::Context<'_>) -> Option<String> {
None
}
}

View file

@ -12,6 +12,7 @@ use std::path::PathBuf;
pub trait Shell: std::fmt::Debug { pub trait Shell: std::fmt::Debug {
fn name(&self, source_map: &SourceMap) -> String; fn name(&self, source_map: &SourceMap) -> String;
fn homedir(&self) -> Option<PathBuf>; fn homedir(&self) -> Option<PathBuf>;
fn ls(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>; fn ls(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>;
fn cd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>; fn cd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>;
fn cp(&self, args: CopyArgs, name: Span, path: &str) -> Result<OutputStream, ShellError>; fn cp(&self, args: CopyArgs, name: Span, path: &str) -> Result<OutputStream, ShellError>;

View file

@ -75,7 +75,7 @@ fn converts_structured_table_to_csv_text_skipping_headers_after_conversion() {
fn converts_from_csv_text_to_structured_table() { fn converts_from_csv_text_to_structured_table() {
Playground::setup("filter_from_csv_test_1", |dirs, sandbox| { Playground::setup("filter_from_csv_test_1", |dirs, sandbox| {
sandbox.with_files(vec![FileWithContentToBeTrimmed( sandbox.with_files(vec![FileWithContentToBeTrimmed(
"los_tres_amigos.txt", "los_tres_caballeros.txt",
r#" r#"
first_name,last_name,rusty_luck first_name,last_name,rusty_luck
Andrés,Robalino,1 Andrés,Robalino,1
@ -87,7 +87,7 @@ fn converts_from_csv_text_to_structured_table() {
let actual = nu!( let actual = nu!(
cwd: dirs.test(), h::pipeline( cwd: dirs.test(), h::pipeline(
r#" r#"
open los_tres_amigos.txt open los_tres_caballeros.txt
| from-csv | from-csv
| get rusty_luck | get rusty_luck
| str --to-int | str --to-int
@ -366,7 +366,8 @@ fn can_convert_table_to_bson_and_back_into_table() {
| get root | get root
| nth 1 | nth 1
| get b | get b
| echo $it"# | echo $it
"#
)); ));
assert_eq!(actual, "whel"); assert_eq!(actual, "whel");
@ -383,7 +384,8 @@ fn can_convert_table_to_sqlite_and_back_into_table() {
| get table_values | get table_values
| nth 2 | nth 2
| get x | get x
| echo $it"# | echo $it
"#
)); ));
assert_eq!(actual, "hello"); assert_eq!(actual, "hello");
@ -398,7 +400,8 @@ fn can_convert_table_to_toml_text_and_from_toml_text_back_into_table() {
| to-toml | to-toml
| from-toml | from-toml
| get package.name | get package.name
| echo $it"# | echo $it
"#
)); ));
assert_eq!(actual, "nu"); assert_eq!(actual, "nu");