mirror of
https://github.com/nushell/nushell.git
synced 2025-06-11 20:46:48 +02:00
Merge branch 'main' into polars_categorical_2
This commit is contained in:
commit
7fe312e53a
52
.github/workflows/beta-test.yml
vendored
Normal file
52
.github/workflows/beta-test.yml
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
name: Test on Beta Toolchain
|
||||
# This workflow is made to run our tests on the beta toolchain to validate that
|
||||
# the beta toolchain works.
|
||||
# We do not intend to test here that we are working correctly but rather that
|
||||
# the beta toolchain works correctly.
|
||||
# The ci.yml handles our actual testing with our guarantees.
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# If this workflow fails, GitHub notifications will go to the last person
|
||||
# who edited this line.
|
||||
# See: https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/monitoring-workflows/notifications-for-workflow-runs
|
||||
- cron: '0 0 * * *' # Runs daily at midnight UTC
|
||||
|
||||
env:
|
||||
NUSHELL_CARGO_PROFILE: ci
|
||||
NU_LOG_LEVEL: DEBUG
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
# this job is more for testing the beta toolchain and not our tests, so if
|
||||
# this fails but the tests of the regular ci pass, then this is fine
|
||||
continue-on-error: true
|
||||
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
platform: [windows-latest, macos-latest, ubuntu-22.04]
|
||||
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- run: rustup update beta
|
||||
|
||||
- name: Tests
|
||||
run: cargo +beta test --workspace --profile ci --exclude nu_plugin_*
|
||||
- name: Check for clean repo
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
echo "there are changes";
|
||||
git status --porcelain
|
||||
exit 1
|
||||
else
|
||||
echo "no changes in working directory";
|
||||
fi
|
376
Cargo.lock
generated
376
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
73
Cargo.toml
73
Cargo.toml
@ -11,7 +11,7 @@ license = "MIT"
|
||||
name = "nu"
|
||||
repository = "https://github.com/nushell/nushell"
|
||||
rust-version = "1.83.0"
|
||||
version = "0.102.1"
|
||||
version = "0.103.1"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@ -92,7 +92,7 @@ filesize = "0.2"
|
||||
filetime = "0.2"
|
||||
heck = "0.5.0"
|
||||
human-date-parser = "0.2.0"
|
||||
indexmap = "2.7"
|
||||
indexmap = "2.8"
|
||||
indicatif = "0.17"
|
||||
interprocess = "2.2.0"
|
||||
is_executable = "1.0"
|
||||
@ -104,13 +104,13 @@ lru = "0.12"
|
||||
lscolors = { version = "0.17", default-features = false }
|
||||
lsp-server = "0.7.8"
|
||||
lsp-types = { version = "0.97.0", features = ["proposed"] }
|
||||
lsp-textdocument = "0.4.1"
|
||||
lsp-textdocument = "0.4.2"
|
||||
mach2 = "0.4"
|
||||
md5 = { version = "0.10", package = "md-5" }
|
||||
miette = "7.5"
|
||||
mime = "0.3.17"
|
||||
mime_guess = "2.0"
|
||||
mockito = { version = "1.6", default-features = false }
|
||||
mockito = { version = "1.7", default-features = false }
|
||||
multipart-rs = "0.1.13"
|
||||
native-tls = "0.2"
|
||||
nix = { version = "0.29", default-features = false }
|
||||
@ -140,7 +140,7 @@ getrandom = "0.2" # pick same version that rand requires
|
||||
rand_chacha = "0.3.1"
|
||||
ratatui = "0.29"
|
||||
rayon = "1.10"
|
||||
reedline = "0.38.0"
|
||||
reedline = "0.39.0"
|
||||
rmp = "0.8"
|
||||
rmp-serde = "1.3"
|
||||
roxmltree = "0.20"
|
||||
@ -161,7 +161,7 @@ syn = "2.0"
|
||||
sysinfo = "0.33"
|
||||
tabled = { version = "0.17.0", default-features = false }
|
||||
tempfile = "3.15"
|
||||
titlecase = "3.0"
|
||||
titlecase = "3.4"
|
||||
toml = "0.8"
|
||||
trash = "5.2"
|
||||
update-informer = { version = "1.2.0", default-features = false, features = ["github", "native-tls", "ureq"] }
|
||||
@ -170,15 +170,15 @@ unicode-segmentation = "1.12"
|
||||
unicode-width = "0.2"
|
||||
ureq = { version = "2.12", default-features = false }
|
||||
url = "2.2"
|
||||
uu_cp = "0.0.29"
|
||||
uu_mkdir = "0.0.29"
|
||||
uu_mktemp = "0.0.29"
|
||||
uu_mv = "0.0.29"
|
||||
uu_touch = "0.0.29"
|
||||
uu_whoami = "0.0.29"
|
||||
uu_uname = "0.0.29"
|
||||
uucore = "0.0.29"
|
||||
uuid = "1.12.0"
|
||||
uu_cp = "0.0.30"
|
||||
uu_mkdir = "0.0.30"
|
||||
uu_mktemp = "0.0.30"
|
||||
uu_mv = "0.0.30"
|
||||
uu_touch = "0.0.30"
|
||||
uu_whoami = "0.0.30"
|
||||
uu_uname = "0.0.30"
|
||||
uucore = "0.0.30"
|
||||
uuid = "1.16.0"
|
||||
v_htmlescape = "0.15.0"
|
||||
wax = "0.6"
|
||||
web-time = "1.1.0"
|
||||
@ -197,22 +197,22 @@ unchecked_duration_subtraction = "warn"
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
nu-cli = { path = "./crates/nu-cli", version = "0.102.1" }
|
||||
nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.102.1" }
|
||||
nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.102.1" }
|
||||
nu-cmd-plugin = { path = "./crates/nu-cmd-plugin", version = "0.102.1", optional = true }
|
||||
nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.102.1" }
|
||||
nu-command = { path = "./crates/nu-command", version = "0.102.1" }
|
||||
nu-engine = { path = "./crates/nu-engine", version = "0.102.1" }
|
||||
nu-explore = { path = "./crates/nu-explore", version = "0.102.1" }
|
||||
nu-lsp = { path = "./crates/nu-lsp/", version = "0.102.1" }
|
||||
nu-parser = { path = "./crates/nu-parser", version = "0.102.1" }
|
||||
nu-path = { path = "./crates/nu-path", version = "0.102.1" }
|
||||
nu-plugin-engine = { path = "./crates/nu-plugin-engine", optional = true, version = "0.102.1" }
|
||||
nu-protocol = { path = "./crates/nu-protocol", version = "0.102.1" }
|
||||
nu-std = { path = "./crates/nu-std", version = "0.102.1" }
|
||||
nu-system = { path = "./crates/nu-system", version = "0.102.1" }
|
||||
nu-utils = { path = "./crates/nu-utils", version = "0.102.1" }
|
||||
nu-cli = { path = "./crates/nu-cli", version = "0.103.1" }
|
||||
nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.103.1" }
|
||||
nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.103.1" }
|
||||
nu-cmd-plugin = { path = "./crates/nu-cmd-plugin", version = "0.103.1", optional = true }
|
||||
nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.103.1" }
|
||||
nu-command = { path = "./crates/nu-command", version = "0.103.1" }
|
||||
nu-engine = { path = "./crates/nu-engine", version = "0.103.1" }
|
||||
nu-explore = { path = "./crates/nu-explore", version = "0.103.1" }
|
||||
nu-lsp = { path = "./crates/nu-lsp/", version = "0.103.1" }
|
||||
nu-parser = { path = "./crates/nu-parser", version = "0.103.1" }
|
||||
nu-path = { path = "./crates/nu-path", version = "0.103.1" }
|
||||
nu-plugin-engine = { path = "./crates/nu-plugin-engine", optional = true, version = "0.103.1" }
|
||||
nu-protocol = { path = "./crates/nu-protocol", version = "0.103.1" }
|
||||
nu-std = { path = "./crates/nu-std", version = "0.103.1" }
|
||||
nu-system = { path = "./crates/nu-system", version = "0.103.1" }
|
||||
nu-utils = { path = "./crates/nu-utils", version = "0.103.1" }
|
||||
reedline = { workspace = true, features = ["bashisms", "sqlite"] }
|
||||
|
||||
crossterm = { workspace = true }
|
||||
@ -220,7 +220,6 @@ ctrlc = { workspace = true }
|
||||
dirs = { workspace = true }
|
||||
log = { workspace = true }
|
||||
miette = { workspace = true, features = ["fancy-no-backtrace", "fancy"] }
|
||||
mimalloc = { version = "0.1.42", default-features = false, optional = true }
|
||||
multipart-rs = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
simplelog = "0.12"
|
||||
@ -242,9 +241,9 @@ nix = { workspace = true, default-features = false, features = [
|
||||
] }
|
||||
|
||||
[dev-dependencies]
|
||||
nu-test-support = { path = "./crates/nu-test-support", version = "0.102.1" }
|
||||
nu-plugin-protocol = { path = "./crates/nu-plugin-protocol", version = "0.102.1" }
|
||||
nu-plugin-core = { path = "./crates/nu-plugin-core", version = "0.102.1" }
|
||||
nu-test-support = { path = "./crates/nu-test-support", version = "0.103.1" }
|
||||
nu-plugin-protocol = { path = "./crates/nu-plugin-protocol", version = "0.103.1" }
|
||||
nu-plugin-core = { path = "./crates/nu-plugin-core", version = "0.103.1" }
|
||||
assert_cmd = "2.0"
|
||||
dirs = { workspace = true }
|
||||
tango-bench = "0.6"
|
||||
@ -274,7 +273,6 @@ default = [
|
||||
"plugin",
|
||||
"trash-support",
|
||||
"sqlite",
|
||||
"mimalloc",
|
||||
]
|
||||
stable = ["default"]
|
||||
# NOTE: individual features are also passed to `nu-cmd-lang` that uses them to generate the feature matrix in the `version` command
|
||||
@ -283,7 +281,6 @@ stable = ["default"]
|
||||
# otherwise the system version will be used. Not enabled by default because it takes a while to build
|
||||
static-link-openssl = ["dep:openssl", "nu-cmd-lang/static-link-openssl"]
|
||||
|
||||
mimalloc = ["nu-cmd-lang/mimalloc", "dep:mimalloc"]
|
||||
# Optional system clipboard support in `reedline`, this behavior has problematic compatibility with some systems.
|
||||
# Missing X server/ Wayland can cause issues
|
||||
system-clipboard = [
|
||||
@ -326,7 +323,7 @@ bench = false
|
||||
# To use a development version of a dependency please use a global override here
|
||||
# changing versions in each sub-crate of the workspace is tedious
|
||||
[patch.crates-io]
|
||||
reedline = { git = "https://github.com/nushell/reedline", branch = "main" }
|
||||
# reedline = { git = "https://github.com/nushell/reedline", branch = "main" }
|
||||
# nu-ansi-term = {git = "https://github.com/nushell/nu-ansi-term.git", branch = "main"}
|
||||
|
||||
# Run all benchmarks with `cargo bench`
|
||||
|
@ -5,28 +5,28 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cli"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
name = "nu-cli"
|
||||
version = "0.102.1"
|
||||
version = "0.103.1"
|
||||
|
||||
[lib]
|
||||
bench = false
|
||||
|
||||
[dev-dependencies]
|
||||
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.102.1" }
|
||||
nu-command = { path = "../nu-command", version = "0.102.1" }
|
||||
nu-test-support = { path = "../nu-test-support", version = "0.102.1" }
|
||||
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.103.1" }
|
||||
nu-command = { path = "../nu-command", version = "0.103.1" }
|
||||
nu-test-support = { path = "../nu-test-support", version = "0.103.1" }
|
||||
rstest = { workspace = true, default-features = false }
|
||||
tempfile = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
nu-cmd-base = { path = "../nu-cmd-base", version = "0.102.1" }
|
||||
nu-engine = { path = "../nu-engine", version = "0.102.1", features = ["os"] }
|
||||
nu-glob = { path = "../nu-glob", version = "0.102.1" }
|
||||
nu-path = { path = "../nu-path", version = "0.102.1" }
|
||||
nu-parser = { path = "../nu-parser", version = "0.102.1" }
|
||||
nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.102.1", optional = true }
|
||||
nu-protocol = { path = "../nu-protocol", version = "0.102.1", features = ["os"] }
|
||||
nu-utils = { path = "../nu-utils", version = "0.102.1" }
|
||||
nu-color-config = { path = "../nu-color-config", version = "0.102.1" }
|
||||
nu-cmd-base = { path = "../nu-cmd-base", version = "0.103.1" }
|
||||
nu-engine = { path = "../nu-engine", version = "0.103.1", features = ["os"] }
|
||||
nu-glob = { path = "../nu-glob", version = "0.103.1" }
|
||||
nu-path = { path = "../nu-path", version = "0.103.1" }
|
||||
nu-parser = { path = "../nu-parser", version = "0.103.1" }
|
||||
nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.103.1", optional = true }
|
||||
nu-protocol = { path = "../nu-protocol", version = "0.103.1", features = ["os"] }
|
||||
nu-utils = { path = "../nu-utils", version = "0.103.1" }
|
||||
nu-color-config = { path = "../nu-color-config", version = "0.103.1" }
|
||||
nu-ansi-term = { workspace = true }
|
||||
reedline = { workspace = true, features = ["bashisms", "sqlite"] }
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct CommandlineEdit;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for CommandlineEdit {
|
||||
fn name(&self) -> &str {
|
||||
"commandline edit"
|
||||
}
|
||||
|
@ -2,9 +2,9 @@ use nu_engine::command_prelude::*;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct CommandlineGetCursor;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for CommandlineGetCursor {
|
||||
fn name(&self) -> &str {
|
||||
"commandline get-cursor"
|
||||
}
|
||||
|
@ -4,6 +4,6 @@ mod get_cursor;
|
||||
mod set_cursor;
|
||||
|
||||
pub use commandline_::Commandline;
|
||||
pub use edit::SubCommand as CommandlineEdit;
|
||||
pub use get_cursor::SubCommand as CommandlineGetCursor;
|
||||
pub use set_cursor::SubCommand as CommandlineSetCursor;
|
||||
pub use edit::CommandlineEdit;
|
||||
pub use get_cursor::CommandlineGetCursor;
|
||||
pub use set_cursor::CommandlineSetCursor;
|
||||
|
@ -3,9 +3,9 @@ use nu_engine::command_prelude::*;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct CommandlineSetCursor;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for CommandlineSetCursor {
|
||||
fn name(&self) -> &str {
|
||||
"commandline set-cursor"
|
||||
}
|
||||
|
@ -307,9 +307,8 @@ impl NuCompleter {
|
||||
let need_externals = !prefix_str.contains(' ');
|
||||
let need_internals = !prefix_str.starts_with('^');
|
||||
let mut span = element_expression.span;
|
||||
span.end = std::cmp::min(span.end, pos + 1);
|
||||
if !need_internals {
|
||||
span = Span::new(span.start + 1, span.end)
|
||||
span.start += 1;
|
||||
};
|
||||
suggestions.extend(self.command_completion_helper(
|
||||
working_set,
|
||||
|
@ -65,10 +65,11 @@ fn complete_rec(
|
||||
|
||||
for entry in result.filter_map(|e| e.ok()) {
|
||||
let entry_name = entry.file_name().to_string_lossy().into_owned();
|
||||
let entry_isdir = entry.path().is_dir() && !entry.path().is_symlink();
|
||||
let entry_isdir = entry.path().is_dir();
|
||||
let mut built = built.clone();
|
||||
built.parts.push(entry_name.clone());
|
||||
built.isdir = entry_isdir;
|
||||
// Symlinks to directories shouldn't have a trailing slash (#13275)
|
||||
built.isdir = entry_isdir && !entry.path().is_symlink();
|
||||
|
||||
if !want_directory || entry_isdir {
|
||||
matcher.add(entry_name.clone(), (entry_name, built));
|
||||
@ -198,10 +199,9 @@ pub fn complete_item(
|
||||
let ls_colors = (engine_state.config.completions.use_ls_colors
|
||||
&& engine_state.config.use_ansi_coloring.get(engine_state))
|
||||
.then(|| {
|
||||
let ls_colors_env_str = match stack.get_env_var(engine_state, "LS_COLORS") {
|
||||
Some(v) => env_to_string("LS_COLORS", v, engine_state, stack).ok(),
|
||||
None => None,
|
||||
};
|
||||
let ls_colors_env_str = stack
|
||||
.get_env_var(engine_state, "LS_COLORS")
|
||||
.and_then(|v| env_to_string("LS_COLORS", v, engine_state, stack).ok());
|
||||
get_ls_colors(ls_colors_env_str)
|
||||
});
|
||||
|
||||
@ -263,19 +263,16 @@ pub fn complete_item(
|
||||
}
|
||||
let is_dir = p.isdir;
|
||||
let path = original_cwd.apply(p, path_separator);
|
||||
let real_path = expand_to_real_path(&path);
|
||||
let metadata = std::fs::symlink_metadata(&real_path).ok();
|
||||
let style = ls_colors.as_ref().map(|lsc| {
|
||||
lsc.style_for_path_with_metadata(
|
||||
&path,
|
||||
std::fs::symlink_metadata(expand_to_real_path(&path))
|
||||
.ok()
|
||||
.as_ref(),
|
||||
)
|
||||
.map(lscolors::Style::to_nu_ansi_term_style)
|
||||
.unwrap_or_default()
|
||||
lsc.style_for_path_with_metadata(&real_path, metadata.as_ref())
|
||||
.map(lscolors::Style::to_nu_ansi_term_style)
|
||||
.unwrap_or_default()
|
||||
});
|
||||
FileSuggestion {
|
||||
span,
|
||||
path: escape_path(path, want_directory),
|
||||
path: escape_path(path),
|
||||
style,
|
||||
is_dir,
|
||||
}
|
||||
@ -284,30 +281,30 @@ pub fn complete_item(
|
||||
}
|
||||
|
||||
// Fix files or folders with quotes or hashes
|
||||
pub fn escape_path(path: String, dir: bool) -> String {
|
||||
pub fn escape_path(path: String) -> String {
|
||||
// make glob pattern have the highest priority.
|
||||
if nu_glob::is_glob(path.as_str()) {
|
||||
if nu_glob::is_glob(path.as_str()) || path.contains('`') {
|
||||
// expand home `~` for https://github.com/nushell/nushell/issues/13905
|
||||
let pathbuf = nu_path::expand_tilde(path);
|
||||
let path = pathbuf.to_string_lossy();
|
||||
return if path.contains('\'') {
|
||||
// decide to use double quote, also need to escape `"` in path
|
||||
// or else users can't do anything with completed path either.
|
||||
format!("\"{}\"", path.replace('"', r#"\""#))
|
||||
if path.contains('\'') {
|
||||
// decide to use double quotes
|
||||
// Path as Debug will do the escaping for `"`, `\`
|
||||
format!("{:?}", path)
|
||||
} else {
|
||||
format!("'{path}'")
|
||||
};
|
||||
}
|
||||
|
||||
let filename_contaminated = !dir && path.contains(['\'', '"', ' ', '#', '(', ')']);
|
||||
let dirname_contaminated = dir && path.contains(['\'', '"', ' ', '#']);
|
||||
let maybe_flag = path.starts_with('-');
|
||||
let maybe_variable = path.starts_with('$');
|
||||
let maybe_number = path.parse::<f64>().is_ok();
|
||||
if filename_contaminated || dirname_contaminated || maybe_flag || maybe_variable || maybe_number
|
||||
{
|
||||
format!("`{path}`")
|
||||
}
|
||||
} else {
|
||||
path
|
||||
let contaminated =
|
||||
path.contains(['\'', '"', ' ', '#', '(', ')', '{', '}', '[', ']', '|', ';']);
|
||||
let maybe_flag = path.starts_with('-');
|
||||
let maybe_variable = path.starts_with('$');
|
||||
let maybe_number = path.parse::<f64>().is_ok();
|
||||
if contaminated || maybe_flag || maybe_variable || maybe_number {
|
||||
format!("`{path}`")
|
||||
} else {
|
||||
path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ use nu_engine::eval_call;
|
||||
use nu_protocol::{
|
||||
ast::{Argument, Call, Expr, Expression},
|
||||
debugger::WithoutDebug,
|
||||
engine::{Stack, StateWorkingSet},
|
||||
engine::{EngineState, Stack, StateWorkingSet},
|
||||
DeclId, PipelineData, Span, Type, Value,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
@ -42,28 +42,37 @@ impl<T: Completer> Completer for CustomCompletion<T> {
|
||||
) -> Vec<SemanticSuggestion> {
|
||||
// Call custom declaration
|
||||
let mut stack_mut = stack.clone();
|
||||
let result = eval_call::<WithoutDebug>(
|
||||
working_set.permanent_state,
|
||||
&mut stack_mut,
|
||||
&Call {
|
||||
decl_id: self.decl_id,
|
||||
head: span,
|
||||
arguments: vec![
|
||||
Argument::Positional(Expression::new_unknown(
|
||||
Expr::String(self.line.clone()),
|
||||
Span::unknown(),
|
||||
Type::String,
|
||||
)),
|
||||
Argument::Positional(Expression::new_unknown(
|
||||
Expr::Int(self.line_pos as i64),
|
||||
Span::unknown(),
|
||||
Type::Int,
|
||||
)),
|
||||
],
|
||||
parser_info: HashMap::new(),
|
||||
},
|
||||
PipelineData::empty(),
|
||||
);
|
||||
let mut eval = |engine_state: &EngineState| {
|
||||
eval_call::<WithoutDebug>(
|
||||
engine_state,
|
||||
&mut stack_mut,
|
||||
&Call {
|
||||
decl_id: self.decl_id,
|
||||
head: span,
|
||||
arguments: vec![
|
||||
Argument::Positional(Expression::new_unknown(
|
||||
Expr::String(self.line.clone()),
|
||||
Span::unknown(),
|
||||
Type::String,
|
||||
)),
|
||||
Argument::Positional(Expression::new_unknown(
|
||||
Expr::Int(self.line_pos as i64),
|
||||
Span::unknown(),
|
||||
Type::Int,
|
||||
)),
|
||||
],
|
||||
parser_info: HashMap::new(),
|
||||
},
|
||||
PipelineData::empty(),
|
||||
)
|
||||
};
|
||||
let result = if self.decl_id.get() < working_set.permanent_state.num_decls() {
|
||||
eval(working_set.permanent_state)
|
||||
} else {
|
||||
let mut engine_state = working_set.permanent_state.clone();
|
||||
let _ = engine_state.merge_delta(working_set.delta.clone());
|
||||
eval(&engine_state)
|
||||
};
|
||||
|
||||
let mut completion_options = orig_options.clone();
|
||||
let mut should_sort = true;
|
||||
|
@ -37,6 +37,15 @@ fn common_comparison_ops() -> Vec<OperatorItem> {
|
||||
]
|
||||
}
|
||||
|
||||
fn all_ops_for_immutable() -> Vec<OperatorItem> {
|
||||
ast::Comparison::iter()
|
||||
.map(operator_to_item)
|
||||
.chain(ast::Math::iter().map(operator_to_item))
|
||||
.chain(ast::Boolean::iter().map(operator_to_item))
|
||||
.chain(ast::Bits::iter().map(operator_to_item))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn collection_comparison_ops() -> Vec<OperatorItem> {
|
||||
let mut ops = common_comparison_ops();
|
||||
ops.push(operator_to_item(Comparison::Has));
|
||||
@ -72,6 +81,10 @@ fn bit_ops() -> Vec<OperatorItem> {
|
||||
ast::Bits::iter().map(operator_to_item).collect()
|
||||
}
|
||||
|
||||
fn all_assignment_ops() -> Vec<OperatorItem> {
|
||||
ast::Assignment::iter().map(operator_to_item).collect()
|
||||
}
|
||||
|
||||
fn numeric_assignment_ops() -> Vec<OperatorItem> {
|
||||
ast::Assignment::iter()
|
||||
.filter(|op| !matches!(op, ast::Assignment::ConcatenateAssign))
|
||||
@ -154,7 +167,7 @@ fn ops_by_value(value: &Value, mutable: bool) -> Vec<OperatorItem> {
|
||||
Value::Filesize { .. } | Value::Duration { .. } => valid_value_with_unit_ops(),
|
||||
Value::Range { .. } | Value::Record { .. } => collection_comparison_ops(),
|
||||
Value::List { .. } => valid_list_ops(),
|
||||
_ => common_comparison_ops(),
|
||||
_ => all_ops_for_immutable(),
|
||||
};
|
||||
if mutable {
|
||||
ops.extend(match value {
|
||||
@ -165,7 +178,11 @@ fn ops_by_value(value: &Value, mutable: bool) -> Vec<OperatorItem> {
|
||||
Value::String { .. } | Value::Binary { .. } | Value::List { .. } => {
|
||||
concat_assignment_ops()
|
||||
}
|
||||
_ => vec![operator_to_item(ast::Assignment::Assign)],
|
||||
Value::Bool { .. }
|
||||
| Value::Date { .. }
|
||||
| Value::Range { .. }
|
||||
| Value::Record { .. } => vec![operator_to_item(ast::Assignment::Assign)],
|
||||
_ => all_assignment_ops(),
|
||||
})
|
||||
}
|
||||
ops
|
||||
@ -223,7 +240,7 @@ impl Completer for OperatorCompletion<'_> {
|
||||
needs_assignment_ops = false;
|
||||
ops_by_value(&value, mutable)
|
||||
}
|
||||
_ => common_comparison_ops(),
|
||||
_ => all_ops_for_immutable(),
|
||||
},
|
||||
_ => common_comparison_ops(),
|
||||
};
|
||||
@ -233,6 +250,7 @@ impl Completer for OperatorCompletion<'_> {
|
||||
Type::Int | Type::Float | Type::Number => numeric_assignment_ops(),
|
||||
Type::Filesize | Type::Duration => numeric_assignment_ops(),
|
||||
Type::String | Type::Binary | Type::List(_) => concat_assignment_ops(),
|
||||
Type::Any => all_assignment_ops(),
|
||||
_ => vec![operator_to_item(ast::Assignment::Assign)],
|
||||
});
|
||||
}
|
||||
|
@ -307,7 +307,12 @@ fn custom_arguments_and_subcommands() {
|
||||
let completion_str = "foo test";
|
||||
let suggestions = completer.complete(completion_str, completion_str.len());
|
||||
// including both subcommand and directory completions
|
||||
let expected = ["foo test bar".into(), folder("test_a"), folder("test_b")];
|
||||
let expected = [
|
||||
"foo test bar".into(),
|
||||
folder("test_a"),
|
||||
file("test_a_symlink"),
|
||||
folder("test_b"),
|
||||
];
|
||||
match_suggestions_by_string(&expected, &suggestions);
|
||||
}
|
||||
|
||||
@ -345,6 +350,21 @@ fn custom_arguments_vs_subcommands() {
|
||||
match_suggestions(&expected, &suggestions);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_completions_defined_inline() {
|
||||
let (_, _, engine, stack) = new_engine();
|
||||
|
||||
let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
|
||||
let completion_str = "def animals [] { [cat dog] }
|
||||
export def say [
|
||||
animal: string@animals
|
||||
] { }; say ";
|
||||
let suggestions = completer.complete(completion_str, completion_str.len());
|
||||
// including only subcommand completions
|
||||
let expected: Vec<_> = vec!["cat", "dog"];
|
||||
match_suggestions(&expected, &suggestions);
|
||||
}
|
||||
|
||||
/// External command only if starts with `^`
|
||||
#[test]
|
||||
fn external_commands_only() {
|
||||
@ -891,6 +911,7 @@ fn partial_completions() {
|
||||
folder(dir.join("partial-a")),
|
||||
folder(dir.join("partial-b")),
|
||||
folder(dir.join("partial-c")),
|
||||
format!("`{}`", folder(dir.join("partial-d("))),
|
||||
];
|
||||
|
||||
// Match the results
|
||||
@ -933,6 +954,7 @@ fn partial_completions() {
|
||||
file(dir.join("partial-b").join("hello_b")),
|
||||
file(dir.join("partial-b").join("hi_b")),
|
||||
file(dir.join("partial-c").join("hello_c")),
|
||||
format!("`{}`", file(dir.join("partial-d(").join(".gitkeep"))),
|
||||
];
|
||||
|
||||
// Match the results
|
||||
@ -980,6 +1002,15 @@ fn partial_completions() {
|
||||
.join("final_partial")
|
||||
.join("somefile"),
|
||||
),
|
||||
format!(
|
||||
"`{}`",
|
||||
file(
|
||||
dir.join("partial-d(")
|
||||
.join("..")
|
||||
.join("final_partial")
|
||||
.join("somefile"),
|
||||
)
|
||||
),
|
||||
];
|
||||
|
||||
// Match the results
|
||||
@ -1060,6 +1091,16 @@ fn partial_completion_with_dot_expansions() {
|
||||
.join("final_partial")
|
||||
.join("somefile"),
|
||||
),
|
||||
format!(
|
||||
"`{}`",
|
||||
file(
|
||||
dir.join("partial-d(")
|
||||
.join("...")
|
||||
.join("partial_completions")
|
||||
.join("final_partial")
|
||||
.join("somefile"),
|
||||
)
|
||||
),
|
||||
];
|
||||
|
||||
// Match the results
|
||||
@ -1384,6 +1425,9 @@ fn file_completion_quoted() {
|
||||
"`-inf`",
|
||||
"`4.2`",
|
||||
"\'[a] bc.txt\'",
|
||||
"`curly-bracket_{.txt`",
|
||||
"`semicolon_;.txt`",
|
||||
"'square-bracket_[.txt'",
|
||||
"`te st.txt`",
|
||||
"`te#st.txt`",
|
||||
"`te'st.txt`",
|
||||
@ -1492,6 +1536,7 @@ fn folder_with_directorycompletions() {
|
||||
folder(dir.join("another")),
|
||||
folder(dir.join("directory_completion")),
|
||||
folder(dir.join("test_a")),
|
||||
file(dir.join("test_a_symlink")),
|
||||
folder(dir.join("test_b")),
|
||||
folder(dir.join(".hidden_folder")),
|
||||
];
|
||||
@ -1594,6 +1639,12 @@ fn folder_with_directorycompletions_with_three_trailing_dots() {
|
||||
.join("...")
|
||||
.join("test_a"),
|
||||
),
|
||||
file(
|
||||
dir.join("directory_completion")
|
||||
.join("folder_inside_folder")
|
||||
.join("...")
|
||||
.join("test_a_symlink"),
|
||||
),
|
||||
folder(
|
||||
dir.join("directory_completion")
|
||||
.join("folder_inside_folder")
|
||||
@ -1666,6 +1717,13 @@ fn folder_with_directorycompletions_do_not_collapse_dots() {
|
||||
.join("..")
|
||||
.join("test_a"),
|
||||
),
|
||||
file(
|
||||
dir.join("directory_completion")
|
||||
.join("folder_inside_folder")
|
||||
.join("..")
|
||||
.join("..")
|
||||
.join("test_a_symlink"),
|
||||
),
|
||||
folder(
|
||||
dir.join("directory_completion")
|
||||
.join("folder_inside_folder")
|
||||
@ -2345,6 +2403,13 @@ fn assignment_operator_completions(mut custom_completer: NuCompleter) {
|
||||
let expected: Vec<_> = vec!["++", "++="];
|
||||
let suggestions = custom_completer.complete("$env.config.keybindings +", 25);
|
||||
match_suggestions(&expected, &suggestions);
|
||||
|
||||
// all operators for type any
|
||||
let suggestions = custom_completer.complete("ls | where name ", 16);
|
||||
assert_eq!(30, suggestions.len());
|
||||
let expected: Vec<_> = vec!["starts-with"];
|
||||
let suggestions = custom_completer.complete("ls | where name starts", 22);
|
||||
match_suggestions(&expected, &suggestions);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -5,7 +5,7 @@ edition = "2021"
|
||||
license = "MIT"
|
||||
name = "nu-cmd-base"
|
||||
repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-base"
|
||||
version = "0.102.1"
|
||||
version = "0.103.1"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@ -13,10 +13,10 @@ version = "0.102.1"
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
nu-engine = { path = "../nu-engine", version = "0.102.1", default-features = false }
|
||||
nu-parser = { path = "../nu-parser", version = "0.102.1" }
|
||||
nu-path = { path = "../nu-path", version = "0.102.1" }
|
||||
nu-protocol = { path = "../nu-protocol", version = "0.102.1", default-features = false }
|
||||
nu-engine = { path = "../nu-engine", version = "0.103.1", default-features = false }
|
||||
nu-parser = { path = "../nu-parser", version = "0.103.1" }
|
||||
nu-path = { path = "../nu-path", version = "0.103.1" }
|
||||
nu-protocol = { path = "../nu-protocol", version = "0.103.1", default-features = false }
|
||||
|
||||
indexmap = { workspace = true }
|
||||
miette = { workspace = true }
|
||||
|
@ -5,7 +5,7 @@ edition = "2021"
|
||||
license = "MIT"
|
||||
name = "nu-cmd-extra"
|
||||
repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-extra"
|
||||
version = "0.102.1"
|
||||
version = "0.103.1"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@ -16,13 +16,13 @@ bench = false
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
nu-cmd-base = { path = "../nu-cmd-base", version = "0.102.1" }
|
||||
nu-engine = { path = "../nu-engine", version = "0.102.1", default-features = false }
|
||||
nu-json = { version = "0.102.1", path = "../nu-json" }
|
||||
nu-parser = { path = "../nu-parser", version = "0.102.1" }
|
||||
nu-pretty-hex = { version = "0.102.1", path = "../nu-pretty-hex" }
|
||||
nu-protocol = { path = "../nu-protocol", version = "0.102.1", default-features = false }
|
||||
nu-utils = { path = "../nu-utils", version = "0.102.1", default-features = false }
|
||||
nu-cmd-base = { path = "../nu-cmd-base", version = "0.103.1" }
|
||||
nu-engine = { path = "../nu-engine", version = "0.103.1", default-features = false }
|
||||
nu-json = { version = "0.103.1", path = "../nu-json" }
|
||||
nu-parser = { path = "../nu-parser", version = "0.103.1" }
|
||||
nu-pretty-hex = { version = "0.103.1", path = "../nu-pretty-hex" }
|
||||
nu-protocol = { path = "../nu-protocol", version = "0.103.1", default-features = false }
|
||||
nu-utils = { path = "../nu-utils", version = "0.103.1", default-features = false }
|
||||
|
||||
# Potential dependencies for extras
|
||||
heck = { workspace = true }
|
||||
@ -37,6 +37,6 @@ itertools = { workspace = true }
|
||||
mime = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.102.1" }
|
||||
nu-command = { path = "../nu-command", version = "0.102.1" }
|
||||
nu-test-support = { path = "../nu-test-support", version = "0.102.1" }
|
||||
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.103.1" }
|
||||
nu-command = { path = "../nu-command", version = "0.103.1" }
|
||||
nu-test-support = { path = "../nu-test-support", version = "0.103.1" }
|
||||
|
@ -1,120 +0,0 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
use nu_protocol::{report_parse_warning, ParseWarning};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BitsInto;
|
||||
|
||||
impl Command for BitsInto {
|
||||
fn name(&self) -> &str {
|
||||
"into bits"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("into bits")
|
||||
.input_output_types(vec![
|
||||
(Type::Binary, Type::String),
|
||||
(Type::Int, Type::String),
|
||||
(Type::Filesize, Type::String),
|
||||
(Type::Duration, Type::String),
|
||||
(Type::String, Type::String),
|
||||
(Type::Bool, Type::String),
|
||||
(Type::table(), Type::table()),
|
||||
(Type::record(), Type::record()),
|
||||
])
|
||||
.allow_variants_without_examples(true) // TODO: supply exhaustive examples
|
||||
.rest(
|
||||
"rest",
|
||||
SyntaxShape::CellPath,
|
||||
"For a data structure input, convert data at the given cell paths.",
|
||||
)
|
||||
.category(Category::Deprecated)
|
||||
}
|
||||
|
||||
fn description(&self) -> &str {
|
||||
"Convert value to a binary string."
|
||||
}
|
||||
|
||||
fn search_terms(&self) -> Vec<&str> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let head = call.head;
|
||||
report_parse_warning(
|
||||
&StateWorkingSet::new(engine_state),
|
||||
&ParseWarning::DeprecatedWarning {
|
||||
old_command: "into bits".into(),
|
||||
new_suggestion: "use `format bits`".into(),
|
||||
span: head,
|
||||
url: "`help format bits`".into(),
|
||||
},
|
||||
);
|
||||
crate::extra::strings::format::format_bits(engine_state, stack, call, input)
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "convert a binary value into a string, padded to 8 places with 0s",
|
||||
example: "0x[1] | into bits",
|
||||
result: Some(Value::string("00000001",
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "convert an int into a string, padded to 8 places with 0s",
|
||||
example: "1 | into bits",
|
||||
result: Some(Value::string("00000001",
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "convert a filesize value into a string, padded to 8 places with 0s",
|
||||
example: "1b | into bits",
|
||||
result: Some(Value::string("00000001",
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "convert a duration value into a string, padded to 8 places with 0s",
|
||||
example: "1ns | into bits",
|
||||
result: Some(Value::string("00000001",
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "convert a boolean value into a string, padded to 8 places with 0s",
|
||||
example: "true | into bits",
|
||||
result: Some(Value::string("00000001",
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "convert a string into a raw binary string, padded with 0s to 8 places",
|
||||
example: "'nushell.sh' | into bits",
|
||||
result: Some(Value::string("01101110 01110101 01110011 01101000 01100101 01101100 01101100 00101110 01110011 01101000",
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(BitsInto {})
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
mod and;
|
||||
mod bits_;
|
||||
mod into;
|
||||
mod not;
|
||||
mod or;
|
||||
mod rotate_left;
|
||||
@ -11,7 +10,6 @@ mod xor;
|
||||
|
||||
pub use and::BitsAnd;
|
||||
pub use bits_::Bits;
|
||||
pub use into::BitsInto;
|
||||
pub use not::BitsNot;
|
||||
pub use or::BitsOr;
|
||||
pub use rotate_left::BitsRol;
|
||||
|
@ -1,74 +0,0 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
use nu_protocol::{report_parse_warning, ParseWarning};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Fmt;
|
||||
|
||||
impl Command for Fmt {
|
||||
fn name(&self) -> &str {
|
||||
"fmt"
|
||||
}
|
||||
|
||||
fn description(&self) -> &str {
|
||||
"Format a number."
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("fmt")
|
||||
.input_output_types(vec![(Type::Number, Type::record())])
|
||||
.category(Category::Deprecated)
|
||||
}
|
||||
|
||||
fn search_terms(&self) -> Vec<&str> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![Example {
|
||||
description: "Get a record containing multiple formats for the number 42",
|
||||
example: "42 | fmt",
|
||||
result: Some(Value::test_record(record! {
|
||||
"binary" => Value::test_string("0b101010"),
|
||||
"debug" => Value::test_string("42"),
|
||||
"display" => Value::test_string("42"),
|
||||
"lowerexp" => Value::test_string("4.2e1"),
|
||||
"lowerhex" => Value::test_string("0x2a"),
|
||||
"octal" => Value::test_string("0o52"),
|
||||
"upperexp" => Value::test_string("4.2E1"),
|
||||
"upperhex" => Value::test_string("0x2A"),
|
||||
})),
|
||||
}]
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let head = call.head;
|
||||
report_parse_warning(
|
||||
&StateWorkingSet::new(engine_state),
|
||||
&ParseWarning::DeprecatedWarning {
|
||||
old_command: "fmt".into(),
|
||||
new_suggestion: "use `format number`".into(),
|
||||
span: head,
|
||||
url: "`help format number`".into(),
|
||||
},
|
||||
);
|
||||
crate::extra::strings::format::format_number(engine_state, stack, call, input)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(Fmt {})
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
mod fmt;
|
||||
|
||||
pub(crate) use fmt::Fmt;
|
@ -1,9 +1,9 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathArcCos;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathArcCos {
|
||||
fn name(&self) -> &str {
|
||||
"math arccos"
|
||||
}
|
||||
@ -114,6 +114,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathArcCos {})
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathArcCosH;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathArcCosH {
|
||||
fn name(&self) -> &str {
|
||||
"math arccosh"
|
||||
}
|
||||
@ -100,6 +100,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathArcCosH {})
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathArcSin;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathArcSin {
|
||||
fn name(&self) -> &str {
|
||||
"math arcsin"
|
||||
}
|
||||
@ -115,6 +115,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathArcSin {})
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathArcSinH;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathArcSinH {
|
||||
fn name(&self) -> &str {
|
||||
"math arcsinh"
|
||||
}
|
||||
@ -88,6 +88,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathArcSinH {})
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathArcTan;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathArcTan {
|
||||
fn name(&self) -> &str {
|
||||
"math arctan"
|
||||
}
|
||||
@ -102,6 +102,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathArcTan {})
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathArcTanH;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathArcTanH {
|
||||
fn name(&self) -> &str {
|
||||
"math arctanh"
|
||||
}
|
||||
@ -101,6 +101,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathArcTanH {})
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathCos;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathCos {
|
||||
fn name(&self) -> &str {
|
||||
"math cos"
|
||||
}
|
||||
@ -108,6 +108,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathCos {})
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathCosH;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathCosH {
|
||||
fn name(&self) -> &str {
|
||||
"math cosh"
|
||||
}
|
||||
@ -88,6 +88,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathCosH {})
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathExp;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathExp {
|
||||
fn name(&self) -> &str {
|
||||
"math exp"
|
||||
}
|
||||
@ -93,6 +93,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathExp {})
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathLn;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathLn {
|
||||
fn name(&self) -> &str {
|
||||
"math ln"
|
||||
}
|
||||
@ -100,6 +100,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathLn {})
|
||||
}
|
||||
}
|
||||
|
@ -15,19 +15,19 @@ mod arcsinh;
|
||||
mod arctan;
|
||||
mod arctanh;
|
||||
|
||||
pub use cos::SubCommand as MathCos;
|
||||
pub use cosh::SubCommand as MathCosH;
|
||||
pub use sin::SubCommand as MathSin;
|
||||
pub use sinh::SubCommand as MathSinH;
|
||||
pub use tan::SubCommand as MathTan;
|
||||
pub use tanh::SubCommand as MathTanH;
|
||||
pub use cos::MathCos;
|
||||
pub use cosh::MathCosH;
|
||||
pub use sin::MathSin;
|
||||
pub use sinh::MathSinH;
|
||||
pub use tan::MathTan;
|
||||
pub use tanh::MathTanH;
|
||||
|
||||
pub use exp::SubCommand as MathExp;
|
||||
pub use ln::SubCommand as MathLn;
|
||||
pub use exp::MathExp;
|
||||
pub use ln::MathLn;
|
||||
|
||||
pub use arccos::SubCommand as MathArcCos;
|
||||
pub use arccosh::SubCommand as MathArcCosH;
|
||||
pub use arcsin::SubCommand as MathArcSin;
|
||||
pub use arcsinh::SubCommand as MathArcSinH;
|
||||
pub use arctan::SubCommand as MathArcTan;
|
||||
pub use arctanh::SubCommand as MathArcTanH;
|
||||
pub use arccos::MathArcCos;
|
||||
pub use arccosh::MathArcCosH;
|
||||
pub use arcsin::MathArcSin;
|
||||
pub use arcsinh::MathArcSinH;
|
||||
pub use arctan::MathArcTan;
|
||||
pub use arctanh::MathArcTanH;
|
||||
|
@ -1,9 +1,9 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathSin;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathSin {
|
||||
fn name(&self) -> &str {
|
||||
"math sin"
|
||||
}
|
||||
@ -108,6 +108,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathSin {})
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathSinH;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathSinH {
|
||||
fn name(&self) -> &str {
|
||||
"math sinh"
|
||||
}
|
||||
@ -87,6 +87,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathSinH {})
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathTan;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathTan {
|
||||
fn name(&self) -> &str {
|
||||
"math tan"
|
||||
}
|
||||
@ -106,6 +106,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathTan {})
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathTanH;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathTanH {
|
||||
fn name(&self) -> &str {
|
||||
"math tanh"
|
||||
}
|
||||
@ -86,6 +86,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathTanH {})
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,11 @@
|
||||
mod bits;
|
||||
mod conversions;
|
||||
mod filters;
|
||||
mod formats;
|
||||
mod math;
|
||||
mod platform;
|
||||
mod strings;
|
||||
|
||||
pub use bits::{
|
||||
Bits, BitsAnd, BitsInto, BitsNot, BitsOr, BitsRol, BitsRor, BitsShl, BitsShr, BitsXor,
|
||||
};
|
||||
pub use bits::{Bits, BitsAnd, BitsNot, BitsOr, BitsRol, BitsRor, BitsShl, BitsShr, BitsXor};
|
||||
pub use formats::ToHtml;
|
||||
pub use math::{MathArcCos, MathArcCosH, MathArcSin, MathArcSinH, MathArcTan, MathArcTanH};
|
||||
pub use math::{MathCos, MathCosH, MathSin, MathSinH, MathTan, MathTanH};
|
||||
@ -29,8 +26,6 @@ pub fn add_extra_command_context(mut engine_state: EngineState) -> EngineState {
|
||||
};
|
||||
}
|
||||
|
||||
bind_command!(conversions::Fmt);
|
||||
|
||||
bind_command!(
|
||||
filters::UpdateCells,
|
||||
filters::EachWhile,
|
||||
@ -63,7 +58,6 @@ pub fn add_extra_command_context(mut engine_state: EngineState) -> EngineState {
|
||||
bind_command! {
|
||||
Bits,
|
||||
BitsAnd,
|
||||
BitsInto,
|
||||
BitsNot,
|
||||
BitsOr,
|
||||
BitsRol,
|
||||
|
@ -111,8 +111,7 @@ impl Command for FormatBits {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: crate public only during deprecation
|
||||
pub(crate) fn format_bits(
|
||||
fn format_bits(
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
|
@ -2,8 +2,6 @@ mod bits;
|
||||
mod command;
|
||||
mod number;
|
||||
|
||||
pub(crate) use bits::FormatBits;
|
||||
pub(crate) use command::FormatPattern;
|
||||
// TODO remove `format_bits` visibility after removal of into bits
|
||||
pub(crate) use bits::{format_bits, FormatBits};
|
||||
// TODO remove `format_number` visibility after removal of into bits
|
||||
pub(crate) use number::{format_number, FormatNumber};
|
||||
pub(crate) use number::FormatNumber;
|
||||
|
@ -3,9 +3,9 @@ use heck::ToLowerCamelCase;
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct StrCamelCase;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for StrCamelCase {
|
||||
fn name(&self) -> &str {
|
||||
"str camel-case"
|
||||
}
|
||||
@ -91,6 +91,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(StrCamelCase {})
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ use heck::ToKebabCase;
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct StrKebabCase;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for StrKebabCase {
|
||||
fn name(&self) -> &str {
|
||||
"str kebab-case"
|
||||
}
|
||||
@ -90,6 +90,6 @@ mod tests {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(StrKebabCase {})
|
||||
}
|
||||
}
|
||||
|
@ -6,13 +6,13 @@ mod snake_case;
|
||||
mod str_;
|
||||
mod title_case;
|
||||
|
||||
pub use camel_case::SubCommand as StrCamelCase;
|
||||
pub use kebab_case::SubCommand as StrKebabCase;
|
||||
pub use pascal_case::SubCommand as StrPascalCase;
|
||||
pub use screaming_snake_case::SubCommand as StrScreamingSnakeCase;
|
||||
pub use snake_case::SubCommand as StrSnakeCase;
|
||||
pub use camel_case::StrCamelCase;
|
||||
pub use kebab_case::StrKebabCase;
|
||||
pub use pascal_case::StrPascalCase;
|
||||
pub use screaming_snake_case::StrScreamingSnakeCase;
|
||||
pub use snake_case::StrSnakeCase;
|
||||
pub use str_::Str;
|
||||
pub use title_case::SubCommand as StrTitleCase;
|
||||
pub use title_case::StrTitleCase;
|
||||
|
||||
use nu_cmd_base::input_handler::{operate as general_operate, CmdArgument};
|
||||
use nu_engine::command_prelude::*;
|
||||
|
@ -3,9 +3,9 @@ use heck::ToUpperCamelCase;
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct StrPascalCase;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for StrPascalCase {
|
||||
fn name(&self) -> &str {
|
||||
"str pascal-case"
|
||||
}
|
||||
@ -91,6 +91,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(StrPascalCase {})
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ use heck::ToShoutySnakeCase;
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct StrScreamingSnakeCase;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for StrScreamingSnakeCase {
|
||||
fn name(&self) -> &str {
|
||||
"str screaming-snake-case"
|
||||
}
|
||||
@ -91,6 +91,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(StrScreamingSnakeCase {})
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ use heck::ToSnakeCase;
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct StrSnakeCase;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for StrSnakeCase {
|
||||
fn name(&self) -> &str {
|
||||
"str snake-case"
|
||||
}
|
||||
@ -91,6 +91,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(StrSnakeCase {})
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ use heck::ToTitleCase;
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct StrTitleCase;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for StrTitleCase {
|
||||
fn name(&self) -> &str {
|
||||
"str title-case"
|
||||
}
|
||||
@ -86,6 +86,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(StrTitleCase {})
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-lang"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
name = "nu-cmd-lang"
|
||||
version = "0.102.1"
|
||||
version = "0.103.1"
|
||||
|
||||
[lib]
|
||||
bench = false
|
||||
@ -15,10 +15,10 @@ bench = false
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
nu-engine = { path = "../nu-engine", version = "0.102.1", default-features = false }
|
||||
nu-parser = { path = "../nu-parser", version = "0.102.1" }
|
||||
nu-protocol = { path = "../nu-protocol", version = "0.102.1", default-features = false }
|
||||
nu-utils = { path = "../nu-utils", version = "0.102.1", default-features = false }
|
||||
nu-engine = { path = "../nu-engine", version = "0.103.1", default-features = false }
|
||||
nu-parser = { path = "../nu-parser", version = "0.103.1" }
|
||||
nu-protocol = { path = "../nu-protocol", version = "0.103.1", default-features = false }
|
||||
nu-utils = { path = "../nu-utils", version = "0.103.1", default-features = false }
|
||||
|
||||
itertools = { workspace = true }
|
||||
shadow-rs = { version = "0.38", default-features = false }
|
||||
@ -42,7 +42,6 @@ plugin = [
|
||||
"os",
|
||||
]
|
||||
|
||||
mimalloc = []
|
||||
trash-support = []
|
||||
sqlite = []
|
||||
static-link-openssl = []
|
||||
|
@ -103,7 +103,7 @@ impl Command for Describe {
|
||||
"category" => Value::test_string("default"),
|
||||
)),
|
||||
)),
|
||||
"first_commit" => Value::test_string("date"),
|
||||
"first_commit" => Value::test_string("datetime"),
|
||||
"my_duration" => Value::test_string("duration"),
|
||||
)),
|
||||
))),
|
||||
|
@ -161,11 +161,7 @@ fn push_version_numbers(record: &mut Record, head: Span) {
|
||||
}
|
||||
|
||||
fn global_allocator() -> &'static str {
|
||||
if cfg!(feature = "mimalloc") {
|
||||
"mimalloc"
|
||||
} else {
|
||||
"standard"
|
||||
}
|
||||
"standard"
|
||||
}
|
||||
|
||||
fn features_enabled() -> Vec<String> {
|
||||
|
@ -5,7 +5,7 @@ edition = "2021"
|
||||
license = "MIT"
|
||||
name = "nu-cmd-plugin"
|
||||
repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-plugin"
|
||||
version = "0.102.1"
|
||||
version = "0.103.1"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@ -13,10 +13,10 @@ version = "0.102.1"
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
nu-engine = { path = "../nu-engine", version = "0.102.1" }
|
||||
nu-path = { path = "../nu-path", version = "0.102.1" }
|
||||
nu-protocol = { path = "../nu-protocol", version = "0.102.1", features = ["plugin"] }
|
||||
nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.102.1" }
|
||||
nu-engine = { path = "../nu-engine", version = "0.103.1" }
|
||||
nu-path = { path = "../nu-path", version = "0.103.1" }
|
||||
nu-protocol = { path = "../nu-protocol", version = "0.103.1", features = ["plugin"] }
|
||||
nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.103.1" }
|
||||
|
||||
itertools = { workspace = true }
|
||||
|
||||
|
@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-color-confi
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
name = "nu-color-config"
|
||||
version = "0.102.1"
|
||||
version = "0.103.1"
|
||||
|
||||
[lib]
|
||||
bench = false
|
||||
@ -14,12 +14,12 @@ bench = false
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
nu-protocol = { path = "../nu-protocol", version = "0.102.1", default-features = false }
|
||||
nu-engine = { path = "../nu-engine", version = "0.102.1", default-features = false }
|
||||
nu-json = { path = "../nu-json", version = "0.102.1" }
|
||||
nu-protocol = { path = "../nu-protocol", version = "0.103.1", default-features = false }
|
||||
nu-engine = { path = "../nu-engine", version = "0.103.1", default-features = false }
|
||||
nu-json = { path = "../nu-json", version = "0.103.1" }
|
||||
nu-ansi-term = { workspace = true }
|
||||
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
|
||||
[dev-dependencies]
|
||||
nu-test-support = { path = "../nu-test-support", version = "0.102.1" }
|
||||
nu-test-support = { path = "../nu-test-support", version = "0.103.1" }
|
@ -120,7 +120,7 @@ impl<'a> StyleComputer<'a> {
|
||||
("int".to_string(), ComputableStyle::Static(Color::White.normal())),
|
||||
("filesize".to_string(), ComputableStyle::Static(Color::Cyan.normal())),
|
||||
("duration".to_string(), ComputableStyle::Static(Color::White.normal())),
|
||||
("date".to_string(), ComputableStyle::Static(Color::Purple.normal())),
|
||||
("datetime".to_string(), ComputableStyle::Static(Color::Purple.normal())),
|
||||
("range".to_string(), ComputableStyle::Static(Color::White.normal())),
|
||||
("float".to_string(), ComputableStyle::Static(Color::White.normal())),
|
||||
("string".to_string(), ComputableStyle::Static(Color::White.normal())),
|
||||
|
@ -5,7 +5,7 @@ edition = "2021"
|
||||
license = "MIT"
|
||||
name = "nu-command"
|
||||
repository = "https://github.com/nushell/nushell/tree/main/crates/nu-command"
|
||||
version = "0.102.1"
|
||||
version = "0.103.1"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@ -16,21 +16,21 @@ bench = false
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
nu-cmd-base = { path = "../nu-cmd-base", version = "0.102.1" }
|
||||
nu-color-config = { path = "../nu-color-config", version = "0.102.1" }
|
||||
nu-engine = { path = "../nu-engine", version = "0.102.1", default-features = false }
|
||||
nu-glob = { path = "../nu-glob", version = "0.102.1" }
|
||||
nu-json = { path = "../nu-json", version = "0.102.1" }
|
||||
nu-parser = { path = "../nu-parser", version = "0.102.1" }
|
||||
nu-path = { path = "../nu-path", version = "0.102.1" }
|
||||
nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.102.1" }
|
||||
nu-protocol = { path = "../nu-protocol", version = "0.102.1", default-features = false }
|
||||
nu-system = { path = "../nu-system", version = "0.102.1" }
|
||||
nu-table = { path = "../nu-table", version = "0.102.1" }
|
||||
nu-term-grid = { path = "../nu-term-grid", version = "0.102.1" }
|
||||
nu-utils = { path = "../nu-utils", version = "0.102.1", default-features = false }
|
||||
nu-cmd-base = { path = "../nu-cmd-base", version = "0.103.1" }
|
||||
nu-color-config = { path = "../nu-color-config", version = "0.103.1" }
|
||||
nu-engine = { path = "../nu-engine", version = "0.103.1", default-features = false }
|
||||
nu-glob = { path = "../nu-glob", version = "0.103.1" }
|
||||
nu-json = { path = "../nu-json", version = "0.103.1" }
|
||||
nu-parser = { path = "../nu-parser", version = "0.103.1" }
|
||||
nu-path = { path = "../nu-path", version = "0.103.1" }
|
||||
nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.103.1" }
|
||||
nu-protocol = { path = "../nu-protocol", version = "0.103.1", default-features = false }
|
||||
nu-system = { path = "../nu-system", version = "0.103.1" }
|
||||
nu-table = { path = "../nu-table", version = "0.103.1" }
|
||||
nu-term-grid = { path = "../nu-term-grid", version = "0.103.1" }
|
||||
nu-utils = { path = "../nu-utils", version = "0.103.1", default-features = false }
|
||||
nu-ansi-term = { workspace = true }
|
||||
nuon = { path = "../nuon", version = "0.102.1" }
|
||||
nuon = { path = "../nuon", version = "0.103.1" }
|
||||
|
||||
alphanumeric-sort = { workspace = true }
|
||||
base64 = { workspace = true }
|
||||
@ -209,8 +209,8 @@ sqlite = ["rusqlite"]
|
||||
trash-support = ["trash"]
|
||||
|
||||
[dev-dependencies]
|
||||
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.102.1" }
|
||||
nu-test-support = { path = "../nu-test-support", version = "0.102.1" }
|
||||
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.103.1" }
|
||||
nu-test-support = { path = "../nu-test-support", version = "0.103.1" }
|
||||
|
||||
dirs = { workspace = true }
|
||||
mockito = { workspace = true, default-features = false }
|
||||
|
@ -13,9 +13,9 @@ impl CmdArgument for Arguments {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct IntoBinary;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for IntoBinary {
|
||||
fn name(&self) -> &str {
|
||||
"into binary"
|
||||
}
|
||||
@ -204,7 +204,7 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(IntoBinary {})
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
|
@ -2,9 +2,9 @@ use nu_cmd_base::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct IntoBool;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for IntoBool {
|
||||
fn name(&self) -> &str {
|
||||
"into bool"
|
||||
}
|
||||
@ -202,7 +202,7 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(IntoBool {})
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -49,9 +49,9 @@ impl Zone {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct IntoDatetime;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for IntoDatetime {
|
||||
fn name(&self) -> &str {
|
||||
"into datetime"
|
||||
}
|
||||
@ -408,13 +408,10 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
||||
Err(reason) => {
|
||||
match NaiveDateTime::parse_from_str(val, &dt.0) {
|
||||
Ok(d) => {
|
||||
let local_offset = *Local::now().offset();
|
||||
let dt_fixed =
|
||||
TimeZone::from_local_datetime(&local_offset, &d)
|
||||
.single()
|
||||
.unwrap_or_default();
|
||||
Local.from_local_datetime(&d).single().unwrap_or_default();
|
||||
|
||||
Value::date (dt_fixed,head)
|
||||
Value::date(dt_fixed.into(),head)
|
||||
}
|
||||
Err(_) => {
|
||||
Value::error (
|
||||
@ -498,14 +495,14 @@ fn list_human_readable_examples(span: Span) -> Value {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::{action, DatetimeFormat, SubCommand, Zone};
|
||||
use super::{action, DatetimeFormat, IntoDatetime, Zone};
|
||||
use nu_protocol::Type::Error;
|
||||
|
||||
#[test]
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(IntoDatetime {})
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -4,9 +4,9 @@ use nu_protocol::{ast::Expr, Unit};
|
||||
|
||||
const NS_PER_SEC: i64 = 1_000_000_000;
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct IntoDuration;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for IntoDuration {
|
||||
fn name(&self) -> &str {
|
||||
"into duration"
|
||||
}
|
||||
@ -277,7 +277,7 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(IntoDuration {})
|
||||
}
|
||||
|
||||
const NS_PER_SEC: i64 = 1_000_000_000;
|
||||
|
@ -4,9 +4,9 @@ use nu_engine::command_prelude::*;
|
||||
use nu_utils::get_system_locale;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct IntoFilesize;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for IntoFilesize {
|
||||
fn name(&self) -> &str {
|
||||
"into filesize"
|
||||
}
|
||||
@ -197,6 +197,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(IntoFilesize {})
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,9 @@ use nu_cmd_base::input_handler::{operate, CellPathOnlyArgs};
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct IntoFloat;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for IntoFloat {
|
||||
fn name(&self) -> &str {
|
||||
"into float"
|
||||
}
|
||||
@ -134,7 +134,7 @@ mod tests {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(IntoFloat {})
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -12,9 +12,9 @@ impl CmdArgument for Arguments {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct IntoGlob;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for IntoGlob {
|
||||
fn name(&self) -> &str {
|
||||
"into glob"
|
||||
}
|
||||
@ -121,6 +121,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(IntoGlob {})
|
||||
}
|
||||
}
|
||||
|
@ -18,9 +18,9 @@ impl CmdArgument for Arguments {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct IntoInt;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for IntoInt {
|
||||
fn name(&self) -> &str {
|
||||
"into int"
|
||||
}
|
||||
@ -521,7 +521,7 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(IntoInt {})
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -12,16 +12,16 @@ mod record;
|
||||
mod string;
|
||||
mod value;
|
||||
|
||||
pub use self::bool::SubCommand as IntoBool;
|
||||
pub use self::filesize::SubCommand as IntoFilesize;
|
||||
pub use binary::SubCommand as IntoBinary;
|
||||
pub use binary::IntoBinary;
|
||||
pub use bool::IntoBool;
|
||||
pub use cell_path::IntoCellPath;
|
||||
pub use command::Into;
|
||||
pub use datetime::SubCommand as IntoDatetime;
|
||||
pub use duration::SubCommand as IntoDuration;
|
||||
pub use float::SubCommand as IntoFloat;
|
||||
pub use glob::SubCommand as IntoGlob;
|
||||
pub use int::SubCommand as IntoInt;
|
||||
pub use record::SubCommand as IntoRecord;
|
||||
pub use string::SubCommand as IntoString;
|
||||
pub use datetime::IntoDatetime;
|
||||
pub use duration::IntoDuration;
|
||||
pub use filesize::IntoFilesize;
|
||||
pub use float::IntoFloat;
|
||||
pub use glob::IntoGlob;
|
||||
pub use int::IntoInt;
|
||||
pub use record::IntoRecord;
|
||||
pub use string::IntoString;
|
||||
pub use value::IntoValue;
|
||||
|
@ -3,9 +3,9 @@ use nu_engine::command_prelude::*;
|
||||
use nu_protocol::format_duration_as_timeperiod;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct IntoRecord;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for IntoRecord {
|
||||
fn name(&self) -> &str {
|
||||
"into record"
|
||||
}
|
||||
@ -243,6 +243,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(IntoRecord {})
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use nu_cmd_base::input_handler::{operate, CmdArgument};
|
||||
use nu_engine::command_prelude::*;
|
||||
use nu_protocol::{shell_error::into_code, Config};
|
||||
use nu_protocol::Config;
|
||||
use nu_utils::get_system_locale;
|
||||
use num_format::ToFormattedString;
|
||||
use std::sync::Arc;
|
||||
@ -19,9 +19,9 @@ impl CmdArgument for Arguments {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct IntoString;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for IntoString {
|
||||
fn name(&self) -> &str {
|
||||
"into string"
|
||||
}
|
||||
@ -215,17 +215,8 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
|
||||
}
|
||||
Value::Bool { val, .. } => Value::string(val.to_string(), span),
|
||||
Value::Date { val, .. } => Value::string(val.format("%c").to_string(), span),
|
||||
Value::String { val, .. } => {
|
||||
if group_digits {
|
||||
let number = val.parse::<i64>().unwrap_or_default();
|
||||
let decimal_value = digits.unwrap_or(0) as usize;
|
||||
Value::string(format_int(number, group_digits, decimal_value), span)
|
||||
} else {
|
||||
Value::string(val.to_string(), span)
|
||||
}
|
||||
}
|
||||
Value::Glob { val, .. } => Value::string(val.to_string(), span),
|
||||
|
||||
Value::String { val, .. } => Value::string(val, span),
|
||||
Value::Glob { val, .. } => Value::string(val, span),
|
||||
Value::Filesize { val, .. } => {
|
||||
if group_digits {
|
||||
let decimal_value = digits.unwrap_or(0) as usize;
|
||||
@ -235,8 +226,6 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
|
||||
}
|
||||
}
|
||||
Value::Duration { val: _, .. } => Value::string(input.to_expanded_string("", config), span),
|
||||
|
||||
Value::Error { error, .. } => Value::string(into_code(error).unwrap_or_default(), span),
|
||||
Value::Nothing { .. } => Value::string("".to_string(), span),
|
||||
Value::Record { .. } => Value::error(
|
||||
// Watch out for CantConvert's argument order
|
||||
@ -272,6 +261,7 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
|
||||
})
|
||||
.unwrap_or_else(|err| Value::error(err, span))
|
||||
}
|
||||
Value::Error { .. } => input.clone(),
|
||||
x => Value::error(
|
||||
ShellError::CantConvert {
|
||||
to_type: String::from("string"),
|
||||
@ -316,6 +306,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(IntoString {})
|
||||
}
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ fn process_cell(val: Value, display_as_filesizes: bool, span: Span) -> Result<Va
|
||||
}
|
||||
} else if DATETIME_DMY_RE.is_match(&val_str).unwrap_or(false) {
|
||||
let dt = parse_date_from_string(&val_str, span).map_err(|_| ShellError::CantConvert {
|
||||
to_type: "date".to_string(),
|
||||
to_type: "datetime".to_string(),
|
||||
from_type: "string".to_string(),
|
||||
span,
|
||||
help: Some(format!(
|
||||
@ -219,7 +219,7 @@ fn process_cell(val: Value, display_as_filesizes: bool, span: Span) -> Result<Va
|
||||
Ok(Value::date(dt, span))
|
||||
} else if DATETIME_YMD_RE.is_match(&val_str).unwrap_or(false) {
|
||||
let dt = parse_date_from_string(&val_str, span).map_err(|_| ShellError::CantConvert {
|
||||
to_type: "date".to_string(),
|
||||
to_type: "datetime".to_string(),
|
||||
from_type: "string".to_string(),
|
||||
span,
|
||||
help: Some(format!(
|
||||
@ -230,7 +230,7 @@ fn process_cell(val: Value, display_as_filesizes: bool, span: Span) -> Result<Va
|
||||
Ok(Value::date(dt, span))
|
||||
} else if DATETIME_YMDZ_RE.is_match(&val_str).unwrap_or(false) {
|
||||
let dt = parse_date_from_string(&val_str, span).map_err(|_| ShellError::CantConvert {
|
||||
to_type: "date".to_string(),
|
||||
to_type: "datetime".to_string(),
|
||||
from_type: "string".to_string(),
|
||||
span,
|
||||
help: Some(format!(
|
||||
|
@ -4,4 +4,4 @@ mod split_cell_path;
|
||||
|
||||
pub use fill::Fill;
|
||||
pub use into::*;
|
||||
pub use split_cell_path::SubCommand as SplitCellPath;
|
||||
pub use split_cell_path::SplitCellPath;
|
||||
|
@ -2,9 +2,9 @@ use nu_engine::command_prelude::*;
|
||||
use nu_protocol::{ast::PathMember, IntoValue};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct SplitCellPath;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for SplitCellPath {
|
||||
fn name(&self) -> &str {
|
||||
"split cell-path"
|
||||
}
|
||||
@ -150,6 +150,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(SplitCellPath {})
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,9 @@ use chrono_humanize::HumanTime;
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct DateHumanize;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for DateHumanize {
|
||||
fn name(&self) -> &str {
|
||||
"date humanize"
|
||||
}
|
||||
@ -101,6 +101,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(DateHumanize {})
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,9 @@ use chrono_tz::TZ_VARIANTS;
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct DateListTimezones;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for DateListTimezones {
|
||||
fn name(&self) -> &str {
|
||||
"date list-timezone"
|
||||
}
|
||||
|
@ -7,8 +7,8 @@ mod to_timezone;
|
||||
mod utils;
|
||||
|
||||
pub use date_::Date;
|
||||
pub use humanize::SubCommand as DateHumanize;
|
||||
pub use list_timezone::SubCommand as DateListTimezones;
|
||||
pub use now::SubCommand as DateNow;
|
||||
pub use to_timezone::SubCommand as DateToTimezone;
|
||||
pub use humanize::DateHumanize;
|
||||
pub use list_timezone::DateListTimezones;
|
||||
pub use now::DateNow;
|
||||
pub use to_timezone::DateToTimezone;
|
||||
pub(crate) use utils::{generate_strftime_list, parse_date_from_string};
|
||||
|
@ -2,9 +2,9 @@ use chrono::Local;
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct DateNow;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for DateNow {
|
||||
fn name(&self) -> &str {
|
||||
"date now"
|
||||
}
|
||||
|
@ -4,9 +4,9 @@ use chrono::{DateTime, FixedOffset, Local, LocalResult, TimeZone};
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct DateToTimezone;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for DateToTimezone {
|
||||
fn name(&self) -> &str {
|
||||
"date to-timezone"
|
||||
}
|
||||
@ -147,6 +147,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(DateToTimezone {})
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,6 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
|
||||
ParEach,
|
||||
ChunkBy,
|
||||
Prepend,
|
||||
Range,
|
||||
Reduce,
|
||||
Reject,
|
||||
Rename,
|
||||
@ -455,7 +454,7 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
|
||||
Job,
|
||||
};
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(all(unix, feature = "os"))]
|
||||
bind_command! {
|
||||
JobUnfreeze,
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ fn convert_string_to_value(
|
||||
Err(x) => match x {
|
||||
nu_json::Error::Syntax(_, row, col) => {
|
||||
let label = x.to_string();
|
||||
let label_span = convert_row_column_to_span(row, col, string_input);
|
||||
let label_span = Span::from_row_column(row, col, string_input);
|
||||
Err(ShellError::GenericError {
|
||||
error: "Error while parsing JSON text".into(),
|
||||
msg: "error parsing JSON text".into(),
|
||||
@ -173,23 +173,3 @@ fn expand_closure(
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
// Converts row+column to a Span, assuming bytes (1-based rows)
|
||||
fn convert_row_column_to_span(row: usize, col: usize, contents: &str) -> Span {
|
||||
let mut cur_row = 1;
|
||||
let mut cur_col = 1;
|
||||
|
||||
for (offset, curr_byte) in contents.bytes().enumerate() {
|
||||
if curr_byte == b'\n' {
|
||||
cur_row += 1;
|
||||
cur_col = 1;
|
||||
}
|
||||
if cur_row >= row && cur_col >= col {
|
||||
return Span::new(offset, offset);
|
||||
} else {
|
||||
cur_col += 1;
|
||||
}
|
||||
}
|
||||
|
||||
Span::new(contents.len(), contents.len())
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ use std::{
|
||||
|
||||
use nu_engine::{command_prelude::*, ClosureEvalOnce};
|
||||
use nu_protocol::{
|
||||
engine::{Closure, Job, ThreadJob},
|
||||
report_shell_error, Signals,
|
||||
engine::{Closure, Job, Redirection, ThreadJob},
|
||||
report_shell_error, OutDest, Signals,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -76,15 +76,18 @@ impl Command for JobSpawn {
|
||||
let result = thread::Builder::new()
|
||||
.name(format!("background job {}", id.get()))
|
||||
.spawn(move || {
|
||||
ClosureEvalOnce::new(&job_state, &job_stack, closure)
|
||||
let mut stack = job_stack.reset_pipes();
|
||||
let stack = stack.push_redirection(
|
||||
Some(Redirection::Pipe(OutDest::Null)),
|
||||
Some(Redirection::Pipe(OutDest::Null)),
|
||||
);
|
||||
ClosureEvalOnce::new_preserve_out_dest(&job_state, &stack, closure)
|
||||
.run_with_input(Value::nothing(head).into_pipeline_data())
|
||||
.and_then(|data| data.into_value(head))
|
||||
.and_then(|data| data.drain())
|
||||
.unwrap_or_else(|err| {
|
||||
if !job_state.signals().interrupted() {
|
||||
report_shell_error(&job_state, &err);
|
||||
}
|
||||
|
||||
Value::nothing(head)
|
||||
});
|
||||
|
||||
{
|
||||
|
@ -4,7 +4,7 @@ mod job_kill;
|
||||
mod job_list;
|
||||
mod job_spawn;
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(all(unix, feature = "os"))]
|
||||
mod job_unfreeze;
|
||||
|
||||
pub use is_admin::IsAdmin;
|
||||
@ -14,5 +14,5 @@ pub use job_list::JobList;
|
||||
|
||||
pub use job_spawn::JobSpawn;
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(all(unix, feature = "os"))]
|
||||
pub use job_unfreeze::JobUnfreeze;
|
||||
|
@ -802,7 +802,7 @@ mod windows_helper {
|
||||
use std::os::windows::prelude::OsStrExt;
|
||||
use windows::Win32::Foundation::FILETIME;
|
||||
use windows::Win32::Storage::FileSystem::{
|
||||
FindFirstFileW, FILE_ATTRIBUTE_DIRECTORY, FILE_ATTRIBUTE_READONLY,
|
||||
FindClose, FindFirstFileW, FILE_ATTRIBUTE_DIRECTORY, FILE_ATTRIBUTE_READONLY,
|
||||
FILE_ATTRIBUTE_REPARSE_POINT, WIN32_FIND_DATAW,
|
||||
};
|
||||
use windows::Win32::System::SystemServices::{
|
||||
@ -925,7 +925,14 @@ mod windows_helper {
|
||||
windows::core::PCWSTR(filename_wide.as_ptr()),
|
||||
&mut find_data,
|
||||
) {
|
||||
Ok(_) => Ok(find_data),
|
||||
Ok(handle) => {
|
||||
// Don't forget to close the Find handle
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-findfirstfilew#remarks
|
||||
// Assumption: WIN32_FIND_DATAW is a pure data struct, so we can let our
|
||||
// find_data outlive the handle.
|
||||
let _ = FindClose(handle);
|
||||
Ok(find_data)
|
||||
}
|
||||
Err(e) => Err(ShellError::Io(IoError::new_with_additional_context(
|
||||
std::io::ErrorKind::Other,
|
||||
span,
|
||||
|
@ -1,11 +1,15 @@
|
||||
#[allow(deprecated)]
|
||||
use nu_engine::{command_prelude::*, current_dir, get_eval_block};
|
||||
use nu_engine::{command_prelude::*, current_dir, eval_call};
|
||||
use nu_protocol::{
|
||||
ast,
|
||||
debugger::{WithDebug, WithoutDebug},
|
||||
shell_error::{self, io::IoError},
|
||||
DataSource, NuGlob, PipelineMetadata,
|
||||
};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
use crate::database::SQLiteDatabase;
|
||||
@ -63,7 +67,6 @@ impl Command for Open {
|
||||
#[allow(deprecated)]
|
||||
let cwd = current_dir(engine_state, stack)?;
|
||||
let mut paths = call.rest::<Spanned<NuGlob>>(engine_state, stack, 0)?;
|
||||
let eval_block = get_eval_block(engine_state);
|
||||
|
||||
if paths.is_empty() && !call.has_positional_args(stack, 0) {
|
||||
// try to use path from pipeline input if there were no positional or spread args
|
||||
@ -192,13 +195,16 @@ impl Command for Open {
|
||||
|
||||
match converter {
|
||||
Some((converter_id, ext)) => {
|
||||
let decl = engine_state.get_decl(converter_id);
|
||||
let command_output = if let Some(block_id) = decl.block_id() {
|
||||
let block = engine_state.get_block(block_id);
|
||||
eval_block(engine_state, stack, block, stream)
|
||||
let open_call = ast::Call {
|
||||
decl_id: converter_id,
|
||||
head: call_span,
|
||||
arguments: vec![],
|
||||
parser_info: HashMap::new(),
|
||||
};
|
||||
let command_output = if engine_state.is_debugging() {
|
||||
eval_call::<WithDebug>(engine_state, stack, &open_call, stream)
|
||||
} else {
|
||||
let call = ast::Call::new(call_span);
|
||||
decl.run(engine_state, stack, &(&call).into(), stream)
|
||||
eval_call::<WithoutDebug>(engine_state, stack, &open_call, stream)
|
||||
};
|
||||
output.push(command_output.map_err(|inner| {
|
||||
ShellError::GenericError{
|
||||
|
@ -158,17 +158,15 @@ impl Command for UTouch {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut expanded_globs = glob(
|
||||
&file_path.to_string_lossy(),
|
||||
Some(engine_state.signals().clone()),
|
||||
)
|
||||
.unwrap_or_else(|_| {
|
||||
panic!(
|
||||
"Failed to process file path: {}",
|
||||
&file_path.to_string_lossy()
|
||||
)
|
||||
})
|
||||
.peekable();
|
||||
let mut expanded_globs =
|
||||
glob(&file_path.to_string_lossy(), engine_state.signals().clone())
|
||||
.unwrap_or_else(|_| {
|
||||
panic!(
|
||||
"Failed to process file path: {}",
|
||||
&file_path.to_string_lossy()
|
||||
)
|
||||
})
|
||||
.peekable();
|
||||
|
||||
if expanded_globs.peek().is_none() {
|
||||
let file_name = file_path.file_name().unwrap_or_else(|| {
|
||||
|
@ -23,6 +23,11 @@ impl Command for Default {
|
||||
SyntaxShape::String,
|
||||
"The name of the column.",
|
||||
)
|
||||
.switch(
|
||||
"empty",
|
||||
"also replace empty items like \"\", {}, and []",
|
||||
Some('e'),
|
||||
)
|
||||
.category(Category::Filters)
|
||||
}
|
||||
|
||||
@ -37,7 +42,8 @@ impl Command for Default {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
default(engine_state, stack, call, input)
|
||||
let empty = call.has_flag(engine_state, stack, "empty")?;
|
||||
default(engine_state, stack, call, input, empty)
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
@ -80,6 +86,20 @@ impl Command for Default {
|
||||
}),
|
||||
])),
|
||||
},
|
||||
Example {
|
||||
description: r#"Replace the empty string in the "a" column of a list"#,
|
||||
example: "[{a:1 b:2} {a:'' b:1}] | default -e 'N/A' a",
|
||||
result: Some(Value::test_list(vec![
|
||||
Value::test_record(record! {
|
||||
"a" => Value::test_int(1),
|
||||
"b" => Value::test_int(2),
|
||||
}),
|
||||
Value::test_record(record! {
|
||||
"a" => Value::test_string("N/A"),
|
||||
"b" => Value::test_int(1),
|
||||
}),
|
||||
])),
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -89,6 +109,7 @@ fn default(
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
default_when_empty: bool,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let metadata = input.metadata();
|
||||
let value: Value = call.req(engine_state, stack, 0)?;
|
||||
@ -104,7 +125,9 @@ fn default(
|
||||
} => {
|
||||
let record = record.to_mut();
|
||||
if let Some(val) = record.get_mut(&column.item) {
|
||||
if matches!(val, Value::Nothing { .. }) {
|
||||
if matches!(val, Value::Nothing { .. })
|
||||
|| (default_when_empty && val.is_empty())
|
||||
{
|
||||
*val = value.clone();
|
||||
}
|
||||
} else {
|
||||
@ -118,7 +141,10 @@ fn default(
|
||||
engine_state.signals(),
|
||||
)
|
||||
.map(|x| x.set_metadata(metadata))
|
||||
} else if input.is_nothing() {
|
||||
} else if input.is_nothing()
|
||||
|| (default_when_empty
|
||||
&& matches!(input, PipelineData::Value(ref value, _) if value.is_empty()))
|
||||
{
|
||||
Ok(value.into_pipeline_data())
|
||||
} else {
|
||||
Ok(input)
|
||||
|
@ -31,7 +31,6 @@ mod merge;
|
||||
mod move_;
|
||||
mod par_each;
|
||||
mod prepend;
|
||||
mod range;
|
||||
mod reduce;
|
||||
mod reject;
|
||||
mod rename;
|
||||
@ -91,7 +90,6 @@ pub use merge::MergeDeep;
|
||||
pub use move_::Move;
|
||||
pub use par_each::ParEach;
|
||||
pub use prepend::Prepend;
|
||||
pub use range::Range;
|
||||
pub use reduce::Reduce;
|
||||
pub use reject::Reject;
|
||||
pub use rename::Rename;
|
||||
|
@ -1,90 +0,0 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
use nu_protocol::{report_parse_warning, ParseWarning};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Range;
|
||||
|
||||
impl Command for Range {
|
||||
fn name(&self) -> &str {
|
||||
"range"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("range")
|
||||
.input_output_types(vec![(
|
||||
Type::List(Box::new(Type::Any)),
|
||||
Type::List(Box::new(Type::Any)),
|
||||
)])
|
||||
.required("rows", SyntaxShape::Range, "Range of rows to return.")
|
||||
.category(Category::Deprecated)
|
||||
}
|
||||
|
||||
fn description(&self) -> &str {
|
||||
"Return only the selected rows."
|
||||
}
|
||||
|
||||
fn search_terms(&self) -> Vec<&str> {
|
||||
vec!["filter", "head", "tail", "slice"]
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
example: "[0,1,2,3,4,5] | range 4..5",
|
||||
description: "Get the last 2 items",
|
||||
result: Some(Value::list(
|
||||
vec![Value::test_int(4), Value::test_int(5)],
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
example: "[0,1,2,3,4,5] | range (-2)..",
|
||||
description: "Get the last 2 items",
|
||||
result: Some(Value::list(
|
||||
vec![Value::test_int(4), Value::test_int(5)],
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
example: "[0,1,2,3,4,5] | range (-3)..-2",
|
||||
description: "Get the next to last 2 items",
|
||||
result: Some(Value::list(
|
||||
vec![Value::test_int(3), Value::test_int(4)],
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let head = call.head;
|
||||
report_parse_warning(
|
||||
&StateWorkingSet::new(engine_state),
|
||||
&ParseWarning::DeprecatedWarning {
|
||||
old_command: "range".into(),
|
||||
new_suggestion: "use `slice`".into(),
|
||||
span: head,
|
||||
url: "`help slice`".into(),
|
||||
},
|
||||
);
|
||||
super::Slice::run(&super::Slice, engine_state, stack, call, input)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(Range {})
|
||||
}
|
||||
}
|
@ -184,26 +184,6 @@ fn convert_nujson_to_value(value: nu_json::Value, span: Span) -> Value {
|
||||
}
|
||||
}
|
||||
|
||||
// Converts row+column to a Span, assuming bytes (1-based rows)
|
||||
fn convert_row_column_to_span(row: usize, col: usize, contents: &str) -> Span {
|
||||
let mut cur_row = 1;
|
||||
let mut cur_col = 1;
|
||||
|
||||
for (offset, curr_byte) in contents.bytes().enumerate() {
|
||||
if curr_byte == b'\n' {
|
||||
cur_row += 1;
|
||||
cur_col = 1;
|
||||
}
|
||||
if cur_row >= row && cur_col >= col {
|
||||
return Span::new(offset, offset);
|
||||
} else {
|
||||
cur_col += 1;
|
||||
}
|
||||
}
|
||||
|
||||
Span::new(contents.len(), contents.len())
|
||||
}
|
||||
|
||||
fn convert_string_to_value(string_input: &str, span: Span) -> Result<Value, ShellError> {
|
||||
match nu_json::from_str(string_input) {
|
||||
Ok(value) => Ok(convert_nujson_to_value(value, span)),
|
||||
@ -211,7 +191,7 @@ fn convert_string_to_value(string_input: &str, span: Span) -> Result<Value, Shel
|
||||
Err(x) => match x {
|
||||
nu_json::Error::Syntax(_, row, col) => {
|
||||
let label = x.to_string();
|
||||
let label_span = convert_row_column_to_span(row, col, string_input);
|
||||
let label_span = Span::from_row_column(row, col, string_input);
|
||||
Err(ShellError::GenericError {
|
||||
error: "Error while parsing JSON text".into(),
|
||||
msg: "error parsing JSON text".into(),
|
||||
@ -240,7 +220,7 @@ fn convert_string_to_value_strict(string_input: &str, span: Span) -> Result<Valu
|
||||
Ok(value) => Ok(convert_nujson_to_value(value, span)),
|
||||
Err(err) => Err(if err.is_syntax() {
|
||||
let label = err.to_string();
|
||||
let label_span = convert_row_column_to_span(err.line(), err.column(), string_input);
|
||||
let label_span = Span::from_row_column(err.line(), err.column(), string_input);
|
||||
ShellError::GenericError {
|
||||
error: "Error while parsing JSON text".into(),
|
||||
msg: "error parsing JSON text".into(),
|
||||
|
@ -2,7 +2,7 @@ use crate::formats::nu_xml_format::{COLUMN_ATTRS_NAME, COLUMN_CONTENT_NAME, COLU
|
||||
use indexmap::IndexMap;
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
use roxmltree::NodeType;
|
||||
use roxmltree::{NodeType, ParsingOptions, TextPos};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FromXml;
|
||||
@ -16,6 +16,11 @@ impl Command for FromXml {
|
||||
Signature::build("from xml")
|
||||
.input_output_types(vec![(Type::String, Type::record())])
|
||||
.switch("keep-comments", "add comment nodes to result", None)
|
||||
.switch(
|
||||
"allow-dtd",
|
||||
"allow parsing documents with DTDs (may result in exponential entity expansion)",
|
||||
None,
|
||||
)
|
||||
.switch(
|
||||
"keep-pi",
|
||||
"add processing instruction nodes to result",
|
||||
@ -50,10 +55,12 @@ string. This way content of every tag is always a table and is easier to parse"#
|
||||
let head = call.head;
|
||||
let keep_comments = call.has_flag(engine_state, stack, "keep-comments")?;
|
||||
let keep_processing_instructions = call.has_flag(engine_state, stack, "keep-pi")?;
|
||||
let allow_dtd = call.has_flag(engine_state, stack, "allow-dtd")?;
|
||||
let info = ParsingInfo {
|
||||
span: head,
|
||||
keep_comments,
|
||||
keep_processing_instructions,
|
||||
allow_dtd,
|
||||
};
|
||||
from_xml(input, &info)
|
||||
}
|
||||
@ -90,6 +97,7 @@ struct ParsingInfo {
|
||||
span: Span,
|
||||
keep_comments: bool,
|
||||
keep_processing_instructions: bool,
|
||||
allow_dtd: bool,
|
||||
}
|
||||
|
||||
fn from_attributes_to_value(attributes: &[roxmltree::Attribute], info: &ParsingInfo) -> Value {
|
||||
@ -198,7 +206,12 @@ fn from_document_to_value(d: &roxmltree::Document, info: &ParsingInfo) -> Value
|
||||
}
|
||||
|
||||
fn from_xml_string_to_value(s: &str, info: &ParsingInfo) -> Result<Value, roxmltree::Error> {
|
||||
let parsed = roxmltree::Document::parse(s)?;
|
||||
let options = ParsingOptions {
|
||||
allow_dtd: info.allow_dtd,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let parsed = roxmltree::Document::parse_with_options(s, options)?;
|
||||
Ok(from_document_to_value(&parsed, info))
|
||||
}
|
||||
|
||||
@ -209,116 +222,135 @@ fn from_xml(input: PipelineData, info: &ParsingInfo) -> Result<PipelineData, She
|
||||
Ok(x) => {
|
||||
Ok(x.into_pipeline_data_with_metadata(metadata.map(|md| md.with_content_type(None))))
|
||||
}
|
||||
Err(err) => Err(process_xml_parse_error(err, span)),
|
||||
Err(err) => Err(process_xml_parse_error(concat_string, err, span)),
|
||||
}
|
||||
}
|
||||
|
||||
fn process_xml_parse_error(err: roxmltree::Error, span: Span) -> ShellError {
|
||||
fn process_xml_parse_error(source: String, err: roxmltree::Error, span: Span) -> ShellError {
|
||||
match err {
|
||||
roxmltree::Error::InvalidXmlPrefixUri(_) => make_cant_convert_error(
|
||||
roxmltree::Error::InvalidXmlPrefixUri(pos) => make_xml_error_spanned(
|
||||
"The `xmlns:xml` attribute must have an <http://www.w3.org/XML/1998/namespace> URI.",
|
||||
span,
|
||||
source, pos,
|
||||
),
|
||||
roxmltree::Error::UnexpectedXmlUri(_) => make_cant_convert_error(
|
||||
roxmltree::Error::UnexpectedXmlUri(pos) => make_xml_error_spanned(
|
||||
"Only the xmlns:xml attribute can have the http://www.w3.org/XML/1998/namespace URI.",
|
||||
span,
|
||||
source, pos,
|
||||
),
|
||||
roxmltree::Error::UnexpectedXmlnsUri(_) => make_cant_convert_error(
|
||||
roxmltree::Error::UnexpectedXmlnsUri(pos) => make_xml_error_spanned(
|
||||
"The http://www.w3.org/2000/xmlns/ URI must not be declared.",
|
||||
span,
|
||||
source, pos,
|
||||
),
|
||||
roxmltree::Error::InvalidElementNamePrefix(_) => {
|
||||
make_cant_convert_error("xmlns can't be used as an element prefix.", span)
|
||||
roxmltree::Error::InvalidElementNamePrefix(pos) => {
|
||||
make_xml_error_spanned("xmlns can't be used as an element prefix.", source, pos)
|
||||
}
|
||||
roxmltree::Error::DuplicatedNamespace(_, _) => {
|
||||
make_cant_convert_error("A namespace was already defined on this element.", span)
|
||||
roxmltree::Error::DuplicatedNamespace(namespace, pos) => {
|
||||
make_xml_error_spanned(format!("Namespace {namespace} was already defined on this element."), source, pos)
|
||||
}
|
||||
roxmltree::Error::UnknownNamespace(prefix, _) => {
|
||||
make_cant_convert_error(format!("Unknown prefix {}", prefix), span)
|
||||
roxmltree::Error::UnknownNamespace(prefix, pos) => {
|
||||
make_xml_error_spanned(format!("Unknown prefix {}", prefix), source, pos)
|
||||
}
|
||||
roxmltree::Error::UnexpectedCloseTag { .. } => {
|
||||
make_cant_convert_error("Unexpected close tag", span)
|
||||
roxmltree::Error::UnexpectedCloseTag(expected, actual, pos) => {
|
||||
make_xml_error_spanned(format!("Unexpected close tag {actual}, expected {expected}"), source, pos)
|
||||
}
|
||||
roxmltree::Error::UnexpectedEntityCloseTag(_) => {
|
||||
make_cant_convert_error("Entity value starts with a close tag.", span)
|
||||
roxmltree::Error::UnexpectedEntityCloseTag(pos) => {
|
||||
make_xml_error_spanned("Entity value starts with a close tag.", source, pos)
|
||||
}
|
||||
roxmltree::Error::UnknownEntityReference(_, _) => make_cant_convert_error(
|
||||
"A reference to an entity that was not defined in the DTD.",
|
||||
span,
|
||||
roxmltree::Error::UnknownEntityReference(entity, pos) => make_xml_error_spanned(
|
||||
format!("Reference to unknown entity {entity} (was not defined in the DTD)"),
|
||||
source, pos,
|
||||
),
|
||||
roxmltree::Error::MalformedEntityReference(_) => {
|
||||
make_cant_convert_error("A malformed entity reference.", span)
|
||||
roxmltree::Error::MalformedEntityReference(pos) => {
|
||||
make_xml_error_spanned("Malformed entity reference.", source, pos)
|
||||
}
|
||||
roxmltree::Error::EntityReferenceLoop(_) => {
|
||||
make_cant_convert_error("A possible entity reference loop.", span)
|
||||
roxmltree::Error::EntityReferenceLoop(pos) => {
|
||||
make_xml_error_spanned("Possible entity reference loop.", source, pos)
|
||||
}
|
||||
roxmltree::Error::InvalidAttributeValue(_) => {
|
||||
make_cant_convert_error("Attribute value cannot have a < character.", span)
|
||||
roxmltree::Error::InvalidAttributeValue(pos) => {
|
||||
make_xml_error_spanned("Attribute value cannot have a < character.", source, pos)
|
||||
}
|
||||
roxmltree::Error::DuplicatedAttribute(_, _) => {
|
||||
make_cant_convert_error("An element has a duplicated attributes.", span)
|
||||
roxmltree::Error::DuplicatedAttribute(attribute, pos) => {
|
||||
make_xml_error_spanned(format!("Element has a duplicated attribute: {attribute}"), source, pos)
|
||||
}
|
||||
roxmltree::Error::NoRootNode => {
|
||||
make_cant_convert_error("The XML document must have at least one element.", span)
|
||||
make_xml_error("The XML document must have at least one element.", span)
|
||||
}
|
||||
roxmltree::Error::UnclosedRootNode => {
|
||||
make_cant_convert_error("The root node was opened but never closed.", span)
|
||||
make_xml_error("The root node was opened but never closed.", span)
|
||||
}
|
||||
roxmltree::Error::DtdDetected => make_cant_convert_error(
|
||||
"An XML with DTD detected. DTDs are currently disabled due to security reasons.",
|
||||
span,
|
||||
roxmltree::Error::DtdDetected => make_xml_error(
|
||||
"XML document with DTD detected.\nDTDs are disabled by default to prevent denial-of-service attacks (use --allow-dtd to parse anyway)",
|
||||
span
|
||||
),
|
||||
roxmltree::Error::NodesLimitReached => {
|
||||
make_cant_convert_error("Node limit was reached.", span)
|
||||
make_xml_error("Node limit was reached.", span)
|
||||
}
|
||||
roxmltree::Error::AttributesLimitReached => {
|
||||
make_cant_convert_error("Attribute limit reached", span)
|
||||
make_xml_error("Attribute limit reached", span)
|
||||
}
|
||||
roxmltree::Error::NamespacesLimitReached => {
|
||||
make_cant_convert_error("Namespace limit reached", span)
|
||||
make_xml_error("Namespace limit reached", span)
|
||||
}
|
||||
roxmltree::Error::UnexpectedDeclaration(_) => {
|
||||
make_cant_convert_error("An XML document can have only one XML declaration and it must be at the start of the document.", span)
|
||||
roxmltree::Error::UnexpectedDeclaration(pos) => {
|
||||
make_xml_error_spanned("An XML document can have only one XML declaration and it must be at the start of the document.", source, pos)
|
||||
}
|
||||
roxmltree::Error::InvalidName(_) => {
|
||||
make_cant_convert_error("Invalid name found.", span)
|
||||
roxmltree::Error::InvalidName(pos) => {
|
||||
make_xml_error_spanned("Invalid name.", source, pos)
|
||||
}
|
||||
roxmltree::Error::NonXmlChar(_, _) => {
|
||||
make_cant_convert_error("A non-XML character has occurred. Valid characters are: <https://www.w3.org/TR/xml/#char32>", span)
|
||||
roxmltree::Error::NonXmlChar(_, pos) => {
|
||||
make_xml_error_spanned("Non-XML character found. Valid characters are: <https://www.w3.org/TR/xml/#char32>", source, pos)
|
||||
}
|
||||
roxmltree::Error::InvalidChar(_, _, _) => {
|
||||
make_cant_convert_error("An invalid/unexpected character in XML.", span)
|
||||
roxmltree::Error::InvalidChar(expected, actual, pos) => {
|
||||
make_xml_error_spanned(
|
||||
format!("Unexpected character {}, expected {}", actual as char, expected as char),
|
||||
source,
|
||||
pos
|
||||
)
|
||||
}
|
||||
roxmltree::Error::InvalidChar2(_, _, _) => {
|
||||
make_cant_convert_error("An invalid/unexpected character in XML.", span)
|
||||
roxmltree::Error::InvalidChar2(expected, actual, pos) => {
|
||||
make_xml_error_spanned(
|
||||
format!("Unexpected character {}, expected {}", actual as char, expected),
|
||||
source,
|
||||
pos
|
||||
)
|
||||
}
|
||||
roxmltree::Error::InvalidString(_, _) => {
|
||||
make_cant_convert_error("An invalid/unexpected string in XML.", span)
|
||||
roxmltree::Error::InvalidString(_, pos) => {
|
||||
make_xml_error_spanned("Invalid/unexpected string in XML.", source, pos)
|
||||
}
|
||||
roxmltree::Error::InvalidExternalID(_) => {
|
||||
make_cant_convert_error("An invalid ExternalID in the DTD.", span)
|
||||
roxmltree::Error::InvalidExternalID(pos) => {
|
||||
make_xml_error_spanned("Invalid ExternalID in the DTD.", source, pos)
|
||||
}
|
||||
roxmltree::Error::InvalidComment(_) => {
|
||||
make_cant_convert_error("A comment cannot contain `--` or end with `-`.", span)
|
||||
roxmltree::Error::InvalidComment(pos) => {
|
||||
make_xml_error_spanned("A comment cannot contain `--` or end with `-`.", source, pos)
|
||||
}
|
||||
roxmltree::Error::InvalidCharacterData(_) => {
|
||||
make_cant_convert_error("A Character Data node contains an invalid data. Currently, only `]]>` is not allowed.", span)
|
||||
roxmltree::Error::InvalidCharacterData(pos) => {
|
||||
make_xml_error_spanned("Character Data node contains an invalid data. Currently, only `]]>` is not allowed.", source, pos)
|
||||
}
|
||||
roxmltree::Error::UnknownToken(_) => {
|
||||
make_cant_convert_error("Unknown token in XML.", span)
|
||||
roxmltree::Error::UnknownToken(pos) => {
|
||||
make_xml_error_spanned("Unknown token in XML.", source, pos)
|
||||
}
|
||||
roxmltree::Error::UnexpectedEndOfStream => {
|
||||
make_cant_convert_error("Unexpected end of stream while parsing XML.", span)
|
||||
make_xml_error("Unexpected end of stream while parsing XML.", span)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn make_cant_convert_error(help: impl Into<String>, span: Span) -> ShellError {
|
||||
ShellError::CantConvert {
|
||||
from_type: Type::String.to_string(),
|
||||
to_type: "XML".to_string(),
|
||||
fn make_xml_error(msg: impl Into<String>, span: Span) -> ShellError {
|
||||
ShellError::GenericError {
|
||||
error: "Failed to parse XML".into(),
|
||||
msg: msg.into(),
|
||||
help: None,
|
||||
span: Some(span),
|
||||
inner: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn make_xml_error_spanned(msg: impl Into<String>, src: String, pos: TextPos) -> ShellError {
|
||||
let span = Span::from_row_column(pos.row as usize, pos.col as usize, &src);
|
||||
ShellError::OutsideSpannedLabeledError {
|
||||
src,
|
||||
error: "Failed to parse XML".into(),
|
||||
msg: msg.into(),
|
||||
span,
|
||||
help: Some(help.into()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -375,6 +407,7 @@ mod tests {
|
||||
span: Span::test_data(),
|
||||
keep_comments: false,
|
||||
keep_processing_instructions: false,
|
||||
allow_dtd: false,
|
||||
};
|
||||
from_xml_string_to_value(xml, &info)
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ impl Command for ToJson {
|
||||
// allow ranges to expand and turn into array
|
||||
let input = input.try_expand_range()?;
|
||||
let value = input.into_value(span)?;
|
||||
let json_value = value_to_json_value(engine_state, &value, serialize_types)?;
|
||||
let json_value = value_to_json_value(engine_state, &value, span, serialize_types)?;
|
||||
|
||||
let json_result = if raw {
|
||||
nu_json::to_string_raw(&json_value)
|
||||
@ -78,16 +78,12 @@ impl Command for ToJson {
|
||||
};
|
||||
Ok(PipelineData::Value(res, Some(metadata)))
|
||||
}
|
||||
_ => Ok(Value::error(
|
||||
ShellError::CantConvert {
|
||||
to_type: "JSON".into(),
|
||||
from_type: value.get_type().to_string(),
|
||||
span,
|
||||
help: None,
|
||||
},
|
||||
_ => Err(ShellError::CantConvert {
|
||||
to_type: "JSON".into(),
|
||||
from_type: value.get_type().to_string(),
|
||||
span,
|
||||
)
|
||||
.into_pipeline_data()),
|
||||
help: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,6 +114,7 @@ impl Command for ToJson {
|
||||
pub fn value_to_json_value(
|
||||
engine_state: &EngineState,
|
||||
v: &Value,
|
||||
call_span: Span,
|
||||
serialize_types: bool,
|
||||
) -> Result<nu_json::Value, ShellError> {
|
||||
let span = v.span();
|
||||
@ -142,24 +139,20 @@ pub fn value_to_json_value(
|
||||
),
|
||||
|
||||
Value::List { vals, .. } => {
|
||||
nu_json::Value::Array(json_list(engine_state, vals, serialize_types)?)
|
||||
nu_json::Value::Array(json_list(engine_state, vals, call_span, serialize_types)?)
|
||||
}
|
||||
Value::Error { error, .. } => return Err(*error.clone()),
|
||||
Value::Closure { val, .. } => {
|
||||
if serialize_types {
|
||||
let block = engine_state.get_block(val.block_id);
|
||||
if let Some(span) = block.span {
|
||||
let contents_bytes = engine_state.get_span_contents(span);
|
||||
let contents_string = String::from_utf8_lossy(contents_bytes);
|
||||
nu_json::Value::String(contents_string.to_string())
|
||||
} else {
|
||||
nu_json::Value::String(format!(
|
||||
"unable to retrieve block contents for json block_id {}",
|
||||
val.block_id.get()
|
||||
))
|
||||
}
|
||||
let closure_string = val.coerce_into_string(engine_state, span)?;
|
||||
nu_json::Value::String(closure_string.to_string())
|
||||
} else {
|
||||
nu_json::Value::Null
|
||||
return Err(ShellError::UnsupportedInput {
|
||||
msg: "closures are currently not deserializable (use --serialize to serialize as a string)".into(),
|
||||
input: "value originates from here".into(),
|
||||
msg_span: call_span,
|
||||
input_span: span,
|
||||
});
|
||||
}
|
||||
}
|
||||
Value::Range { .. } => nu_json::Value::Null,
|
||||
@ -171,14 +164,14 @@ pub fn value_to_json_value(
|
||||
for (k, v) in &**val {
|
||||
m.insert(
|
||||
k.clone(),
|
||||
value_to_json_value(engine_state, v, serialize_types)?,
|
||||
value_to_json_value(engine_state, v, call_span, serialize_types)?,
|
||||
);
|
||||
}
|
||||
nu_json::Value::Object(m)
|
||||
}
|
||||
Value::Custom { val, .. } => {
|
||||
let collected = val.to_base_value(span)?;
|
||||
value_to_json_value(engine_state, &collected, serialize_types)?
|
||||
value_to_json_value(engine_state, &collected, call_span, serialize_types)?
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -186,12 +179,18 @@ pub fn value_to_json_value(
|
||||
fn json_list(
|
||||
engine_state: &EngineState,
|
||||
input: &[Value],
|
||||
call_span: Span,
|
||||
serialize_types: bool,
|
||||
) -> Result<Vec<nu_json::Value>, ShellError> {
|
||||
let mut out = vec![];
|
||||
|
||||
for value in input {
|
||||
out.push(value_to_json_value(engine_state, value, serialize_types)?);
|
||||
out.push(value_to_json_value(
|
||||
engine_state,
|
||||
value,
|
||||
call_span,
|
||||
serialize_types,
|
||||
)?);
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
|
@ -22,6 +22,11 @@ impl Command for ToMsgpack {
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build(self.name())
|
||||
.input_output_type(Type::Any, Type::Binary)
|
||||
.switch(
|
||||
"serialize",
|
||||
"serialize nushell types that cannot be deserialized",
|
||||
Some('s'),
|
||||
)
|
||||
.category(Category::Formats)
|
||||
}
|
||||
|
||||
@ -69,8 +74,8 @@ MessagePack: https://msgpack.org/
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
_engine_state: &EngineState,
|
||||
_stack: &mut Stack,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
@ -83,7 +88,16 @@ MessagePack: https://msgpack.org/
|
||||
let value = input.into_value(value_span)?;
|
||||
let mut out = vec![];
|
||||
|
||||
write_value(&mut out, &value, 0)?;
|
||||
let serialize_types = call.has_flag(engine_state, stack, "serialize")?;
|
||||
|
||||
write_value(
|
||||
&mut out,
|
||||
&value,
|
||||
0,
|
||||
engine_state,
|
||||
call.head,
|
||||
serialize_types,
|
||||
)?;
|
||||
|
||||
Ok(Value::binary(out, call.head).into_pipeline_data_with_metadata(Some(metadata)))
|
||||
}
|
||||
@ -148,6 +162,9 @@ pub(crate) fn write_value(
|
||||
out: &mut impl io::Write,
|
||||
value: &Value,
|
||||
depth: usize,
|
||||
engine_state: &EngineState,
|
||||
call_span: Span,
|
||||
serialize_types: bool,
|
||||
) -> Result<(), WriteError> {
|
||||
use mp::ValueWriteError::InvalidMarkerWrite;
|
||||
let span = value.span();
|
||||
@ -196,6 +213,9 @@ pub(crate) fn write_value(
|
||||
out,
|
||||
&Value::list(val.into_range_iter(span, Signals::empty()).collect(), span),
|
||||
depth,
|
||||
engine_state,
|
||||
call_span,
|
||||
serialize_types,
|
||||
)?;
|
||||
}
|
||||
Value::String { val, .. } => {
|
||||
@ -208,13 +228,20 @@ pub(crate) fn write_value(
|
||||
mp::write_map_len(out, convert(val.len(), span)?).err_span(span)?;
|
||||
for (k, v) in val.iter() {
|
||||
mp::write_str(out, k).err_span(span)?;
|
||||
write_value(out, v, depth + 1)?;
|
||||
write_value(out, v, depth + 1, engine_state, call_span, serialize_types)?;
|
||||
}
|
||||
}
|
||||
Value::List { vals, .. } => {
|
||||
mp::write_array_len(out, convert(vals.len(), span)?).err_span(span)?;
|
||||
for val in vals {
|
||||
write_value(out, val, depth + 1)?;
|
||||
write_value(
|
||||
out,
|
||||
val,
|
||||
depth + 1,
|
||||
engine_state,
|
||||
call_span,
|
||||
serialize_types,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
Value::Nothing { .. } => {
|
||||
@ -222,11 +249,20 @@ pub(crate) fn write_value(
|
||||
.map_err(InvalidMarkerWrite)
|
||||
.err_span(span)?;
|
||||
}
|
||||
Value::Closure { .. } => {
|
||||
// Closures can't be converted
|
||||
mp::write_nil(out)
|
||||
.map_err(InvalidMarkerWrite)
|
||||
.err_span(span)?;
|
||||
Value::Closure { val, .. } => {
|
||||
if serialize_types {
|
||||
let closure_string = val
|
||||
.coerce_into_string(engine_state, span)
|
||||
.map_err(|err| WriteError::Shell(Box::new(err)))?;
|
||||
mp::write_str(out, &closure_string).err_span(span)?;
|
||||
} else {
|
||||
return Err(WriteError::Shell(Box::new(ShellError::UnsupportedInput {
|
||||
msg: "closures are currently not deserializable (use --serialize to serialize as a string)".into(),
|
||||
input: "value originates from here".into(),
|
||||
msg_span: call_span,
|
||||
input_span: span,
|
||||
})));
|
||||
}
|
||||
}
|
||||
Value::Error { error, .. } => {
|
||||
return Err(WriteError::Shell(error.clone()));
|
||||
@ -249,7 +285,14 @@ pub(crate) fn write_value(
|
||||
mp::write_bin(out, val).err_span(span)?;
|
||||
}
|
||||
Value::Custom { val, .. } => {
|
||||
write_value(out, &val.to_base_value(span)?, depth)?;
|
||||
write_value(
|
||||
out,
|
||||
&val.to_base_value(span)?,
|
||||
depth,
|
||||
engine_state,
|
||||
call_span,
|
||||
serialize_types,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -32,6 +32,11 @@ impl Command for ToMsgpackz {
|
||||
"Window size for brotli compression (default 20)",
|
||||
Some('w'),
|
||||
)
|
||||
.switch(
|
||||
"serialize",
|
||||
"serialize nushell types that cannot be deserialized",
|
||||
Some('s'),
|
||||
)
|
||||
.category(Category::Formats)
|
||||
}
|
||||
|
||||
@ -69,6 +74,7 @@ impl Command for ToMsgpackz {
|
||||
.get_flag(engine_state, stack, "window-size")?
|
||||
.map(to_u32)
|
||||
.transpose()?;
|
||||
let serialize_types = call.has_flag(engine_state, stack, "serialize")?;
|
||||
|
||||
let value_span = input.span().unwrap_or(call.head);
|
||||
let value = input.into_value(value_span)?;
|
||||
@ -80,7 +86,14 @@ impl Command for ToMsgpackz {
|
||||
window_size.map(|w| w.item).unwrap_or(DEFAULT_WINDOW_SIZE),
|
||||
);
|
||||
|
||||
write_value(&mut out, &value, 0)?;
|
||||
write_value(
|
||||
&mut out,
|
||||
&value,
|
||||
0,
|
||||
engine_state,
|
||||
call.head,
|
||||
serialize_types,
|
||||
)?;
|
||||
out.flush()
|
||||
.map_err(|err| IoError::new(err.kind(), call.head, None))?;
|
||||
drop(out);
|
||||
|
@ -69,16 +69,9 @@ impl Command for ToNuon {
|
||||
match nuon::to_nuon(engine_state, &value, style, Some(span), serialize_types) {
|
||||
Ok(serde_nuon_string) => Ok(Value::string(serde_nuon_string, span)
|
||||
.into_pipeline_data_with_metadata(Some(metadata))),
|
||||
_ => Ok(Value::error(
|
||||
ShellError::CantConvert {
|
||||
to_type: "NUON".into(),
|
||||
from_type: value.get_type().to_string(),
|
||||
span,
|
||||
help: None,
|
||||
},
|
||||
span,
|
||||
)
|
||||
.into_pipeline_data_with_metadata(Some(metadata))),
|
||||
Err(error) => {
|
||||
Ok(Value::error(error, span).into_pipeline_data_with_metadata(Some(metadata)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
use crate::math::utils::ensure_bounded;
|
||||
use nu_engine::command_prelude::*;
|
||||
use nu_protocol::Range;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathAbs;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathAbs {
|
||||
fn name(&self) -> &str {
|
||||
"math abs"
|
||||
}
|
||||
@ -21,6 +23,7 @@ impl Command for SubCommand {
|
||||
Type::List(Box::new(Type::Duration)),
|
||||
Type::List(Box::new(Type::Duration)),
|
||||
),
|
||||
(Type::Range, Type::List(Box::new(Type::Number))),
|
||||
])
|
||||
.allow_variants_without_examples(true)
|
||||
.category(Category::Math)
|
||||
@ -46,6 +49,19 @@ impl Command for SubCommand {
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let head = call.head;
|
||||
if let PipelineData::Value(
|
||||
Value::Range {
|
||||
ref val,
|
||||
internal_span,
|
||||
},
|
||||
..,
|
||||
) = input
|
||||
{
|
||||
match &**val {
|
||||
Range::IntRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
Range::FloatRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
}
|
||||
}
|
||||
input.map(move |value| abs_helper(value, head), engine_state.signals())
|
||||
}
|
||||
|
||||
@ -56,6 +72,19 @@ impl Command for SubCommand {
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let head = call.head;
|
||||
if let PipelineData::Value(
|
||||
Value::Range {
|
||||
ref val,
|
||||
internal_span,
|
||||
},
|
||||
..,
|
||||
) = input
|
||||
{
|
||||
match &**val {
|
||||
Range::IntRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
Range::FloatRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
}
|
||||
}
|
||||
input.map(
|
||||
move |value| abs_helper(value, head),
|
||||
working_set.permanent().signals(),
|
||||
@ -105,6 +134,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathAbs {})
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,9 @@ use nu_engine::command_prelude::*;
|
||||
|
||||
const NS_PER_SEC: i64 = 1_000_000_000;
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathAvg;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathAvg {
|
||||
fn name(&self) -> &str {
|
||||
"math avg"
|
||||
}
|
||||
@ -104,6 +104,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathAvg {})
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
use crate::math::utils::ensure_bounded;
|
||||
use nu_engine::command_prelude::*;
|
||||
use nu_protocol::Range;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathCeil;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathCeil {
|
||||
fn name(&self) -> &str {
|
||||
"math ceil"
|
||||
}
|
||||
@ -16,6 +18,7 @@ impl Command for SubCommand {
|
||||
Type::List(Box::new(Type::Number)),
|
||||
Type::List(Box::new(Type::Int)),
|
||||
),
|
||||
(Type::Range, Type::List(Box::new(Type::Number))),
|
||||
])
|
||||
.allow_variants_without_examples(true)
|
||||
.category(Category::Math)
|
||||
@ -45,6 +48,19 @@ impl Command for SubCommand {
|
||||
if matches!(input, PipelineData::Empty) {
|
||||
return Err(ShellError::PipelineEmpty { dst_span: head });
|
||||
}
|
||||
if let PipelineData::Value(
|
||||
Value::Range {
|
||||
ref val,
|
||||
internal_span,
|
||||
},
|
||||
..,
|
||||
) = input
|
||||
{
|
||||
match &**val {
|
||||
Range::IntRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
Range::FloatRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
}
|
||||
}
|
||||
input.map(move |value| operate(value, head), engine_state.signals())
|
||||
}
|
||||
|
||||
@ -59,6 +75,19 @@ impl Command for SubCommand {
|
||||
if matches!(input, PipelineData::Empty) {
|
||||
return Err(ShellError::PipelineEmpty { dst_span: head });
|
||||
}
|
||||
if let PipelineData::Value(
|
||||
Value::Range {
|
||||
ref val,
|
||||
internal_span,
|
||||
},
|
||||
..,
|
||||
) = input
|
||||
{
|
||||
match &**val {
|
||||
Range::IntRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
Range::FloatRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
}
|
||||
}
|
||||
input.map(
|
||||
move |value| operate(value, head),
|
||||
working_set.permanent().signals(),
|
||||
@ -103,6 +132,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathCeil {})
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
use crate::math::utils::ensure_bounded;
|
||||
use nu_engine::command_prelude::*;
|
||||
use nu_protocol::Range;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathFloor;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathFloor {
|
||||
fn name(&self) -> &str {
|
||||
"math floor"
|
||||
}
|
||||
@ -16,6 +18,7 @@ impl Command for SubCommand {
|
||||
Type::List(Box::new(Type::Number)),
|
||||
Type::List(Box::new(Type::Int)),
|
||||
),
|
||||
(Type::Range, Type::List(Box::new(Type::Number))),
|
||||
])
|
||||
.allow_variants_without_examples(true)
|
||||
.category(Category::Math)
|
||||
@ -45,6 +48,19 @@ impl Command for SubCommand {
|
||||
if matches!(input, PipelineData::Empty) {
|
||||
return Err(ShellError::PipelineEmpty { dst_span: head });
|
||||
}
|
||||
if let PipelineData::Value(
|
||||
Value::Range {
|
||||
ref val,
|
||||
internal_span,
|
||||
},
|
||||
..,
|
||||
) = input
|
||||
{
|
||||
match &**val {
|
||||
Range::IntRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
Range::FloatRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
}
|
||||
}
|
||||
input.map(move |value| operate(value, head), engine_state.signals())
|
||||
}
|
||||
|
||||
@ -59,6 +75,19 @@ impl Command for SubCommand {
|
||||
if matches!(input, PipelineData::Empty) {
|
||||
return Err(ShellError::PipelineEmpty { dst_span: head });
|
||||
}
|
||||
if let PipelineData::Value(
|
||||
Value::Range {
|
||||
ref val,
|
||||
internal_span,
|
||||
},
|
||||
..,
|
||||
) = input
|
||||
{
|
||||
match &**val {
|
||||
Range::IntRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
Range::FloatRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
}
|
||||
}
|
||||
input.map(
|
||||
move |value| operate(value, head),
|
||||
working_set.permanent().signals(),
|
||||
@ -103,6 +132,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathFloor {})
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
use crate::math::utils::ensure_bounded;
|
||||
use nu_engine::command_prelude::*;
|
||||
use nu_protocol::Range;
|
||||
use nu_protocol::Signals;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathLog;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathLog {
|
||||
fn name(&self) -> &str {
|
||||
"math log"
|
||||
}
|
||||
@ -22,6 +24,7 @@ impl Command for SubCommand {
|
||||
Type::List(Box::new(Type::Number)),
|
||||
Type::List(Box::new(Type::Float)),
|
||||
),
|
||||
(Type::Range, Type::List(Box::new(Type::Number))),
|
||||
])
|
||||
.allow_variants_without_examples(true)
|
||||
.category(Category::Math)
|
||||
@ -46,7 +49,21 @@ impl Command for SubCommand {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let head = call.head;
|
||||
let base: Spanned<f64> = call.req(engine_state, stack, 0)?;
|
||||
if let PipelineData::Value(
|
||||
Value::Range {
|
||||
ref val,
|
||||
internal_span,
|
||||
},
|
||||
..,
|
||||
) = input
|
||||
{
|
||||
match &**val {
|
||||
Range::IntRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
Range::FloatRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
}
|
||||
}
|
||||
log(base, call.head, input, engine_state.signals())
|
||||
}
|
||||
|
||||
@ -56,7 +73,21 @@ impl Command for SubCommand {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let head = call.head;
|
||||
let base: Spanned<f64> = call.req_const(working_set, 0)?;
|
||||
if let PipelineData::Value(
|
||||
Value::Range {
|
||||
ref val,
|
||||
internal_span,
|
||||
},
|
||||
..,
|
||||
) = input
|
||||
{
|
||||
match &**val {
|
||||
Range::IntRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
Range::FloatRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
}
|
||||
}
|
||||
log(base, call.head, input, working_set.permanent().signals())
|
||||
}
|
||||
|
||||
@ -159,6 +190,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathLog {})
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,9 @@ use crate::math::{
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathMax;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathMax {
|
||||
fn name(&self) -> &str {
|
||||
"math max"
|
||||
}
|
||||
@ -97,6 +97,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathMax {})
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ use nu_engine::command_prelude::*;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathMedian;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathMedian {
|
||||
fn name(&self) -> &str {
|
||||
"math median"
|
||||
}
|
||||
@ -151,6 +151,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathMedian {})
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,9 @@ use crate::math::{
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathMin;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathMin {
|
||||
fn name(&self) -> &str {
|
||||
"math min"
|
||||
}
|
||||
@ -95,6 +95,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathMin {})
|
||||
}
|
||||
}
|
||||
|
@ -17,20 +17,20 @@ mod sum;
|
||||
mod utils;
|
||||
mod variance;
|
||||
|
||||
pub use abs::SubCommand as MathAbs;
|
||||
pub use avg::SubCommand as MathAvg;
|
||||
pub use ceil::SubCommand as MathCeil;
|
||||
pub use floor::SubCommand as MathFloor;
|
||||
pub use abs::MathAbs;
|
||||
pub use avg::MathAvg;
|
||||
pub use ceil::MathCeil;
|
||||
pub use floor::MathFloor;
|
||||
pub use math_::MathCommand as Math;
|
||||
pub use max::SubCommand as MathMax;
|
||||
pub use median::SubCommand as MathMedian;
|
||||
pub use min::SubCommand as MathMin;
|
||||
pub use mode::SubCommand as MathMode;
|
||||
pub use product::SubCommand as MathProduct;
|
||||
pub use round::SubCommand as MathRound;
|
||||
pub use sqrt::SubCommand as MathSqrt;
|
||||
pub use stddev::SubCommand as MathStddev;
|
||||
pub use sum::SubCommand as MathSum;
|
||||
pub use variance::SubCommand as MathVariance;
|
||||
pub use max::MathMax;
|
||||
pub use median::MathMedian;
|
||||
pub use min::MathMin;
|
||||
pub use mode::MathMode;
|
||||
pub use product::MathProduct;
|
||||
pub use round::MathRound;
|
||||
pub use sqrt::MathSqrt;
|
||||
pub use stddev::MathStddev;
|
||||
pub use sum::MathSum;
|
||||
pub use variance::MathVariance;
|
||||
|
||||
pub use self::log::SubCommand as MathLog;
|
||||
pub use log::MathLog;
|
||||
|
@ -3,7 +3,7 @@ use nu_engine::command_prelude::*;
|
||||
use std::{cmp::Ordering, collections::HashMap};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathMode;
|
||||
|
||||
#[derive(Hash, Eq, PartialEq, Debug)]
|
||||
enum NumberTypes {
|
||||
@ -28,7 +28,7 @@ impl HashableType {
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathMode {
|
||||
fn name(&self) -> &str {
|
||||
"math mode"
|
||||
}
|
||||
@ -110,7 +110,7 @@ impl Command for SubCommand {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mode(values: &[Value], _span: Span, head: Span) -> Result<Value, ShellError> {
|
||||
pub fn mode(values: &[Value], span: Span, head: Span) -> Result<Value, ShellError> {
|
||||
//In e-q, Value doesn't implement Hash or Eq, so we have to get the values inside
|
||||
// But f64 doesn't implement Hash, so we get the binary representation to use as
|
||||
// key in the HashMap
|
||||
@ -130,11 +130,11 @@ pub fn mode(values: &[Value], _span: Span, head: Span) -> Result<Value, ShellErr
|
||||
NumberTypes::Filesize,
|
||||
)),
|
||||
Value::Error { error, .. } => Err(*error.clone()),
|
||||
other => Err(ShellError::UnsupportedInput {
|
||||
_ => Err(ShellError::UnsupportedInput {
|
||||
msg: "Unable to give a result with this input".to_string(),
|
||||
input: "value originates from here".into(),
|
||||
msg_span: head,
|
||||
input_span: other.span(),
|
||||
input_span: span,
|
||||
}),
|
||||
})
|
||||
.collect::<Result<Vec<HashableType>, ShellError>>()?;
|
||||
@ -183,6 +183,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathMode {})
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,9 @@ use crate::math::{
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathProduct;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathProduct {
|
||||
fn name(&self) -> &str {
|
||||
"math product"
|
||||
}
|
||||
@ -88,6 +88,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathProduct {})
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
use crate::math::utils::ensure_bounded;
|
||||
use nu_engine::command_prelude::*;
|
||||
use nu_protocol::Range;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathRound;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathRound {
|
||||
fn name(&self) -> &str {
|
||||
"math round"
|
||||
}
|
||||
@ -16,6 +18,7 @@ impl Command for SubCommand {
|
||||
Type::List(Box::new(Type::Number)),
|
||||
Type::List(Box::new(Type::Number)),
|
||||
),
|
||||
(Type::Range, Type::List(Box::new(Type::Number))),
|
||||
])
|
||||
.allow_variants_without_examples(true)
|
||||
.named(
|
||||
@ -52,6 +55,19 @@ impl Command for SubCommand {
|
||||
if matches!(input, PipelineData::Empty) {
|
||||
return Err(ShellError::PipelineEmpty { dst_span: head });
|
||||
}
|
||||
if let PipelineData::Value(
|
||||
Value::Range {
|
||||
ref val,
|
||||
internal_span,
|
||||
},
|
||||
..,
|
||||
) = input
|
||||
{
|
||||
match &**val {
|
||||
Range::IntRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
Range::FloatRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
}
|
||||
}
|
||||
input.map(
|
||||
move |value| operate(value, head, precision_param),
|
||||
engine_state.signals(),
|
||||
@ -70,6 +86,19 @@ impl Command for SubCommand {
|
||||
if matches!(input, PipelineData::Empty) {
|
||||
return Err(ShellError::PipelineEmpty { dst_span: head });
|
||||
}
|
||||
if let PipelineData::Value(
|
||||
Value::Range {
|
||||
ref val,
|
||||
internal_span,
|
||||
},
|
||||
..,
|
||||
) = input
|
||||
{
|
||||
match &**val {
|
||||
Range::IntRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
Range::FloatRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
}
|
||||
}
|
||||
input.map(
|
||||
move |value| operate(value, head, precision_param),
|
||||
working_set.permanent().signals(),
|
||||
@ -153,6 +182,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathRound {})
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
use crate::math::utils::ensure_bounded;
|
||||
use nu_engine::command_prelude::*;
|
||||
use nu_protocol::Range;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathSqrt;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathSqrt {
|
||||
fn name(&self) -> &str {
|
||||
"math sqrt"
|
||||
}
|
||||
@ -16,6 +18,7 @@ impl Command for SubCommand {
|
||||
Type::List(Box::new(Type::Number)),
|
||||
Type::List(Box::new(Type::Float)),
|
||||
),
|
||||
(Type::Range, Type::List(Box::new(Type::Number))),
|
||||
])
|
||||
.allow_variants_without_examples(true)
|
||||
.category(Category::Math)
|
||||
@ -45,6 +48,19 @@ impl Command for SubCommand {
|
||||
if matches!(input, PipelineData::Empty) {
|
||||
return Err(ShellError::PipelineEmpty { dst_span: head });
|
||||
}
|
||||
if let PipelineData::Value(
|
||||
Value::Range {
|
||||
ref val,
|
||||
internal_span,
|
||||
},
|
||||
..,
|
||||
) = input
|
||||
{
|
||||
match &**val {
|
||||
Range::IntRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
Range::FloatRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
}
|
||||
}
|
||||
input.map(move |value| operate(value, head), engine_state.signals())
|
||||
}
|
||||
|
||||
@ -59,6 +75,19 @@ impl Command for SubCommand {
|
||||
if matches!(input, PipelineData::Empty) {
|
||||
return Err(ShellError::PipelineEmpty { dst_span: head });
|
||||
}
|
||||
if let PipelineData::Value(
|
||||
Value::Range {
|
||||
ref val,
|
||||
internal_span,
|
||||
},
|
||||
..,
|
||||
) = input
|
||||
{
|
||||
match &**val {
|
||||
Range::IntRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
Range::FloatRange(range) => ensure_bounded(range.end(), internal_span, head)?,
|
||||
}
|
||||
}
|
||||
input.map(
|
||||
move |value| operate(value, head),
|
||||
working_set.permanent().signals(),
|
||||
@ -127,6 +156,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathSqrt {})
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ use crate::math::utils::run_with_function;
|
||||
use nu_engine::command_prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
pub struct MathStddev;
|
||||
|
||||
impl Command for SubCommand {
|
||||
impl Command for MathStddev {
|
||||
fn name(&self) -> &str {
|
||||
"math stddev"
|
||||
}
|
||||
@ -14,6 +14,7 @@ impl Command for SubCommand {
|
||||
Signature::build("math stddev")
|
||||
.input_output_types(vec![
|
||||
(Type::List(Box::new(Type::Number)), Type::Number),
|
||||
(Type::Range, Type::Number),
|
||||
(Type::table(), Type::record()),
|
||||
(Type::record(), Type::record()),
|
||||
])
|
||||
@ -53,6 +54,18 @@ impl Command for SubCommand {
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let sample = call.has_flag(engine_state, stack, "sample")?;
|
||||
let name = call.head;
|
||||
let span = input.span().unwrap_or(name);
|
||||
let input: PipelineData = match input.try_expand_range() {
|
||||
Err(_) => {
|
||||
return Err(ShellError::IncorrectValue {
|
||||
msg: "Range must be bounded".to_string(),
|
||||
val_span: span,
|
||||
call_span: name,
|
||||
});
|
||||
}
|
||||
Ok(val) => val,
|
||||
};
|
||||
run_with_function(call, input, compute_stddev(sample))
|
||||
}
|
||||
|
||||
@ -63,6 +76,18 @@ impl Command for SubCommand {
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let sample = call.has_flag_const(working_set, "sample")?;
|
||||
let name = call.head;
|
||||
let span = input.span().unwrap_or(name);
|
||||
let input: PipelineData = match input.try_expand_range() {
|
||||
Err(_) => {
|
||||
return Err(ShellError::IncorrectValue {
|
||||
msg: "Range must be bounded".to_string(),
|
||||
val_span: span,
|
||||
call_span: name,
|
||||
});
|
||||
}
|
||||
Ok(val) => val,
|
||||
};
|
||||
run_with_function(call, input, compute_stddev(sample))
|
||||
}
|
||||
|
||||
@ -111,6 +136,6 @@ mod test {
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(SubCommand {})
|
||||
test_examples(MathStddev {})
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user