forked from extern/nushell
Refactor: introduce general operate
commands to reduce duplicate code (#6879)
* make format filesize more flexible * make code simpler * finish refactor on bytes commands * finish refactor on str commands * fimplify code * rename from column_paths to cell_paths
This commit is contained in:
parent
843d8c2242
commit
457514590d
@ -1,4 +1,4 @@
|
||||
use super::{operate, BytesArgument};
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
@ -10,12 +10,12 @@ struct Arguments {
|
||||
added_data: Vec<u8>,
|
||||
index: Option<usize>,
|
||||
end: bool,
|
||||
column_paths: Option<Vec<CellPath>>,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
}
|
||||
|
||||
impl BytesArgument for Arguments {
|
||||
fn take_column_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.column_paths.take()
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,12 +62,8 @@ impl Command for BytesAdd {
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let added_data: Vec<u8> = call.req(engine_state, stack, 0)?;
|
||||
let column_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let column_paths = if column_paths.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(column_paths)
|
||||
};
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let index: Option<usize> = call.get_flag(engine_state, stack, "index")?;
|
||||
let end = call.has_flag("end");
|
||||
|
||||
@ -75,7 +71,7 @@ impl Command for BytesAdd {
|
||||
added_data,
|
||||
index,
|
||||
end,
|
||||
column_paths,
|
||||
cell_paths,
|
||||
};
|
||||
operate(add, arg, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
@ -118,7 +114,25 @@ impl Command for BytesAdd {
|
||||
}
|
||||
}
|
||||
|
||||
fn add(input: &[u8], args: &Arguments, span: Span) -> Value {
|
||||
fn add(val: &Value, args: &Arguments, span: Span) -> Value {
|
||||
match val {
|
||||
Value::Binary {
|
||||
val,
|
||||
span: val_span,
|
||||
} => add_impl(val, args, *val_span),
|
||||
other => Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
format!(
|
||||
"Input's type is {}. This command only works with bytes.",
|
||||
other.get_type()
|
||||
),
|
||||
span,
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn add_impl(input: &[u8], args: &Arguments, span: Span) -> Value {
|
||||
match args.index {
|
||||
None => {
|
||||
if args.end {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{operate, BytesArgument};
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
@ -15,12 +15,12 @@ struct Arguments {
|
||||
start: isize,
|
||||
end: isize,
|
||||
arg_span: Span,
|
||||
column_paths: Option<Vec<CellPath>>,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
}
|
||||
|
||||
impl BytesArgument for Arguments {
|
||||
fn take_column_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.column_paths.take()
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,17 +141,13 @@ impl Command for BytesAt {
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let range: Value = call.req(engine_state, stack, 0)?;
|
||||
let (start, end, arg_span) = parse_range(range, call.head)?;
|
||||
let column_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let column_paths = if column_paths.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(column_paths)
|
||||
};
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let arg = Arguments {
|
||||
start,
|
||||
end,
|
||||
arg_span,
|
||||
column_paths,
|
||||
cell_paths,
|
||||
};
|
||||
operate(at, arg, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
@ -228,7 +224,25 @@ impl Command for BytesAt {
|
||||
}
|
||||
}
|
||||
|
||||
fn at(input: &[u8], arg: &Arguments, span: Span) -> Value {
|
||||
fn at(val: &Value, args: &Arguments, span: Span) -> Value {
|
||||
match val {
|
||||
Value::Binary {
|
||||
val,
|
||||
span: val_span,
|
||||
} => at_impl(val, args, *val_span),
|
||||
other => Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
format!(
|
||||
"Input's type is {}. This command only works with bytes.",
|
||||
other.get_type()
|
||||
),
|
||||
span,
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn at_impl(input: &[u8], arg: &Arguments, span: Span) -> Value {
|
||||
let len: isize = input.len() as isize;
|
||||
|
||||
let start: isize = if arg.start < 0 {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{operate, BytesArgument};
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
@ -8,12 +8,12 @@ use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShap
|
||||
|
||||
struct Arguments {
|
||||
pattern: Vec<u8>,
|
||||
column_paths: Option<Vec<CellPath>>,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
}
|
||||
|
||||
impl BytesArgument for Arguments {
|
||||
fn take_column_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.column_paths.take()
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,15 +53,11 @@ impl Command for BytesEndsWith {
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let pattern: Vec<u8> = call.req(engine_state, stack, 0)?;
|
||||
let column_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let column_paths = if column_paths.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(column_paths)
|
||||
};
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let arg = Arguments {
|
||||
pattern,
|
||||
column_paths,
|
||||
cell_paths,
|
||||
};
|
||||
operate(ends_with, arg, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
@ -96,10 +92,24 @@ impl Command for BytesEndsWith {
|
||||
}
|
||||
}
|
||||
|
||||
fn ends_with(input: &[u8], Arguments { pattern, .. }: &Arguments, span: Span) -> Value {
|
||||
Value::Bool {
|
||||
val: input.ends_with(pattern),
|
||||
span,
|
||||
fn ends_with(val: &Value, args: &Arguments, span: Span) -> Value {
|
||||
match val {
|
||||
Value::Binary {
|
||||
val,
|
||||
span: val_span,
|
||||
} => Value::Bool {
|
||||
val: val.ends_with(&args.pattern),
|
||||
span: *val_span,
|
||||
},
|
||||
other => Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
format!(
|
||||
"Input's type is {}. This command only works with bytes.",
|
||||
other.get_type()
|
||||
),
|
||||
span,
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{operate, BytesArgument};
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::{Call, CellPath};
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
@ -10,12 +10,12 @@ struct Arguments {
|
||||
pattern: Vec<u8>,
|
||||
end: bool,
|
||||
all: bool,
|
||||
column_paths: Option<Vec<CellPath>>,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
}
|
||||
|
||||
impl BytesArgument for Arguments {
|
||||
fn take_column_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.column_paths.take()
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,17 +60,13 @@ impl Command for BytesIndexOf {
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let pattern: Vec<u8> = call.req(engine_state, stack, 0)?;
|
||||
let column_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let column_paths = if column_paths.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(column_paths)
|
||||
};
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let arg = Arguments {
|
||||
pattern,
|
||||
end: call.has_flag("end"),
|
||||
all: call.has_flag("all"),
|
||||
column_paths,
|
||||
cell_paths,
|
||||
};
|
||||
operate(index_of, arg, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
@ -126,7 +122,25 @@ impl Command for BytesIndexOf {
|
||||
}
|
||||
}
|
||||
|
||||
fn index_of(input: &[u8], arg: &Arguments, span: Span) -> Value {
|
||||
fn index_of(val: &Value, args: &Arguments, span: Span) -> Value {
|
||||
match val {
|
||||
Value::Binary {
|
||||
val,
|
||||
span: val_span,
|
||||
} => index_of_impl(val, args, *val_span),
|
||||
other => Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
format!(
|
||||
"Input's type is {}. This command only works with bytes.",
|
||||
other.get_type()
|
||||
),
|
||||
span,
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn index_of_impl(input: &[u8], arg: &Arguments, span: Span) -> Value {
|
||||
if arg.all {
|
||||
search_all_index(input, &arg.pattern, arg.end, span)
|
||||
} else {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{operate, BytesArgument};
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
@ -10,12 +10,12 @@ use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShap
|
||||
pub struct BytesLen;
|
||||
|
||||
struct Arguments {
|
||||
column_paths: Option<Vec<CellPath>>,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
}
|
||||
|
||||
impl BytesArgument for Arguments {
|
||||
fn take_column_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.column_paths.take()
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,13 +49,9 @@ impl Command for BytesLen {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let column_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let column_paths = if column_paths.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(column_paths)
|
||||
};
|
||||
let arg = Arguments { column_paths };
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let arg = Arguments { cell_paths };
|
||||
operate(length, arg, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
|
||||
@ -78,10 +74,24 @@ impl Command for BytesLen {
|
||||
}
|
||||
}
|
||||
|
||||
fn length(input: &[u8], _arg: &Arguments, span: Span) -> Value {
|
||||
Value::Int {
|
||||
val: input.len() as i64,
|
||||
span,
|
||||
fn length(val: &Value, _args: &Arguments, span: Span) -> Value {
|
||||
match val {
|
||||
Value::Binary {
|
||||
val,
|
||||
span: val_span,
|
||||
} => Value::Int {
|
||||
val: val.len() as i64,
|
||||
span: *val_span,
|
||||
},
|
||||
other => Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
format!(
|
||||
"Input's type is {}. This command only works with bytes.",
|
||||
other.get_type()
|
||||
),
|
||||
span,
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,11 +11,6 @@ mod replace;
|
||||
mod reverse;
|
||||
mod starts_with;
|
||||
|
||||
use nu_protocol::ast::CellPath;
|
||||
use nu_protocol::{PipelineData, ShellError, Span, Value};
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub use add::BytesAdd;
|
||||
pub use at::BytesAt;
|
||||
pub use build_::BytesBuild;
|
||||
@ -28,71 +23,3 @@ pub use remove::BytesRemove;
|
||||
pub use replace::BytesReplace;
|
||||
pub use reverse::BytesReverse;
|
||||
pub use starts_with::BytesStartsWith;
|
||||
|
||||
trait BytesArgument {
|
||||
fn take_column_paths(&mut self) -> Option<Vec<CellPath>>;
|
||||
}
|
||||
|
||||
/// map input pipeline data, for each elements, if it's Binary, invoke relative `cmd` with `arg`.
|
||||
fn operate<C, A>(
|
||||
cmd: C,
|
||||
mut arg: A,
|
||||
input: PipelineData,
|
||||
span: Span,
|
||||
ctrlc: Option<Arc<AtomicBool>>,
|
||||
) -> Result<PipelineData, ShellError>
|
||||
where
|
||||
A: BytesArgument + Send + Sync + 'static,
|
||||
C: Fn(&[u8], &A, Span) -> Value + Send + Sync + 'static + Clone + Copy,
|
||||
{
|
||||
match arg.take_column_paths() {
|
||||
None => input.map(
|
||||
move |v| match v {
|
||||
Value::Binary {
|
||||
val,
|
||||
span: val_span,
|
||||
} => cmd(&val, &arg, val_span),
|
||||
other => Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
format!(
|
||||
"Input's type is {}. This command only works with bytes.",
|
||||
other.get_type()
|
||||
),
|
||||
span,
|
||||
),
|
||||
},
|
||||
},
|
||||
ctrlc,
|
||||
),
|
||||
Some(column_paths) => {
|
||||
let arg = Arc::new(arg);
|
||||
input.map(
|
||||
move |mut v| {
|
||||
for path in &column_paths {
|
||||
let opt = arg.clone();
|
||||
let r = v.update_cell_path(
|
||||
&path.members,
|
||||
Box::new(move |old| {
|
||||
match old {
|
||||
Value::Binary {val, span: val_span} => cmd(val, &opt, *val_span),
|
||||
other => Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
format!(
|
||||
"Input's type is {}. This command only works with bytes.",
|
||||
other.get_type()
|
||||
),
|
||||
span,
|
||||
),
|
||||
}}}),
|
||||
);
|
||||
if let Err(error) = r {
|
||||
return Value::Error { error };
|
||||
}
|
||||
}
|
||||
v
|
||||
},
|
||||
ctrlc,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{operate, BytesArgument};
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::{
|
||||
ast::{Call, CellPath},
|
||||
@ -9,13 +9,13 @@ use nu_protocol::{
|
||||
struct Arguments {
|
||||
pattern: Vec<u8>,
|
||||
end: bool,
|
||||
column_paths: Option<Vec<CellPath>>,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
all: bool,
|
||||
}
|
||||
|
||||
impl BytesArgument for Arguments {
|
||||
fn take_column_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.column_paths.take()
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,12 +55,8 @@ impl Command for BytesRemove {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let column_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let column_paths = if column_paths.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(column_paths)
|
||||
};
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let pattern_to_remove = call.req::<Spanned<Vec<u8>>>(engine_state, stack, 0)?;
|
||||
if pattern_to_remove.item.is_empty() {
|
||||
return Err(ShellError::UnsupportedInput(
|
||||
@ -73,7 +69,7 @@ impl Command for BytesRemove {
|
||||
let arg = Arguments {
|
||||
pattern: pattern_to_remove,
|
||||
end: call.has_flag("end"),
|
||||
column_paths,
|
||||
cell_paths,
|
||||
all: call.has_flag("all"),
|
||||
};
|
||||
|
||||
@ -135,7 +131,25 @@ impl Command for BytesRemove {
|
||||
}
|
||||
}
|
||||
|
||||
fn remove(input: &[u8], arg: &Arguments, span: Span) -> Value {
|
||||
fn remove(val: &Value, args: &Arguments, span: Span) -> Value {
|
||||
match val {
|
||||
Value::Binary {
|
||||
val,
|
||||
span: val_span,
|
||||
} => remove_impl(val, args, *val_span),
|
||||
other => Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
format!(
|
||||
"Input's type is {}. This command only works with bytes.",
|
||||
other.get_type()
|
||||
),
|
||||
span,
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_impl(input: &[u8], arg: &Arguments, span: Span) -> Value {
|
||||
let mut result = vec![];
|
||||
let remove_all = arg.all;
|
||||
let input_len = input.len();
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{operate, BytesArgument};
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::{
|
||||
ast::{Call, CellPath},
|
||||
@ -9,13 +9,13 @@ use nu_protocol::{
|
||||
struct Arguments {
|
||||
find: Vec<u8>,
|
||||
replace: Vec<u8>,
|
||||
column_paths: Option<Vec<CellPath>>,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
all: bool,
|
||||
}
|
||||
|
||||
impl BytesArgument for Arguments {
|
||||
fn take_column_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.column_paths.take()
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,12 +55,8 @@ impl Command for BytesReplace {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let column_paths: Vec<CellPath> = call.rest(engine_state, stack, 2)?;
|
||||
let column_paths = if column_paths.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(column_paths)
|
||||
};
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 2)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let find = call.req::<Spanned<Vec<u8>>>(engine_state, stack, 0)?;
|
||||
if find.item.is_empty() {
|
||||
return Err(ShellError::UnsupportedInput(
|
||||
@ -72,7 +68,7 @@ impl Command for BytesReplace {
|
||||
let arg = Arguments {
|
||||
find: find.item,
|
||||
replace: call.req::<Vec<u8>>(engine_state, stack, 1)?,
|
||||
column_paths,
|
||||
cell_paths,
|
||||
all: call.has_flag("all"),
|
||||
};
|
||||
|
||||
@ -126,7 +122,25 @@ impl Command for BytesReplace {
|
||||
}
|
||||
}
|
||||
|
||||
fn replace(input: &[u8], arg: &Arguments, span: Span) -> Value {
|
||||
fn replace(val: &Value, args: &Arguments, span: Span) -> Value {
|
||||
match val {
|
||||
Value::Binary {
|
||||
val,
|
||||
span: val_span,
|
||||
} => replace_impl(val, args, *val_span),
|
||||
other => Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
format!(
|
||||
"Input's type is {}. This command only works with bytes.",
|
||||
other.get_type()
|
||||
),
|
||||
span,
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn replace_impl(input: &[u8], arg: &Arguments, span: Span) -> Value {
|
||||
let mut replaced = vec![];
|
||||
let replace_all = arg.all;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{operate, BytesArgument};
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
@ -7,12 +7,12 @@ use nu_protocol::Category;
|
||||
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value};
|
||||
|
||||
struct Arguments {
|
||||
column_paths: Option<Vec<CellPath>>,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
}
|
||||
|
||||
impl BytesArgument for Arguments {
|
||||
fn take_column_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.column_paths.take()
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,13 +50,9 @@ impl Command for BytesReverse {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let column_paths: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
|
||||
let column_paths = if column_paths.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(column_paths)
|
||||
};
|
||||
let arg = Arguments { column_paths };
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let arg = Arguments { cell_paths };
|
||||
operate(reverse, arg, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
|
||||
@ -82,12 +78,28 @@ impl Command for BytesReverse {
|
||||
}
|
||||
}
|
||||
|
||||
fn reverse(input: &[u8], _args: &Arguments, span: Span) -> Value {
|
||||
let mut reversed_input = input.to_vec();
|
||||
reversed_input.reverse();
|
||||
Value::Binary {
|
||||
val: reversed_input,
|
||||
span,
|
||||
fn reverse(val: &Value, _args: &Arguments, span: Span) -> Value {
|
||||
match val {
|
||||
Value::Binary {
|
||||
val,
|
||||
span: val_span,
|
||||
} => {
|
||||
let mut reversed_input = val.to_vec();
|
||||
reversed_input.reverse();
|
||||
Value::Binary {
|
||||
val: reversed_input,
|
||||
span: *val_span,
|
||||
}
|
||||
}
|
||||
other => Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
format!(
|
||||
"Input's type is {}. This command only works with bytes.",
|
||||
other.get_type()
|
||||
),
|
||||
span,
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{operate, BytesArgument};
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
@ -8,12 +8,12 @@ use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShap
|
||||
|
||||
struct Arguments {
|
||||
pattern: Vec<u8>,
|
||||
column_paths: Option<Vec<CellPath>>,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
}
|
||||
|
||||
impl BytesArgument for Arguments {
|
||||
fn take_column_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.column_paths.take()
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,15 +53,11 @@ impl Command for BytesStartsWith {
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let pattern: Vec<u8> = call.req(engine_state, stack, 0)?;
|
||||
let column_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let column_paths = if column_paths.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(column_paths)
|
||||
};
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let arg = Arguments {
|
||||
pattern,
|
||||
column_paths,
|
||||
cell_paths,
|
||||
};
|
||||
operate(
|
||||
starts_with,
|
||||
@ -102,10 +98,24 @@ impl Command for BytesStartsWith {
|
||||
}
|
||||
}
|
||||
|
||||
fn starts_with(input: &[u8], Arguments { pattern, .. }: &Arguments, span: Span) -> Value {
|
||||
Value::Bool {
|
||||
val: input.starts_with(pattern),
|
||||
span,
|
||||
fn starts_with(val: &Value, args: &Arguments, span: Span) -> Value {
|
||||
match val {
|
||||
Value::Binary {
|
||||
val,
|
||||
span: val_span,
|
||||
} => Value::Bool {
|
||||
val: val.starts_with(&args.pattern),
|
||||
span: *val_span,
|
||||
},
|
||||
other => Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
format!(
|
||||
"Input's type is {}. This command only works with bytes.",
|
||||
other.get_type()
|
||||
),
|
||||
span,
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
51
crates/nu-command/src/input_handler.rs
Normal file
51
crates/nu-command/src/input_handler.rs
Normal file
@ -0,0 +1,51 @@
|
||||
use nu_protocol::ast::CellPath;
|
||||
use nu_protocol::{PipelineData, ShellError, Span, Value};
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub trait CmdArgument {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>>;
|
||||
}
|
||||
|
||||
/// A simple wrapper for `PipelineData::map` method.
|
||||
///
|
||||
/// In detail, for each elements, invoking relative `cmd` with `arg`.
|
||||
///
|
||||
/// If `arg` tell us that it's column path is not None, only map over data under these columns.
|
||||
/// Else it will apply each column inside a table.
|
||||
///
|
||||
/// The validation of input element should be handle by `cmd` itself.
|
||||
pub fn operate<C, A>(
|
||||
cmd: C,
|
||||
mut arg: A,
|
||||
input: PipelineData,
|
||||
span: Span,
|
||||
ctrlc: Option<Arc<AtomicBool>>,
|
||||
) -> Result<PipelineData, ShellError>
|
||||
where
|
||||
A: CmdArgument + Send + Sync + 'static,
|
||||
C: Fn(&Value, &A, Span) -> Value + Send + Sync + 'static + Clone + Copy,
|
||||
{
|
||||
match arg.take_cell_paths() {
|
||||
None => input.map(move |v| cmd(&v, &arg, v.span().unwrap_or(span)), ctrlc),
|
||||
Some(column_paths) => {
|
||||
let arg = Arc::new(arg);
|
||||
input.map(
|
||||
move |mut v| {
|
||||
for path in &column_paths {
|
||||
let opt = arg.clone();
|
||||
let r = v.update_cell_path(
|
||||
&path.members,
|
||||
Box::new(move |old| cmd(old, &opt, old.span().unwrap_or(span))),
|
||||
);
|
||||
if let Err(error) = r {
|
||||
return Value::Error { error };
|
||||
}
|
||||
}
|
||||
v
|
||||
},
|
||||
ctrlc,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ mod filters;
|
||||
mod formats;
|
||||
mod generators;
|
||||
mod hash;
|
||||
mod input_handler;
|
||||
mod math;
|
||||
mod misc;
|
||||
mod network;
|
||||
|
@ -1,11 +1,22 @@
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::{Call, CellPath};
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
format_filesize, Category, Example, IntoPipelineData, PipelineData, PipelineMetadata,
|
||||
ShellError, Signature, Span, SyntaxShape, Value,
|
||||
format_filesize, Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape,
|
||||
Value,
|
||||
};
|
||||
use std::iter;
|
||||
|
||||
struct Arguments {
|
||||
format_value: String,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
}
|
||||
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FileSize;
|
||||
@ -17,15 +28,15 @@ impl Command for FileSize {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("format filesize")
|
||||
.required(
|
||||
"field",
|
||||
SyntaxShape::String,
|
||||
"the name of the column to update",
|
||||
)
|
||||
.required(
|
||||
"format value",
|
||||
SyntaxShape::String,
|
||||
"the format into which convert the filesizes",
|
||||
"the format into which convert the file sizes",
|
||||
)
|
||||
.rest(
|
||||
"rest",
|
||||
SyntaxShape::CellPath,
|
||||
"optinally find and replace text by column paths",
|
||||
)
|
||||
.category(Category::Strings)
|
||||
}
|
||||
@ -45,98 +56,62 @@ impl Command for FileSize {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let field = call.req::<Value>(engine_state, stack, 0)?.as_string()?;
|
||||
let format_value = call
|
||||
.req::<Value>(engine_state, stack, 1)?
|
||||
.req::<Value>(engine_state, stack, 0)?
|
||||
.as_string()?
|
||||
.to_ascii_lowercase();
|
||||
let span = call.head;
|
||||
let input_metadata = input.metadata();
|
||||
let data_as_value = input.into_value(span);
|
||||
|
||||
// Something need to consider:
|
||||
// 1. what if input data type is not table? For now just output nothing.
|
||||
// 2. what if value is not a FileSize type? For now just return nothing too for the value.
|
||||
match data_as_value {
|
||||
Value::List { vals, span } => {
|
||||
format_impl(vals, field, format_value, span, input_metadata)
|
||||
}
|
||||
_ => Ok(Value::Nothing { span }.into_pipeline_data()),
|
||||
}
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let arg = Arguments {
|
||||
format_value,
|
||||
cell_paths,
|
||||
};
|
||||
operate(
|
||||
format_value_impl,
|
||||
arg,
|
||||
input,
|
||||
call.head,
|
||||
engine_state.ctrlc.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "Convert the size row to KB",
|
||||
example: "ls | format filesize size KB",
|
||||
example: "ls | format filesize KB size",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Convert the apparent row to B",
|
||||
example: "du | format filesize apparent B",
|
||||
example: "du | format filesize B apparent",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Convert the size data to MB",
|
||||
example: "4Gb | format filesize MB",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
fn format_impl(
|
||||
vals: Vec<Value>,
|
||||
field: String,
|
||||
format_value: String,
|
||||
input_span: Span,
|
||||
input_metadata: Option<PipelineMetadata>,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let records: Vec<Value> = vals
|
||||
.into_iter()
|
||||
.map(|rec| {
|
||||
let record_span = rec.span();
|
||||
match rec {
|
||||
Value::Record { cols, vals, span } => {
|
||||
let mut new_cols = vec![];
|
||||
let mut new_vals = vec![];
|
||||
for (c, v) in iter::zip(cols, vals) {
|
||||
// find column to format, try format the value.
|
||||
if c == field {
|
||||
new_vals.push(format_value_impl(v, &format_value, span));
|
||||
} else {
|
||||
new_vals.push(v);
|
||||
}
|
||||
new_cols.push(c);
|
||||
}
|
||||
Value::Record {
|
||||
cols: new_cols,
|
||||
vals: new_vals,
|
||||
span,
|
||||
}
|
||||
}
|
||||
_ => Value::Nothing {
|
||||
span: match record_span {
|
||||
Ok(s) => s,
|
||||
Err(_) => input_span,
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let result = Value::List {
|
||||
vals: records,
|
||||
span: input_span,
|
||||
}
|
||||
.into_pipeline_data();
|
||||
Ok(result.set_metadata(input_metadata))
|
||||
}
|
||||
|
||||
fn format_value_impl(val: Value, format_value: &str, span: Span) -> Value {
|
||||
fn format_value_impl(val: &Value, arg: &Arguments, span: Span) -> Value {
|
||||
match val {
|
||||
Value::Filesize { val, span } => Value::String {
|
||||
// don't need to concern about metric, we just format units by what user input.
|
||||
val: format_filesize(val, format_value, false),
|
||||
span,
|
||||
val: format_filesize(*val, &arg.format_value, false),
|
||||
span: *span,
|
||||
},
|
||||
other => Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
format!(
|
||||
"Input's type is not supported, support type: <filesize>, current_type: {}",
|
||||
other.get_type()
|
||||
),
|
||||
span,
|
||||
),
|
||||
},
|
||||
_ => Value::Nothing { span },
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,10 +22,22 @@ pub use upcase::SubCommand as StrUpcase;
|
||||
|
||||
use nu_engine::CallExt;
|
||||
|
||||
use crate::input_handler::{operate as general_operate, CmdArgument};
|
||||
use nu_protocol::ast::{Call, CellPath};
|
||||
use nu_protocol::engine::{EngineState, Stack};
|
||||
use nu_protocol::{PipelineData, ShellError, Span, Value};
|
||||
|
||||
struct Arguments<F: Fn(&str) -> String + Send + Sync + 'static> {
|
||||
case_operation: &'static F,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
}
|
||||
|
||||
impl<F: Fn(&str) -> String + Send + Sync + 'static> CmdArgument for Arguments<F> {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn operate<F>(
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
@ -36,35 +48,20 @@ pub fn operate<F>(
|
||||
where
|
||||
F: Fn(&str) -> String + Send + Sync + 'static,
|
||||
{
|
||||
let head = call.head;
|
||||
let column_paths: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
|
||||
|
||||
input.map(
|
||||
move |v| {
|
||||
if column_paths.is_empty() {
|
||||
action(&v, case_operation, head)
|
||||
} else {
|
||||
let mut ret = v;
|
||||
for path in &column_paths {
|
||||
let r = ret.update_cell_path(
|
||||
&path.members,
|
||||
Box::new(move |old| action(old, case_operation, head)),
|
||||
);
|
||||
if let Err(error) = r {
|
||||
return Value::Error { error };
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
},
|
||||
engine_state.ctrlc.clone(),
|
||||
)
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let args = Arguments {
|
||||
case_operation,
|
||||
cell_paths,
|
||||
};
|
||||
general_operate(action, args, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
|
||||
pub fn action<F>(input: &Value, case_operation: &F, head: Span) -> Value
|
||||
fn action<F>(input: &Value, args: &Arguments<F>, head: Span) -> Value
|
||||
where
|
||||
F: Fn(&str) -> String + Send + Sync + 'static,
|
||||
{
|
||||
let case_operation = args.case_operation;
|
||||
match input {
|
||||
Value::String { val, .. } => Value::String {
|
||||
val: case_operation(val),
|
||||
|
@ -1,15 +1,27 @@
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::Category;
|
||||
use nu_protocol::{
|
||||
Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
|
||||
};
|
||||
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
|
||||
struct Arguments {
|
||||
substring: String,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
case_insensitive: bool,
|
||||
not_contain: bool,
|
||||
}
|
||||
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for SubCommand {
|
||||
fn name(&self) -> &str {
|
||||
"str contains"
|
||||
@ -43,7 +55,15 @@ impl Command for SubCommand {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
operate(engine_state, stack, call, input)
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let args = Arguments {
|
||||
substring: call.req::<String>(engine_state, stack, 0)?,
|
||||
cell_paths,
|
||||
case_insensitive: call.has_flag("insensitive"),
|
||||
not_contain: call.has_flag("not"),
|
||||
};
|
||||
operate(action, args, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
@ -175,53 +195,21 @@ impl Command for SubCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn operate(
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let head = call.head;
|
||||
let substring: Spanned<String> = call.req(engine_state, stack, 0)?;
|
||||
let column_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let case_insensitive = call.has_flag("insensitive");
|
||||
let not_contain = call.has_flag("not");
|
||||
|
||||
input.map(
|
||||
move |v| {
|
||||
if column_paths.is_empty() {
|
||||
action(&v, case_insensitive, not_contain, &substring.item, head)
|
||||
} else {
|
||||
let mut ret = v;
|
||||
for path in &column_paths {
|
||||
let p = substring.item.clone();
|
||||
let r = ret.update_cell_path(
|
||||
&path.members,
|
||||
Box::new(move |old| action(old, case_insensitive, not_contain, &p, head)),
|
||||
);
|
||||
if let Err(error) = r {
|
||||
return Value::Error { error };
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
},
|
||||
engine_state.ctrlc.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
fn action(
|
||||
input: &Value,
|
||||
case_insensitive: bool,
|
||||
not_contain: bool,
|
||||
substring: &str,
|
||||
Arguments {
|
||||
case_insensitive,
|
||||
not_contain,
|
||||
substring,
|
||||
..
|
||||
}: &Arguments,
|
||||
head: Span,
|
||||
) -> Value {
|
||||
match input {
|
||||
Value::String { val, .. } => Value::Bool {
|
||||
val: match case_insensitive {
|
||||
true => {
|
||||
if not_contain {
|
||||
if *not_contain {
|
||||
!val.to_lowercase()
|
||||
.contains(substring.to_lowercase().as_str())
|
||||
} else {
|
||||
@ -230,7 +218,7 @@ fn action(
|
||||
}
|
||||
}
|
||||
false => {
|
||||
if not_contain {
|
||||
if *not_contain {
|
||||
!val.contains(substring)
|
||||
} else {
|
||||
val.contains(substring)
|
||||
|
@ -1,14 +1,26 @@
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::{
|
||||
ast::{Call, CellPath},
|
||||
engine::{Command, EngineState, Stack},
|
||||
levenshtein_distance, Category, Example, PipelineData, ShellError, Signature, Span, Spanned,
|
||||
levenshtein_distance, Category, Example, PipelineData, ShellError, Signature, Span,
|
||||
SyntaxShape, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
|
||||
struct Arguments {
|
||||
compare_string: String,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
}
|
||||
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for SubCommand {
|
||||
fn name(&self) -> &str {
|
||||
"str distance"
|
||||
@ -44,7 +56,14 @@ impl Command for SubCommand {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
operate(engine_state, stack, call, input)
|
||||
let compare_string: String = call.req(engine_state, stack, 0)?;
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let args = Arguments {
|
||||
compare_string,
|
||||
cell_paths,
|
||||
};
|
||||
operate(action, args, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
@ -63,40 +82,8 @@ impl Command for SubCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn operate(
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let head = call.head;
|
||||
let compare_string: Spanned<String> = call.req(engine_state, stack, 0)?;
|
||||
let column_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
|
||||
input.map(
|
||||
move |v| {
|
||||
if column_paths.is_empty() {
|
||||
action(&v, &compare_string.item, head)
|
||||
} else {
|
||||
let mut ret = v;
|
||||
for path in &column_paths {
|
||||
let c = compare_string.item.clone();
|
||||
let r = ret.update_cell_path(
|
||||
&path.members,
|
||||
Box::new(move |old| action(old, &c, head)),
|
||||
);
|
||||
if let Err(error) = r {
|
||||
return Value::Error { error };
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
},
|
||||
engine_state.ctrlc.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
fn action(input: &Value, compare_string: &str, head: Span) -> Value {
|
||||
fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
||||
let compare_string = &args.compare_string;
|
||||
match &input {
|
||||
Value::String { val, .. } => {
|
||||
let distance = levenshtein_distance(val, compare_string);
|
||||
|
@ -1,11 +1,22 @@
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::Category;
|
||||
use nu_protocol::Spanned;
|
||||
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value};
|
||||
|
||||
struct Arguments {
|
||||
substring: String,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
}
|
||||
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
|
||||
@ -40,7 +51,13 @@ impl Command for SubCommand {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
operate(engine_state, stack, call, input)
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let args = Arguments {
|
||||
substring: call.req::<String>(engine_state, stack, 0)?,
|
||||
cell_paths,
|
||||
};
|
||||
operate(action, args, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
@ -65,43 +82,10 @@ impl Command for SubCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn operate(
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let head = call.head;
|
||||
let substring: Spanned<String> = call.req(engine_state, stack, 0)?;
|
||||
let column_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
|
||||
input.map(
|
||||
move |v| {
|
||||
if column_paths.is_empty() {
|
||||
action(&v, &substring.item, head)
|
||||
} else {
|
||||
let mut ret = v;
|
||||
for path in &column_paths {
|
||||
let p = substring.item.clone();
|
||||
let r = ret.update_cell_path(
|
||||
&path.members,
|
||||
Box::new(move |old| action(old, &p, head)),
|
||||
);
|
||||
if let Err(error) = r {
|
||||
return Value::Error { error };
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
},
|
||||
engine_state.ctrlc.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
fn action(input: &Value, substring: &str, head: Span) -> Value {
|
||||
fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
||||
match input {
|
||||
Value::String { val, .. } => Value::Bool {
|
||||
val: val.ends_with(substring),
|
||||
val: val.ends_with(&args.substring),
|
||||
span: head,
|
||||
},
|
||||
other => Value::Error {
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
@ -5,13 +6,18 @@ use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::Category;
|
||||
use nu_protocol::Spanned;
|
||||
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value};
|
||||
use std::sync::Arc;
|
||||
|
||||
struct Arguments {
|
||||
end: bool,
|
||||
substring: String,
|
||||
range: Option<Value>,
|
||||
column_paths: Vec<CellPath>,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
}
|
||||
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -58,7 +64,16 @@ impl Command for SubCommand {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
operate(engine_state, stack, call, input)
|
||||
let substring: Spanned<String> = call.req(engine_state, stack, 0)?;
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let args = Arguments {
|
||||
substring: substring.item,
|
||||
range: call.get_flag(engine_state, stack, "range")?,
|
||||
end: call.has_flag("end"),
|
||||
cell_paths,
|
||||
};
|
||||
operate(action, args, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
@ -97,44 +112,6 @@ impl Command for SubCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn operate(
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let substring: Spanned<String> = call.req(engine_state, stack, 0)?;
|
||||
|
||||
let options = Arc::new(Arguments {
|
||||
substring: substring.item,
|
||||
range: call.get_flag(engine_state, stack, "range")?,
|
||||
end: call.has_flag("end"),
|
||||
column_paths: call.rest(engine_state, stack, 1)?,
|
||||
});
|
||||
let head = call.head;
|
||||
input.map(
|
||||
move |v| {
|
||||
if options.column_paths.is_empty() {
|
||||
action(&v, &options, head)
|
||||
} else {
|
||||
let mut ret = v;
|
||||
for path in &options.column_paths {
|
||||
let opt = options.clone();
|
||||
let r = ret.update_cell_path(
|
||||
&path.members,
|
||||
Box::new(move |old| action(old, &opt, head)),
|
||||
);
|
||||
if let Err(error) = r {
|
||||
return Value::Error { error };
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
},
|
||||
engine_state.ctrlc.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
fn action(
|
||||
input: &Value,
|
||||
Arguments {
|
||||
@ -294,7 +271,7 @@ mod tests {
|
||||
val: String::from(""),
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
column_paths: vec![],
|
||||
cell_paths: None,
|
||||
end: false,
|
||||
};
|
||||
|
||||
@ -316,7 +293,7 @@ mod tests {
|
||||
val: String::from(""),
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
column_paths: vec![],
|
||||
cell_paths: None,
|
||||
end: false,
|
||||
};
|
||||
|
||||
@ -339,7 +316,7 @@ mod tests {
|
||||
val: String::from("1"),
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
column_paths: vec![],
|
||||
cell_paths: None,
|
||||
end: false,
|
||||
};
|
||||
|
||||
@ -361,7 +338,7 @@ mod tests {
|
||||
val: String::from(",5"),
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
column_paths: vec![],
|
||||
cell_paths: None,
|
||||
end: false,
|
||||
};
|
||||
|
||||
@ -383,7 +360,7 @@ mod tests {
|
||||
val: String::from("2,6"),
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
column_paths: vec![],
|
||||
cell_paths: None,
|
||||
end: false,
|
||||
};
|
||||
|
||||
@ -405,7 +382,7 @@ mod tests {
|
||||
val: String::from("2,4"),
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
column_paths: vec![],
|
||||
cell_paths: None,
|
||||
end: false,
|
||||
};
|
||||
|
||||
|
@ -1,13 +1,23 @@
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::Category;
|
||||
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
|
||||
struct Arguments {
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
}
|
||||
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for SubCommand {
|
||||
fn name(&self) -> &str {
|
||||
"str length"
|
||||
@ -38,7 +48,10 @@ impl Command for SubCommand {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
operate(engine_state, stack, call, input)
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let args = Arguments { cell_paths };
|
||||
operate(action, args, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
@ -60,35 +73,7 @@ impl Command for SubCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn operate(
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let head = call.head;
|
||||
let column_paths: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
|
||||
input.map(
|
||||
move |v| {
|
||||
if column_paths.is_empty() {
|
||||
action(&v, head)
|
||||
} else {
|
||||
let mut ret = v;
|
||||
for path in &column_paths {
|
||||
let r =
|
||||
ret.update_cell_path(&path.members, Box::new(move |old| action(old, head)));
|
||||
if let Err(error) = r {
|
||||
return Value::Error { error };
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
},
|
||||
engine_state.ctrlc.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
fn action(input: &Value, head: Span) -> Value {
|
||||
fn action(input: &Value, _arg: &Arguments, head: Span) -> Value {
|
||||
match input {
|
||||
Value::String { val, .. } => Value::Int {
|
||||
val: val.len() as i64,
|
||||
|
@ -1,15 +1,21 @@
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::Category;
|
||||
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value};
|
||||
use std::sync::Arc;
|
||||
|
||||
struct Arguments {
|
||||
length: Option<i64>,
|
||||
character: Option<String>,
|
||||
column_paths: Vec<CellPath>,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
}
|
||||
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -52,7 +58,21 @@ impl Command for SubCommand {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
operate(engine_state, stack, call, input)
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let args = Arguments {
|
||||
length: call.get_flag(engine_state, stack, "length")?,
|
||||
character: call.get_flag(engine_state, stack, "character")?,
|
||||
cell_paths,
|
||||
};
|
||||
|
||||
if args.length.expect("this exists") < 0 {
|
||||
return Err(ShellError::UnsupportedInput(
|
||||
String::from("The length of the string cannot be negative"),
|
||||
call.head,
|
||||
));
|
||||
}
|
||||
operate(action, args, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
@ -93,49 +113,6 @@ impl Command for SubCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn operate(
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let options = Arc::new(Arguments {
|
||||
length: call.get_flag(engine_state, stack, "length")?,
|
||||
character: call.get_flag(engine_state, stack, "character")?,
|
||||
column_paths: call.rest(engine_state, stack, 0)?,
|
||||
});
|
||||
|
||||
if options.length.expect("this exists") < 0 {
|
||||
return Err(ShellError::UnsupportedInput(
|
||||
String::from("The length of the string cannot be negative"),
|
||||
call.head,
|
||||
));
|
||||
}
|
||||
|
||||
let head = call.head;
|
||||
input.map(
|
||||
move |v| {
|
||||
if options.column_paths.is_empty() {
|
||||
action(&v, &options, head)
|
||||
} else {
|
||||
let mut ret = v;
|
||||
for path in &options.column_paths {
|
||||
let opt = options.clone();
|
||||
let r = ret.update_cell_path(
|
||||
&path.members,
|
||||
Box::new(move |old| action(old, &opt, head)),
|
||||
);
|
||||
if let Err(error) = r {
|
||||
return Value::Error { error };
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
},
|
||||
engine_state.ctrlc.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
fn action(
|
||||
input: &Value,
|
||||
Arguments {
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use fancy_regex::{NoExpand, Regex};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::{
|
||||
@ -5,17 +6,22 @@ use nu_protocol::{
|
||||
engine::{Command, EngineState, Stack},
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
struct Arguments {
|
||||
all: bool,
|
||||
find: Spanned<String>,
|
||||
replace: Spanned<String>,
|
||||
column_paths: Vec<CellPath>,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
literal_replace: bool,
|
||||
no_regex: bool,
|
||||
}
|
||||
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
|
||||
@ -62,7 +68,22 @@ impl Command for SubCommand {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
operate(engine_state, stack, call, input)
|
||||
let find: Spanned<String> = call.req(engine_state, stack, 0)?;
|
||||
let replace: Spanned<String> = call.req(engine_state, stack, 1)?;
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 2)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let literal_replace = call.has_flag("no-expand");
|
||||
let no_regex = call.has_flag("string");
|
||||
|
||||
let args = Arguments {
|
||||
all: call.has_flag("all"),
|
||||
find,
|
||||
replace,
|
||||
cell_paths,
|
||||
literal_replace,
|
||||
no_regex,
|
||||
};
|
||||
operate(action, args, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
@ -154,50 +175,6 @@ impl Command for SubCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn operate(
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let head = call.head;
|
||||
let find: Spanned<String> = call.req(engine_state, stack, 0)?;
|
||||
let replace: Spanned<String> = call.req(engine_state, stack, 1)?;
|
||||
let literal_replace = call.has_flag("no-expand");
|
||||
let no_regex = call.has_flag("string");
|
||||
|
||||
let options = Arc::new(Arguments {
|
||||
all: call.has_flag("all"),
|
||||
find,
|
||||
replace,
|
||||
column_paths: call.rest(engine_state, stack, 2)?,
|
||||
literal_replace,
|
||||
no_regex,
|
||||
});
|
||||
|
||||
input.map(
|
||||
move |v| {
|
||||
if options.column_paths.is_empty() {
|
||||
action(&v, &options, head)
|
||||
} else {
|
||||
let mut ret = v;
|
||||
for path in &options.column_paths {
|
||||
let opt = options.clone();
|
||||
let r = ret.update_cell_path(
|
||||
&path.members,
|
||||
Box::new(move |old| action(old, &opt, head)),
|
||||
);
|
||||
if let Err(error) = r {
|
||||
return Value::Error { error };
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
},
|
||||
engine_state.ctrlc.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
struct FindReplace<'a>(&'a str, &'a str);
|
||||
|
||||
fn action(
|
||||
@ -305,7 +282,7 @@ mod tests {
|
||||
let options = Arguments {
|
||||
find: test_spanned_string("Cargo.(.+)"),
|
||||
replace: test_spanned_string("Carga.$1"),
|
||||
column_paths: vec![],
|
||||
cell_paths: None,
|
||||
literal_replace: false,
|
||||
all: false,
|
||||
no_regex: false,
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
@ -8,6 +9,16 @@ use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShap
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
|
||||
struct Arguments {
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
}
|
||||
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for SubCommand {
|
||||
fn name(&self) -> &str {
|
||||
"str reverse"
|
||||
@ -38,7 +49,10 @@ impl Command for SubCommand {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
operate(engine_state, stack, call, input)
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let args = Arguments { cell_paths };
|
||||
operate(action, args, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
@ -76,35 +90,7 @@ impl Command for SubCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn operate(
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let head = call.head;
|
||||
let column_paths: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
|
||||
input.map(
|
||||
move |v| {
|
||||
if column_paths.is_empty() {
|
||||
action(&v, head)
|
||||
} else {
|
||||
let mut ret = v;
|
||||
for path in &column_paths {
|
||||
let r =
|
||||
ret.update_cell_path(&path.members, Box::new(move |old| action(old, head)));
|
||||
if let Err(error) = r {
|
||||
return Value::Error { error };
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
},
|
||||
engine_state.ctrlc.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
fn action(input: &Value, head: Span) -> Value {
|
||||
fn action(input: &Value, _arg: &Arguments, head: Span) -> Value {
|
||||
match input {
|
||||
Value::String { val, .. } => Value::String {
|
||||
val: val.chars().rev().collect::<String>(),
|
||||
|
@ -1,15 +1,21 @@
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::Category;
|
||||
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value};
|
||||
use std::sync::Arc;
|
||||
|
||||
struct Arguments {
|
||||
length: Option<i64>,
|
||||
character: Option<String>,
|
||||
column_paths: Vec<CellPath>,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
}
|
||||
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -52,7 +58,21 @@ impl Command for SubCommand {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
operate(engine_state, stack, call, input)
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let args = Arguments {
|
||||
length: call.get_flag(engine_state, stack, "length")?,
|
||||
character: call.get_flag(engine_state, stack, "character")?,
|
||||
cell_paths,
|
||||
};
|
||||
|
||||
if args.length.expect("this exists") < 0 {
|
||||
return Err(ShellError::UnsupportedInput(
|
||||
String::from("The length of the string cannot be negative"),
|
||||
call.head,
|
||||
));
|
||||
}
|
||||
operate(action, args, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
@ -93,49 +113,6 @@ impl Command for SubCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn operate(
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let options = Arc::new(Arguments {
|
||||
length: call.get_flag(engine_state, stack, "length")?,
|
||||
character: call.get_flag(engine_state, stack, "character")?,
|
||||
column_paths: call.rest(engine_state, stack, 0)?,
|
||||
});
|
||||
|
||||
if options.length.expect("this exists") < 0 {
|
||||
return Err(ShellError::UnsupportedInput(
|
||||
String::from("The length of the string cannot be negative"),
|
||||
call.head,
|
||||
));
|
||||
}
|
||||
|
||||
let head = call.head;
|
||||
input.map(
|
||||
move |v| {
|
||||
if options.column_paths.is_empty() {
|
||||
action(&v, &options, head)
|
||||
} else {
|
||||
let mut ret = v;
|
||||
for path in &options.column_paths {
|
||||
let opt = options.clone();
|
||||
let r = ret.update_cell_path(
|
||||
&path.members,
|
||||
Box::new(move |old| action(old, &opt, head)),
|
||||
);
|
||||
if let Err(error) = r {
|
||||
return Value::Error { error };
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
},
|
||||
engine_state.ctrlc.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
fn action(
|
||||
input: &Value,
|
||||
Arguments {
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
@ -5,11 +6,16 @@ use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::Category;
|
||||
use nu_protocol::Spanned;
|
||||
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value};
|
||||
use std::sync::Arc;
|
||||
|
||||
struct Arguments {
|
||||
substring: String,
|
||||
column_paths: Vec<CellPath>,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
}
|
||||
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -47,7 +53,14 @@ impl Command for SubCommand {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
operate(engine_state, stack, call, input)
|
||||
let substring: Spanned<String> = call.req(engine_state, stack, 0)?;
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let args = Arguments {
|
||||
substring: substring.item,
|
||||
cell_paths,
|
||||
};
|
||||
operate(action, args, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
@ -80,42 +93,6 @@ impl Command for SubCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn operate(
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let substring: Spanned<String> = call.req(engine_state, stack, 0)?;
|
||||
|
||||
let options = Arc::new(Arguments {
|
||||
substring: substring.item,
|
||||
column_paths: call.rest(engine_state, stack, 1)?,
|
||||
});
|
||||
let head = call.head;
|
||||
input.map(
|
||||
move |v| {
|
||||
if options.column_paths.is_empty() {
|
||||
action(&v, &options, head)
|
||||
} else {
|
||||
let mut ret = v;
|
||||
for path in &options.column_paths {
|
||||
let opt = options.clone();
|
||||
let r = ret.update_cell_path(
|
||||
&path.members,
|
||||
Box::new(move |old| action(old, &opt, head)),
|
||||
);
|
||||
if let Err(error) = r {
|
||||
return Value::Error { error };
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
},
|
||||
engine_state.ctrlc.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
fn action(input: &Value, Arguments { substring, .. }: &Arguments, head: Span) -> Value {
|
||||
match input {
|
||||
Value::String { val: s, .. } => {
|
||||
|
@ -1,17 +1,23 @@
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::ast::CellPath;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value};
|
||||
use std::cmp::Ordering;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
|
||||
struct Arguments {
|
||||
range: Value,
|
||||
column_paths: Vec<CellPath>,
|
||||
indexes: Substring,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
}
|
||||
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -59,7 +65,15 @@ impl Command for SubCommand {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
operate(engine_state, stack, call, input)
|
||||
let range = call.req(engine_state, stack, 0)?;
|
||||
let indexes: Substring = process_arguments(&range, call.head)?.into();
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let args = Arguments {
|
||||
indexes,
|
||||
cell_paths,
|
||||
};
|
||||
operate(action, args, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
@ -99,44 +113,8 @@ impl Command for SubCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn operate(
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let options = Arc::new(Arguments {
|
||||
range: call.req(engine_state, stack, 0)?,
|
||||
column_paths: call.rest(engine_state, stack, 1)?,
|
||||
});
|
||||
|
||||
let head = call.head;
|
||||
let indexes: Arc<Substring> = Arc::new(process_arguments(&options, head)?.into());
|
||||
|
||||
input.map(
|
||||
move |v| {
|
||||
if options.column_paths.is_empty() {
|
||||
action(&v, &indexes, head)
|
||||
} else {
|
||||
let mut ret = v;
|
||||
for path in &options.column_paths {
|
||||
let indexes = indexes.clone();
|
||||
let r = ret.update_cell_path(
|
||||
&path.members,
|
||||
Box::new(move |old| action(old, &indexes, head)),
|
||||
);
|
||||
if let Err(error) = r {
|
||||
return Value::Error { error };
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
},
|
||||
engine_state.ctrlc.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
fn action(input: &Value, options: &Substring, head: Span) -> Value {
|
||||
fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
||||
let options = &args.indexes;
|
||||
match input {
|
||||
Value::String { val: s, .. } => {
|
||||
let len: isize = s.len() as isize;
|
||||
@ -203,8 +181,8 @@ fn action(input: &Value, options: &Substring, head: Span) -> Value {
|
||||
}
|
||||
}
|
||||
|
||||
fn process_arguments(options: &Arguments, head: Span) -> Result<(isize, isize), ShellError> {
|
||||
let search = match &options.range {
|
||||
fn process_arguments(range: &Value, head: Span) -> Result<(isize, isize), ShellError> {
|
||||
let search = match range {
|
||||
Value::Range { val, .. } => {
|
||||
let start = val.from()?;
|
||||
let end = val.to()?;
|
||||
@ -357,7 +335,14 @@ mod tests {
|
||||
|
||||
for expectation in &cases {
|
||||
let expected = expectation.expected;
|
||||
let actual = action(&word, &expectation.options(), Span::test_data());
|
||||
let actual = action(
|
||||
&word,
|
||||
&super::Arguments {
|
||||
indexes: expectation.options(),
|
||||
cell_paths: None,
|
||||
},
|
||||
Span::test_data(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
actual,
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::input_handler::{operate, CmdArgument};
|
||||
use fancy_regex::Regex;
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::{
|
||||
@ -10,8 +11,16 @@ use nu_protocol::{
|
||||
pub struct SubCommand;
|
||||
|
||||
struct Arguments {
|
||||
character: Option<Spanned<String>>,
|
||||
column_paths: Vec<CellPath>,
|
||||
to_trim: Option<char>,
|
||||
closure_flags: ClosureFlags,
|
||||
cell_paths: Option<Vec<CellPath>>,
|
||||
mode: ActionMode,
|
||||
}
|
||||
|
||||
impl CmdArgument for Arguments {
|
||||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
|
||||
self.cell_paths.take()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Copy, Clone)]
|
||||
@ -74,7 +83,45 @@ impl Command for SubCommand {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||
operate(engine_state, stack, call, input, &trim)
|
||||
let character = call.get_flag::<Spanned<String>>(engine_state, stack, "char")?;
|
||||
let to_trim = match character.as_ref() {
|
||||
Some(v) => {
|
||||
if v.item.chars().count() > 1 {
|
||||
return Err(ShellError::GenericError(
|
||||
"Trim only works with single character".into(),
|
||||
"needs single character".into(),
|
||||
Some(v.span),
|
||||
None,
|
||||
Vec::new(),
|
||||
));
|
||||
}
|
||||
v.item.chars().next()
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then(|| cell_paths);
|
||||
let mode = match cell_paths {
|
||||
None => ActionMode::Global,
|
||||
Some(_) => ActionMode::Local,
|
||||
};
|
||||
let args = Arguments {
|
||||
to_trim,
|
||||
closure_flags: ClosureFlags {
|
||||
all_flag: call.has_flag("all"),
|
||||
left_trim: call.has_flag("left"),
|
||||
right_trim: call.has_flag("right"),
|
||||
format_flag: call.has_flag("format"),
|
||||
both_flag: call.has_flag("both")
|
||||
|| (!call.has_flag("all")
|
||||
&& !call.has_flag("left")
|
||||
&& !call.has_flag("right")
|
||||
&& !call.has_flag("format")), // this is the case if no flags are provided
|
||||
},
|
||||
cell_paths,
|
||||
mode,
|
||||
};
|
||||
operate(action, args, input, call.head, engine_state.ctrlc.clone())
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
@ -118,118 +165,25 @@ impl Command for SubCommand {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn operate<F>(
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
trim_operation: &'static F,
|
||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError>
|
||||
where
|
||||
F: Fn(&str, Option<char>, &ClosureFlags) -> String + Send + Sync + 'static,
|
||||
{
|
||||
let head = call.head;
|
||||
let (options, closure_flags, input) = (
|
||||
Arguments {
|
||||
character: call.get_flag(engine_state, stack, "char")?,
|
||||
column_paths: call.rest(engine_state, stack, 0)?,
|
||||
},
|
||||
ClosureFlags {
|
||||
all_flag: call.has_flag("all"),
|
||||
left_trim: call.has_flag("left"),
|
||||
right_trim: call.has_flag("right"),
|
||||
format_flag: call.has_flag("format"),
|
||||
both_flag: call.has_flag("both")
|
||||
|| (!call.has_flag("all")
|
||||
&& !call.has_flag("left")
|
||||
&& !call.has_flag("right")
|
||||
&& !call.has_flag("format")), // this is the case if no flags are provided
|
||||
},
|
||||
input,
|
||||
);
|
||||
let to_trim = match options.character.as_ref() {
|
||||
Some(v) => {
|
||||
if v.item.chars().count() > 1 {
|
||||
return Err(ShellError::GenericError(
|
||||
"Trim only works with single character".into(),
|
||||
"needs single character".into(),
|
||||
Some(v.span),
|
||||
None,
|
||||
Vec::new(),
|
||||
));
|
||||
}
|
||||
v.item.chars().next()
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
input.map(
|
||||
move |v| {
|
||||
if options.column_paths.is_empty() {
|
||||
action(
|
||||
&v,
|
||||
head,
|
||||
to_trim,
|
||||
&closure_flags,
|
||||
&trim_operation,
|
||||
ActionMode::Global,
|
||||
)
|
||||
} else {
|
||||
let mut ret = v;
|
||||
for path in &options.column_paths {
|
||||
let r = ret.update_cell_path(
|
||||
&path.members,
|
||||
Box::new(move |old| {
|
||||
action(
|
||||
old,
|
||||
head,
|
||||
to_trim,
|
||||
&closure_flags,
|
||||
&trim_operation,
|
||||
ActionMode::Local,
|
||||
)
|
||||
}),
|
||||
);
|
||||
if let Err(error) = r {
|
||||
return Value::Error { error };
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
},
|
||||
engine_state.ctrlc.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum ActionMode {
|
||||
Local,
|
||||
Global,
|
||||
}
|
||||
|
||||
pub fn action<F>(
|
||||
input: &Value,
|
||||
head: Span,
|
||||
char_: Option<char>,
|
||||
closure_flags: &ClosureFlags,
|
||||
trim_operation: &F,
|
||||
mode: ActionMode,
|
||||
) -> Value
|
||||
where
|
||||
F: Fn(&str, Option<char>, &ClosureFlags) -> String + Send + Sync + 'static,
|
||||
{
|
||||
fn action(input: &Value, arg: &Arguments, head: Span) -> Value {
|
||||
let char_ = arg.to_trim;
|
||||
let closure_flags = &arg.closure_flags;
|
||||
let mode = &arg.mode;
|
||||
match input {
|
||||
Value::String { val: s, .. } => Value::String {
|
||||
val: trim_operation(s, char_, closure_flags),
|
||||
val: trim(s, char_, closure_flags),
|
||||
span: head,
|
||||
},
|
||||
other => match mode {
|
||||
ActionMode::Global => match other {
|
||||
Value::Record { cols, vals, span } => {
|
||||
let new_vals = vals
|
||||
.iter()
|
||||
.map(|v| action(v, head, char_, closure_flags, trim_operation, mode))
|
||||
.collect();
|
||||
let new_vals = vals.iter().map(|v| action(v, arg, head)).collect();
|
||||
|
||||
Value::Record {
|
||||
cols: cols.to_vec(),
|
||||
@ -238,10 +192,7 @@ where
|
||||
}
|
||||
}
|
||||
Value::List { vals, span } => {
|
||||
let new_vals = vals
|
||||
.iter()
|
||||
.map(|v| action(v, head, char_, closure_flags, trim_operation, mode))
|
||||
.collect();
|
||||
let new_vals = vals.iter().map(|v| action(v, arg, head)).collect();
|
||||
|
||||
Value::List {
|
||||
vals: new_vals,
|
||||
@ -374,14 +325,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Local,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Local,
|
||||
};
|
||||
let actual = action(&word, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -393,15 +343,13 @@ mod tests {
|
||||
both_flag: true,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
let actual = action(&word, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -413,15 +361,14 @@ mod tests {
|
||||
both_flag: true,
|
||||
..Default::default()
|
||||
};
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&number,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let actual = action(&number, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -435,14 +382,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&row,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
let actual = action(&row, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -455,14 +401,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&row,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
let actual = action(&row, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -475,14 +420,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
Span::test_data(),
|
||||
Some('!'),
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Local,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: Some('!'),
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Local,
|
||||
};
|
||||
let actual = action(&word, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
#[test]
|
||||
@ -494,14 +438,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
Span::test_data(),
|
||||
Some(' '),
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Local,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: Some(' '),
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Local,
|
||||
};
|
||||
let actual = action(&word, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -517,15 +460,13 @@ mod tests {
|
||||
all_flag: true,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&row,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
let actual = action(&row, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -571,14 +512,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&row,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
let actual = action(&row, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -591,14 +531,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
Span::test_data(),
|
||||
Some('.'),
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Local,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: Some('.'),
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Local,
|
||||
};
|
||||
let actual = action(&word, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -611,14 +550,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&row,
|
||||
Span::test_data(),
|
||||
Some('!'),
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: Some('!'),
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
let actual = action(&row, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -664,14 +602,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&row,
|
||||
Span::test_data(),
|
||||
Some('#'),
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: Some('#'),
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
let actual = action(&row, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -684,14 +621,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Local,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Local,
|
||||
};
|
||||
let actual = action(&word, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -704,14 +640,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&number,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
let actual = action(&number, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -724,14 +659,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
let actual = action(&word, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -744,14 +678,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&row,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
let actual = action(&row, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -796,15 +729,13 @@ mod tests {
|
||||
left_trim: true,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&row,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
let actual = action(&row, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -817,14 +748,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
Span::test_data(),
|
||||
Some('!'),
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Local,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: Some('!'),
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Local,
|
||||
};
|
||||
let actual = action(&word, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
#[test]
|
||||
@ -835,15 +765,13 @@ mod tests {
|
||||
right_trim: true,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Local,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Local,
|
||||
};
|
||||
let actual = action(&word, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -855,15 +783,13 @@ mod tests {
|
||||
right_trim: true,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
let actual = action(&word, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -876,14 +802,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&number,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
let actual = action(&number, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -896,14 +821,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&row,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
let actual = action(&row, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -949,14 +873,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&row,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
let actual = action(&row, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -969,14 +892,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
Span::test_data(),
|
||||
Some('#'),
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Local,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: Some('#'),
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Local,
|
||||
};
|
||||
let actual = action(&word, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -989,14 +911,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
Span::test_data(),
|
||||
Some(' '),
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Local,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: Some(' '),
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Local,
|
||||
};
|
||||
let actual = action(&word, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -1008,15 +929,13 @@ mod tests {
|
||||
format_flag: true,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
Span::test_data(),
|
||||
Some(' '),
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Local,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: Some(' '),
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Local,
|
||||
};
|
||||
let actual = action(&word, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
#[test]
|
||||
@ -1028,14 +947,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&number,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
let actual = action(&number, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -1048,14 +966,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&row,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
let actual = action(&row, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -1101,14 +1018,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&row,
|
||||
Span::test_data(),
|
||||
None,
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
let actual = action(&row, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -1121,14 +1037,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
Span::test_data(),
|
||||
Some('.'),
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Local,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: Some('.'),
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Local,
|
||||
};
|
||||
let actual = action(&word, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -1142,14 +1057,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
Span::test_data(),
|
||||
Some(' '),
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Local,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: Some(' '),
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Local,
|
||||
};
|
||||
let actual = action(&word, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@ -1163,14 +1077,13 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
Span::test_data(),
|
||||
Some(' '),
|
||||
&closure_flags,
|
||||
&trim,
|
||||
ActionMode::Global,
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: Some(' '),
|
||||
closure_flags,
|
||||
cell_paths: None,
|
||||
mode: ActionMode::Global,
|
||||
};
|
||||
let actual = action(&word, &args, Span::test_data());
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ fn format_filesize_works() {
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
ls
|
||||
| format filesize size KB
|
||||
| format filesize KB size
|
||||
| get size
|
||||
| first
|
||||
"#
|
||||
@ -80,7 +80,7 @@ fn format_filesize_works_with_nonempty_files() {
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(),
|
||||
"ls sample.toml | format filesize size B | get size | first"
|
||||
"ls sample.toml | format filesize B size | get size | first"
|
||||
);
|
||||
|
||||
#[cfg(not(windows))]
|
||||
|
Loading…
Reference in New Issue
Block a user