Short-hand flags (#1378)

* typo fixes

* Change signature to take in short-hand flags

* update help information

* Parse short-hand flags as their long counterparts

* lints

* Modified a couple tests to use shorthand flags
This commit is contained in:
Corvus Corax 2020-02-11 20:24:31 -06:00 committed by GitHub
parent 2ab8d035e6
commit c0be02a434
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 344 additions and 110 deletions

View File

@ -183,7 +183,11 @@ fn with_empty_context(source: &Text, callback: impl FnOnce(ExpandContext)) {
SyntaxShape::Pattern, SyntaxShape::Pattern,
"a path to get the directory contents from", "a path to get the directory contents from",
) )
.switch("full", "list all available columns for each entry"), .switch(
"full",
"list all available columns for each entry",
Some('f'),
),
); );
callback(ExpandContext::new(Box::new(registry), source, None)) callback(ExpandContext::new(Box::new(registry), source, None))

View File

@ -361,9 +361,20 @@ impl SpannedToken {
} }
} }
pub(crate) fn as_flag(&self, value: &str, source: &Text) -> Option<Flag> { pub(crate) fn as_flag(&self, value: &str, short: Option<char>, source: &Text) -> Option<Flag> {
match self.unspanned() { match self.unspanned() {
Token::Flag(flag @ Flag { .. }) if value == flag.name().slice(source) => Some(*flag), Token::Flag(flag @ Flag { .. }) => {
let name = flag.name().slice(source);
let is_long = flag.kind == FlagKind::Longhand && value == name;
let is_short = flag.kind == FlagKind::Shorthand
&& short.is_some()
&& short == name.chars().nth(0);
if is_long || is_short {
Some(*flag)
} else {
None
}
}
_ => None, _ => None,
} }
} }

View File

@ -31,8 +31,8 @@ pub fn parse_command_tail(
trace!(target: "nu::parse::trace_remaining", "looking for {} : {:?}", name, kind); trace!(target: "nu::parse::trace_remaining", "looking for {} : {:?}", name, kind);
match &kind.0 { match &kind.0 {
NamedType::Switch => { NamedType::Switch(s) => {
let switch = extract_switch(name, tail); let switch = extract_switch(name, *s, tail);
match switch { match switch {
None => named.insert_switch(name, None), None => named.insert_switch(name, None),
@ -45,8 +45,8 @@ pub fn parse_command_tail(
} }
} }
} }
NamedType::Mandatory(syntax_type) => { NamedType::Mandatory(s, syntax_type) => {
match extract_mandatory(config, name, tail, command_span) { match extract_mandatory(config, name, *s, tail, command_span) {
Err(err) => { Err(err) => {
// remember this error, but continue coloring // remember this error, but continue coloring
found_error = Some(err); found_error = Some(err);
@ -71,8 +71,8 @@ pub fn parse_command_tail(
} }
} }
} }
NamedType::Optional(syntax_type) => { NamedType::Optional(s, syntax_type) => {
match extract_optional(name, tail) { match extract_optional(name, *s, tail) {
Err(err) => { Err(err) => {
// remember this error, but continue coloring // remember this error, but continue coloring
found_error = Some(err); found_error = Some(err);
@ -270,10 +270,14 @@ fn expand_spaced_expr<
fn extract_switch( fn extract_switch(
name: &str, name: &str,
short: Option<char>,
tokens: &mut hir::TokensIterator<'_>, tokens: &mut hir::TokensIterator<'_>,
) -> Option<(usize, Spanned<Flag>)> { ) -> Option<(usize, Spanned<Flag>)> {
let source = tokens.source(); let source = tokens.source();
let switch = tokens.extract(|t| t.as_flag(name, &source).map(|flag| flag.spanned(t.span()))); let switch = tokens.extract(|t| {
t.as_flag(name, short, &source)
.map(|flag| flag.spanned(t.span()))
});
match switch { match switch {
None => None, None => None,
@ -287,11 +291,15 @@ fn extract_switch(
fn extract_mandatory( fn extract_mandatory(
config: &Signature, config: &Signature,
name: &str, name: &str,
short: Option<char>,
tokens: &mut hir::TokensIterator<'_>, tokens: &mut hir::TokensIterator<'_>,
span: Span, span: Span,
) -> Result<(usize, Spanned<Flag>), ParseError> { ) -> Result<(usize, Spanned<Flag>), ParseError> {
let source = tokens.source(); let source = tokens.source();
let flag = tokens.extract(|t| t.as_flag(name, &source).map(|flag| flag.spanned(t.span()))); let flag = tokens.extract(|t| {
t.as_flag(name, short, &source)
.map(|flag| flag.spanned(t.span()))
});
match flag { match flag {
None => Err(ParseError::argument_error( None => Err(ParseError::argument_error(
@ -308,10 +316,14 @@ fn extract_mandatory(
fn extract_optional( fn extract_optional(
name: &str, name: &str,
short: Option<char>,
tokens: &mut hir::TokensIterator<'_>, tokens: &mut hir::TokensIterator<'_>,
) -> Result<Option<(usize, Spanned<Flag>)>, ParseError> { ) -> Result<Option<(usize, Spanned<Flag>)>, ParseError> {
let source = tokens.source(); let source = tokens.source();
let flag = tokens.extract(|t| t.as_flag(name, &source).map(|flag| flag.spanned(t.span()))); let flag = tokens.extract(|t| {
t.as_flag(name, short, &source)
.map(|flag| flag.spanned(t.span()))
});
match flag { match flag {
None => Ok(None), None => Ok(None),

View File

@ -7,18 +7,28 @@ use serde::{Deserialize, Serialize};
/// The types of named parameter that a command can have /// The types of named parameter that a command can have
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub enum NamedType { pub enum NamedType {
/// A flag without any associated argument. eg) `foo --bar` /// A flag without any associated argument. eg) `foo --bar, foo -b`
Switch, Switch(Option<char>),
/// A mandatory flag, with associated argument. eg) `foo --required xyz` /// A mandatory flag, with associated argument. eg) `foo --required xyz, foo -r xyz`
Mandatory(SyntaxShape), Mandatory(Option<char>, SyntaxShape),
/// An optional flag, with associated argument. eg) `foo --optional abc` /// An optional flag, with associated argument. eg) `foo --optional abc, foo -o abc`
Optional(SyntaxShape), Optional(Option<char>, SyntaxShape),
}
impl NamedType {
pub fn get_short(&self) -> Option<char> {
match self {
NamedType::Switch(s) => *s,
NamedType::Mandatory(s, _) => *s,
NamedType::Optional(s, _) => *s,
}
}
} }
/// The type of positional arguments /// The type of positional arguments
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PositionalType { pub enum PositionalType {
/// A mandatory postional argument with the expected shape of the value /// A mandatory positional argument with the expected shape of the value
Mandatory(String, SyntaxShape), Mandatory(String, SyntaxShape),
/// An optional positional argument with the expected shape of the value /// An optional positional argument with the expected shape of the value
Optional(String, SyntaxShape), Optional(String, SyntaxShape),
@ -120,7 +130,10 @@ impl Signature {
pub fn allowed(&self) -> Vec<String> { pub fn allowed(&self) -> Vec<String> {
let mut allowed = indexmap::IndexSet::new(); let mut allowed = indexmap::IndexSet::new();
for (name, _) in &self.named { for (name, (t, _)) in &self.named {
if let Some(c) = t.get_short() {
allowed.insert(format!("-{}", c));
}
allowed.insert(format!("--{}", name)); allowed.insert(format!("--{}", name));
} }
@ -157,14 +170,14 @@ impl PrettyDebugWithSource for Signature {
} }
impl Signature { impl Signature {
/// Create a new command signagure with the given name /// Create a new command signature with the given name
pub fn new(name: impl Into<String>) -> Signature { pub fn new(name: impl Into<String>) -> Signature {
Signature { Signature {
name: name.into(), name: name.into(),
usage: String::new(), usage: String::new(),
positional: vec![], positional: vec![],
rest_positional: None, rest_positional: None,
named: indexmap::indexmap! {"help".into() => (NamedType::Switch, "Display this help message".into())}, named: indexmap::indexmap! {"help".into() => (NamedType::Switch(Some('h')), "Display this help message".into())},
is_filter: false, is_filter: false,
yields: None, yields: None,
input: None, input: None,
@ -218,9 +231,16 @@ impl Signature {
name: impl Into<String>, name: impl Into<String>,
ty: impl Into<SyntaxShape>, ty: impl Into<SyntaxShape>,
desc: impl Into<String>, desc: impl Into<String>,
short: Option<char>,
) -> Signature { ) -> Signature {
self.named let s = short.and_then(|c| {
.insert(name.into(), (NamedType::Optional(ty.into()), desc.into())); debug_assert!(!self.get_shorts().contains(&c));
Some(c)
});
self.named.insert(
name.into(),
(NamedType::Optional(s, ty.into()), desc.into()),
);
self self
} }
@ -231,17 +251,35 @@ impl Signature {
name: impl Into<String>, name: impl Into<String>,
ty: impl Into<SyntaxShape>, ty: impl Into<SyntaxShape>,
desc: impl Into<String>, desc: impl Into<String>,
short: Option<char>,
) -> Signature { ) -> Signature {
self.named let s = short.and_then(|c| {
.insert(name.into(), (NamedType::Mandatory(ty.into()), desc.into())); debug_assert!(!self.get_shorts().contains(&c));
Some(c)
});
self.named.insert(
name.into(),
(NamedType::Mandatory(s, ty.into()), desc.into()),
);
self self
} }
/// Add a switch to the signature /// Add a switch to the signature
pub fn switch(mut self, name: impl Into<String>, desc: impl Into<String>) -> Signature { pub fn switch(
mut self,
name: impl Into<String>,
desc: impl Into<String>,
short: Option<char>,
) -> Signature {
let s = short.and_then(|c| {
debug_assert!(!self.get_shorts().contains(&c));
Some(c)
});
self.named self.named
.insert(name.into(), (NamedType::Switch, desc.into())); .insert(name.into(), (NamedType::Switch(s), desc.into()));
self self
} }
@ -268,4 +306,15 @@ impl Signature {
self.input = Some(ty); self.input = Some(ty);
self self
} }
/// Get list of the short-hand flags
pub fn get_shorts(&self) -> Vec<char> {
let mut shorts = Vec::new();
for (_, (t, _)) in &self.named {
if let Some(c) = t.get_short() {
shorts.push(c);
}
}
shorts
}
} }

View File

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

View File

@ -15,7 +15,7 @@ impl Plugin for Fetch {
SyntaxShape::Path, SyntaxShape::Path,
"the URL to fetch the contents from", "the URL to fetch the contents from",
) )
.switch("raw", "fetch contents as text rather than a table") .switch("raw", "fetch contents as text rather than a table", Some('r'))
.filter()) .filter())
} }

View File

@ -16,9 +16,21 @@ 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. Optionally use the column of a table.") .desc("Increment a value or version. Optionally use the column of a table.")
.switch("major", "increment the major version (eg 1.2.1 -> 2.0.0)") .switch(
.switch("minor", "increment the minor version (eg 1.2.1 -> 1.3.0)") "major",
.switch("patch", "increment the patch version (eg 1.2.1 -> 1.2.2)") "increment the major version (eg 1.2.1 -> 2.0.0)",
Some('M'),
)
.switch(
"minor",
"increment the minor version (eg 1.2.1 -> 1.3.0)",
Some('m'),
)
.switch(
"patch",
"increment the patch version (eg 1.2.1 -> 1.2.2)",
Some('p'),
)
.rest(SyntaxShape::ColumnPath, "the column(s) to update") .rest(SyntaxShape::ColumnPath, "the column(s) to update")
.filter()) .filter())
} }

View File

@ -12,23 +12,35 @@ impl Plugin for Post {
.desc("Post content to a url and retrieve data as a table if possible.") .desc("Post content to a url and retrieve data as a table if possible.")
.required("path", SyntaxShape::Any, "the URL to post to") .required("path", SyntaxShape::Any, "the URL to post to")
.required("body", SyntaxShape::Any, "the contents of the post body") .required("body", SyntaxShape::Any, "the contents of the post body")
.named("user", SyntaxShape::Any, "the username when authenticating") .named(
"user",
SyntaxShape::Any,
"the username when authenticating",
Some('u'),
)
.named( .named(
"password", "password",
SyntaxShape::Any, SyntaxShape::Any,
"the password when authenticating", "the password when authenticating",
Some('p'),
) )
.named( .named(
"content-type", "content-type",
SyntaxShape::Any, SyntaxShape::Any,
"the MIME type of content to post", "the MIME type of content to post",
Some('t'),
) )
.named( .named(
"content-length", "content-length",
SyntaxShape::Any, SyntaxShape::Any,
"the length of the content being posted", "the length of the content being posted",
Some('l'),
)
.switch(
"raw",
"return values as a string instead of a table",
Some('r'),
) )
.switch("raw", "return values as a string instead of a table")
.filter()) .filter())
} }

View File

@ -15,19 +15,26 @@ 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 column of a table") .desc("Apply string function. Optional use the column of a table")
.switch("downcase", "convert string to lowercase") .switch("downcase", "convert string to lowercase", Some('d'))
.switch("upcase", "convert string to uppercase") .switch("upcase", "convert string to uppercase", Some('U'))
.switch("to-int", "convert string to integer") .switch("to-int", "convert string to integer", Some('i'))
.named("replace", SyntaxShape::String, "replaces the string") .named(
"replace",
SyntaxShape::String,
"replaces the string",
Some('r'),
)
.named( .named(
"find-replace", "find-replace",
SyntaxShape::Any, SyntaxShape::Any,
"finds and replaces [pattern replacement]", "finds and replaces [pattern replacement]",
Some('f'),
) )
.named( .named(
"substring", "substring",
SyntaxShape::String, SyntaxShape::String,
"convert string to portion of original, requires \"start,end\"", "convert string to portion of original, requires \"start,end\"",
Some('s'),
) )
.rest(SyntaxShape::ColumnPath, "the column(s) to convert") .rest(SyntaxShape::ColumnPath, "the column(s) to convert")
.filter()) .filter())

View File

@ -31,21 +31,34 @@ impl WholeStreamCommand for Config {
"load", "load",
SyntaxShape::Path, SyntaxShape::Path,
"load the config from the path give", "load the config from the path give",
Some('l'),
) )
.named( .named(
"set", "set",
SyntaxShape::Any, SyntaxShape::Any,
"set a value in the config, eg) --set [key value]", "set a value in the config, eg) --set [key value]",
Some('s'),
) )
.named( .named(
"set_into", "set_into",
SyntaxShape::Member, SyntaxShape::Member,
"sets a variable from values in the pipeline", "sets a variable from values in the pipeline",
Some('i'),
) )
.named("get", SyntaxShape::Any, "get a value from the config") .named(
.named("remove", SyntaxShape::Any, "remove a value from the config") "get",
.switch("clear", "clear the config") SyntaxShape::Any,
.switch("path", "return the path to the config file") "get a value from the config",
Some('g'),
)
.named(
"remove",
SyntaxShape::Any,
"remove a value from the config",
Some('r'),
)
.switch("clear", "clear the config", Some('c'))
.switch("path", "return the path to the config file", Some('p'))
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View File

@ -24,7 +24,11 @@ impl PerItemCommand for Cpy {
Signature::build("cp") Signature::build("cp")
.required("src", SyntaxShape::Pattern, "the place to copy from") .required("src", SyntaxShape::Pattern, "the place to copy from")
.required("dst", SyntaxShape::Path, "the place to copy to") .required("dst", SyntaxShape::Path, "the place to copy to")
.switch("recursive", "copy recursively through subdirectories") .switch(
"recursive",
"copy recursively through subdirectories",
Some('r'),
)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View File

@ -18,8 +18,8 @@ impl WholeStreamCommand for Date {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("date") Signature::build("date")
.switch("utc", "use universal time (UTC)") .switch("utc", "use universal time (UTC)", Some('u'))
.switch("local", "use the local time") .switch("local", "use the local time", Some('l'))
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View File

@ -16,7 +16,7 @@ impl WholeStreamCommand for Debug {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("debug").switch("raw", "Prints the raw value representation.") Signature::build("debug").switch("raw", "Prints the raw value representation.", Some('r'))
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View File

@ -40,14 +40,33 @@ impl PerItemCommand for Du {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build(NAME) Signature::build(NAME)
.optional("path", SyntaxShape::Pattern, "starting directory") .optional("path", SyntaxShape::Pattern, "starting directory")
.switch("all", "Output File sizes as well as directory sizes") .switch(
.switch("deref", "Dereference symlinks to their targets for size") "all",
.named("exclude", SyntaxShape::Pattern, "Exclude these file names") "Output File sizes as well as directory sizes",
.named("max-depth", SyntaxShape::Int, "Directory recursion limit") Some('a'),
)
.switch(
"deref",
"Dereference symlinks to their targets for size",
Some('r'),
)
.named(
"exclude",
SyntaxShape::Pattern,
"Exclude these file names",
Some('x'),
)
.named(
"max-depth",
SyntaxShape::Int,
"Directory recursion limit",
Some('d'),
)
.named( .named(
"min-size", "min-size",
SyntaxShape::Int, SyntaxShape::Int,
"Exclude files below this size", "Exclude files below this size",
Some('m'),
) )
} }

View File

@ -23,6 +23,7 @@ impl WholeStreamCommand for EvaluateBy {
"evaluate_with", "evaluate_with",
SyntaxShape::String, SyntaxShape::String,
"the name of the column to evaluate by", "the name of the column to evaluate by",
Some('w'),
) )
} }

View File

@ -12,7 +12,7 @@ impl WholeStreamCommand for Exit {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("exit").switch("now", "exit out of the shell immediately") Signature::build("exit").switch("now", "exit out of the shell immediately", Some('n'))
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View File

@ -23,8 +23,13 @@ impl WholeStreamCommand for FromCSV {
"separator", "separator",
SyntaxShape::String, SyntaxShape::String,
"a character to separate columns, defaults to ','", "a character to separate columns, defaults to ','",
Some('s'),
)
.switch(
"headerless",
"don't treat the first row as column names",
None,
) )
.switch("headerless", "don't treat the first row as column names")
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View File

@ -16,7 +16,11 @@ impl WholeStreamCommand for FromJSON {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("from-json").switch("objects", "treat each line as a separate value") Signature::build("from-json").switch(
"objects",
"treat each line as a separate value",
Some('o'),
)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View File

@ -19,8 +19,11 @@ impl WholeStreamCommand for FromODS {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("from-ods") Signature::build("from-ods").switch(
.switch("headerless", "don't treat the first row as column names") "headerless",
"don't treat the first row as column names",
None,
)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View File

@ -27,12 +27,17 @@ impl WholeStreamCommand for FromSSV {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build(STRING_REPRESENTATION) Signature::build(STRING_REPRESENTATION)
.switch("headerless", "don't treat the first row as column names") .switch(
.switch("aligned-columns", "assume columns are aligned") "headerless",
"don't treat the first row as column names",
None,
)
.switch("aligned-columns", "assume columns are aligned", Some('a'))
.named( .named(
"minimum-spaces", "minimum-spaces",
SyntaxShape::Int, SyntaxShape::Int,
"the mininum spaces to separate columns", "the minimum spaces to separate columns",
Some('m'),
) )
} }

View File

@ -17,8 +17,11 @@ impl WholeStreamCommand for FromTSV {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("from-tsv") Signature::build("from-tsv").switch(
.switch("headerless", "don't treat the first row as column names") "headerless",
"don't treat the first row as column names",
None,
)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View File

@ -19,8 +19,11 @@ impl WholeStreamCommand for FromXLSX {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("from-xlsx") Signature::build("from-xlsx").switch(
.switch("headerless", "don't treat the first row as column names") "headerless",
"don't treat the first row as column names",
None,
)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View File

@ -171,34 +171,67 @@ pub(crate) fn get_help(
if !signature.named.is_empty() { if !signature.named.is_empty() {
long_desc.push_str("\nflags:\n"); long_desc.push_str("\nflags:\n");
for (flag, ty) in signature.named { for (flag, ty) in signature.named {
match ty.0 { let msg = match ty.0 {
NamedType::Switch => { NamedType::Switch(s) => {
long_desc.push_str(&format!( if let Some(c) = s {
" --{}{} {}\n", format!(
flag, " -{}, --{}{} {}\n",
if !ty.1.is_empty() { ":" } else { "" }, c,
ty.1 flag,
)); if !ty.1.is_empty() { ":" } else { "" },
ty.1
)
} else {
format!(
" --{}{} {}\n",
flag,
if !ty.1.is_empty() { ":" } else { "" },
ty.1
)
}
} }
NamedType::Mandatory(m) => { NamedType::Mandatory(s, m) => {
long_desc.push_str(&format!( if let Some(c) = s {
" --{} <{}> (required parameter){} {}\n", format!(
flag, " -{}, --{} <{}> (required parameter){} {}\n",
m.display(), c,
if !ty.1.is_empty() { ":" } else { "" }, flag,
ty.1 m.display(),
)); if !ty.1.is_empty() { ":" } else { "" },
ty.1
)
} else {
format!(
" --{} <{}> (required parameter){} {}\n",
flag,
m.display(),
if !ty.1.is_empty() { ":" } else { "" },
ty.1
)
}
} }
NamedType::Optional(o) => { NamedType::Optional(s, o) => {
long_desc.push_str(&format!( if let Some(c) = s {
" --{} <{}>{} {}\n", format!(
flag, " -{}, --{} <{}>{} {}\n",
o.display(), c,
if !ty.1.is_empty() { ":" } else { "" }, flag,
ty.1 o.display(),
)); if !ty.1.is_empty() { ":" } else { "" },
ty.1
)
} else {
format!(
" --{} <{}>{} {}\n",
flag,
o.display(),
if !ty.1.is_empty() { ":" } else { "" },
ty.1
)
}
} }
} };
long_desc.push_str(&msg);
} }
} }

View File

@ -29,8 +29,8 @@ impl PerItemCommand for Kill {
"process id of process that is to be killed", "process id of process that is to be killed",
) )
.rest(SyntaxShape::Int, "rest of processes to kill") .rest(SyntaxShape::Int, "rest of processes to kill")
.switch("force", "forcefully kill the process") .switch("force", "forcefully kill the process", Some('f'))
.switch("quiet", "won't print anything to the console") .switch("quiet", "won't print anything to the console", Some('q'))
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View File

@ -29,11 +29,20 @@ impl PerItemCommand for Ls {
SyntaxShape::Pattern, SyntaxShape::Pattern,
"a path to get the directory contents from", "a path to get the directory contents from",
) )
.switch("full", "list all available columns for each entry") .switch(
.switch("short-names", "only print the file names and not the path") "full",
"list all available columns for each entry",
Some('f'),
)
.switch(
"short-names",
"only print the file names and not the path",
Some('s'),
)
.switch( .switch(
"with-symlink-targets", "with-symlink-targets",
"display the paths to the target files that symlinks point to", "display the paths to the target files that symlinks point to",
Some('w'),
) )
} }

View File

@ -24,6 +24,7 @@ impl WholeStreamCommand for MapMaxBy {
"column_name", "column_name",
SyntaxShape::String, SyntaxShape::String,
"the name of the column to map-max the table's rows", "the name of the column to map-max the table's rows",
Some('c'),
) )
} }

View File

@ -20,7 +20,11 @@ impl PerItemCommand for Open {
SyntaxShape::Path, SyntaxShape::Path,
"the file path to load values from", "the file path to load values from",
) )
.switch("raw", "load content as a string insead of a table") .switch(
"raw",
"load content as a string instead of a table",
Some('r'),
)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View File

@ -23,8 +23,16 @@ impl WholeStreamCommand for Pivot {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("pivot") Signature::build("pivot")
.switch("header-row", "treat the first row as column names") .switch(
.switch("ignore-titles", "don't pivot the column names into values") "header-row",
"treat the first row as column names",
Some('h'),
)
.switch(
"ignore-titles",
"don't pivot the column names into values",
Some('i'),
)
.rest( .rest(
SyntaxShape::String, SyntaxShape::String,
"the names to give columns once pivoted", "the names to give columns once pivoted",

View File

@ -23,6 +23,7 @@ impl WholeStreamCommand for ReduceBy {
"reduce_with", "reduce_with",
SyntaxShape::String, SyntaxShape::String,
"the command to reduce by with", "the command to reduce by with",
Some('w'),
) )
} }

View File

@ -26,8 +26,9 @@ impl PerItemCommand for Remove {
.switch( .switch(
"trash", "trash",
"use the platform's recycle bin instead of permanently deleting", "use the platform's recycle bin instead of permanently deleting",
Some('t'),
) )
.switch("recursive", "delete subdirectories recursively") .switch("recursive", "delete subdirectories recursively", Some('r'))
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View File

@ -98,6 +98,7 @@ impl WholeStreamCommand for Save {
.switch( .switch(
"raw", "raw",
"treat values as-is rather than auto-converting based on file extension", "treat values as-is rather than auto-converting based on file extension",
Some('r'),
) )
} }

View File

@ -27,7 +27,7 @@ impl WholeStreamCommand for SplitBy {
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {
"Creates a new table with the data from the inner tables splitted by the column given." "Creates a new table with the data from the inner tables split by the column given."
} }
fn run( fn run(

View File

@ -29,7 +29,7 @@ impl WholeStreamCommand for SplitColumn {
SyntaxShape::Any, SyntaxShape::Any,
"the character that denotes what separates columns", "the character that denotes what separates columns",
) )
.switch("collapse-empty", "remove empty columns") .switch("collapse-empty", "remove empty columns", Some('c'))
.rest(SyntaxShape::Member, "column names to give the new columns") .rest(SyntaxShape::Member, "column names to give the new columns")
} }

View File

@ -28,16 +28,22 @@ impl WholeStreamCommand for TSortBy {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("t-sort-by") Signature::build("t-sort-by")
.switch("show-columns", "Displays the column names sorted") .switch(
"show-columns",
"Displays the column names sorted",
Some('c'),
)
.named( .named(
"group_by", "group_by",
SyntaxShape::String, SyntaxShape::String,
"the name of the column to group by", "the name of the column to group by",
Some('g'),
) )
.named( .named(
"split_by", "split_by",
SyntaxShape::String, SyntaxShape::String,
"the name of the column within the grouped by table to split by", "the name of the column within the grouped by table to split by",
Some('s'),
) )
} }

View File

@ -20,6 +20,7 @@ impl WholeStreamCommand for Table {
"start_number", "start_number",
SyntaxShape::Number, SyntaxShape::Number,
"row number to start viewing from", "row number to start viewing from",
Some('n'),
) )
} }

View File

@ -21,6 +21,7 @@ impl WholeStreamCommand for ToCSV {
Signature::build("to-csv").switch( Signature::build("to-csv").switch(
"headerless", "headerless",
"do not output the columns names as the first row", "do not output the columns names as the first row",
None,
) )
} }

View File

@ -20,6 +20,7 @@ impl WholeStreamCommand for ToTSV {
Signature::build("to-tsv").switch( Signature::build("to-tsv").switch(
"headerless", "headerless",
"do not output the column names as the first row", "do not output the column names as the first row",
None,
) )
} }

View File

@ -15,7 +15,7 @@ impl WholeStreamCommand for Which {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("which") Signature::build("which")
.required("application", SyntaxShape::String, "application") .required("application", SyntaxShape::String, "application")
.switch("all", "list all executables") .switch("all", "list all executables", Some('a'))
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View File

@ -60,9 +60,9 @@ fn signature_dict(signature: Signature, tag: impl Into<Tag>) -> Value {
for (name, ty) in signature.named.iter() { for (name, ty) in signature.named.iter() {
match ty.0 { match ty.0 {
NamedType::Mandatory(_) => sig.push_value(for_spec(name, "flag", true, &tag)), NamedType::Mandatory(_, _) => sig.push_value(for_spec(name, "flag", true, &tag)),
NamedType::Optional(_) => sig.push_value(for_spec(name, "flag", false, &tag)), NamedType::Optional(_, _) => sig.push_value(for_spec(name, "flag", false, &tag)),
NamedType::Switch => sig.push_value(for_spec(name, "switch", false, &tag)), NamedType::Switch(_) => sig.push_value(for_spec(name, "switch", false, &tag)),
} }
} }

View File

@ -60,7 +60,7 @@ fn copies_the_directory_inside_directory_if_path_to_copy_is_directory_and_with_r
nu!( nu!(
cwd: dirs.test(), cwd: dirs.test(),
"cp originals expected --recursive" "cp originals expected -r"
); );
assert!(expected_dir.exists()); assert!(expected_dir.exists());

View File

@ -5,7 +5,7 @@ fn lines() {
let actual = nu!( let actual = nu!(
cwd: "tests/fixtures/formats", pipeline( cwd: "tests/fixtures/formats", pipeline(
r#" r#"
open cargo_sample.toml --raw open cargo_sample.toml -r
| lines | lines
| skip-while $it != "[dependencies]" | skip-while $it != "[dependencies]"
| skip 1 | skip 1

View File

@ -81,7 +81,7 @@ fn removes_deeply_nested_directories_with_wildcard_and_recursive_flag() {
nu!( nu!(
cwd: dirs.test(), cwd: dirs.test(),
"rm --recursive src/*" "rm -r src/*"
); );
assert!(!files_exist_at( assert!(!files_exist_at(

View File

@ -61,7 +61,7 @@ fn from_json_text_recognizing_objects_independently_to_table() {
cwd: dirs.test(), pipeline( cwd: dirs.test(), pipeline(
r#" r#"
open katz.txt open katz.txt
| from-json --objects | from-json -o
| where name == "GorbyPuff" | where name == "GorbyPuff"
| get rusty_luck | get rusty_luck
| echo $it | echo $it

View File

@ -74,7 +74,7 @@ fn from_ssv_text_treating_first_line_as_data_with_flag() {
cwd: dirs.test(), pipeline( cwd: dirs.test(), pipeline(
r#" r#"
open oc_get_svc.txt open oc_get_svc.txt
| from-ssv --headerless --aligned-columns | from-ssv --headerless -a
| first | first
| get Column1 | get Column1
| echo $it | echo $it

View File

@ -65,7 +65,7 @@ fn semversion_major_inc() {
let actual = nu!( let actual = nu!(
cwd: dirs.test(), cwd: dirs.test(),
"open sample.toml | inc package.version --major | get package.version | echo $it" "open sample.toml | inc package.version -M | get package.version | echo $it"
); );
assert_eq!(actual, "1.0.0"); assert_eq!(actual, "1.0.0");

View File

@ -46,7 +46,7 @@ fn downcases() {
let actual = nu!( let actual = nu!(
cwd: dirs.test(), cwd: dirs.test(),
"open sample.toml | str dependency.name --downcase | get dependency.name | echo $it" "open sample.toml | str dependency.name -d | get dependency.name | echo $it"
); );
assert_eq!(actual, "light"); assert_eq!(actual, "light");