Fix incorrect handling of boolean flags for builtin commands (#11492)

# Description
Possible fix of #11456
This PR fixes a bug where builtin commands did not respect the logic of
dynamically passed boolean flags. The reason is
[has_flag](6f59abaf43/crates/nu-protocol/src/ast/call.rs (L204C5-L212C6))
method did not evaluate and take into consideration expression used with
flag.

To address this issue a solution is proposed:
1. `has_flag` method is moved to `CallExt` and new logic to evaluate
expression and check if it is a boolean value is added
2. `has_flag_const` method is added to `CallExt` which is a constant
version of `has_flag`
3. `has_named` method is added to `Call` which is basically the old
logic of `has_flag`
4. All usages of `has_flag` in code are updated, mostly to pass
`engine_state` and `stack` to new `has_flag`. In `run_const` commands it
is replaced with `has_flag_const`. And in a few select places: parser,
`to nuon` and `into string` old logic via `has_named` is used.

# User-Facing Changes
Explicit values of boolean flags are now respected in builtin commands.
Before:

![image](https://github.com/nushell/nushell/assets/17511668/f9fbabb2-3cfd-43f9-ba9e-ece76d80043c)
After:

![image](https://github.com/nushell/nushell/assets/17511668/21867596-2075-437f-9c85-45563ac70083)

Another example:
Before:

![image](https://github.com/nushell/nushell/assets/17511668/efdbc5ca-5227-45a4-ac5b-532cdc2bbf5f)
After:

![image](https://github.com/nushell/nushell/assets/17511668/2907d5c5-aa93-404d-af1c-21cdc3d44646)


# Tests + Formatting
Added test reproducing some variants of original issue.
This commit is contained in:
Artemiy 2024-01-11 18:19:48 +03:00 committed by GitHub
parent 62272975f2
commit 1867bb1a88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
149 changed files with 771 additions and 504 deletions

View File

@ -71,7 +71,7 @@ impl Command for Commandline {
if let Some(cmd) = call.opt::<Value>(engine_state, stack, 0)? {
let mut repl = engine_state.repl_state.lock().expect("repl state mutex");
if call.has_flag("cursor") {
if call.has_flag(engine_state, stack, "cursor")? {
let cmd_str = cmd.as_string()?;
match cmd_str.parse::<i64>() {
Ok(n) => {
@ -96,9 +96,9 @@ impl Command for Commandline {
})
}
}
} else if call.has_flag("append") {
} else if call.has_flag(engine_state, stack, "append")? {
repl.buffer.push_str(&cmd.as_string()?);
} else if call.has_flag("insert") {
} else if call.has_flag(engine_state, stack, "insert")? {
let cmd_str = cmd.as_string()?;
let cursor_pos = repl.cursor_pos;
repl.buffer.insert_str(cursor_pos, &cmd_str);
@ -110,10 +110,10 @@ impl Command for Commandline {
Ok(Value::nothing(call.head).into_pipeline_data())
} else {
let mut repl = engine_state.repl_state.lock().expect("repl state mutex");
if call.has_flag("cursor-end") {
if call.has_flag(engine_state, stack, "cursor-end")? {
repl.cursor_pos = repl.buffer.graphemes(true).count();
Ok(Value::nothing(call.head).into_pipeline_data())
} else if call.has_flag("cursor") {
} else if call.has_flag(engine_state, stack, "cursor")? {
let char_pos = repl
.buffer
.grapheme_indices(true)

View File

@ -1,3 +1,4 @@
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
@ -40,7 +41,7 @@ impl Command for History {
fn run(
&self,
engine_state: &EngineState,
_stack: &mut Stack,
stack: &mut Stack,
call: &Call,
_input: PipelineData,
) -> Result<PipelineData, ShellError> {
@ -48,8 +49,8 @@ impl Command for History {
// todo for sqlite history this command should be an alias to `open ~/.config/nushell/history.sqlite3 | get history`
if let Some(config_path) = nu_path::config_dir() {
let clear = call.has_flag("clear");
let long = call.has_flag("long");
let clear = call.has_flag(engine_state, stack, "clear")?;
let long = call.has_flag(engine_state, stack, "long")?;
let ctrlc = engine_state.ctrlc.clone();
let mut history_path = config_path;

View File

@ -54,8 +54,8 @@ Since this command has no output, there is no point in piping it with other comm
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let args: Vec<Value> = call.rest(engine_state, stack, 0)?;
let no_newline = call.has_flag("no-newline");
let to_stderr = call.has_flag("stderr");
let no_newline = call.has_flag(engine_state, stack, "no-newline")?;
let to_stderr = call.has_flag(engine_state, stack, "stderr")?;
// This will allow for easy printing of pipelines as well
if !args.is_empty() {

View File

@ -110,7 +110,7 @@ fn command(
) -> Result<PipelineData, ShellError> {
let other: Value = call.req(engine_state, stack, 0)?;
let axis = if call.has_flag("col") {
let axis = if call.has_flag(engine_state, stack, "col")? {
Axis::Column
} else {
Axis::Row

View File

@ -92,7 +92,7 @@ fn command(
let subset_slice = subset.as_ref().map(|cols| &cols[..]);
let keep_strategy = if call.has_flag("last") {
let keep_strategy = if call.has_flag(engine_state, stack, "last")? {
UniqueKeepStrategy::Last
} else {
UniqueKeepStrategy::First

View File

@ -1,4 +1,5 @@
use super::super::values::NuDataFrame;
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
@ -78,12 +79,12 @@ impl Command for Dummies {
}
fn command(
_engine_state: &EngineState,
_stack: &mut Stack,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let drop_first: bool = call.has_flag("drop-first");
let drop_first: bool = call.has_flag(engine_state, stack, "drop-first")?;
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
df.as_ref()

View File

@ -139,7 +139,7 @@ fn from_parquet(
stack: &mut Stack,
call: &Call,
) -> Result<Value, ShellError> {
if call.has_flag("lazy") {
if call.has_flag(engine_state, stack, "lazy")? {
let file: String = call.req(engine_state, stack, 0)?;
let args = ScanArgsParquet {
n_rows: None,
@ -238,7 +238,7 @@ fn from_ipc(
stack: &mut Stack,
call: &Call,
) -> Result<Value, ShellError> {
if call.has_flag("lazy") {
if call.has_flag(engine_state, stack, "lazy")? {
let file: String = call.req(engine_state, stack, 0)?;
let args = ScanArgsIpc {
n_rows: None,
@ -363,12 +363,12 @@ fn from_csv(
call: &Call,
) -> Result<Value, ShellError> {
let delimiter: Option<Spanned<String>> = call.get_flag(engine_state, stack, "delimiter")?;
let no_header: bool = call.has_flag("no-header");
let no_header: bool = call.has_flag(engine_state, stack, "no-header")?;
let infer_schema: Option<usize> = call.get_flag(engine_state, stack, "infer-schema")?;
let skip_rows: Option<usize> = call.get_flag(engine_state, stack, "skip-rows")?;
let columns: Option<Vec<String>> = call.get_flag(engine_state, stack, "columns")?;
if call.has_flag("lazy") {
if call.has_flag(engine_state, stack, "lazy")? {
let file: String = call.req(engine_state, stack, 0)?;
let csv_reader = LazyCsvReader::new(file);

View File

@ -88,8 +88,8 @@ fn command(
let seed: Option<u64> = call
.get_flag::<i64>(engine_state, stack, "seed")?
.map(|val| val as u64);
let replace: bool = call.has_flag("replace");
let shuffle: bool = call.has_flag("shuffle");
let replace: bool = call.has_flag(engine_state, stack, "replace")?;
let shuffle: bool = call.has_flag(engine_state, stack, "shuffle")?;
let df = NuDataFrame::try_from_pipeline(input, call.head)?;

View File

@ -70,7 +70,7 @@ fn command(
) -> Result<PipelineData, ShellError> {
let file_name: Spanned<PathBuf> = call.req(engine_state, stack, 0)?;
let delimiter: Option<Spanned<String>> = call.get_flag(engine_state, stack, "delimiter")?;
let no_header: bool = call.has_flag("no-header");
let no_header: bool = call.has_flag(engine_state, stack, "no-header")?;
let mut df = NuDataFrame::try_from_pipeline(input, call.head)?;

View File

@ -100,7 +100,7 @@ fn dataframe_command(
input: Value,
) -> Result<PipelineData, ShellError> {
let rows: Option<usize> = call.get_flag(engine_state, stack, "rows")?;
let tail: bool = call.has_flag("tail");
let tail: bool = call.has_flag(engine_state, stack, "tail")?;
let df = NuDataFrame::try_from_value(input)?;

View File

@ -171,9 +171,9 @@ impl Command for LazyJoin {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let left = call.has_flag("left");
let outer = call.has_flag("outer");
let cross = call.has_flag("cross");
let left = call.has_flag(engine_state, stack, "left")?;
let outer = call.has_flag(engine_state, stack, "outer")?;
let cross = call.has_flag(engine_state, stack, "cross")?;
let how = if left {
JoinType::Left

View File

@ -107,8 +107,8 @@ impl Command for LazySortBy {
let vals: Vec<Value> = call.rest(engine_state, stack, 0)?;
let value = Value::list(vals, call.head);
let expressions = NuExpression::extract_exprs(value)?;
let nulls_last = call.has_flag("nulls-last");
let maintain_order = call.has_flag("maintain-order");
let nulls_last = call.has_flag(engine_state, stack, "nulls-last")?;
let maintain_order = call.has_flag(engine_state, stack, "maintain-order")?;
let reverse: Option<Vec<bool>> = call.get_flag(engine_state, stack, "reverse")?;
let reverse = match reverse {

View File

@ -103,7 +103,7 @@ fn command(
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let cum_type: Spanned<String> = call.req(engine_state, stack, 0)?;
let reverse = call.has_flag("reverse");
let reverse = call.has_flag(engine_state, stack, "reverse")?;
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let series = df.as_series(call.head)?;

View File

@ -64,7 +64,7 @@ fn command(
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let format: String = call.req(engine_state, stack, 0)?;
let not_exact = call.has_flag("not-exact");
let not_exact = call.has_flag(engine_state, stack, "not-exact")?;
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let series = df.as_series(call.head)?;

View File

@ -128,7 +128,7 @@ fn command(
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let format: String = call.req(engine_state, stack, 0)?;
let not_exact = call.has_flag("not-exact");
let not_exact = call.has_flag(engine_state, stack, "not-exact")?;
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let series = df.as_series(call.head)?;

View File

@ -1,5 +1,6 @@
use super::super::super::values::{Column, NuDataFrame};
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
@ -92,18 +93,18 @@ impl Command for ArgSort {
}
fn command(
_engine_state: &EngineState,
_stack: &mut Stack,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let sort_options = SortOptions {
descending: call.has_flag("reverse"),
nulls_last: call.has_flag("nulls-last"),
descending: call.has_flag(engine_state, stack, "reverse")?,
nulls_last: call.has_flag(engine_state, stack, "nulls-last")?,
multithreaded: true,
maintain_order: call.has_flag("maintain-order"),
maintain_order: call.has_flag(engine_state, stack, "maintain-order")?,
};
let mut res = df

View File

@ -114,8 +114,8 @@ fn command_lazy(
call: &Call,
lazy: NuLazyFrame,
) -> Result<PipelineData, ShellError> {
let last = call.has_flag("last");
let maintain = call.has_flag("maintain-order");
let last = call.has_flag(engine_state, stack, "last")?;
let maintain = call.has_flag(engine_state, stack, "maintain-order")?;
let subset: Option<Value> = call.get_flag(engine_state, stack, "subset")?;
let subset = match subset {

View File

@ -54,7 +54,7 @@ impl Command for BitsNot {
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let signed = call.has_flag("signed");
let signed = call.has_flag(engine_state, stack, "signed")?;
let number_bytes: Option<Spanned<String>> =
call.get_flag(engine_state, stack, "number-bytes")?;
let bytes_len = get_number_bytes(number_bytes.as_ref());

View File

@ -57,7 +57,7 @@ impl Command for BitsRol {
) -> Result<PipelineData, ShellError> {
let head = call.head;
let bits: usize = call.req(engine_state, stack, 0)?;
let signed = call.has_flag("signed");
let signed = call.has_flag(engine_state, stack, "signed")?;
let number_bytes: Option<Spanned<String>> =
call.get_flag(engine_state, stack, "number-bytes")?;
let bytes_len = get_number_bytes(number_bytes.as_ref());

View File

@ -57,7 +57,7 @@ impl Command for BitsRor {
) -> Result<PipelineData, ShellError> {
let head = call.head;
let bits: usize = call.req(engine_state, stack, 0)?;
let signed = call.has_flag("signed");
let signed = call.has_flag(engine_state, stack, "signed")?;
let number_bytes: Option<Spanned<String>> =
call.get_flag(engine_state, stack, "number-bytes")?;
let bytes_len = get_number_bytes(number_bytes.as_ref());

View File

@ -57,7 +57,7 @@ impl Command for BitsShl {
) -> Result<PipelineData, ShellError> {
let head = call.head;
let bits: usize = call.req(engine_state, stack, 0)?;
let signed = call.has_flag("signed");
let signed = call.has_flag(engine_state, stack, "signed")?;
let number_bytes: Option<Spanned<String>> =
call.get_flag(engine_state, stack, "number-bytes")?;
let bytes_len = get_number_bytes(number_bytes.as_ref());

View File

@ -57,7 +57,7 @@ impl Command for BitsShr {
) -> Result<PipelineData, ShellError> {
let head = call.head;
let bits: usize = call.req(engine_state, stack, 0)?;
let signed = call.has_flag("signed");
let signed = call.has_flag(engine_state, stack, "signed")?;
let number_bytes: Option<Spanned<String>> =
call.get_flag(engine_state, stack, "number-bytes")?;
let bytes_len = get_number_bytes(number_bytes.as_ref());

View File

@ -100,7 +100,7 @@ impl Command for RollLeft {
let by: Option<usize> = call.get_flag(engine_state, stack, "by")?;
let metadata = input.metadata();
let cells_only = call.has_flag("cells-only");
let cells_only = call.has_flag(engine_state, stack, "cells-only")?;
let value = input.into_value(call.head);
let rotated_value =
horizontal_rotate_value(value, by, cells_only, &HorizontalDirection::Left)?;

View File

@ -100,7 +100,7 @@ impl Command for RollRight {
let by: Option<usize> = call.get_flag(engine_state, stack, "by")?;
let metadata = input.metadata();
let cells_only = call.has_flag("cells-only");
let cells_only = call.has_flag(engine_state, stack, "cells-only")?;
let value = input.into_value(call.head);
let rotated_value =
horizontal_rotate_value(value, by, cells_only, &HorizontalDirection::Right)?;

View File

@ -167,7 +167,7 @@ pub fn rotate(
let mut new_values = vec![];
let mut not_a_record = false;
let mut total_rows = values.len();
let ccw: bool = call.has_flag("ccw");
let ccw: bool = call.has_flag(engine_state, stack, "ccw")?;
if !ccw {
values.reverse();

View File

@ -239,11 +239,11 @@ fn to_html(
stack: &mut Stack,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let html_color = call.has_flag("html-color");
let no_color = call.has_flag("no-color");
let dark = call.has_flag("dark");
let partial = call.has_flag("partial");
let list = call.has_flag("list");
let html_color = call.has_flag(engine_state, stack, "html-color")?;
let no_color = call.has_flag(engine_state, stack, "no-color")?;
let dark = call.has_flag(engine_state, stack, "dark")?;
let partial = call.has_flag(engine_state, stack, "partial")?;
let list = call.has_flag(engine_state, stack, "list")?;
let theme: Option<Spanned<String>> = call.get_flag(engine_state, stack, "theme")?;
let config = engine_state.get_config();

View File

@ -1,3 +1,4 @@
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Span, Type, Value};
@ -35,12 +36,12 @@ impl Command for SubCommand {
fn run(
&self,
engine_state: &EngineState,
_stack: &mut Stack,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let use_degrees = call.has_flag("degrees");
let use_degrees = call.has_flag(engine_state, stack, "degrees")?;
// This doesn't match explicit nulls
if matches!(input, PipelineData::Empty) {
return Err(ShellError::PipelineEmpty { dst_span: head });

View File

@ -1,3 +1,4 @@
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Span, Type, Value};
@ -35,12 +36,12 @@ impl Command for SubCommand {
fn run(
&self,
engine_state: &EngineState,
_stack: &mut Stack,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let use_degrees = call.has_flag("degrees");
let use_degrees = call.has_flag(engine_state, stack, "degrees")?;
// This doesn't match explicit nulls
if matches!(input, PipelineData::Empty) {
return Err(ShellError::PipelineEmpty { dst_span: head });

View File

@ -1,3 +1,4 @@
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Span, Type, Value};
@ -35,12 +36,12 @@ impl Command for SubCommand {
fn run(
&self,
engine_state: &EngineState,
_stack: &mut Stack,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let use_degrees = call.has_flag("degrees");
let use_degrees = call.has_flag(engine_state, stack, "degrees")?;
// This doesn't match explicit nulls
if matches!(input, PipelineData::Empty) {
return Err(ShellError::PipelineEmpty { dst_span: head });

View File

@ -1,3 +1,4 @@
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Span, Type, Value};
@ -34,12 +35,12 @@ impl Command for SubCommand {
fn run(
&self,
engine_state: &EngineState,
_stack: &mut Stack,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let use_degrees = call.has_flag("degrees");
let use_degrees = call.has_flag(engine_state, stack, "degrees")?;
// This doesn't match explicit nulls
if matches!(input, PipelineData::Empty) {
return Err(ShellError::PipelineEmpty { dst_span: head });

View File

@ -1,3 +1,4 @@
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Span, Type, Value};
@ -34,12 +35,12 @@ impl Command for SubCommand {
fn run(
&self,
engine_state: &EngineState,
_stack: &mut Stack,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let use_degrees = call.has_flag("degrees");
let use_degrees = call.has_flag(engine_state, stack, "degrees")?;
// This doesn't match explicit nulls
if matches!(input, PipelineData::Empty) {
return Err(ShellError::PipelineEmpty { dst_span: head });

View File

@ -1,3 +1,4 @@
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Span, Type, Value};
@ -34,12 +35,12 @@ impl Command for SubCommand {
fn run(
&self,
engine_state: &EngineState,
_stack: &mut Stack,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let use_degrees = call.has_flag("degrees");
let use_degrees = call.has_flag(engine_state, stack, "degrees")?;
// This doesn't match explicit nulls
if matches!(input, PipelineData::Empty) {
return Err(ShellError::PipelineEmpty { dst_span: head });

View File

@ -67,7 +67,7 @@ impl Command for Collect {
)
.map(|x| x.set_metadata(metadata));
if call.has_flag("keep-env") {
if call.has_flag(engine_state, stack, "keep-env")? {
redirect_env(engine_state, stack, &stack_captures);
// for when we support `data | let x = $in;`
// remove the variables added earlier

View File

@ -1,3 +1,4 @@
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Closure, Command, EngineState, Stack, StateWorkingSet},
@ -44,20 +45,30 @@ impl Command for Describe {
fn run(
&self,
engine_state: &EngineState,
_stack: &mut Stack,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
run(Some(engine_state), call, input)
let options = Options {
no_collect: call.has_flag(engine_state, stack, "no-collect")?,
detailed: call.has_flag(engine_state, stack, "detailed")?,
collect_lazyrecords: call.has_flag(engine_state, stack, "collect-lazyrecords")?,
};
run(Some(engine_state), call, input, options)
}
fn run_const(
&self,
_working_set: &StateWorkingSet,
working_set: &StateWorkingSet,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
run(None, call, input)
let options = Options {
no_collect: call.has_flag_const(working_set, "no-collect")?,
detailed: call.has_flag_const(working_set, "detailed")?,
collect_lazyrecords: call.has_flag_const(working_set, "collect-lazyrecords")?,
};
run(None, call, input, options)
}
fn examples(&self) -> Vec<Example> {
@ -148,15 +159,21 @@ impl Command for Describe {
}
}
#[derive(Clone, Copy)]
struct Options {
no_collect: bool,
detailed: bool,
collect_lazyrecords: bool,
}
fn run(
engine_state: Option<&EngineState>,
call: &Call,
input: PipelineData,
options: Options,
) -> Result<PipelineData, ShellError> {
let metadata = input.metadata().clone().map(Box::new);
let head = call.head;
let no_collect: bool = call.has_flag("no-collect");
let detailed = call.has_flag("detailed");
let description: Value = match input {
PipelineData::ExternalStream {
@ -165,7 +182,7 @@ fn run(
ref exit_code,
..
} => {
if detailed {
if options.detailed {
Value::record(
record!(
"type" => Value::string("stream", head),
@ -212,23 +229,23 @@ fn run(
}
}
PipelineData::ListStream(_, _) => {
if detailed {
if options.detailed {
Value::record(
record!(
"type" => Value::string("stream", head),
"origin" => Value::string("nushell", head),
"subtype" => {
if no_collect {
if options.no_collect {
Value::string("any", head)
} else {
describe_value(input.into_value(head), head, engine_state, call)?
describe_value(input.into_value(head), head, engine_state, call, options)?
}
},
"metadata" => metadata_to_value(metadata, head),
),
head,
)
} else if no_collect {
} else if options.no_collect {
Value::string("stream", head)
} else {
let value = input.into_value(head);
@ -242,13 +259,13 @@ fn run(
}
_ => {
let value = input.into_value(head);
if !detailed {
if !options.detailed {
match value {
Value::CustomValue { val, .. } => Value::string(val.value_string(), head),
_ => Value::string(value.get_type().to_string(), head),
}
} else {
describe_value(value, head, engine_state, call)?
describe_value(value, head, engine_state, call, options)?
}
}
};
@ -273,12 +290,13 @@ fn describe_value(
head: nu_protocol::Span,
engine_state: Option<&EngineState>,
call: &Call,
options: Options,
) -> Result<Value, ShellError> {
Ok(match value {
Value::CustomValue { val, internal_span } => Value::record(
record!(
"type" => Value::string("custom", head),
"subtype" => run(engine_state,call, val.to_base_value(internal_span)?.into_pipeline_data())?.into_value(head),
"subtype" => run(engine_state,call, val.to_base_value(internal_span)?.into_pipeline_data(), options)?.into_value(head),
),
head,
),
@ -303,6 +321,7 @@ fn describe_value(
head,
engine_state,
call,
options,
)?);
}
@ -321,7 +340,7 @@ fn describe_value(
"length" => Value::int(vals.len() as i64, head),
"values" => Value::list(vals.into_iter().map(|v|
Ok(compact_primitive_description(
describe_value(v, head, engine_state, call)?
describe_value(v, head, engine_state, call, options)?
))
)
.collect::<Result<Vec<Value>, ShellError>>()?, head),
@ -381,16 +400,15 @@ fn describe_value(
head,
),
Value::LazyRecord { val, .. } => {
let collect_lazyrecords: bool = call.has_flag("collect-lazyrecords");
let mut record = Record::new();
record.push("type", Value::string("record", head));
record.push("lazy", Value::bool(true, head));
if collect_lazyrecords {
if options.collect_lazyrecords {
let collected = val.collect()?;
if let Value::Record { mut val, .. } =
describe_value(collected, head, engine_state, call)?
describe_value(collected, head, engine_state, call, options)?
{
record.push("length", Value::int(val.len() as i64, head));
for (_k, v) in val.iter_mut() {
@ -399,6 +417,7 @@ fn describe_value(
head,
engine_state,
call,
options,
)?);
}

View File

@ -70,11 +70,13 @@ impl Command for Do {
) -> Result<PipelineData, ShellError> {
let block: Closure = call.req(engine_state, caller_stack, 0)?;
let rest: Vec<Value> = call.rest(engine_state, caller_stack, 1)?;
let ignore_all_errors = call.has_flag("ignore-errors");
let ignore_shell_errors = ignore_all_errors || call.has_flag("ignore-shell-errors");
let ignore_program_errors = ignore_all_errors || call.has_flag("ignore-program-errors");
let capture_errors = call.has_flag("capture-errors");
let has_env = call.has_flag("env");
let ignore_all_errors = call.has_flag(engine_state, caller_stack, "ignore-errors")?;
let ignore_shell_errors = ignore_all_errors
|| call.has_flag(engine_state, caller_stack, "ignore-shell-errors")?;
let ignore_program_errors = ignore_all_errors
|| call.has_flag(engine_state, caller_stack, "ignore-program-errors")?;
let capture_errors = call.has_flag(engine_state, caller_stack, "capture-errors")?;
let has_env = call.has_flag(engine_state, caller_stack, "env")?;
let mut callee_stack = caller_stack.captures_to_stack(block.captures);
let block = engine_state.get_block(block.block_id);

View File

@ -46,7 +46,7 @@ impl Command for ErrorMake {
) -> Result<PipelineData, ShellError> {
let arg: Value = call.req(engine_state, stack, 0)?;
let throw_span = if call.has_flag("unspanned") {
let throw_span = if call.has_flag(engine_state, stack, "unspanned")? {
None
} else {
Some(call.head)

View File

@ -74,7 +74,7 @@ impl Command for For {
let block: Block = call.req(engine_state, stack, 2)?;
let numbered = call.has_flag("numbered");
let numbered = call.has_flag(engine_state, stack, "numbered")?;
let ctrlc = engine_state.ctrlc.clone();
let engine_state = engine_state.clone();

View File

@ -42,7 +42,7 @@ impl Command for HideEnv {
_input: PipelineData,
) -> Result<PipelineData, ShellError> {
let env_var_names: Vec<Spanned<String>> = call.rest(engine_state, stack, 0)?;
let ignore_errors = call.has_flag("ignore-errors");
let ignore_errors = call.has_flag(engine_state, stack, "ignore-errors")?;
for name in env_var_names {
if !stack.remove_env_var(engine_state, &name.item) && !ignore_errors {

View File

@ -75,7 +75,7 @@ impl Command for BytesAdd {
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
let cell_paths = (!cell_paths.is_empty()).then_some(cell_paths);
let index: Option<usize> = call.get_flag(engine_state, stack, "index")?;
let end = call.has_flag("end");
let end = call.has_flag(engine_state, stack, "end")?;
let arg = Arguments {
added_data,

View File

@ -1,4 +1,4 @@
use nu_engine::{eval_expression, CallExt};
use nu_engine::eval_expression;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{

View File

@ -73,8 +73,8 @@ impl Command for BytesIndexOf {
let cell_paths = (!cell_paths.is_empty()).then_some(cell_paths);
let arg = Arguments {
pattern,
end: call.has_flag("end"),
all: call.has_flag("all"),
end: call.has_flag(engine_state, stack, "end")?,
all: call.has_flag(engine_state, stack, "all")?,
cell_paths,
};
operate(index_of, arg, input, call.head, engine_state.ctrlc.clone())

View File

@ -74,9 +74,9 @@ impl Command for BytesRemove {
let pattern_to_remove: Vec<u8> = pattern_to_remove.item;
let arg = Arguments {
pattern: pattern_to_remove,
end: call.has_flag("end"),
end: call.has_flag(engine_state, stack, "end")?,
cell_paths,
all: call.has_flag("all"),
all: call.has_flag(engine_state, stack, "all")?,
};
operate(remove, arg, input, call.head, engine_state.ctrlc.clone())

View File

@ -76,7 +76,7 @@ impl Command for BytesReplace {
find: find.item,
replace: call.req::<Vec<u8>>(engine_state, stack, 1)?,
cell_paths,
all: call.has_flag("all"),
all: call.has_flag(engine_state, stack, "all")?,
};
operate(replace, arg, input, call.head, engine_state.ctrlc.clone())

View File

@ -148,7 +148,7 @@ fn into_binary(
_ => {
let args = Arguments {
cell_paths,
compact: call.has_flag("compact"),
compact: call.has_flag(engine_state, stack, "compact")?,
};
operate(action, args, input, call.head, engine_state.ctrlc.clone())
}

View File

@ -116,9 +116,9 @@ impl Command for SubCommand {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
if call.has_flag("list") {
if call.has_flag(engine_state, stack, "list")? {
Ok(generate_strftime_list(call.head, true).into_pipeline_data())
} else if call.has_flag("list-human") {
} else if call.has_flag(engine_state, stack, "list-human")? {
Ok(list_human_readable_examples(call.head).into_pipeline_data())
} else {
let cell_paths = call.rest(engine_state, stack, 0)?;

View File

@ -11,7 +11,6 @@ use num_format::ToFormattedString;
struct Arguments {
decimals_value: Option<i64>,
decimals: bool,
cell_paths: Option<Vec<CellPath>>,
config: Config,
}
@ -148,11 +147,10 @@ fn string_helper(
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let decimals = call.has_flag("decimals");
let head = call.head;
let decimals_value: Option<i64> = call.get_flag(engine_state, stack, "decimals")?;
if let Some(decimal_val) = decimals_value {
if decimals && decimal_val.is_negative() {
if decimal_val.is_negative() {
return Err(ShellError::TypeMismatch {
err_message: "Cannot accept negative integers for decimals arguments".to_string(),
span: head,
@ -164,7 +162,6 @@ fn string_helper(
let config = engine_state.get_config().clone();
let args = Arguments {
decimals_value,
decimals,
cell_paths,
config,
};
@ -186,7 +183,6 @@ fn string_helper(
}
fn action(input: &Value, args: &Arguments, span: Span) -> Value {
let decimals = args.decimals;
let digits = args.decimals_value;
let config = &args.config;
match input {
@ -196,8 +192,8 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
Value::string(res, span)
}
Value::Float { val, .. } => {
if decimals {
let decimal_value = digits.unwrap_or(2) as usize;
if let Some(decimal_value) = digits {
let decimal_value = decimal_value as usize;
Value::string(format!("{val:.decimal_value$}"), span)
} else {
Value::string(val.to_string(), span)

View File

@ -41,8 +41,8 @@ impl Command for Ast {
_input: PipelineData,
) -> Result<PipelineData, ShellError> {
let pipeline: Spanned<String> = call.req(engine_state, stack, 0)?;
let to_json = call.has_flag("json");
let minify = call.has_flag("minify");
let to_json = call.has_flag(engine_state, stack, "json")?;
let minify = call.has_flag(engine_state, stack, "minify")?;
let mut working_set = StateWorkingSet::new(engine_state);
let block_output = parse(&mut working_set, None, pipeline.item.as_bytes(), false);
let error_output = working_set.parse_errors.first();

View File

@ -1,3 +1,4 @@
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Span, Type, Value};
@ -31,13 +32,13 @@ impl Command for Debug {
fn run(
&self,
engine_state: &EngineState,
_stack: &mut Stack,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let config = engine_state.get_config().clone();
let raw = call.has_flag("raw");
let raw = call.has_flag(engine_state, stack, "raw")?;
// Should PipelineData::Empty result in an error here?

View File

@ -1,4 +1,4 @@
use nu_engine::env_to_strings;
use nu_engine::{env_to_strings, CallExt};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
@ -59,7 +59,7 @@ impl Command for ConfigEnv {
input: PipelineData,
) -> Result<PipelineData, ShellError> {
// `--default` flag handling
if call.has_flag("default") {
if call.has_flag(engine_state, stack, "default")? {
let head = call.head;
return Ok(Value::string(nu_utils::get_default_env(), head).into_pipeline_data());
}

View File

@ -1,4 +1,4 @@
use nu_engine::env_to_strings;
use nu_engine::{env_to_strings, CallExt};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
@ -63,7 +63,7 @@ impl Command for ConfigNu {
input: PipelineData,
) -> Result<PipelineData, ShellError> {
// `--default` flag handling
if call.has_flag("default") {
if call.has_flag(engine_state, stack, "default")? {
let head = call.head;
return Ok(Value::string(nu_utils::get_default_config(), head).into_pipeline_data());
}

View File

@ -1,4 +1,5 @@
use chrono::Local;
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
@ -39,14 +40,14 @@ impl Command for ConfigReset {
fn run(
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
_input: PipelineData,
) -> Result<PipelineData, ShellError> {
let only_nu = call.has_flag("nu");
let only_env = call.has_flag("env");
let no_backup = call.has_flag("without-backup");
let only_nu = call.has_flag(engine_state, stack, "nu")?;
let only_env = call.has_flag(engine_state, stack, "env")?;
let no_backup = call.has_flag(engine_state, stack, "without-backup")?;
let span = call.head;
let mut config_path = match nu_path::config_dir() {
Some(path) => path,

View File

@ -76,11 +76,11 @@ impl Command for Cp {
) -> Result<PipelineData, ShellError> {
let src: Spanned<String> = call.req(engine_state, stack, 0)?;
let dst: Spanned<String> = call.req(engine_state, stack, 1)?;
let recursive = call.has_flag("recursive");
let verbose = call.has_flag("verbose");
let interactive = call.has_flag("interactive");
let progress = call.has_flag("progress");
let update_mode = call.has_flag("update");
let recursive = call.has_flag(engine_state, stack, "recursive")?;
let verbose = call.has_flag(engine_state, stack, "verbose")?;
let interactive = call.has_flag(engine_state, stack, "interactive")?;
let progress = call.has_flag(engine_state, stack, "progress")?;
let update_mode = call.has_flag(engine_state, stack, "update")?;
let current_dir_path = current_dir(engine_state, stack)?;
let destination = current_dir_path.join(dst.item.as_str());
@ -229,7 +229,7 @@ impl Command for Cp {
inner: vec![],
})?;
let not_follow_symlink = call.has_flag("no-symlink");
let not_follow_symlink = call.has_flag(engine_state, stack, "no-symlink")?;
let sources = sources.paths_applying_with(|(source_file, depth_level)| {
let mut dest = destination.clone();

View File

@ -137,9 +137,9 @@ impl Command for Glob {
let span = call.head;
let glob_pattern: Spanned<String> = call.req(engine_state, stack, 0)?;
let depth = call.get_flag(engine_state, stack, "depth")?;
let no_dirs = call.has_flag("no-dir");
let no_files = call.has_flag("no-file");
let no_symlinks = call.has_flag("no-symlink");
let no_dirs = call.has_flag(engine_state, stack, "no-dir")?;
let no_files = call.has_flag(engine_state, stack, "no-file")?;
let no_symlinks = call.has_flag(engine_state, stack, "no-symlink")?;
let paths_to_exclude: Option<Value> = call.get_flag(engine_state, stack, "exclude")?;

View File

@ -73,13 +73,13 @@ impl Command for Ls {
call: &Call,
_input: PipelineData,
) -> Result<PipelineData, ShellError> {
let all = call.has_flag("all");
let long = call.has_flag("long");
let short_names = call.has_flag("short-names");
let full_paths = call.has_flag("full-paths");
let du = call.has_flag("du");
let directory = call.has_flag("directory");
let use_mime_type = call.has_flag("mime-type");
let all = call.has_flag(engine_state, stack, "all")?;
let long = call.has_flag(engine_state, stack, "long")?;
let short_names = call.has_flag(engine_state, stack, "short-names")?;
let full_paths = call.has_flag(engine_state, stack, "full-paths")?;
let du = call.has_flag(engine_state, stack, "du")?;
let directory = call.has_flag(engine_state, stack, "directory")?;
let use_mime_type = call.has_flag(engine_state, stack, "mime-type")?;
let ctrl_c = engine_state.ctrlc.clone();
let call_span = call.head;
let cwd = current_dir(engine_state, stack)?;

View File

@ -51,7 +51,7 @@ impl Command for Mkdir {
.map(|dir| path.join(dir))
.peekable();
let is_verbose = call.has_flag("verbose");
let is_verbose = call.has_flag(engine_state, stack, "verbose")?;
let mut stream: VecDeque<Value> = VecDeque::new();
if directories.peek().is_none() {

View File

@ -84,9 +84,9 @@ impl Command for Mktemp {
.cloned()
.map(|i: Spanned<String>| i.item)
.unwrap_or("tmp.XXXXXXXXXX".to_string()); // same as default in coreutils
let directory = call.has_flag("directory");
let directory = call.has_flag(engine_state, stack, "directory")?;
let suffix = call.get_flag(engine_state, stack, "suffix")?;
let tmpdir = call.has_flag("tmpdir");
let tmpdir = call.has_flag(engine_state, stack, "tmpdir")?;
let tmpdir_path = call
.get_flag(engine_state, stack, "tmpdir-path")?
.map(|i: Spanned<PathBuf>| i.item);

View File

@ -65,10 +65,10 @@ impl Command for Mv {
// TODO: handle invalid directory or insufficient permissions when moving
let spanned_source: Spanned<String> = call.req(engine_state, stack, 0)?;
let spanned_destination: Spanned<String> = call.req(engine_state, stack, 1)?;
let verbose = call.has_flag("verbose");
let interactive = call.has_flag("interactive");
let force = call.has_flag("force");
let update_mode = call.has_flag("update");
let verbose = call.has_flag(engine_state, stack, "verbose")?;
let interactive = call.has_flag(engine_state, stack, "interactive")?;
let force = call.has_flag(engine_state, stack, "force")?;
let update_mode = call.has_flag(engine_state, stack, "update")?;
let ctrlc = engine_state.ctrlc.clone();

View File

@ -59,7 +59,7 @@ impl Command for Open {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let raw = call.has_flag("raw");
let raw = call.has_flag(engine_state, stack, "raw")?;
let call_span = call.head;
let ctrlc = engine_state.ctrlc.clone();
let cwd = current_dir(engine_state, stack)?;

View File

@ -124,13 +124,13 @@ fn rm(
stack: &mut Stack,
call: &Call,
) -> Result<PipelineData, ShellError> {
let trash = call.has_flag("trash");
let permanent = call.has_flag("permanent");
let recursive = call.has_flag("recursive");
let force = call.has_flag("force");
let verbose = call.has_flag("verbose");
let interactive = call.has_flag("interactive");
let interactive_once = call.has_flag("interactive-once") && !interactive;
let trash = call.has_flag(engine_state, stack, "trash")?;
let permanent = call.has_flag(engine_state, stack, "permanent")?;
let recursive = call.has_flag(engine_state, stack, "recursive")?;
let force = call.has_flag(engine_state, stack, "force")?;
let verbose = call.has_flag(engine_state, stack, "verbose")?;
let interactive = call.has_flag(engine_state, stack, "interactive")?;
let interactive_once = call.has_flag(engine_state, stack, "interactive-once")? && !interactive;
let ctrlc = engine_state.ctrlc.clone();

View File

@ -63,10 +63,10 @@ impl Command for Save {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let raw = call.has_flag("raw");
let append = call.has_flag("append");
let force = call.has_flag("force");
let progress = call.has_flag("progress");
let raw = call.has_flag(engine_state, stack, "raw")?;
let append = call.has_flag(engine_state, stack, "append")?;
let force = call.has_flag(engine_state, stack, "force")?;
let progress = call.has_flag(engine_state, stack, "progress")?;
let out_append = if let Some(Expression {
expr: Expr::Bool(out_append),
..

View File

@ -67,10 +67,10 @@ impl Command for Touch {
call: &Call,
_input: PipelineData,
) -> Result<PipelineData, ShellError> {
let mut change_mtime: bool = call.has_flag("modified");
let mut change_atime: bool = call.has_flag("access");
let use_reference: bool = call.has_flag("reference");
let no_create: bool = call.has_flag("no-create");
let mut change_mtime: bool = call.has_flag(engine_state, stack, "modified")?;
let mut change_atime: bool = call.has_flag(engine_state, stack, "access")?;
let use_reference: bool = call.has_flag(engine_state, stack, "reference")?;
let no_create: bool = call.has_flag(engine_state, stack, "no-create")?;
let target: String = call.req(engine_state, stack, 0)?;
let rest: Vec<String> = call.rest(engine_state, stack, 1)?;

View File

@ -96,19 +96,19 @@ impl Command for UCp {
call: &Call,
_input: PipelineData,
) -> Result<PipelineData, ShellError> {
let interactive = call.has_flag("interactive");
let (update, copy_mode) = if call.has_flag("update") {
let interactive = call.has_flag(engine_state, stack, "interactive")?;
let (update, copy_mode) = if call.has_flag(engine_state, stack, "update")? {
(UpdateMode::ReplaceIfOlder, CopyMode::Update)
} else {
(UpdateMode::ReplaceAll, CopyMode::Copy)
};
let force = call.has_flag("force");
let no_clobber = call.has_flag("no-clobber");
let progress = call.has_flag("progress");
let recursive = call.has_flag("recursive");
let verbose = call.has_flag("verbose");
let force = call.has_flag(engine_state, stack, "force")?;
let no_clobber = call.has_flag(engine_state, stack, "no-clobber")?;
let progress = call.has_flag(engine_state, stack, "progress")?;
let recursive = call.has_flag(engine_state, stack, "recursive")?;
let verbose = call.has_flag(engine_state, stack, "verbose")?;
let debug = call.has_flag("debug");
let debug = call.has_flag(engine_state, stack, "debug")?;
let overwrite = if no_clobber {
uu_cp::OverwriteMode::NoClobber
} else if interactive {

View File

@ -57,7 +57,7 @@ impl Command for UMkdir {
.map(|dir| nu_path::expand_path_with(dir, &cwd))
.peekable();
let is_verbose = call.has_flag("verbose");
let is_verbose = call.has_flag(engine_state, stack, "verbose")?;
if directories.peek().is_none() {
return Err(ShellError::MissingParameter {

View File

@ -96,7 +96,7 @@ impl Command for Watch {
.get_block(capture_block.block_id)
.clone();
let verbose = call.has_flag("verbose");
let verbose = call.has_flag(engine_state, stack, "verbose")?;
let debounce_duration_flag: Option<Spanned<i64>> =
call.get_flag(engine_state, stack, "debounce-ms")?;

View File

@ -51,7 +51,7 @@ impl Command for Compact {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let empty = call.has_flag("empty");
let empty = call.has_flag(engine_state, stack, "empty")?;
compact(engine_state, stack, call, input, empty)
}

View File

@ -114,7 +114,7 @@ with 'transpose' first."#
) -> Result<PipelineData, ShellError> {
let capture_block: Closure = call.req(engine_state, stack, 0)?;
let keep_empty = call.has_flag("keep-empty");
let keep_empty = call.has_flag(engine_state, stack, "keep-empty")?;
let metadata = input.metadata();
let ctrlc = engine_state.ctrlc.clone();

View File

@ -71,7 +71,7 @@ impl Command for Every {
stride => stride,
};
let skip = call.has_flag("skip");
let skip = call.has_flag(engine_state, stack, "skip")?;
let metadata = input.metadata();

View File

@ -219,7 +219,7 @@ impl Command for Find {
fn find_with_regex(
regex: String,
engine_state: &EngineState,
_stack: &mut Stack,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
@ -227,10 +227,10 @@ fn find_with_regex(
let ctrlc = engine_state.ctrlc.clone();
let config = engine_state.get_config().clone();
let insensitive = call.has_flag("ignore-case");
let multiline = call.has_flag("multiline");
let dotall = call.has_flag("dotall");
let invert = call.has_flag("invert");
let insensitive = call.has_flag(engine_state, stack, "ignore-case")?;
let multiline = call.has_flag(engine_state, stack, "multiline")?;
let dotall = call.has_flag(engine_state, stack, "dotall")?;
let invert = call.has_flag(engine_state, stack, "invert")?;
let flags = match (insensitive, multiline, dotall) {
(false, false, false) => "",
@ -336,7 +336,7 @@ fn find_with_rest_and_highlight(
let engine_state = engine_state.clone();
let config = engine_state.get_config().clone();
let filter_config = engine_state.get_config().clone();
let invert = call.has_flag("invert");
let invert = call.has_flag(&engine_state, stack, "invert")?;
let terms = call.rest::<Value>(&engine_state, stack, 0)?;
let lower_terms = terms
.iter()

View File

@ -128,7 +128,7 @@ fn flatten(
) -> Result<PipelineData, ShellError> {
let columns: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
let metadata = input.metadata();
let flatten_all = call.has_flag("all");
let flatten_all = call.has_flag(engine_state, stack, "all")?;
input
.flat_map(

View File

@ -66,8 +66,8 @@ If multiple cell paths are given, this will produce a list of values."#
let span = call.head;
let mut cell_path: CellPath = call.req(engine_state, stack, 0)?;
let mut rest: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
let ignore_errors = call.has_flag("ignore-errors");
let sensitive = call.has_flag("sensitive");
let ignore_errors = call.has_flag(engine_state, stack, "ignore-errors")?;
let sensitive = call.has_flag(engine_state, stack, "sensitive")?;
let ctrlc = engine_state.ctrlc.clone();
let metadata = input.metadata();

View File

@ -188,7 +188,7 @@ pub fn group_by(
None => group_no_grouper(values)?,
};
let value = if call.has_flag("to-table") {
let value = if call.has_flag(engine_state, stack, "to-table")? {
groups_to_table(groups, span)
} else {
groups_to_record(groups, span)

View File

@ -75,7 +75,7 @@ impl Command for Join {
.opt(engine_state, stack, 2)?
.unwrap_or_else(|| l_on.clone());
let span = call.head;
let join_type = join_type(call)?;
let join_type = join_type(engine_state, stack, call)?;
// FIXME: we should handle ListStreams properly instead of collecting
let collected_input = input.into_value(span);
@ -116,12 +116,16 @@ impl Command for Join {
}
}
fn join_type(call: &Call) -> Result<JoinType, nu_protocol::ShellError> {
fn join_type(
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
) -> Result<JoinType, nu_protocol::ShellError> {
match (
call.has_flag("inner"),
call.has_flag("left"),
call.has_flag("right"),
call.has_flag("outer"),
call.has_flag(engine_state, stack, "inner")?,
call.has_flag(engine_state, stack, "left")?,
call.has_flag(engine_state, stack, "right")?,
call.has_flag(engine_state, stack, "outer")?,
) {
(_, false, false, false) => Ok(JoinType::Inner),
(false, true, false, false) => Ok(JoinType::Left),

View File

@ -1,3 +1,4 @@
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
@ -30,13 +31,13 @@ impl Command for Lines {
fn run(
&self,
engine_state: &EngineState,
_stack: &mut Stack,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let ctrlc = engine_state.ctrlc.clone();
let skip_empty = call.has_flag("skip-empty");
let skip_empty = call.has_flag(engine_state, stack, "skip-empty")?;
// match \r\n or \n
static LINE_BREAK_REGEX: Lazy<Regex> =

View File

@ -121,7 +121,7 @@ impl Command for ParEach {
let capture_block: Closure = call.req(engine_state, stack, 0)?;
let threads: Option<usize> = call.get_flag(engine_state, stack, "threads")?;
let max_threads = threads.unwrap_or(0);
let keep_order = call.has_flag("keep-order");
let keep_order = call.has_flag(engine_state, stack, "keep-order")?;
let metadata = input.metadata();
let ctrlc = engine_state.ctrlc.clone();
let outer_ctrlc = engine_state.ctrlc.clone();

View File

@ -133,7 +133,7 @@ impl Command for Reject {
}
let span = call.head;
let ignore_errors = call.has_flag("ignore-errors");
let ignore_errors = call.has_flag(engine_state, stack, "ignore-errors")?;
if ignore_errors {
for cell_path in &mut new_columns {
cell_path.make_optional();

View File

@ -137,7 +137,7 @@ produce a table, a list will produce a list, and a record will produce a record.
}
}
}
let ignore_errors = call.has_flag("ignore-errors");
let ignore_errors = call.has_flag(engine_state, stack, "ignore-errors")?;
let span = call.head;
if ignore_errors {
@ -235,7 +235,7 @@ fn select(
let columns = new_columns;
let input = if !unique_rows.is_empty() {
// let skip = call.has_flag("skip");
// let skip = call.has_flag(engine_state, stack, "skip")?;
let metadata = input.metadata();
let pipeline_iter: PipelineIterator = input.into_iter();

View File

@ -1,4 +1,5 @@
use alphanumeric_sort::compare_str;
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
@ -134,20 +135,20 @@ impl Command for Sort {
fn run(
&self,
engine_state: &EngineState,
_stack: &mut Stack,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let reverse = call.has_flag("reverse");
let insensitive = call.has_flag("ignore-case");
let natural = call.has_flag("natural");
let reverse = call.has_flag(engine_state, stack, "reverse")?;
let insensitive = call.has_flag(engine_state, stack, "ignore-case")?;
let natural = call.has_flag(engine_state, stack, "natural")?;
let metadata = &input.metadata();
let span = input.span().unwrap_or(call.head);
match input {
// Records have two sorting methods, toggled by presence or absence of -v
PipelineData::Value(Value::Record { val, .. }, ..) => {
let sort_by_value = call.has_flag("values");
let sort_by_value = call.has_flag(engine_state, stack, "values")?;
let record = sort_record(val, span, sort_by_value, reverse, insensitive, natural);
Ok(record.into_pipeline_data())
}

View File

@ -85,9 +85,9 @@ impl Command for SortBy {
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let columns: Vec<String> = call.rest(engine_state, stack, 0)?;
let reverse = call.has_flag("reverse");
let insensitive = call.has_flag("ignore-case");
let natural = call.has_flag("natural");
let reverse = call.has_flag(engine_state, stack, "reverse")?;
let insensitive = call.has_flag(engine_state, stack, "ignore-case")?;
let natural = call.has_flag(engine_state, stack, "natural")?;
let metadata = &input.metadata();
let mut vec: Vec<_> = input.into_iter_strict(call.head)?.collect();

View File

@ -145,11 +145,11 @@ pub fn transpose(
) -> Result<PipelineData, ShellError> {
let name = call.head;
let args = TransposeArgs {
header_row: call.has_flag("header-row"),
ignore_titles: call.has_flag("ignore-titles"),
as_record: call.has_flag("as-record"),
keep_last: call.has_flag("keep-last"),
keep_all: call.has_flag("keep-all"),
header_row: call.has_flag(engine_state, stack, "header-row")?,
ignore_titles: call.has_flag(engine_state, stack, "ignore-titles")?,
as_record: call.has_flag(engine_state, stack, "as-record")?,
keep_last: call.has_flag(engine_state, stack, "keep-last")?,
keep_all: call.has_flag(engine_state, stack, "keep-all")?,
rest: call.rest(engine_state, stack, 0)?,
};

View File

@ -1,5 +1,6 @@
use crate::formats::value_to_string;
use itertools::Itertools;
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
@ -247,7 +248,7 @@ fn generate_results_with_count(head: Span, uniq_values: Vec<ValueCounter>) -> Ve
pub fn uniq(
engine_state: &EngineState,
_stack: &mut Stack,
stack: &mut Stack,
call: &Call,
input: Vec<Value>,
item_mapper: Box<dyn Fn(ItemMapperState) -> ValueCounter>,
@ -255,10 +256,10 @@ pub fn uniq(
) -> Result<PipelineData, ShellError> {
let ctrlc = engine_state.ctrlc.clone();
let head = call.head;
let flag_show_count = call.has_flag("count");
let flag_show_repeated = call.has_flag("repeated");
let flag_ignore_case = call.has_flag("ignore-case");
let flag_only_uniques = call.has_flag("unique");
let flag_show_count = call.has_flag(engine_state, stack, "count")?;
let flag_show_repeated = call.has_flag(engine_state, stack, "repeated")?;
let flag_ignore_case = call.has_flag(engine_state, stack, "ignore-case")?;
let flag_only_uniques = call.has_flag(engine_state, stack, "unique")?;
let uniq_values = input
.into_iter()

View File

@ -120,7 +120,7 @@ impl Command for Window {
let ctrlc = engine_state.ctrlc.clone();
let metadata = input.metadata();
let stride: Option<usize> = call.get_flag(engine_state, stack, "stride")?;
let remainder = call.has_flag("remainder");
let remainder = call.has_flag(engine_state, stack, "remainder")?;
let stride = stride.unwrap_or(1);

View File

@ -166,9 +166,9 @@ fn from_csv(
.get_flag(engine_state, stack, "escape")?
.map(|v: Value| v.as_char())
.transpose()?;
let no_infer = call.has_flag("no-infer");
let noheaders = call.has_flag("noheaders");
let flexible = call.has_flag("flexible");
let no_infer = call.has_flag(engine_state, stack, "no-infer")?;
let noheaders = call.has_flag(engine_state, stack, "noheaders")?;
let flexible = call.has_flag(engine_state, stack, "flexible")?;
let trim = trim_from_str(call.get_flag(engine_state, stack, "trim")?)?;
let config = DelimitedReaderConfig {

View File

@ -1,3 +1,4 @@
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
@ -47,7 +48,7 @@ impl Command for FromJson {
fn run(
&self,
engine_state: &EngineState,
_stack: &mut Stack,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
@ -59,7 +60,7 @@ impl Command for FromJson {
}
// TODO: turn this into a structured underline of the nu_json error
if call.has_flag("objects") {
if call.has_flag(engine_state, stack, "objects")? {
let converted_lines: Vec<Value> = string_input
.lines()
.filter_map(move |x| {

View File

@ -289,8 +289,8 @@ fn from_ssv(
) -> Result<PipelineData, ShellError> {
let name = call.head;
let noheaders = call.has_flag("noheaders");
let aligned_columns = call.has_flag("aligned-columns");
let noheaders = call.has_flag(engine_state, stack, "noheaders")?;
let aligned_columns = call.has_flag(engine_state, stack, "aligned-columns")?;
let minimum_spaces: Option<Spanned<usize>> =
call.get_flag(engine_state, stack, "minimum-spaces")?;

View File

@ -132,9 +132,9 @@ fn from_tsv(
.get_flag(engine_state, stack, "escape")?
.map(|v: Value| v.as_char())
.transpose()?;
let no_infer = call.has_flag("no-infer");
let noheaders = call.has_flag("noheaders");
let flexible = call.has_flag("flexible");
let no_infer = call.has_flag(engine_state, stack, "no-infer")?;
let noheaders = call.has_flag(engine_state, stack, "noheaders")?;
let flexible = call.has_flag(engine_state, stack, "flexible")?;
let trim = trim_from_str(call.get_flag(engine_state, stack, "trim")?)?;
let config = DelimitedReaderConfig {

View File

@ -1,5 +1,6 @@
use crate::formats::nu_xml_format::{COLUMN_ATTRS_NAME, COLUMN_CONTENT_NAME, COLUMN_TAG_NAME};
use indexmap::map::IndexMap;
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
@ -46,14 +47,14 @@ string. This way content of every tag is always a table and is easier to parse"#
fn run(
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let keep_comments = call.has_flag("keep-comments");
let keep_processing_instructions = call.has_flag("keep-pi");
let keep_comments = call.has_flag(engine_state, stack, "keep-comments")?;
let keep_processing_instructions = call.has_flag(engine_state, stack, "keep-pi")?;
let info = ParsingInfo {
span: head,
keep_comments,

View File

@ -67,7 +67,7 @@ impl Command for ToCsv {
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let noheaders = call.has_flag("noheaders");
let noheaders = call.has_flag(engine_state, stack, "noheaders")?;
let separator: Option<Spanned<String>> = call.get_flag(engine_state, stack, "separator")?;
let config = engine_state.get_config();
to_csv(input, noheaders, separator, head, config)

View File

@ -44,8 +44,8 @@ impl Command for ToJson {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let raw = call.has_flag("raw");
let use_tabs = call.has_flag("tabs");
let raw = call.has_flag(engine_state, stack, "raw")?;
let use_tabs = call.has_flag(engine_state, stack, "tabs")?;
let span = call.head;
// allow ranges to expand and turn into array

View File

@ -1,5 +1,6 @@
use indexmap::map::IndexMap;
use nu_cmd_base::formats::to::delimited::merge_descriptors;
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
@ -67,13 +68,13 @@ impl Command for ToMd {
fn run(
&self,
engine_state: &EngineState,
_stack: &mut Stack,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let pretty = call.has_flag("pretty");
let per_element = call.has_flag("per-element");
let pretty = call.has_flag(engine_state, stack, "pretty")?;
let per_element = call.has_flag(engine_state, stack, "per-element")?;
let config = engine_state.get_config();
to_md(input, pretty, per_element, config, head)
}

View File

@ -53,20 +53,18 @@ impl Command for ToNuon {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let raw = call.has_flag("raw");
let use_tabs = call.has_flag("tabs");
let use_indent = call.has_flag("indent");
let raw = call.has_flag(engine_state, stack, "raw")?;
let tabs: Option<usize> = call.get_flag(engine_state, stack, "tabs")?;
let indent: Option<usize> = call.get_flag(engine_state, stack, "indent")?;
let span = call.head;
let value = input.into_value(span);
let nuon_result = if raw {
value_to_string(&value, span, 0, None)
} else if use_tabs {
let tab_count: usize = call.get_flag(engine_state, stack, "tabs")?.unwrap_or(1);
} else if let Some(tab_count) = tabs {
value_to_string(&value, span, 0, Some(&"\t".repeat(tab_count)))
} else if use_indent {
let indent: usize = call.get_flag(engine_state, stack, "indent")?.unwrap_or(2);
} else if let Some(indent) = indent {
value_to_string(&value, span, 0, Some(&" ".repeat(indent)))
} else {
value_to_string(&value, span, 0, None)

View File

@ -1,4 +1,5 @@
use crate::formats::to::delimited::to_delimited_data;
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
@ -49,12 +50,12 @@ impl Command for ToTsv {
fn run(
&self,
engine_state: &EngineState,
_stack: &mut Stack,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let noheaders = call.has_flag("noheaders");
let noheaders = call.has_flag(engine_state, stack, "noheaders")?;
let config = engine_state.get_config();
to_tsv(input, noheaders, head, config)
}

View File

@ -101,10 +101,10 @@ pub fn cal(
let (current_year, current_month, current_day) = get_current_date();
let arguments = Arguments {
year: call.has_flag("year"),
month: call.has_flag("month"),
month_names: call.has_flag("month-names"),
quarter: call.has_flag("quarter"),
year: call.has_flag(engine_state, stack, "year")?,
month: call.has_flag(engine_state, stack, "month")?,
month_names: call.has_flag(engine_state, stack, "month-names")?,
quarter: call.has_flag(engine_state, stack, "quarter")?,
full_year: call.get_flag(engine_state, stack, "full-year")?,
week_start: call.get_flag(engine_state, stack, "week-start")?,
};

View File

@ -129,7 +129,7 @@ impl Command for SeqDate {
let end_date: Option<Spanned<String>> = call.get_flag(engine_state, stack, "end-date")?;
let increment: Option<Spanned<i64>> = call.get_flag(engine_state, stack, "increment")?;
let days: Option<Spanned<i64>> = call.get_flag(engine_state, stack, "days")?;
let reverse = call.has_flag("reverse");
let reverse = call.has_flag(engine_state, stack, "reverse")?;
let outformat = match output_format {
Some(s) => Some(Value::string(s.item, s.span)),

View File

@ -87,7 +87,7 @@ where
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let binary = call.has_flag("binary");
let binary = call.has_flag(engine_state, stack, "binary")?;
let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
let cell_paths = (!cell_paths.is_empty()).then_some(cell_paths);
let args = Arguments { binary, cell_paths };

View File

@ -1,5 +1,6 @@
use super::variance::compute_variance as variance;
use crate::math::utils::run_with_function;
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Span, Type, Value};
@ -40,12 +41,12 @@ impl Command for SubCommand {
fn run(
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let sample = call.has_flag("sample");
let sample = call.has_flag(engine_state, stack, "sample")?;
run_with_function(call, input, compute_stddev(sample))
}

View File

@ -1,4 +1,5 @@
use crate::math::utils::run_with_function;
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Span, Type, Value};
@ -32,12 +33,12 @@ impl Command for SubCommand {
fn run(
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let sample = call.has_flag("sample");
let sample = call.has_flag(engine_state, stack, "sample")?;
run_with_function(call, input, compute_variance(sample))
}

View File

@ -170,13 +170,13 @@ fn run_delete(
headers: call.get_flag(engine_state, stack, "headers")?,
data: call.get_flag(engine_state, stack, "data")?,
content_type: call.get_flag(engine_state, stack, "content-type")?,
raw: call.has_flag("raw"),
insecure: call.has_flag("insecure"),
raw: call.has_flag(engine_state, stack, "raw")?,
insecure: call.has_flag(engine_state, stack, "insecure")?,
user: call.get_flag(engine_state, stack, "user")?,
password: call.get_flag(engine_state, stack, "password")?,
timeout: call.get_flag(engine_state, stack, "max-time")?,
full: call.has_flag("full"),
allow_errors: call.has_flag("allow-errors"),
full: call.has_flag(engine_state, stack, "full")?,
allow_errors: call.has_flag(engine_state, stack, "allow-errors")?,
redirect: call.get_flag(engine_state, stack, "redirect-mode")?,
};

View File

@ -154,13 +154,13 @@ fn run_get(
let args = Arguments {
url: call.req(engine_state, stack, 0)?,
headers: call.get_flag(engine_state, stack, "headers")?,
raw: call.has_flag("raw"),
insecure: call.has_flag("insecure"),
raw: call.has_flag(engine_state, stack, "raw")?,
insecure: call.has_flag(engine_state, stack, "insecure")?,
user: call.get_flag(engine_state, stack, "user")?,
password: call.get_flag(engine_state, stack, "password")?,
timeout: call.get_flag(engine_state, stack, "max-time")?,
full: call.has_flag("full"),
allow_errors: call.has_flag("allow-errors"),
full: call.has_flag(engine_state, stack, "full")?,
allow_errors: call.has_flag(engine_state, stack, "allow-errors")?,
redirect: call.get_flag(engine_state, stack, "redirect-mode")?,
};
helper(engine_state, stack, call, args)

View File

@ -132,7 +132,7 @@ fn run_head(
let args = Arguments {
url: call.req(engine_state, stack, 0)?,
headers: call.get_flag(engine_state, stack, "headers")?,
insecure: call.has_flag("insecure"),
insecure: call.has_flag(engine_state, stack, "insecure")?,
user: call.get_flag(engine_state, stack, "user")?,
password: call.get_flag(engine_state, stack, "password")?,
timeout: call.get_flag(engine_state, stack, "max-time")?,

View File

@ -139,11 +139,11 @@ fn run_get(
let args = Arguments {
url: call.req(engine_state, stack, 0)?,
headers: call.get_flag(engine_state, stack, "headers")?,
insecure: call.has_flag("insecure"),
insecure: call.has_flag(engine_state, stack, "insecure")?,
user: call.get_flag(engine_state, stack, "user")?,
password: call.get_flag(engine_state, stack, "password")?,
timeout: call.get_flag(engine_state, stack, "max-time")?,
allow_errors: call.has_flag("allow-errors"),
allow_errors: call.has_flag(engine_state, stack, "allow-errors")?,
};
helper(engine_state, stack, call, args)
}

Some files were not shown because too many files have changed in this diff Show More