forked from extern/nushell
Add subcommands. Switch from-* and to-* to them (#1708)
This commit is contained in:
parent
453087248a
commit
a9968046ed
@ -320,6 +320,7 @@ pub fn create_default_context(
|
|||||||
whole_stream_command(Histogram),
|
whole_stream_command(Histogram),
|
||||||
whole_stream_command(Sum),
|
whole_stream_command(Sum),
|
||||||
// File format output
|
// File format output
|
||||||
|
whole_stream_command(To),
|
||||||
whole_stream_command(ToBSON),
|
whole_stream_command(ToBSON),
|
||||||
whole_stream_command(ToCSV),
|
whole_stream_command(ToCSV),
|
||||||
whole_stream_command(ToHTML),
|
whole_stream_command(ToHTML),
|
||||||
@ -332,6 +333,7 @@ pub fn create_default_context(
|
|||||||
whole_stream_command(ToURL),
|
whole_stream_command(ToURL),
|
||||||
whole_stream_command(ToYAML),
|
whole_stream_command(ToYAML),
|
||||||
// File format input
|
// File format input
|
||||||
|
whole_stream_command(From),
|
||||||
whole_stream_command(FromCSV),
|
whole_stream_command(FromCSV),
|
||||||
whole_stream_command(FromEML),
|
whole_stream_command(FromEML),
|
||||||
whole_stream_command(FromTSV),
|
whole_stream_command(FromTSV),
|
||||||
|
@ -31,6 +31,7 @@ pub(crate) mod evaluate_by;
|
|||||||
pub(crate) mod exit;
|
pub(crate) mod exit;
|
||||||
pub(crate) mod first;
|
pub(crate) mod first;
|
||||||
pub(crate) mod format;
|
pub(crate) mod format;
|
||||||
|
pub(crate) mod from;
|
||||||
pub(crate) mod from_bson;
|
pub(crate) mod from_bson;
|
||||||
pub(crate) mod from_csv;
|
pub(crate) mod from_csv;
|
||||||
pub(crate) mod from_eml;
|
pub(crate) mod from_eml;
|
||||||
@ -101,6 +102,7 @@ pub(crate) mod sum;
|
|||||||
pub(crate) mod t_sort_by;
|
pub(crate) mod t_sort_by;
|
||||||
pub(crate) mod table;
|
pub(crate) mod table;
|
||||||
pub(crate) mod tags;
|
pub(crate) mod tags;
|
||||||
|
pub(crate) mod to;
|
||||||
pub(crate) mod to_bson;
|
pub(crate) mod to_bson;
|
||||||
pub(crate) mod to_csv;
|
pub(crate) mod to_csv;
|
||||||
pub(crate) mod to_html;
|
pub(crate) mod to_html;
|
||||||
@ -150,6 +152,7 @@ pub(crate) use evaluate_by::EvaluateBy;
|
|||||||
pub(crate) use exit::Exit;
|
pub(crate) use exit::Exit;
|
||||||
pub(crate) use first::First;
|
pub(crate) use first::First;
|
||||||
pub(crate) use format::Format;
|
pub(crate) use format::Format;
|
||||||
|
pub(crate) use from::From;
|
||||||
pub(crate) use from_bson::FromBSON;
|
pub(crate) use from_bson::FromBSON;
|
||||||
pub(crate) use from_csv::FromCSV;
|
pub(crate) use from_csv::FromCSV;
|
||||||
pub(crate) use from_eml::FromEML;
|
pub(crate) use from_eml::FromEML;
|
||||||
@ -219,6 +222,7 @@ pub(crate) use sum::Sum;
|
|||||||
pub(crate) use t_sort_by::TSortBy;
|
pub(crate) use t_sort_by::TSortBy;
|
||||||
pub(crate) use table::Table;
|
pub(crate) use table::Table;
|
||||||
pub(crate) use tags::Tags;
|
pub(crate) use tags::Tags;
|
||||||
|
pub(crate) use to::To;
|
||||||
pub(crate) use to_bson::ToBSON;
|
pub(crate) use to_bson::ToBSON;
|
||||||
pub(crate) use to_csv::ToCSV;
|
pub(crate) use to_csv::ToCSV;
|
||||||
pub(crate) use to_html::ToHTML;
|
pub(crate) use to_html::ToHTML;
|
||||||
|
@ -51,7 +51,7 @@ pub(crate) fn run_internal_command(
|
|||||||
}
|
}
|
||||||
CommandAction::AutoConvert(tagged_contents, extension) => {
|
CommandAction::AutoConvert(tagged_contents, extension) => {
|
||||||
let contents_tag = tagged_contents.tag.clone();
|
let contents_tag = tagged_contents.tag.clone();
|
||||||
let command_name = format!("from-{}", extension);
|
let command_name = format!("from {}", extension);
|
||||||
let command = command.clone();
|
let command = command.clone();
|
||||||
if let Some(converter) = context.registry.get_command(&command_name) {
|
if let Some(converter) = context.registry.get_command(&command_name) {
|
||||||
let new_args = RawCommandArgs {
|
let new_args = RawCommandArgs {
|
||||||
|
@ -407,7 +407,7 @@ impl Command {
|
|||||||
|
|
||||||
pub fn run(&self, args: CommandArgs, registry: &CommandRegistry) -> OutputStream {
|
pub fn run(&self, args: CommandArgs, registry: &CommandRegistry) -> OutputStream {
|
||||||
if args.call_info.switch_present("help") {
|
if args.call_info.switch_present("help") {
|
||||||
get_help(self.name(), self.usage(), self.signature()).into()
|
get_help(self.name(), self.usage(), self.signature(), registry).into()
|
||||||
} else {
|
} else {
|
||||||
match self.0.run(args, registry) {
|
match self.0.run(args, registry) {
|
||||||
Ok(stream) => stream,
|
Ok(stream) => stream,
|
||||||
|
@ -95,7 +95,7 @@ fn enter(
|
|||||||
let tagged_contents = contents.into_value(&contents_tag);
|
let tagged_contents = contents.into_value(&contents_tag);
|
||||||
|
|
||||||
if let Some(extension) = file_extension {
|
if let Some(extension) = file_extension {
|
||||||
let command_name = format!("from-{}", extension);
|
let command_name = format!("from {}", extension);
|
||||||
if let Some(converter) =
|
if let Some(converter) =
|
||||||
registry.get_command(&command_name)
|
registry.get_command(&command_name)
|
||||||
{
|
{
|
||||||
|
31
crates/nu-cli/src/commands/from.rs
Normal file
31
crates/nu-cli/src/commands/from.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
use crate::commands::WholeStreamCommand;
|
||||||
|
use crate::prelude::*;
|
||||||
|
use nu_errors::ShellError;
|
||||||
|
use nu_protocol::Signature;
|
||||||
|
|
||||||
|
pub struct From;
|
||||||
|
|
||||||
|
impl WholeStreamCommand for From {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"from"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build("from")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(&self) -> &str {
|
||||||
|
"Parse content (string or binary) as a table."
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(
|
||||||
|
&self,
|
||||||
|
_args: CommandArgs,
|
||||||
|
registry: &CommandRegistry,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
|
Ok(
|
||||||
|
crate::commands::help::get_help(self.name(), self.usage(), self.signature(), registry)
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -10,15 +10,15 @@ pub struct FromBSON;
|
|||||||
|
|
||||||
impl WholeStreamCommand for FromBSON {
|
impl WholeStreamCommand for FromBSON {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"from-bson"
|
"from bson"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("from-bson")
|
Signature::build("from bson")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
"Parse text as .bson and create table."
|
"Parse binary as .bson and create table."
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
|
@ -14,11 +14,11 @@ pub struct FromCSVArgs {
|
|||||||
|
|
||||||
impl WholeStreamCommand for FromCSV {
|
impl WholeStreamCommand for FromCSV {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"from-csv"
|
"from csv"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("from-csv")
|
Signature::build("from csv")
|
||||||
.named(
|
.named(
|
||||||
"separator",
|
"separator",
|
||||||
SyntaxShape::String,
|
SyntaxShape::String,
|
||||||
|
@ -18,11 +18,11 @@ pub struct FromEMLArgs {
|
|||||||
|
|
||||||
impl WholeStreamCommand for FromEML {
|
impl WholeStreamCommand for FromEML {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"from-eml"
|
"from eml"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("from-eml").named(
|
Signature::build("from eml").named(
|
||||||
"preview-body",
|
"preview-body",
|
||||||
SyntaxShape::Int,
|
SyntaxShape::Int,
|
||||||
"How many bytes of the body to preview",
|
"How many bytes of the body to preview",
|
||||||
|
@ -11,11 +11,11 @@ pub struct FromIcs;
|
|||||||
|
|
||||||
impl WholeStreamCommand for FromIcs {
|
impl WholeStreamCommand for FromIcs {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"from-ics"
|
"from ics"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("from-ics")
|
Signature::build("from ics")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -8,11 +8,11 @@ pub struct FromINI;
|
|||||||
|
|
||||||
impl WholeStreamCommand for FromINI {
|
impl WholeStreamCommand for FromINI {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"from-ini"
|
"from ini"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("from-ini")
|
Signature::build("from ini")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -12,11 +12,11 @@ pub struct FromJSONArgs {
|
|||||||
|
|
||||||
impl WholeStreamCommand for FromJSON {
|
impl WholeStreamCommand for FromJSON {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"from-json"
|
"from json"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("from-json").switch(
|
Signature::build("from json").switch(
|
||||||
"objects",
|
"objects",
|
||||||
"treat each line as a separate value",
|
"treat each line as a separate value",
|
||||||
Some('o'),
|
Some('o'),
|
||||||
|
@ -15,11 +15,11 @@ pub struct FromODSArgs {
|
|||||||
|
|
||||||
impl WholeStreamCommand for FromODS {
|
impl WholeStreamCommand for FromODS {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"from-ods"
|
"from ods"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("from-ods").switch(
|
Signature::build("from ods").switch(
|
||||||
"headerless",
|
"headerless",
|
||||||
"don't treat the first row as column names",
|
"don't treat the first row as column names",
|
||||||
None,
|
None,
|
||||||
|
@ -10,11 +10,11 @@ pub struct FromSQLite;
|
|||||||
|
|
||||||
impl WholeStreamCommand for FromSQLite {
|
impl WholeStreamCommand for FromSQLite {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"from-sqlite"
|
"from sqlite"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("from-sqlite")
|
Signature::build("from sqlite")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
@ -34,11 +34,11 @@ pub struct FromDB;
|
|||||||
|
|
||||||
impl WholeStreamCommand for FromDB {
|
impl WholeStreamCommand for FromDB {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"from-db"
|
"from db"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("from-db")
|
Signature::build("from db")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -17,7 +17,7 @@ pub struct FromSSVArgs {
|
|||||||
minimum_spaces: Option<Tagged<usize>>,
|
minimum_spaces: Option<Tagged<usize>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const STRING_REPRESENTATION: &str = "from-ssv";
|
const STRING_REPRESENTATION: &str = "from ssv";
|
||||||
const DEFAULT_MINIMUM_SPACES: usize = 2;
|
const DEFAULT_MINIMUM_SPACES: usize = 2;
|
||||||
|
|
||||||
impl WholeStreamCommand for FromSSV {
|
impl WholeStreamCommand for FromSSV {
|
||||||
|
@ -7,11 +7,11 @@ pub struct FromTOML;
|
|||||||
|
|
||||||
impl WholeStreamCommand for FromTOML {
|
impl WholeStreamCommand for FromTOML {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"from-toml"
|
"from toml"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("from-toml")
|
Signature::build("from toml")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -13,11 +13,11 @@ pub struct FromTSVArgs {
|
|||||||
|
|
||||||
impl WholeStreamCommand for FromTSV {
|
impl WholeStreamCommand for FromTSV {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"from-tsv"
|
"from tsv"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("from-tsv").switch(
|
Signature::build("from tsv").switch(
|
||||||
"headerless",
|
"headerless",
|
||||||
"don't treat the first row as column names",
|
"don't treat the first row as column names",
|
||||||
None,
|
None,
|
||||||
|
@ -7,11 +7,11 @@ pub struct FromURL;
|
|||||||
|
|
||||||
impl WholeStreamCommand for FromURL {
|
impl WholeStreamCommand for FromURL {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"from-url"
|
"from url"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("from-url")
|
Signature::build("from url")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -11,11 +11,11 @@ pub struct FromVcf;
|
|||||||
|
|
||||||
impl WholeStreamCommand for FromVcf {
|
impl WholeStreamCommand for FromVcf {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"from-vcf"
|
"from vcf"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("from-vcf")
|
Signature::build("from vcf")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -15,11 +15,11 @@ pub struct FromXLSXArgs {
|
|||||||
|
|
||||||
impl WholeStreamCommand for FromXLSX {
|
impl WholeStreamCommand for FromXLSX {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"from-xlsx"
|
"from xlsx"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("from-xlsx").switch(
|
Signature::build("from xlsx").switch(
|
||||||
"headerless",
|
"headerless",
|
||||||
"don't treat the first row as column names",
|
"don't treat the first row as column names",
|
||||||
None,
|
None,
|
||||||
|
@ -7,11 +7,11 @@ pub struct FromXML;
|
|||||||
|
|
||||||
impl WholeStreamCommand for FromXML {
|
impl WholeStreamCommand for FromXML {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"from-xml"
|
"from xml"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("from-xml")
|
Signature::build("from xml")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -7,11 +7,11 @@ pub struct FromYAML;
|
|||||||
|
|
||||||
impl WholeStreamCommand for FromYAML {
|
impl WholeStreamCommand for FromYAML {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"from-yaml"
|
"from yaml"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("from-yaml")
|
Signature::build("from yaml")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
@ -31,11 +31,11 @@ pub struct FromYML;
|
|||||||
|
|
||||||
impl WholeStreamCommand for FromYML {
|
impl WholeStreamCommand for FromYML {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"from-yml"
|
"from yml"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("from-yml")
|
Signature::build("from yml")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -14,7 +14,7 @@ pub struct Help;
|
|||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct HelpArgs {
|
pub struct HelpArgs {
|
||||||
command: Option<Tagged<String>>,
|
rest: Vec<Tagged<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WholeStreamCommand for Help {
|
impl WholeStreamCommand for Help {
|
||||||
@ -23,11 +23,7 @@ impl WholeStreamCommand for Help {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("help").optional(
|
Signature::build("help").rest(SyntaxShape::String, "the name of command to get help on")
|
||||||
"command",
|
|
||||||
SyntaxShape::String,
|
|
||||||
"the name of command(s) to get help on",
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
@ -44,15 +40,19 @@ impl WholeStreamCommand for Help {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn help(
|
fn help(
|
||||||
HelpArgs { command }: HelpArgs,
|
HelpArgs { rest }: HelpArgs,
|
||||||
RunnableContext { registry, name, .. }: RunnableContext,
|
RunnableContext { registry, name, .. }: RunnableContext,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
if let Some(document) = command {
|
if let Some(document) = rest.get(0) {
|
||||||
let mut help = VecDeque::new();
|
let mut help = VecDeque::new();
|
||||||
if document.item == "commands" {
|
if document.item == "commands" {
|
||||||
let mut sorted_names = registry.names();
|
let mut sorted_names = registry.names();
|
||||||
sorted_names.sort();
|
sorted_names.sort();
|
||||||
for cmd in sorted_names {
|
for cmd in sorted_names {
|
||||||
|
// If it's a subcommand, don't list it during the commands list
|
||||||
|
if cmd.contains(' ') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let mut short_desc = TaggedDictBuilder::new(name.clone());
|
let mut short_desc = TaggedDictBuilder::new(name.clone());
|
||||||
let document_tag = document.tag.clone();
|
let document_tag = document.tag.clone();
|
||||||
let value = command_dict(
|
let value = command_dict(
|
||||||
@ -82,13 +82,31 @@ fn help(
|
|||||||
|
|
||||||
help.push_back(ReturnSuccess::value(short_desc.into_value()));
|
help.push_back(ReturnSuccess::value(short_desc.into_value()));
|
||||||
}
|
}
|
||||||
|
} else if rest.len() == 2 {
|
||||||
|
// Check for a subcommand
|
||||||
|
let command_name = format!("{} {}", rest[0].item, rest[1].item);
|
||||||
|
if let Some(command) = registry.get_command(&command_name) {
|
||||||
|
return Ok(get_help(
|
||||||
|
&command.name(),
|
||||||
|
&command.usage(),
|
||||||
|
command.signature(),
|
||||||
|
®istry,
|
||||||
|
)
|
||||||
|
.into());
|
||||||
|
}
|
||||||
} else if let Some(command) = registry.get_command(&document.item) {
|
} else if let Some(command) = registry.get_command(&document.item) {
|
||||||
return Ok(get_help(&command.name(), &command.usage(), command.signature()).into());
|
return Ok(get_help(
|
||||||
|
&command.name(),
|
||||||
|
&command.usage(),
|
||||||
|
command.signature(),
|
||||||
|
®istry,
|
||||||
|
)
|
||||||
|
.into());
|
||||||
} else {
|
} else {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Can't find command (use 'help commands' for full list)",
|
"Can't find command (use 'help commands' for full list)",
|
||||||
"can't find command",
|
"can't find command",
|
||||||
document.tag,
|
document.tag.span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let help = futures::stream::iter(help);
|
let help = futures::stream::iter(help);
|
||||||
@ -128,6 +146,7 @@ pub(crate) fn get_help(
|
|||||||
cmd_name: &str,
|
cmd_name: &str,
|
||||||
cmd_usage: &str,
|
cmd_usage: &str,
|
||||||
cmd_sig: Signature,
|
cmd_sig: Signature,
|
||||||
|
registry: &CommandRegistry,
|
||||||
) -> impl Into<OutputStream> {
|
) -> impl Into<OutputStream> {
|
||||||
let mut help = VecDeque::new();
|
let mut help = VecDeque::new();
|
||||||
let mut long_desc = String::new();
|
let mut long_desc = String::new();
|
||||||
@ -137,6 +156,15 @@ pub(crate) fn get_help(
|
|||||||
|
|
||||||
let signature = cmd_sig;
|
let signature = cmd_sig;
|
||||||
|
|
||||||
|
let mut subcommands = String::new();
|
||||||
|
for name in registry.names() {
|
||||||
|
if name.starts_with(&format!("{} ", cmd_name)) {
|
||||||
|
let subcommand = registry.get_command(&name).expect("This shouldn't happen");
|
||||||
|
|
||||||
|
subcommands.push_str(&format!(" {} - {}\n", name, subcommand.usage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut one_liner = String::new();
|
let mut one_liner = String::new();
|
||||||
one_liner.push_str(&signature.name);
|
one_liner.push_str(&signature.name);
|
||||||
one_liner.push_str(" ");
|
one_liner.push_str(" ");
|
||||||
@ -156,14 +184,23 @@ pub(crate) fn get_help(
|
|||||||
one_liner.push_str(" ...args");
|
one_liner.push_str(" ...args");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !subcommands.is_empty() {
|
||||||
|
one_liner.push_str("<subcommand> ");
|
||||||
|
}
|
||||||
|
|
||||||
if !signature.named.is_empty() {
|
if !signature.named.is_empty() {
|
||||||
one_liner.push_str("{flags} ");
|
one_liner.push_str("{flags} ");
|
||||||
}
|
}
|
||||||
|
|
||||||
long_desc.push_str(&format!("\nUsage:\n > {}\n", one_liner));
|
long_desc.push_str(&format!("\nUsage:\n > {}\n", one_liner));
|
||||||
|
|
||||||
|
if !subcommands.is_empty() {
|
||||||
|
long_desc.push_str("\nSubcommands:\n");
|
||||||
|
long_desc.push_str(&subcommands);
|
||||||
|
}
|
||||||
|
|
||||||
if !signature.positional.is_empty() || signature.rest_positional.is_some() {
|
if !signature.positional.is_empty() || signature.rest_positional.is_some() {
|
||||||
long_desc.push_str("\nparameters:\n");
|
long_desc.push_str("\nParameters:\n");
|
||||||
for positional in signature.positional {
|
for positional in signature.positional {
|
||||||
match positional.0 {
|
match positional.0 {
|
||||||
PositionalType::Mandatory(name, _m) => {
|
PositionalType::Mandatory(name, _m) => {
|
||||||
@ -180,7 +217,7 @@ 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 {
|
||||||
let msg = match ty.0 {
|
let msg = match ty.0 {
|
||||||
NamedType::Switch(s) => {
|
NamedType::Switch(s) => {
|
||||||
|
@ -221,7 +221,7 @@ fn save(
|
|||||||
let content : Result<Vec<u8>, ShellError> = 'scope: loop {
|
let content : Result<Vec<u8>, ShellError> = 'scope: loop {
|
||||||
break if !save_raw {
|
break if !save_raw {
|
||||||
if let Some(extension) = full_path.extension() {
|
if let Some(extension) = full_path.extension() {
|
||||||
let command_name = format!("to-{}", extension.to_string_lossy());
|
let command_name = format!("to {}", extension.to_string_lossy());
|
||||||
if let Some(converter) = registry.get_command(&command_name) {
|
if let Some(converter) = registry.get_command(&command_name) {
|
||||||
let new_args = RawCommandArgs {
|
let new_args = RawCommandArgs {
|
||||||
host,
|
host,
|
||||||
|
31
crates/nu-cli/src/commands/to.rs
Normal file
31
crates/nu-cli/src/commands/to.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
use crate::commands::WholeStreamCommand;
|
||||||
|
use crate::prelude::*;
|
||||||
|
use nu_errors::ShellError;
|
||||||
|
use nu_protocol::Signature;
|
||||||
|
|
||||||
|
pub struct To;
|
||||||
|
|
||||||
|
impl WholeStreamCommand for To {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"to"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build("to")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(&self) -> &str {
|
||||||
|
"Convert table into an output format."
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(
|
||||||
|
&self,
|
||||||
|
_args: CommandArgs,
|
||||||
|
registry: &CommandRegistry,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
|
Ok(
|
||||||
|
crate::commands::help::get_help(self.name(), self.usage(), self.signature(), registry)
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -12,11 +12,11 @@ pub struct ToBSON;
|
|||||||
|
|
||||||
impl WholeStreamCommand for ToBSON {
|
impl WholeStreamCommand for ToBSON {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"to-bson"
|
"to bson"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("to-bson")
|
Signature::build("to bson")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -14,11 +14,11 @@ pub struct ToCSVArgs {
|
|||||||
|
|
||||||
impl WholeStreamCommand for ToCSV {
|
impl WholeStreamCommand for ToCSV {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"to-csv"
|
"to csv"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("to-csv")
|
Signature::build("to csv")
|
||||||
.named(
|
.named(
|
||||||
"separator",
|
"separator",
|
||||||
SyntaxShape::String,
|
SyntaxShape::String,
|
||||||
|
@ -10,11 +10,11 @@ pub struct ToHTML;
|
|||||||
|
|
||||||
impl WholeStreamCommand for ToHTML {
|
impl WholeStreamCommand for ToHTML {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"to-html"
|
"to html"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("to-html")
|
Signature::build("to html")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -7,11 +7,11 @@ pub struct ToJSON;
|
|||||||
|
|
||||||
impl WholeStreamCommand for ToJSON {
|
impl WholeStreamCommand for ToJSON {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"to-json"
|
"to json"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("to-json")
|
Signature::build("to json")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -9,11 +9,11 @@ pub struct ToMarkdown;
|
|||||||
|
|
||||||
impl WholeStreamCommand for ToMarkdown {
|
impl WholeStreamCommand for ToMarkdown {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"to-md"
|
"to md"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("to-md")
|
Signature::build("to md")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -10,11 +10,11 @@ pub struct ToSQLite;
|
|||||||
|
|
||||||
impl WholeStreamCommand for ToSQLite {
|
impl WholeStreamCommand for ToSQLite {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"to-sqlite"
|
"to sqlite"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("to-sqlite")
|
Signature::build("to sqlite")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
@ -38,11 +38,11 @@ pub struct ToDB;
|
|||||||
|
|
||||||
impl WholeStreamCommand for ToDB {
|
impl WholeStreamCommand for ToDB {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"to-db"
|
"to db"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("to-db")
|
Signature::build("to db")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -7,11 +7,11 @@ pub struct ToTOML;
|
|||||||
|
|
||||||
impl WholeStreamCommand for ToTOML {
|
impl WholeStreamCommand for ToTOML {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"to-toml"
|
"to toml"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("to-toml")
|
Signature::build("to toml")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -13,11 +13,11 @@ pub struct ToTSVArgs {
|
|||||||
|
|
||||||
impl WholeStreamCommand for ToTSV {
|
impl WholeStreamCommand for ToTSV {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"to-tsv"
|
"to tsv"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
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,
|
None,
|
||||||
|
@ -7,11 +7,11 @@ pub struct ToURL;
|
|||||||
|
|
||||||
impl WholeStreamCommand for ToURL {
|
impl WholeStreamCommand for ToURL {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"to-url"
|
"to url"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("to-url")
|
Signature::build("to url")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -7,11 +7,11 @@ pub struct ToYAML;
|
|||||||
|
|
||||||
impl WholeStreamCommand for ToYAML {
|
impl WholeStreamCommand for ToYAML {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"to-yaml"
|
"to yaml"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("to-yaml")
|
Signature::build("to yaml")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@ -8,7 +8,7 @@ fn alias_args_work() {
|
|||||||
cwd: dirs.root(),
|
cwd: dirs.root(),
|
||||||
r#"
|
r#"
|
||||||
alias double_echo [a b] {echo $a $b}
|
alias double_echo [a b] {echo $a $b}
|
||||||
double_echo 1 2 | to-json
|
double_echo 1 2 | to json
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ fn discards_empty_rows_by_default() {
|
|||||||
cwd: dirs.test(), pipeline(
|
cwd: dirs.test(), pipeline(
|
||||||
r#"
|
r#"
|
||||||
echo "[1,2,3,14,null]"
|
echo "[1,2,3,14,null]"
|
||||||
| from-json
|
| from json
|
||||||
| compact
|
| compact
|
||||||
| count
|
| count
|
||||||
| echo $it
|
| echo $it
|
||||||
|
@ -4,7 +4,7 @@ use nu_test_support::nu;
|
|||||||
fn drop_rows() {
|
fn drop_rows() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: "tests/fixtures/formats",
|
cwd: "tests/fixtures/formats",
|
||||||
r#"echo '[{"foo": 3}, {"foo": 8}, {"foo": 4}]' | from-json | drop 2 | get foo | sum | echo $it"#
|
r#"echo '[{"foo": 3}, {"foo": 8}, {"foo": 4}]' | from json | drop 2 | get foo | sum | echo $it"#
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(actual, "3");
|
assert_eq!(actual, "3");
|
||||||
|
@ -5,7 +5,7 @@ fn each_works_separately() {
|
|||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: "tests/fixtures/formats", pipeline(
|
cwd: "tests/fixtures/formats", pipeline(
|
||||||
r#"
|
r#"
|
||||||
echo [1 2 3] | each { echo $it 10 | sum } | to-json | echo $it
|
echo [1 2 3] | each { echo $it 10 | sum } | to json | echo $it
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -240,7 +240,7 @@ fn errors_fetching_by_index_out_of_bounds() {
|
|||||||
fn quoted_column_access() {
|
fn quoted_column_access() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: "tests/fixtures/formats",
|
cwd: "tests/fixtures/formats",
|
||||||
r#"echo '[{"foo bar": {"baz": 4}}]' | from-json | get "foo bar".baz | echo $it"#
|
r#"echo '[{"foo bar": {"baz": 4}}]' | from json | get "foo bar".baz | echo $it"#
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(actual, "4");
|
assert_eq!(actual, "4");
|
||||||
|
@ -9,7 +9,7 @@ fn headers_uses_first_row_as_header() {
|
|||||||
| get Sheet1
|
| get Sheet1
|
||||||
| headers
|
| headers
|
||||||
| get header0
|
| get header0
|
||||||
| from-json"#
|
| from json"#
|
||||||
));
|
));
|
||||||
|
|
||||||
assert_eq!(actual, "r1c0r2c0")
|
assert_eq!(actual, "r1c0r2c0")
|
||||||
@ -24,7 +24,7 @@ fn headers_adds_missing_column_name() {
|
|||||||
| get Sheet1
|
| get Sheet1
|
||||||
| headers
|
| headers
|
||||||
| get Column1
|
| get Column1
|
||||||
| from-json"#
|
| from json"#
|
||||||
));
|
));
|
||||||
|
|
||||||
assert_eq!(actual, "r1c1r2c1")
|
assert_eq!(actual, "r1c1r2c1")
|
||||||
|
@ -125,7 +125,7 @@ fn compound_where() {
|
|||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: "tests/fixtures/formats", pipeline(
|
cwd: "tests/fixtures/formats", pipeline(
|
||||||
r#"
|
r#"
|
||||||
echo '[{"a": 1, "b": 1}, {"a": 2, "b": 1}, {"a": 2, "b": 2}]' | from-json | where a == 2 && b == 1 | to-json
|
echo '[{"a": 1, "b": 1}, {"a": 2, "b": 1}, {"a": 2, "b": 2}]' | from json | where a == 2 && b == 1 | to json
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ fn compound_where_paren() {
|
|||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: "tests/fixtures/formats", pipeline(
|
cwd: "tests/fixtures/formats", pipeline(
|
||||||
r#"
|
r#"
|
||||||
echo '[{"a": 1, "b": 1}, {"a": 2, "b": 1}, {"a": 2, "b": 2}]' | from-json | where (a == 2 && b == 1) || b == 2 | to-json
|
echo '[{"a": 1, "b": 1}, {"a": 2, "b": 1}, {"a": 2, "b": 2}]' | from json | where (a == 2 && b == 1) || b == 2 | to json
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ fn uniq_when_keys_out_of_order() {
|
|||||||
cwd: "tests/fixtures/formats", pipeline(
|
cwd: "tests/fixtures/formats", pipeline(
|
||||||
r#"
|
r#"
|
||||||
echo '[{"a": "a", "b": [1,2,3]},{"b": [1,2,3], "a": "a"}]'
|
echo '[{"a": "a", "b": [1,2,3]},{"b": [1,2,3], "a": "a"}]'
|
||||||
| from-json
|
| from json
|
||||||
| uniq
|
| uniq
|
||||||
| count
|
| count
|
||||||
| echo $it
|
| echo $it
|
||||||
|
@ -14,7 +14,7 @@ fn filters_by_unit_size_comparison() {
|
|||||||
fn filters_with_nothing_comparison() {
|
fn filters_with_nothing_comparison() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: "tests/fixtures/formats",
|
cwd: "tests/fixtures/formats",
|
||||||
r#"echo '[{"foo": 3}, {"foo": null}, {"foo": 4}]' | from-json | where foo > 1 | get foo | sum | echo $it"#
|
r#"echo '[{"foo": 3}, {"foo": null}, {"foo": 4}]' | from json | where foo > 1 | get foo | sum | echo $it"#
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(actual, "7");
|
assert_eq!(actual, "7");
|
||||||
@ -24,7 +24,7 @@ fn filters_with_nothing_comparison() {
|
|||||||
fn where_in_table() {
|
fn where_in_table() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: "tests/fixtures/formats",
|
cwd: "tests/fixtures/formats",
|
||||||
r#"echo '[{"name": "foo", "size": 3}, {"name": "foo", "size": 2}, {"name": "bar", "size": 4}]' | from-json | where name in: ["foo"] | get size | sum | echo $it"#
|
r#"echo '[{"name": "foo", "size": 3}, {"name": "foo", "size": 2}, {"name": "bar", "size": 4}]' | from json | where name in: ["foo"] | get size | sum | echo $it"#
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(actual, "5");
|
assert_eq!(actual, "5");
|
||||||
@ -34,7 +34,7 @@ fn where_in_table() {
|
|||||||
fn where_not_in_table() {
|
fn where_not_in_table() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: "tests/fixtures/formats",
|
cwd: "tests/fixtures/formats",
|
||||||
r#"echo '[{"name": "foo", "size": 3}, {"name": "foo", "size": 2}, {"name": "bar", "size": 4}]' | from-json | where name not-in: ["foo"] | get size | sum | echo $it"#
|
r#"echo '[{"name": "foo", "size": 3}, {"name": "foo", "size": 2}, {"name": "bar", "size": 4}]' | from json | where name not-in: ["foo"] | get size | sum | echo $it"#
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(actual, "4");
|
assert_eq!(actual, "4");
|
||||||
|
@ -19,7 +19,7 @@ fn wrap_rows_into_a_row() {
|
|||||||
cwd: dirs.test(), pipeline(
|
cwd: dirs.test(), pipeline(
|
||||||
r#"
|
r#"
|
||||||
open los_tres_caballeros.txt
|
open los_tres_caballeros.txt
|
||||||
| from-csv
|
| from csv
|
||||||
| wrap caballeros
|
| wrap caballeros
|
||||||
| get caballeros
|
| get caballeros
|
||||||
| nth 0
|
| nth 0
|
||||||
@ -49,7 +49,7 @@ fn wrap_rows_into_a_table() {
|
|||||||
cwd: dirs.test(), pipeline(
|
cwd: dirs.test(), pipeline(
|
||||||
r#"
|
r#"
|
||||||
open los_tres_caballeros.txt
|
open los_tres_caballeros.txt
|
||||||
| from-csv
|
| from csv
|
||||||
| get last_name
|
| get last_name
|
||||||
| wrap caballero
|
| wrap caballero
|
||||||
| nth 2
|
| nth 2
|
||||||
|
@ -6,8 +6,8 @@ fn table_to_bson_and_back_into_table() {
|
|||||||
cwd: "tests/fixtures/formats", pipeline(
|
cwd: "tests/fixtures/formats", pipeline(
|
||||||
r#"
|
r#"
|
||||||
open sample.bson
|
open sample.bson
|
||||||
| to-bson
|
| to bson
|
||||||
| from-bson
|
| from bson
|
||||||
| get root
|
| get root
|
||||||
| get 1.b
|
| get 1.b
|
||||||
| echo $it
|
| echo $it
|
||||||
|
@ -6,7 +6,7 @@ use nu_test_support::{nu, pipeline};
|
|||||||
fn table_to_csv_text_and_from_csv_text_back_into_table() {
|
fn table_to_csv_text_and_from_csv_text_back_into_table() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: "tests/fixtures/formats",
|
cwd: "tests/fixtures/formats",
|
||||||
"open caco3_plastics.csv | to-csv | from-csv | first 1 | get origin | echo $it"
|
"open caco3_plastics.csv | to csv | from csv | first 1 | get origin | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(actual, "SPAIN");
|
assert_eq!(actual, "SPAIN");
|
||||||
@ -32,7 +32,7 @@ fn table_to_csv_text() {
|
|||||||
| trim
|
| trim
|
||||||
| split-column "," a b c d origin
|
| split-column "," a b c d origin
|
||||||
| last 1
|
| last 1
|
||||||
| to-csv
|
| to csv
|
||||||
| lines
|
| lines
|
||||||
| nth 1
|
| nth 1
|
||||||
| echo $it
|
| echo $it
|
||||||
@ -63,7 +63,7 @@ fn table_to_csv_text_skipping_headers_after_conversion() {
|
|||||||
| trim
|
| trim
|
||||||
| split-column "," a b c d origin
|
| split-column "," a b c d origin
|
||||||
| last 1
|
| last 1
|
||||||
| to-csv --headerless
|
| to csv --headerless
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
@ -117,7 +117,7 @@ fn from_csv_text_to_table() {
|
|||||||
cwd: dirs.test(), pipeline(
|
cwd: dirs.test(), pipeline(
|
||||||
r#"
|
r#"
|
||||||
open los_tres_caballeros.txt
|
open los_tres_caballeros.txt
|
||||||
| from-csv
|
| from csv
|
||||||
| get rusty_luck
|
| get rusty_luck
|
||||||
| count
|
| count
|
||||||
| echo $it
|
| echo $it
|
||||||
@ -145,7 +145,7 @@ fn from_csv_text_with_separator_to_table() {
|
|||||||
cwd: dirs.test(), pipeline(
|
cwd: dirs.test(), pipeline(
|
||||||
r#"
|
r#"
|
||||||
open los_tres_caballeros.txt
|
open los_tres_caballeros.txt
|
||||||
| from-csv --separator ';'
|
| from csv --separator ';'
|
||||||
| get rusty_luck
|
| get rusty_luck
|
||||||
| count
|
| count
|
||||||
| echo $it
|
| echo $it
|
||||||
@ -173,7 +173,7 @@ fn from_csv_text_with_tab_separator_to_table() {
|
|||||||
cwd: dirs.test(), pipeline(
|
cwd: dirs.test(), pipeline(
|
||||||
r#"
|
r#"
|
||||||
open los_tres_caballeros.txt
|
open los_tres_caballeros.txt
|
||||||
| from-csv --separator '\t'
|
| from csv --separator '\t'
|
||||||
| get rusty_luck
|
| get rusty_luck
|
||||||
| count
|
| count
|
||||||
| echo $it
|
| echo $it
|
||||||
@ -200,7 +200,7 @@ fn from_csv_text_skipping_headers_to_table() {
|
|||||||
cwd: dirs.test(), pipeline(
|
cwd: dirs.test(), pipeline(
|
||||||
r#"
|
r#"
|
||||||
open los_tres_amigos.txt
|
open los_tres_amigos.txt
|
||||||
| from-csv --headerless
|
| from csv --headerless
|
||||||
| get Column3
|
| get Column3
|
||||||
| count
|
| count
|
||||||
| echo $it
|
| echo $it
|
||||||
|
@ -5,7 +5,7 @@ fn out_html_simple() {
|
|||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: ".", pipeline(
|
cwd: ".", pipeline(
|
||||||
r#"
|
r#"
|
||||||
echo 3 | to-html
|
echo 3 | to html
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ fn out_html_table() {
|
|||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: ".", pipeline(
|
cwd: ".", pipeline(
|
||||||
r#"
|
r#"
|
||||||
echo '{"name": "jason"}' | from-json | to-html
|
echo '{"name": "jason"}' | from json | to html
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ fn from_ics_text_to_table() {
|
|||||||
cwd: dirs.test(), pipeline(
|
cwd: dirs.test(), pipeline(
|
||||||
r#"
|
r#"
|
||||||
open calendar.txt
|
open calendar.txt
|
||||||
| from-ics
|
| from ics
|
||||||
| get events
|
| get events
|
||||||
| get properties
|
| get properties
|
||||||
| where name == "SUMMARY"
|
| where name == "SUMMARY"
|
||||||
|
@ -8,8 +8,8 @@ fn table_to_json_text_and_from_json_text_back_into_table() {
|
|||||||
cwd: "tests/fixtures/formats", pipeline(
|
cwd: "tests/fixtures/formats", pipeline(
|
||||||
r#"
|
r#"
|
||||||
open sgml_description.json
|
open sgml_description.json
|
||||||
| to-json
|
| to json
|
||||||
| from-json
|
| from json
|
||||||
| get glossary.GlossDiv.GlossList.GlossEntry.GlossSee
|
| get glossary.GlossDiv.GlossList.GlossEntry.GlossSee
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
@ -37,7 +37,7 @@ fn from_json_text_to_table() {
|
|||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: dirs.test(),
|
cwd: dirs.test(),
|
||||||
"open katz.txt | from-json | get katz | get rusty_luck | count | echo $it"
|
"open katz.txt | from json | get katz | get rusty_luck | count | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(actual, "4");
|
assert_eq!(actual, "4");
|
||||||
@ -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 -o
|
| from json -o
|
||||||
| where name == "GorbyPuff"
|
| where name == "GorbyPuff"
|
||||||
| get rusty_luck
|
| get rusty_luck
|
||||||
| echo $it
|
| echo $it
|
||||||
@ -90,8 +90,8 @@ fn table_to_json_text() {
|
|||||||
| lines
|
| lines
|
||||||
| split-column "," name luck
|
| split-column "," name luck
|
||||||
| pick name
|
| pick name
|
||||||
| to-json
|
| to json
|
||||||
| from-json
|
| from json
|
||||||
| nth 0
|
| nth 0
|
||||||
| get name
|
| get name
|
||||||
| echo $it
|
| echo $it
|
||||||
|
@ -5,7 +5,7 @@ fn out_md_simple() {
|
|||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: ".", pipeline(
|
cwd: ".", pipeline(
|
||||||
r#"
|
r#"
|
||||||
echo 3 | to-md
|
echo 3 | to md
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ fn out_md_table() {
|
|||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: ".", pipeline(
|
cwd: ".", pipeline(
|
||||||
r#"
|
r#"
|
||||||
echo '{"name": "jason"}' | from-json | to-md
|
echo '{"name": "jason"}' | from json | to md
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@ fn table_to_sqlite_and_back_into_table() {
|
|||||||
cwd: "tests/fixtures/formats", pipeline(
|
cwd: "tests/fixtures/formats", pipeline(
|
||||||
r#"
|
r#"
|
||||||
open sample.db
|
open sample.db
|
||||||
| to-sqlite
|
| to sqlite
|
||||||
| from-sqlite
|
| from sqlite
|
||||||
| get table_values
|
| get table_values
|
||||||
| nth 2
|
| nth 2
|
||||||
| get x
|
| get x
|
||||||
|
@ -19,7 +19,7 @@ fn from_ssv_text_to_table() {
|
|||||||
cwd: dirs.test(), pipeline(
|
cwd: dirs.test(), pipeline(
|
||||||
r#"
|
r#"
|
||||||
open oc_get_svc.txt
|
open oc_get_svc.txt
|
||||||
| from-ssv
|
| from ssv
|
||||||
| nth 0
|
| nth 0
|
||||||
| get IP
|
| get IP
|
||||||
| echo $it
|
| echo $it
|
||||||
@ -47,7 +47,7 @@ fn from_ssv_text_to_table_with_separator_specified() {
|
|||||||
cwd: dirs.test(), pipeline(
|
cwd: dirs.test(), pipeline(
|
||||||
r#"
|
r#"
|
||||||
open oc_get_svc.txt
|
open oc_get_svc.txt
|
||||||
| from-ssv --minimum-spaces 3
|
| from ssv --minimum-spaces 3
|
||||||
| nth 0
|
| nth 0
|
||||||
| get IP
|
| get IP
|
||||||
| echo $it
|
| echo $it
|
||||||
@ -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 -a
|
| from ssv --headerless -a
|
||||||
| first
|
| first
|
||||||
| get Column1
|
| get Column1
|
||||||
| echo $it
|
| echo $it
|
||||||
@ -85,7 +85,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
|
| from ssv --headerless
|
||||||
| first
|
| first
|
||||||
| get Column1
|
| get Column1
|
||||||
| echo $it
|
| echo $it
|
||||||
|
@ -6,8 +6,8 @@ fn table_to_toml_text_and_from_toml_text_back_into_table() {
|
|||||||
cwd: "tests/fixtures/formats", pipeline(
|
cwd: "tests/fixtures/formats", pipeline(
|
||||||
r#"
|
r#"
|
||||||
open cargo_sample.toml
|
open cargo_sample.toml
|
||||||
| to-toml
|
| to toml
|
||||||
| from-toml
|
| from toml
|
||||||
| get package.name
|
| get package.name
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
|
@ -6,7 +6,7 @@ use nu_test_support::{nu, pipeline};
|
|||||||
fn table_to_tsv_text_and_from_tsv_text_back_into_table() {
|
fn table_to_tsv_text_and_from_tsv_text_back_into_table() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: "tests/fixtures/formats",
|
cwd: "tests/fixtures/formats",
|
||||||
"open caco3_plastics.tsv | to-tsv | from-tsv | first 1 | get origin | echo $it"
|
"open caco3_plastics.tsv | to tsv | from tsv | first 1 | get origin | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(actual, "SPAIN");
|
assert_eq!(actual, "SPAIN");
|
||||||
@ -16,7 +16,7 @@ fn table_to_tsv_text_and_from_tsv_text_back_into_table() {
|
|||||||
fn table_to_tsv_text_and_from_tsv_text_back_into_table_using_csv_separator() {
|
fn table_to_tsv_text_and_from_tsv_text_back_into_table_using_csv_separator() {
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: "tests/fixtures/formats",
|
cwd: "tests/fixtures/formats",
|
||||||
r"open caco3_plastics.tsv | to-tsv | from-csv --separator '\t' | first 1 | get origin | echo $it"
|
r"open caco3_plastics.tsv | to tsv | from csv --separator '\t' | first 1 | get origin | echo $it"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(actual, "SPAIN");
|
assert_eq!(actual, "SPAIN");
|
||||||
@ -41,7 +41,7 @@ fn table_to_tsv_text() {
|
|||||||
| lines
|
| lines
|
||||||
| split-column "\t" a b c d origin
|
| split-column "\t" a b c d origin
|
||||||
| last 1
|
| last 1
|
||||||
| to-tsv
|
| to tsv
|
||||||
| lines
|
| lines
|
||||||
| nth 1
|
| nth 1
|
||||||
| echo $it
|
| echo $it
|
||||||
@ -71,7 +71,7 @@ fn table_to_tsv_text_skipping_headers_after_conversion() {
|
|||||||
| lines
|
| lines
|
||||||
| split-column "\t" a b c d origin
|
| split-column "\t" a b c d origin
|
||||||
| last 1
|
| last 1
|
||||||
| to-tsv --headerless
|
| to tsv --headerless
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
@ -97,7 +97,7 @@ fn from_tsv_text_to_table() {
|
|||||||
cwd: dirs.test(), pipeline(
|
cwd: dirs.test(), pipeline(
|
||||||
r#"
|
r#"
|
||||||
open los_tres_amigos.txt
|
open los_tres_amigos.txt
|
||||||
| from-tsv
|
| from tsv
|
||||||
| get rusty_luck
|
| get rusty_luck
|
||||||
| count
|
| count
|
||||||
| echo $it
|
| echo $it
|
||||||
@ -124,7 +124,7 @@ fn from_tsv_text_skipping_headers_to_table() {
|
|||||||
cwd: dirs.test(), pipeline(
|
cwd: dirs.test(), pipeline(
|
||||||
r#"
|
r#"
|
||||||
open los_tres_amigos.txt
|
open los_tres_amigos.txt
|
||||||
| from-tsv --headerless
|
| from tsv --headerless
|
||||||
| get Column3
|
| get Column3
|
||||||
| count
|
| count
|
||||||
| echo $it
|
| echo $it
|
||||||
|
@ -6,8 +6,8 @@ fn can_encode_and_decode_urlencoding() {
|
|||||||
cwd: "tests/fixtures/formats", pipeline(
|
cwd: "tests/fixtures/formats", pipeline(
|
||||||
r#"
|
r#"
|
||||||
open sample.url
|
open sample.url
|
||||||
| to-url
|
| to url
|
||||||
| from-url
|
| from url
|
||||||
| get cheese
|
| get cheese
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
|
@ -70,7 +70,7 @@ fn from_vcf_text_to_table() {
|
|||||||
cwd: dirs.test(), pipeline(
|
cwd: dirs.test(), pipeline(
|
||||||
r#"
|
r#"
|
||||||
open contacts.txt
|
open contacts.txt
|
||||||
| from-vcf
|
| from vcf
|
||||||
| get properties
|
| get properties
|
||||||
| where name == "EMAIL"
|
| where name == "EMAIL"
|
||||||
| first
|
| first
|
||||||
|
@ -6,8 +6,8 @@ fn table_to_yaml_text_and_from_yaml_text_back_into_table() {
|
|||||||
cwd: "tests/fixtures/formats", pipeline(
|
cwd: "tests/fixtures/formats", pipeline(
|
||||||
r#"
|
r#"
|
||||||
open appveyor.yml
|
open appveyor.yml
|
||||||
| to-yaml
|
| to yaml
|
||||||
| from-yaml
|
| from yaml
|
||||||
| get environment.global.PROJECT_NAME
|
| get environment.global.PROJECT_NAME
|
||||||
| echo $it
|
| echo $it
|
||||||
"#
|
"#
|
||||||
|
@ -848,16 +848,22 @@ fn parse_internal_command(
|
|||||||
lite_cmd: &LiteCommand,
|
lite_cmd: &LiteCommand,
|
||||||
registry: &dyn SignatureRegistry,
|
registry: &dyn SignatureRegistry,
|
||||||
signature: &Signature,
|
signature: &Signature,
|
||||||
|
mut idx: usize,
|
||||||
) -> (InternalCommand, Option<ParseError>) {
|
) -> (InternalCommand, Option<ParseError>) {
|
||||||
// This is a known internal command, so we need to work with the arguments and parse them according to the expected types
|
// This is a known internal command, so we need to work with the arguments and parse them according to the expected types
|
||||||
let mut internal_command = InternalCommand::new(
|
|
||||||
lite_cmd.name.item.clone(),
|
let (name, name_span) = if idx == 0 {
|
||||||
lite_cmd.name.span,
|
(lite_cmd.name.item.clone(), lite_cmd.name.span)
|
||||||
lite_cmd.span(),
|
} else {
|
||||||
);
|
(
|
||||||
|
format!("{} {}", lite_cmd.name.item, lite_cmd.args[0].item),
|
||||||
|
Span::new(lite_cmd.name.span.start(), lite_cmd.args[0].span.end()),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut internal_command = InternalCommand::new(name, name_span, lite_cmd.span());
|
||||||
internal_command.args.set_initial_flags(&signature);
|
internal_command.args.set_initial_flags(&signature);
|
||||||
|
|
||||||
let mut idx = 0;
|
|
||||||
let mut current_positional = 0;
|
let mut current_positional = 0;
|
||||||
let mut named = NamedArguments::new();
|
let mut named = NamedArguments::new();
|
||||||
let mut positional = vec![];
|
let mut positional = vec![];
|
||||||
@ -1051,12 +1057,31 @@ fn classify_pipeline(
|
|||||||
garbage(lite_cmd.span())
|
garbage(lite_cmd.span())
|
||||||
};
|
};
|
||||||
commands.push(ClassifiedCommand::Expr(Box::new(expr)))
|
commands.push(ClassifiedCommand::Expr(Box::new(expr)))
|
||||||
} else if let Some(signature) = registry.get(&lite_cmd.name.item) {
|
} else {
|
||||||
let (internal_command, err) = parse_internal_command(&lite_cmd, registry, &signature);
|
if !lite_cmd.args.is_empty() {
|
||||||
|
// Check if it's a sub-command
|
||||||
|
if let Some(signature) =
|
||||||
|
registry.get(&format!("{} {}", lite_cmd.name.item, lite_cmd.args[0].item))
|
||||||
|
{
|
||||||
|
let (internal_command, err) =
|
||||||
|
parse_internal_command(&lite_cmd, registry, &signature, 1);
|
||||||
|
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
commands.push(ClassifiedCommand::Internal(internal_command))
|
commands.push(ClassifiedCommand::Internal(internal_command));
|
||||||
} else {
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if it's an internal command
|
||||||
|
if let Some(signature) = registry.get(&lite_cmd.name.item) {
|
||||||
|
let (internal_command, err) =
|
||||||
|
parse_internal_command(&lite_cmd, registry, &signature, 0);
|
||||||
|
|
||||||
|
error = error.or(err);
|
||||||
|
commands.push(ClassifiedCommand::Internal(internal_command));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let name = lite_cmd.name.clone().map(|v| {
|
let name = lite_cmd.name.clone().map(|v| {
|
||||||
let trimmed = trim_quotes(&v);
|
let trimmed = trim_quotes(&v);
|
||||||
expand_path(&trimmed).to_string()
|
expand_path(&trimmed).to_string()
|
||||||
|
@ -33,10 +33,13 @@ pub struct InternalCommand {
|
|||||||
impl InternalCommand {
|
impl InternalCommand {
|
||||||
pub fn new(name: String, name_span: Span, full_span: Span) -> InternalCommand {
|
pub fn new(name: String, name_span: Span, full_span: Span) -> InternalCommand {
|
||||||
InternalCommand {
|
InternalCommand {
|
||||||
name: name.clone(),
|
name,
|
||||||
name_span,
|
name_span,
|
||||||
args: crate::hir::Call::new(
|
args: crate::hir::Call::new(
|
||||||
Box::new(SpannedExpression::new(Expression::string(name), name_span)),
|
Box::new(SpannedExpression::new(
|
||||||
|
Expression::Command(name_span),
|
||||||
|
name_span,
|
||||||
|
)),
|
||||||
full_span,
|
full_span,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
@ -21,10 +21,10 @@ You can save the name of files in a directory like this:
|
|||||||
> ls | where type == File | pick name | save filenames.csv
|
> ls | where type == File | pick name | save filenames.csv
|
||||||
```
|
```
|
||||||
|
|
||||||
Or you can format it in supported formats using one of the `to-*` commands:
|
Or you can format it in supported formats using one of the `to` commands:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
> ls | where type == File | pick name | to-csv | save filenames
|
> ls | where type == File | pick name | to csv | save filenames
|
||||||
```
|
```
|
||||||
|
|
||||||
`filename.csv` and `filenames` are both `csv` formatted files. Nu auto-converts the format if a supported file extension is given.
|
`filename.csv` and `filenames` are both `csv` formatted files. Nu auto-converts the format if a supported file extension is given.
|
@ -119,7 +119,7 @@ fn converts_to_int() {
|
|||||||
cwd: "tests/fixtures/formats", pipeline(
|
cwd: "tests/fixtures/formats", pipeline(
|
||||||
r#"
|
r#"
|
||||||
echo '{number_as_string: "1"}'
|
echo '{number_as_string: "1"}'
|
||||||
| from-json
|
| from json
|
||||||
| str number_as_string --to-int
|
| str number_as_string --to-int
|
||||||
| rename number
|
| rename number
|
||||||
| where number == 1
|
| where number == 1
|
||||||
|
@ -48,13 +48,6 @@ fn automatically_change_directory_with_trailing_slash_and_same_name_as_command()
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[test]
|
|
||||||
// fn correctly_escape_external_arguments() {
|
|
||||||
// let actual = nu!(cwd: ".", r#"^echo '[{"foo": "bar"}]' | from-json | to-json"#);
|
|
||||||
|
|
||||||
// assert_eq!(actual, "{\"foo\":\"bar\"}");
|
|
||||||
// }
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn correctly_escape_external_arguments() {
|
fn correctly_escape_external_arguments() {
|
||||||
let actual = nu!(cwd: ".", r#"^echo '$0'"#);
|
let actual = nu!(cwd: ".", r#"^echo '$0'"#);
|
||||||
|
@ -152,7 +152,7 @@ mod tilde_expansion {
|
|||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: dirs.test(), pipeline(
|
cwd: dirs.test(), pipeline(
|
||||||
r#"
|
r#"
|
||||||
ls | sort-by name | group-by type | each { get File.name | echo $it } | to-json
|
ls | sort-by name | group-by type | each { get File.name | echo $it } | to json
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user