nushell/crates/nu-cmd-base/src/util.rs

127 lines
4.3 KiB
Rust
Raw Normal View History

use nu_protocol::{
ast::RangeInclusion,
engine::{EngineState, Stack, StateWorkingSet},
report_error, Range, ShellError, Span, Value,
};
use std::path::PathBuf;
pub fn get_init_cwd() -> PathBuf {
std::env::current_dir().unwrap_or_else(|_| {
std::env::var("PWD")
.map(Into::into)
.unwrap_or_else(|_| nu_path::home_dir().unwrap_or_default())
})
}
pub fn get_guaranteed_cwd(engine_state: &EngineState, stack: &Stack) -> PathBuf {
nu_engine::env::current_dir(engine_state, stack).unwrap_or_else(|e| {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &e);
crate::util::get_init_cwd()
})
}
type MakeRangeError = fn(&str, Span) -> ShellError;
pub fn process_range(range: &Range) -> Result<(isize, isize), MakeRangeError> {
let start = match &range.from {
Fix process_range on 32-bit platforms (#8842) # Description This PR fixes `commands::str_::substrings_the_input_and_treats_end_index_as_length_if_blank_end_index_given` testcase on 32-bit platform. ``` failures: ---- commands::str_::substrings_the_input_and_treats_end_index_as_length_if_blank_end_index_given stdout ---- === stderr thread 'commands::str_::substrings_the_input_and_treats_end_index_as_length_if_blank_end_index_given' panicked at 'assertion failed: `(left == right)` left: `"arepa"`, right: `"arepas"`', crates/nu-command/tests/commands/str_/mod.rs:363:9 failures: commands::str_::substrings_the_input_and_treats_end_index_as_length_if_blank_end_index_given test result: FAILED. 1072 passed; 1 failed; 23 ignored; 0 measured; 0 filtered out; finished in 2.98s error: test failed, to rerun pass `-p nu-command --test main` ``` https://gitlab.alpinelinux.org/nibon7/aports/-/jobs/1005935#L3864 https://gitlab.alpinelinux.org/nibon7/aports/-/jobs/1005931#L3867 # User-Facing Changes N/A # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-04-10 20:52:42 +02:00
Value::Int { val, .. } => isize::try_from(*val).unwrap_or_default(),
Value::Nothing { .. } => 0,
_ => {
return Err(|msg, span| ShellError::TypeMismatch {
err_message: msg.to_string(),
span,
})
}
};
let end = match &range.to {
Value::Int { val, .. } => {
if matches!(range.inclusion, RangeInclusion::Inclusive) {
Fix process_range on 32-bit platforms (#8842) # Description This PR fixes `commands::str_::substrings_the_input_and_treats_end_index_as_length_if_blank_end_index_given` testcase on 32-bit platform. ``` failures: ---- commands::str_::substrings_the_input_and_treats_end_index_as_length_if_blank_end_index_given stdout ---- === stderr thread 'commands::str_::substrings_the_input_and_treats_end_index_as_length_if_blank_end_index_given' panicked at 'assertion failed: `(left == right)` left: `"arepa"`, right: `"arepas"`', crates/nu-command/tests/commands/str_/mod.rs:363:9 failures: commands::str_::substrings_the_input_and_treats_end_index_as_length_if_blank_end_index_given test result: FAILED. 1072 passed; 1 failed; 23 ignored; 0 measured; 0 filtered out; finished in 2.98s error: test failed, to rerun pass `-p nu-command --test main` ``` https://gitlab.alpinelinux.org/nibon7/aports/-/jobs/1005935#L3864 https://gitlab.alpinelinux.org/nibon7/aports/-/jobs/1005931#L3867 # User-Facing Changes N/A # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-04-10 20:52:42 +02:00
isize::try_from(*val).unwrap_or(isize::max_value())
} else {
Fix process_range on 32-bit platforms (#8842) # Description This PR fixes `commands::str_::substrings_the_input_and_treats_end_index_as_length_if_blank_end_index_given` testcase on 32-bit platform. ``` failures: ---- commands::str_::substrings_the_input_and_treats_end_index_as_length_if_blank_end_index_given stdout ---- === stderr thread 'commands::str_::substrings_the_input_and_treats_end_index_as_length_if_blank_end_index_given' panicked at 'assertion failed: `(left == right)` left: `"arepa"`, right: `"arepas"`', crates/nu-command/tests/commands/str_/mod.rs:363:9 failures: commands::str_::substrings_the_input_and_treats_end_index_as_length_if_blank_end_index_given test result: FAILED. 1072 passed; 1 failed; 23 ignored; 0 measured; 0 filtered out; finished in 2.98s error: test failed, to rerun pass `-p nu-command --test main` ``` https://gitlab.alpinelinux.org/nibon7/aports/-/jobs/1005935#L3864 https://gitlab.alpinelinux.org/nibon7/aports/-/jobs/1005931#L3867 # User-Facing Changes N/A # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-04-10 20:52:42 +02:00
isize::try_from(*val).unwrap_or(isize::max_value()) - 1
}
}
Value::Nothing { .. } => isize::max_value(),
_ => {
return Err(|msg, span| ShellError::TypeMismatch {
err_message: msg.to_string(),
span,
})
}
};
Ok((start, end))
}
const HELP_MSG: &str = "Nushell's config file can be found with the command: $nu.config-path. \
For more help: (https://nushell.sh/book/configuration.html#configurations-with-built-in-commands)";
fn get_editor_commandline(
value: &Value,
var_name: &str,
) -> Result<(String, Vec<String>), ShellError> {
match value {
Value::String { val, .. } if !val.is_empty() => Ok((val.to_string(), Vec::new())),
Value::List { vals, .. } if !vals.is_empty() => {
Name the `Value` conversion functions more clearly (#11851) # Description This PR renames the conversion functions on `Value` to be more consistent. It follows the Rust [API guidelines](https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv) for ad-hoc conversions. The conversion functions on `Value` now come in a few forms: - `coerce_{type}` takes a `&Value` and attempts to convert the value to `type` (e.g., `i64` are converted to `f64`). This is the old behavior of some of the `as_{type}` functions -- these functions have simply been renamed to better reflect what they do. - The new `as_{type}` functions take a `&Value` and returns an `Ok` result only if the value is of `type` (no conversion is attempted). The returned value will be borrowed if `type` is non-`Copy`, otherwise an owned value is returned. - `into_{type}` exists for non-`Copy` types, but otherwise does not attempt conversion just like `as_type`. It takes an owned `Value` and always returns an owned result. - `coerce_into_{type}` has the same relationship with `coerce_{type}` as `into_{type}` does with `as_{type}`. - `to_{kind}_string`: conversion to different string formats (debug, abbreviated, etc.). Only two of the old string conversion functions were removed, the rest have been renamed only. - `to_{type}`: other conversion functions. Currently, only `to_path` exists. (And `to_string` through `Display`.) This table summaries the above: | Form | Cost | Input Ownership | Output Ownership | Converts `Value` case/`type` | | ---------------------------- | ----- | --------------- | ---------------- | -------- | | `as_{type}` | Cheap | Borrowed | Borrowed/Owned | No | | `into_{type}` | Cheap | Owned | Owned | No | | `coerce_{type}` | Cheap | Borrowed | Borrowed/Owned | Yes | | `coerce_into_{type}` | Cheap | Owned | Owned | Yes | | `to_{kind}_string` | Expensive | Borrowed | Owned | Yes | | `to_{type}` | Expensive | Borrowed | Owned | Yes | # User-Facing Changes Breaking API change for `Value` in `nu-protocol` which is exposed as part of the plugin API.
2024-02-17 19:14:16 +01:00
let mut editor_cmd = vals.iter().map(|l| l.coerce_string());
match editor_cmd.next().transpose()? {
Some(editor) if !editor.is_empty() => {
let params = editor_cmd.collect::<Result<_, ShellError>>()?;
Ok((editor, params))
}
_ => Err(ShellError::GenericError {
error: "Editor executable is missing".into(),
msg: "Set the first element to an executable".into(),
span: Some(value.span()),
help: Some(HELP_MSG.into()),
inner: vec![],
}),
}
}
Value::String { .. } | Value::List { .. } => Err(ShellError::GenericError {
error: format!("{var_name} should be a non-empty string or list<String>"),
msg: "Specify an executable here".into(),
span: Some(value.span()),
help: Some(HELP_MSG.into()),
inner: vec![],
}),
x => Err(ShellError::CantConvert {
to_type: "string or list<string>".into(),
from_type: x.get_type().to_string(),
span: value.span(),
help: None,
}),
}
}
pub fn get_editor(
engine_state: &EngineState,
stack: &Stack,
span: Span,
) -> Result<(String, Vec<String>), ShellError> {
let config = engine_state.get_config();
let env_vars = stack.get_env_vars(engine_state);
if let Ok(buff_editor) =
get_editor_commandline(&config.buffer_editor, "$env.config.buffer_editor")
{
Ok(buff_editor)
} else if let Some(value) = env_vars.get("EDITOR") {
get_editor_commandline(value, "$env.EDITOR")
} else if let Some(value) = env_vars.get("VISUAL") {
get_editor_commandline(value, "$env.VISUAL")
} else {
Err(ShellError::GenericError {
error: "No editor configured".into(),
msg:
"Please specify one via `$env.config.buffer_editor` or `$env.EDITOR`/`$env.VISUAL`"
.into(),
span: Some(span),
help: Some(HELP_MSG.into()),
inner: vec![],
})
}
}