forked from extern/nushell
Path commands: Put column path args behid flag; Allow path join
appending without flag (#4008)
* Change path join signature * Appending now works without flag * Column path operation is behind a -c flag * Move column path arg retrieval to a function Also improves errors * Fix path join tests * Propagate column path changes to all path commands * Update path command examples with columns paths * Modernize path command examples by removing "echo" * Improve structured path error message * Fix typo
This commit is contained in:
parent
7fc65067cf
commit
cc3653cfd9
@ -1,4 +1,4 @@
|
||||
use super::{operate, PathSubcommandArguments};
|
||||
use super::{column_paths_from_args, operate, PathSubcommandArguments};
|
||||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_errors::ShellError;
|
||||
@ -9,13 +9,13 @@ use std::path::Path;
|
||||
pub struct PathBasename;
|
||||
|
||||
struct PathBasenameArguments {
|
||||
rest: Vec<ColumnPath>,
|
||||
columns: Vec<ColumnPath>,
|
||||
replace: Option<Tagged<String>>,
|
||||
}
|
||||
|
||||
impl PathSubcommandArguments for PathBasenameArguments {
|
||||
fn get_column_paths(&self) -> &Vec<ColumnPath> {
|
||||
&self.rest
|
||||
&self.columns
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,10 +26,11 @@ impl WholeStreamCommand for PathBasename {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("path basename")
|
||||
.rest(
|
||||
"rest",
|
||||
SyntaxShape::ColumnPath,
|
||||
.named(
|
||||
"columns",
|
||||
SyntaxShape::Table,
|
||||
"Optionally operate by column path",
|
||||
Some('c'),
|
||||
)
|
||||
.named(
|
||||
"replace",
|
||||
@ -46,7 +47,7 @@ impl WholeStreamCommand for PathBasename {
|
||||
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
let cmd_args = Arc::new(PathBasenameArguments {
|
||||
rest: args.rest(0)?,
|
||||
columns: column_paths_from_args(&args)?,
|
||||
replace: args.get_flag("replace")?,
|
||||
});
|
||||
|
||||
@ -58,12 +59,17 @@ impl WholeStreamCommand for PathBasename {
|
||||
vec![
|
||||
Example {
|
||||
description: "Get basename of a path",
|
||||
example: "echo 'C:\\Users\\joe\\test.txt' | path basename",
|
||||
example: "'C:\\Users\\joe\\test.txt' | path basename",
|
||||
result: Some(vec![Value::from("test.txt")]),
|
||||
},
|
||||
Example {
|
||||
description: "Get basename of a path in a column",
|
||||
example: "ls .. | path basename -c [ name ]",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Replace basename of a path",
|
||||
example: "echo 'C:\\Users\\joe\\test.txt' | path basename -r 'spam.png'",
|
||||
example: "'C:\\Users\\joe\\test.txt' | path basename -r 'spam.png'",
|
||||
result: Some(vec![Value::from(UntaggedValue::filepath(
|
||||
"C:\\Users\\joe\\spam.png",
|
||||
))]),
|
||||
@ -76,12 +82,17 @@ impl WholeStreamCommand for PathBasename {
|
||||
vec![
|
||||
Example {
|
||||
description: "Get basename of a path",
|
||||
example: "echo '/home/joe/test.txt' | path basename",
|
||||
example: "'/home/joe/test.txt' | path basename",
|
||||
result: Some(vec![Value::from("test.txt")]),
|
||||
},
|
||||
Example {
|
||||
description: "Get basename of a path in a column",
|
||||
example: "ls .. | path basename -c [ name ]",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Replace basename of a path",
|
||||
example: "echo '/home/joe/test.txt' | path basename -r 'spam.png'",
|
||||
example: "'/home/joe/test.txt' | path basename -r 'spam.png'",
|
||||
result: Some(vec![Value::from(UntaggedValue::filepath(
|
||||
"/home/joe/spam.png",
|
||||
))]),
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{operate, PathSubcommandArguments};
|
||||
use super::{column_paths_from_args, operate, PathSubcommandArguments};
|
||||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_errors::ShellError;
|
||||
@ -9,14 +9,14 @@ use std::path::Path;
|
||||
pub struct PathDirname;
|
||||
|
||||
struct PathDirnameArguments {
|
||||
rest: Vec<ColumnPath>,
|
||||
columns: Vec<ColumnPath>,
|
||||
replace: Option<Tagged<String>>,
|
||||
num_levels: Option<Tagged<u32>>,
|
||||
}
|
||||
|
||||
impl PathSubcommandArguments for PathDirnameArguments {
|
||||
fn get_column_paths(&self) -> &Vec<ColumnPath> {
|
||||
&self.rest
|
||||
&self.columns
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,10 +27,11 @@ impl WholeStreamCommand for PathDirname {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("path dirname")
|
||||
.rest(
|
||||
"rest",
|
||||
SyntaxShape::ColumnPath,
|
||||
.named(
|
||||
"columns",
|
||||
SyntaxShape::Table,
|
||||
"Optionally operate by column path",
|
||||
Some('c'),
|
||||
)
|
||||
.named(
|
||||
"replace",
|
||||
@ -53,7 +54,7 @@ impl WholeStreamCommand for PathDirname {
|
||||
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
let cmd_args = Arc::new(PathDirnameArguments {
|
||||
rest: args.rest(0)?,
|
||||
columns: column_paths_from_args(&args)?,
|
||||
replace: args.get_flag("replace")?,
|
||||
num_levels: args.get_flag("num-levels")?,
|
||||
});
|
||||
@ -66,20 +67,25 @@ impl WholeStreamCommand for PathDirname {
|
||||
vec![
|
||||
Example {
|
||||
description: "Get dirname of a path",
|
||||
example: "echo 'C:\\Users\\joe\\code\\test.txt' | path dirname",
|
||||
example: "'C:\\Users\\joe\\code\\test.txt' | path dirname",
|
||||
result: Some(vec![Value::from(UntaggedValue::filepath(
|
||||
"C:\\Users\\joe\\code",
|
||||
))]),
|
||||
},
|
||||
Example {
|
||||
description: "Get dirname of a path in a column",
|
||||
example: "ls ('.' | path expand) | path dirname -c [ name ]",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Walk up two levels",
|
||||
example: "echo 'C:\\Users\\joe\\code\\test.txt' | path dirname -n 2",
|
||||
example: "'C:\\Users\\joe\\code\\test.txt' | path dirname -n 2",
|
||||
result: Some(vec![Value::from(UntaggedValue::filepath("C:\\Users\\joe"))]),
|
||||
},
|
||||
Example {
|
||||
description: "Replace the part that would be returned with a custom path",
|
||||
example:
|
||||
"echo 'C:\\Users\\joe\\code\\test.txt' | path dirname -n 2 -r C:\\Users\\viking",
|
||||
"'C:\\Users\\joe\\code\\test.txt' | path dirname -n 2 -r C:\\Users\\viking",
|
||||
result: Some(vec![Value::from(UntaggedValue::filepath(
|
||||
"C:\\Users\\viking\\code\\test.txt",
|
||||
))]),
|
||||
@ -92,17 +98,22 @@ impl WholeStreamCommand for PathDirname {
|
||||
vec![
|
||||
Example {
|
||||
description: "Get dirname of a path",
|
||||
example: "echo '/home/joe/code/test.txt' | path dirname",
|
||||
example: "'/home/joe/code/test.txt' | path dirname",
|
||||
result: Some(vec![Value::from(UntaggedValue::filepath("/home/joe/code"))]),
|
||||
},
|
||||
Example {
|
||||
description: "Get dirname of a path in a column",
|
||||
example: "ls ('.' | path expand) | path dirname -c [ name ]",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Walk up two levels",
|
||||
example: "echo '/home/joe/code/test.txt' | path dirname -n 2",
|
||||
example: "'/home/joe/code/test.txt' | path dirname -n 2",
|
||||
result: Some(vec![Value::from(UntaggedValue::filepath("/home/joe"))]),
|
||||
},
|
||||
Example {
|
||||
description: "Replace the part that would be returned with a custom path",
|
||||
example: "echo '/home/joe/code/test.txt' | path dirname -n 2 -r /home/viking",
|
||||
example: "'/home/joe/code/test.txt' | path dirname -n 2 -r /home/viking",
|
||||
result: Some(vec![Value::from(UntaggedValue::filepath(
|
||||
"/home/viking/code/test.txt",
|
||||
))]),
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{operate, PathSubcommandArguments};
|
||||
use super::{column_paths_from_args, operate, PathSubcommandArguments};
|
||||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_errors::ShellError;
|
||||
@ -8,12 +8,12 @@ use std::path::Path;
|
||||
pub struct PathExists;
|
||||
|
||||
struct PathExistsArguments {
|
||||
rest: Vec<ColumnPath>,
|
||||
columns: Vec<ColumnPath>,
|
||||
}
|
||||
|
||||
impl PathSubcommandArguments for PathExistsArguments {
|
||||
fn get_column_paths(&self) -> &Vec<ColumnPath> {
|
||||
&self.rest
|
||||
&self.columns
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,10 +23,11 @@ impl WholeStreamCommand for PathExists {
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("path exists").rest(
|
||||
"rest",
|
||||
SyntaxShape::ColumnPath,
|
||||
Signature::build("path exists").named(
|
||||
"columns",
|
||||
SyntaxShape::Table,
|
||||
"Optionally operate by column path",
|
||||
Some('c'),
|
||||
)
|
||||
}
|
||||
|
||||
@ -37,7 +38,7 @@ impl WholeStreamCommand for PathExists {
|
||||
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
let cmd_args = Arc::new(PathExistsArguments {
|
||||
rest: args.rest(0)?,
|
||||
columns: column_paths_from_args(&args)?,
|
||||
});
|
||||
|
||||
Ok(operate(args.input, &action, tag.span, cmd_args))
|
||||
@ -45,20 +46,34 @@ impl WholeStreamCommand for PathExists {
|
||||
|
||||
#[cfg(windows)]
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![Example {
|
||||
description: "Check if a file exists",
|
||||
example: "echo 'C:\\Users\\joe\\todo.txt' | path exists",
|
||||
result: Some(vec![Value::from(UntaggedValue::boolean(false))]),
|
||||
}]
|
||||
vec![
|
||||
Example {
|
||||
description: "Check if a file exists",
|
||||
example: "'C:\\Users\\joe\\todo.txt' | path exists",
|
||||
result: Some(vec![Value::from(UntaggedValue::boolean(false))]),
|
||||
},
|
||||
Example {
|
||||
description: "Check if a file exists in a column",
|
||||
example: "ls | path exists -c [ name ]",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![Example {
|
||||
description: "Check if a file exists",
|
||||
example: "echo '/home/joe/todo.txt' | path exists",
|
||||
result: Some(vec![Value::from(UntaggedValue::boolean(false))]),
|
||||
}]
|
||||
vec![
|
||||
Example {
|
||||
description: "Check if a file exists",
|
||||
example: "'/home/joe/todo.txt' | path exists",
|
||||
result: Some(vec![Value::from(UntaggedValue::boolean(false))]),
|
||||
},
|
||||
Example {
|
||||
description: "Check if a file exists in a column",
|
||||
example: "ls | path exists -c [ name ]",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{operate, PathSubcommandArguments};
|
||||
use super::{column_paths_from_args, operate, PathSubcommandArguments};
|
||||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_errors::ShellError;
|
||||
@ -11,12 +11,12 @@ pub struct PathExpand;
|
||||
|
||||
struct PathExpandArguments {
|
||||
strict: bool,
|
||||
rest: Vec<ColumnPath>,
|
||||
columns: Vec<ColumnPath>,
|
||||
}
|
||||
|
||||
impl PathSubcommandArguments for PathExpandArguments {
|
||||
fn get_column_paths(&self) -> &Vec<ColumnPath> {
|
||||
&self.rest
|
||||
&self.columns
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,10 +32,11 @@ impl WholeStreamCommand for PathExpand {
|
||||
"Throw an error if the path could not be expanded",
|
||||
Some('s'),
|
||||
)
|
||||
.rest(
|
||||
"rest",
|
||||
SyntaxShape::ColumnPath,
|
||||
.named(
|
||||
"columns",
|
||||
SyntaxShape::Table,
|
||||
"Optionally operate by column path",
|
||||
Some('c'),
|
||||
)
|
||||
}
|
||||
|
||||
@ -47,7 +48,7 @@ impl WholeStreamCommand for PathExpand {
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
let cmd_args = Arc::new(PathExpandArguments {
|
||||
strict: args.has_flag("strict"),
|
||||
rest: args.rest(0)?,
|
||||
columns: column_paths_from_args(&args)?,
|
||||
});
|
||||
|
||||
Ok(operate(args.input, &action, tag.span, cmd_args))
|
||||
@ -63,6 +64,11 @@ impl WholeStreamCommand for PathExpand {
|
||||
UntaggedValue::filepath(r"C:\Users\joe\bar").into_value(Span::new(0, 25))
|
||||
]),
|
||||
},
|
||||
Example {
|
||||
description: "Expand a path in a column",
|
||||
example: "ls | path expand -c [ name ]",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Expand a relative path",
|
||||
example: r"'foo\..\bar' | path expand",
|
||||
@ -83,6 +89,11 @@ impl WholeStreamCommand for PathExpand {
|
||||
UntaggedValue::filepath("/home/joe/bar").into_value(Span::new(0, 22))
|
||||
]),
|
||||
},
|
||||
Example {
|
||||
description: "Expand a path in a column",
|
||||
example: "ls | path expand -c [ name ]",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Expand a relative path",
|
||||
example: "'foo/../bar' | path expand",
|
||||
|
@ -1,4 +1,6 @@
|
||||
use super::{handle_value, join_path, operate_column_paths, PathSubcommandArguments};
|
||||
use super::{
|
||||
column_paths_from_args, handle_value, join_path, operate_column_paths, PathSubcommandArguments,
|
||||
};
|
||||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_errors::ShellError;
|
||||
@ -9,13 +11,13 @@ use std::path::{Path, PathBuf};
|
||||
pub struct PathJoin;
|
||||
|
||||
struct PathJoinArguments {
|
||||
rest: Vec<ColumnPath>,
|
||||
columns: Vec<ColumnPath>,
|
||||
append: Option<Tagged<PathBuf>>,
|
||||
}
|
||||
|
||||
impl PathSubcommandArguments for PathJoinArguments {
|
||||
fn get_column_paths(&self) -> &Vec<ColumnPath> {
|
||||
&self.rest
|
||||
&self.columns
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,16 +28,16 @@ impl WholeStreamCommand for PathJoin {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("path join")
|
||||
.rest(
|
||||
"rest",
|
||||
SyntaxShape::ColumnPath,
|
||||
"Optionally operate by column path",
|
||||
)
|
||||
.named(
|
||||
"columns",
|
||||
SyntaxShape::Table,
|
||||
"Optionally operate by column path",
|
||||
Some('c'),
|
||||
)
|
||||
.optional(
|
||||
"append",
|
||||
SyntaxShape::FilePath,
|
||||
"Path to append to the input",
|
||||
Some('a'),
|
||||
)
|
||||
}
|
||||
|
||||
@ -50,9 +52,10 @@ the output of 'path parse' and 'path split' subcommands."#
|
||||
|
||||
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
|
||||
let cmd_args = Arc::new(PathJoinArguments {
|
||||
rest: args.rest(0)?,
|
||||
append: args.get_flag("append")?,
|
||||
columns: column_paths_from_args(&args)?,
|
||||
append: args.opt(0)?,
|
||||
});
|
||||
|
||||
Ok(operate_join(args.input, &action, tag, cmd_args))
|
||||
@ -63,21 +66,26 @@ the output of 'path parse' and 'path split' subcommands."#
|
||||
vec![
|
||||
Example {
|
||||
description: "Append a filename to a path",
|
||||
example: r"echo 'C:\Users\viking' | path join -a spam.txt",
|
||||
example: r"'C:\Users\viking' | path join spam.txt",
|
||||
result: Some(vec![Value::from(UntaggedValue::filepath(
|
||||
r"C:\Users\viking\spam.txt",
|
||||
))]),
|
||||
},
|
||||
Example {
|
||||
description: "Append a filename to a path inside a column",
|
||||
example: r"ls | path join spam.txt -c [ name ]",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Join a list of parts into a path",
|
||||
example: r"echo [ 'C:' '\' 'Users' 'viking' 'spam.txt' ] | path join",
|
||||
example: r"[ 'C:' '\' 'Users' 'viking' 'spam.txt' ] | path join",
|
||||
result: Some(vec![Value::from(UntaggedValue::filepath(
|
||||
r"C:\Users\viking\spam.txt",
|
||||
))]),
|
||||
},
|
||||
Example {
|
||||
description: "Join a structured path into a path",
|
||||
example: r"echo [ [parent stem extension]; ['C:\Users\viking' 'spam' 'txt']] | path join",
|
||||
example: r"[ [parent stem extension]; ['C:\Users\viking' 'spam' 'txt']] | path join",
|
||||
result: Some(vec![Value::from(UntaggedValue::filepath(
|
||||
r"C:\Users\viking\spam.txt",
|
||||
))]),
|
||||
@ -90,21 +98,26 @@ the output of 'path parse' and 'path split' subcommands."#
|
||||
vec![
|
||||
Example {
|
||||
description: "Append a filename to a path",
|
||||
example: r"echo '/home/viking' | path join -a spam.txt",
|
||||
example: r"'/home/viking' | path join spam.txt",
|
||||
result: Some(vec![Value::from(UntaggedValue::filepath(
|
||||
r"/home/viking/spam.txt",
|
||||
))]),
|
||||
},
|
||||
Example {
|
||||
description: "Append a filename to a path inside a column",
|
||||
example: r"ls | path join spam.txt -c [ name ]",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Join a list of parts into a path",
|
||||
example: r"echo [ '/' 'home' 'viking' 'spam.txt' ] | path join",
|
||||
example: r"[ '/' 'home' 'viking' 'spam.txt' ] | path join",
|
||||
result: Some(vec![Value::from(UntaggedValue::filepath(
|
||||
r"/home/viking/spam.txt",
|
||||
))]),
|
||||
},
|
||||
Example {
|
||||
description: "Join a structured path into a path",
|
||||
example: r"echo [[ parent stem extension ]; [ '/home/viking' 'spam' 'txt' ]] | path join",
|
||||
example: r"[[ parent stem extension ]; [ '/home/viking' 'spam' 'txt' ]] | path join",
|
||||
result: Some(vec![Value::from(UntaggedValue::filepath(
|
||||
r"/home/viking/spam.txt",
|
||||
))]),
|
||||
|
@ -61,7 +61,7 @@ fn encode_path(
|
||||
ALLOWED_COLUMNS.join(", ")
|
||||
);
|
||||
return Err(ShellError::labeled_error_with_secondary(
|
||||
"Invalid column name",
|
||||
"Expected structured path table",
|
||||
msg,
|
||||
new_span,
|
||||
"originates from here",
|
||||
@ -216,3 +216,36 @@ where
|
||||
operate_column_paths(input, action, span, args)
|
||||
}
|
||||
}
|
||||
|
||||
fn column_paths_from_args(args: &CommandArgs) -> Result<Vec<ColumnPath>, ShellError> {
|
||||
let column_paths: Option<Vec<Value>> = args.get_flag("columns")?;
|
||||
let has_columns = column_paths.is_some();
|
||||
let column_paths = match column_paths {
|
||||
Some(cols) => {
|
||||
let mut c = Vec::new();
|
||||
for col in cols {
|
||||
let colpath = ColumnPath::build(&col.convert_to_string().spanned_unknown());
|
||||
if !colpath.is_empty() {
|
||||
c.push(colpath)
|
||||
}
|
||||
}
|
||||
c
|
||||
}
|
||||
None => Vec::new(),
|
||||
};
|
||||
|
||||
if has_columns && column_paths.is_empty() {
|
||||
let colval: Option<Value> = args.get_flag("columns")?;
|
||||
let colspan = match colval {
|
||||
Some(v) => v.tag.span,
|
||||
None => Span::unknown(),
|
||||
};
|
||||
return Err(ShellError::labeled_error(
|
||||
"Requires a list of columns",
|
||||
"must be a list of columns",
|
||||
colspan,
|
||||
));
|
||||
}
|
||||
|
||||
Ok(column_paths)
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{operate, PathSubcommandArguments};
|
||||
use super::{column_paths_from_args, operate, PathSubcommandArguments};
|
||||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_errors::ShellError;
|
||||
@ -11,13 +11,13 @@ use std::path::Path;
|
||||
pub struct PathParse;
|
||||
|
||||
struct PathParseArguments {
|
||||
rest: Vec<ColumnPath>,
|
||||
columns: Vec<ColumnPath>,
|
||||
extension: Option<Tagged<String>>,
|
||||
}
|
||||
|
||||
impl PathSubcommandArguments for PathParseArguments {
|
||||
fn get_column_paths(&self) -> &Vec<ColumnPath> {
|
||||
&self.rest
|
||||
&self.columns
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,10 +28,11 @@ impl WholeStreamCommand for PathParse {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("path parse")
|
||||
.rest(
|
||||
"rest",
|
||||
SyntaxShape::ColumnPath,
|
||||
.named(
|
||||
"columns",
|
||||
SyntaxShape::Table,
|
||||
"Optionally operate by column path",
|
||||
Some('c'),
|
||||
)
|
||||
.named(
|
||||
"extension",
|
||||
@ -53,7 +54,7 @@ On Windows, an extra 'prefix' column is added."#
|
||||
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
let cmd_args = Arc::new(PathParseArguments {
|
||||
rest: args.rest(0)?,
|
||||
columns: column_paths_from_args(&args)?,
|
||||
extension: args.get_flag("extension")?,
|
||||
});
|
||||
|
||||
@ -65,22 +66,22 @@ On Windows, an extra 'prefix' column is added."#
|
||||
vec![
|
||||
Example {
|
||||
description: "Parse a single path",
|
||||
example: r"echo 'C:\Users\viking\spam.txt' | path parse",
|
||||
example: r"'C:\Users\viking\spam.txt' | path parse",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Replace a complex extension",
|
||||
example: r"echo 'C:\Users\viking\spam.tar.gz' | path parse -e tar.gz | update extension { 'txt' }",
|
||||
example: r"'C:\Users\viking\spam.tar.gz' | path parse -e tar.gz | update extension { 'txt' }",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Ignore the extension",
|
||||
example: r"echo 'C:\Users\viking.d' | path parse -e ''",
|
||||
example: r"'C:\Users\viking.d' | path parse -e ''",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Parse all paths under the 'name' column",
|
||||
example: r"ls | path parse name",
|
||||
example: r"ls | path parse -c [ name ]",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
@ -91,22 +92,22 @@ On Windows, an extra 'prefix' column is added."#
|
||||
vec![
|
||||
Example {
|
||||
description: "Parse a path",
|
||||
example: r"echo '/home/viking/spam.txt' | path parse",
|
||||
example: r"'/home/viking/spam.txt' | path parse",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Replace a complex extension",
|
||||
example: r"echo '/home/viking/spam.tar.gz' | path parse -e tar.gz | update extension { 'txt' }",
|
||||
example: r"'/home/viking/spam.tar.gz' | path parse -e tar.gz | update extension { 'txt' }",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Ignore the extension",
|
||||
example: r"echo '/etc/conf.d' | path parse -e ''",
|
||||
example: r"'/etc/conf.d' | path parse -e ''",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Parse all paths under the 'name' column",
|
||||
example: r"ls | path parse name",
|
||||
example: r"ls | path parse -c [ name ]",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{operate, PathSubcommandArguments};
|
||||
use super::{column_paths_from_args, operate, PathSubcommandArguments};
|
||||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_errors::ShellError;
|
||||
@ -10,12 +10,12 @@ pub struct PathRelativeTo;
|
||||
|
||||
struct PathRelativeToArguments {
|
||||
path: Tagged<PathBuf>,
|
||||
rest: Vec<ColumnPath>,
|
||||
columns: Vec<ColumnPath>,
|
||||
}
|
||||
|
||||
impl PathSubcommandArguments for PathRelativeToArguments {
|
||||
fn get_column_paths(&self) -> &Vec<ColumnPath> {
|
||||
&self.rest
|
||||
&self.columns
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,10 +31,11 @@ impl WholeStreamCommand for PathRelativeTo {
|
||||
SyntaxShape::FilePath,
|
||||
"Parent shared with the input path",
|
||||
)
|
||||
.rest(
|
||||
"rest",
|
||||
SyntaxShape::ColumnPath,
|
||||
.named(
|
||||
"columns",
|
||||
SyntaxShape::Table,
|
||||
"Optionally operate by column path",
|
||||
Some('c'),
|
||||
)
|
||||
}
|
||||
|
||||
@ -52,7 +53,7 @@ path."#
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
let cmd_args = Arc::new(PathRelativeToArguments {
|
||||
path: args.req(0)?,
|
||||
rest: args.rest(1)?,
|
||||
columns: column_paths_from_args(&args)?,
|
||||
});
|
||||
|
||||
Ok(operate(args.input, &action, tag.span, cmd_args))
|
||||
@ -66,6 +67,11 @@ path."#
|
||||
example: r"'C:\Users\viking' | path relative-to 'C:\Users'",
|
||||
result: Some(vec![Value::from(UntaggedValue::filepath(r"viking"))]),
|
||||
},
|
||||
Example {
|
||||
description: "Find a relative path from two absolute paths in a column",
|
||||
example: "ls ~ | path relative-to ~ -c [ name ]",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Find a relative path from two relative paths",
|
||||
example: r"'eggs\bacon\sausage\spam' | path relative-to 'eggs\bacon\sausage'",
|
||||
@ -82,6 +88,11 @@ path."#
|
||||
example: r"'/home/viking' | path relative-to '/home'",
|
||||
result: Some(vec![Value::from(UntaggedValue::filepath(r"viking"))]),
|
||||
},
|
||||
Example {
|
||||
description: "Find a relative path from two absolute paths in a column",
|
||||
example: "ls ~ | path relative-to ~ -c [ name ]",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Find a relative path from two relative paths",
|
||||
example: r"'eggs/bacon/sausage/spam' | path relative-to 'eggs/bacon/sausage'",
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{handle_value, operate_column_paths, PathSubcommandArguments};
|
||||
use super::{column_paths_from_args, handle_value, operate_column_paths, PathSubcommandArguments};
|
||||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_errors::ShellError;
|
||||
@ -8,12 +8,12 @@ use std::path::Path;
|
||||
pub struct PathSplit;
|
||||
|
||||
struct PathSplitArguments {
|
||||
rest: Vec<ColumnPath>,
|
||||
columns: Vec<ColumnPath>,
|
||||
}
|
||||
|
||||
impl PathSubcommandArguments for PathSplitArguments {
|
||||
fn get_column_paths(&self) -> &Vec<ColumnPath> {
|
||||
&self.rest
|
||||
&self.columns
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,10 +23,11 @@ impl WholeStreamCommand for PathSplit {
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("path split").rest(
|
||||
"rest",
|
||||
SyntaxShape::ColumnPath,
|
||||
Signature::build("path split").named(
|
||||
"columns",
|
||||
SyntaxShape::Table,
|
||||
"Optionally operate by column path",
|
||||
Some('c'),
|
||||
)
|
||||
}
|
||||
|
||||
@ -37,7 +38,7 @@ impl WholeStreamCommand for PathSplit {
|
||||
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
let cmd_args = Arc::new(PathSplitArguments {
|
||||
rest: args.rest(0)?,
|
||||
columns: column_paths_from_args(&args)?,
|
||||
});
|
||||
|
||||
Ok(operate_split(args.input, &action, tag.span, cmd_args))
|
||||
@ -48,7 +49,7 @@ impl WholeStreamCommand for PathSplit {
|
||||
vec![
|
||||
Example {
|
||||
description: "Split a path into parts",
|
||||
example: r"echo 'C:\Users\viking\spam.txt' | path split",
|
||||
example: r"'C:\Users\viking\spam.txt' | path split",
|
||||
result: Some(vec![
|
||||
Value::from(UntaggedValue::string("C:")),
|
||||
Value::from(UntaggedValue::string(r"\")),
|
||||
@ -59,7 +60,7 @@ impl WholeStreamCommand for PathSplit {
|
||||
},
|
||||
Example {
|
||||
description: "Split all paths under the 'name' column",
|
||||
example: r"ls | path split name",
|
||||
example: r"ls ('.' | path expand) | path split -c [ name ]",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
@ -70,7 +71,7 @@ impl WholeStreamCommand for PathSplit {
|
||||
vec![
|
||||
Example {
|
||||
description: "Split a path into parts",
|
||||
example: r"echo '/home/viking/spam.txt' | path split",
|
||||
example: r"'/home/viking/spam.txt' | path split",
|
||||
result: Some(vec![
|
||||
Value::from(UntaggedValue::string("/")),
|
||||
Value::from(UntaggedValue::string("home")),
|
||||
@ -80,7 +81,7 @@ impl WholeStreamCommand for PathSplit {
|
||||
},
|
||||
Example {
|
||||
description: "Split all paths under the 'name' column",
|
||||
example: r"ls | path split name",
|
||||
example: r"ls ('.' | path expand) | path split -c [ name ]",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{operate, PathSubcommandArguments};
|
||||
use super::{column_paths_from_args, operate, PathSubcommandArguments};
|
||||
use crate::prelude::*;
|
||||
use nu_engine::filesystem::filesystem_shell::get_file_type;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
@ -9,12 +9,12 @@ use std::path::Path;
|
||||
pub struct PathType;
|
||||
|
||||
struct PathTypeArguments {
|
||||
rest: Vec<ColumnPath>,
|
||||
columns: Vec<ColumnPath>,
|
||||
}
|
||||
|
||||
impl PathSubcommandArguments for PathTypeArguments {
|
||||
fn get_column_paths(&self) -> &Vec<ColumnPath> {
|
||||
&self.rest
|
||||
&self.columns
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,10 +24,11 @@ impl WholeStreamCommand for PathType {
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("path type").rest(
|
||||
"rest",
|
||||
SyntaxShape::ColumnPath,
|
||||
Signature::build("path type").named(
|
||||
"columns",
|
||||
SyntaxShape::Table,
|
||||
"Optionally operate by column path",
|
||||
Some('c'),
|
||||
)
|
||||
}
|
||||
|
||||
@ -38,18 +39,25 @@ impl WholeStreamCommand for PathType {
|
||||
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
let cmd_args = Arc::new(PathTypeArguments {
|
||||
rest: args.rest(0)?,
|
||||
columns: column_paths_from_args(&args)?,
|
||||
});
|
||||
|
||||
Ok(operate(args.input, &action, tag.span, cmd_args))
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![Example {
|
||||
description: "Show type of a filepath",
|
||||
example: "echo '.' | path type",
|
||||
result: Some(vec![Value::from("Dir")]),
|
||||
}]
|
||||
vec![
|
||||
Example {
|
||||
description: "Show type of a filepath",
|
||||
example: "'.' | path type",
|
||||
result: Some(vec![Value::from("Dir")]),
|
||||
},
|
||||
Example {
|
||||
description: "Show type of a filepath in a column",
|
||||
example: "ls | path type -c [ name ]",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ fn returns_path_joined_with_column_path() {
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo [ [name]; [eggs] ]
|
||||
| path join -a spam.txt name
|
||||
| path join spam.txt -c [ name ]
|
||||
| get name
|
||||
"#
|
||||
));
|
||||
@ -23,7 +23,7 @@ fn returns_path_joined_from_list() {
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo [ home viking spam.txt ]
|
||||
| path join
|
||||
| path join
|
||||
"#
|
||||
));
|
||||
|
||||
@ -37,7 +37,7 @@ fn appends_slash_when_joined_with_empty_path() {
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "/some/dir"
|
||||
| path join -a ''
|
||||
| path join ''
|
||||
"#
|
||||
));
|
||||
|
||||
@ -51,7 +51,7 @@ fn returns_joined_path_when_joining_empty_path() {
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo ""
|
||||
| path join -a foo.txt
|
||||
| path join foo.txt
|
||||
"#
|
||||
));
|
||||
|
||||
|
@ -48,7 +48,7 @@ fn parses_custom_extension_gets_extension() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo 'home/viking/spam.tar.gz'
|
||||
echo 'home/viking/spam.tar.gz'
|
||||
| path parse -e tar.gz
|
||||
| get extension
|
||||
"#
|
||||
@ -62,7 +62,7 @@ fn parses_custom_extension_gets_stem() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo 'home/viking/spam.tar.gz'
|
||||
echo 'home/viking/spam.tar.gz'
|
||||
| path parse -e tar.gz
|
||||
| get stem
|
||||
"#
|
||||
@ -76,7 +76,7 @@ fn parses_ignoring_extension_gets_extension() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo 'home/viking/spam.tar.gz'
|
||||
echo 'home/viking/spam.tar.gz'
|
||||
| path parse -e ''
|
||||
| get extension
|
||||
"#
|
||||
@ -90,7 +90,7 @@ fn parses_ignoring_extension_gets_stem() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo 'home/viking/spam.tar.gz'
|
||||
echo 'home/viking/spam.tar.gz'
|
||||
| path parse -e ""
|
||||
| get stem
|
||||
"#
|
||||
@ -105,7 +105,7 @@ fn parses_column_path_extension() {
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo [[home, barn]; ['home/viking/spam.txt', 'barn/cow/moo.png']]
|
||||
| path parse home barn
|
||||
| path parse -c [ home barn ]
|
||||
| get barn
|
||||
| get extension
|
||||
"#
|
||||
|
@ -18,7 +18,7 @@ fn splits_correctly_single_path() {
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo ['home/viking/spam.txt']
|
||||
| path split
|
||||
| path split
|
||||
| last
|
||||
"#
|
||||
));
|
||||
@ -37,7 +37,7 @@ fn splits_correctly_with_column_path() {
|
||||
['home/viking/spam.txt', 'barn/cow/moo.png']
|
||||
['home/viking/eggs.txt', 'barn/goat/cheese.png']
|
||||
]
|
||||
| path split home barn
|
||||
| path split -c [ home barn ]
|
||||
| get barn
|
||||
| length
|
||||
"#
|
||||
|
@ -101,6 +101,7 @@ impl FromValue for i64 {
|
||||
v.as_i64()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromValue for Tagged<i64> {
|
||||
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||
let tag = v.tag.clone();
|
||||
|
Loading…
Reference in New Issue
Block a user