mirror of
https://github.com/nushell/nushell.git
synced 2025-06-13 05:26:59 +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"
|
name = "nu"
|
||||||
repository = "https://github.com/nushell/nushell"
|
repository = "https://github.com/nushell/nushell"
|
||||||
rust-version = "1.83.0"
|
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
|
# 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"
|
filetime = "0.2"
|
||||||
heck = "0.5.0"
|
heck = "0.5.0"
|
||||||
human-date-parser = "0.2.0"
|
human-date-parser = "0.2.0"
|
||||||
indexmap = "2.7"
|
indexmap = "2.8"
|
||||||
indicatif = "0.17"
|
indicatif = "0.17"
|
||||||
interprocess = "2.2.0"
|
interprocess = "2.2.0"
|
||||||
is_executable = "1.0"
|
is_executable = "1.0"
|
||||||
@ -104,13 +104,13 @@ lru = "0.12"
|
|||||||
lscolors = { version = "0.17", default-features = false }
|
lscolors = { version = "0.17", default-features = false }
|
||||||
lsp-server = "0.7.8"
|
lsp-server = "0.7.8"
|
||||||
lsp-types = { version = "0.97.0", features = ["proposed"] }
|
lsp-types = { version = "0.97.0", features = ["proposed"] }
|
||||||
lsp-textdocument = "0.4.1"
|
lsp-textdocument = "0.4.2"
|
||||||
mach2 = "0.4"
|
mach2 = "0.4"
|
||||||
md5 = { version = "0.10", package = "md-5" }
|
md5 = { version = "0.10", package = "md-5" }
|
||||||
miette = "7.5"
|
miette = "7.5"
|
||||||
mime = "0.3.17"
|
mime = "0.3.17"
|
||||||
mime_guess = "2.0"
|
mime_guess = "2.0"
|
||||||
mockito = { version = "1.6", default-features = false }
|
mockito = { version = "1.7", default-features = false }
|
||||||
multipart-rs = "0.1.13"
|
multipart-rs = "0.1.13"
|
||||||
native-tls = "0.2"
|
native-tls = "0.2"
|
||||||
nix = { version = "0.29", default-features = false }
|
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"
|
rand_chacha = "0.3.1"
|
||||||
ratatui = "0.29"
|
ratatui = "0.29"
|
||||||
rayon = "1.10"
|
rayon = "1.10"
|
||||||
reedline = "0.38.0"
|
reedline = "0.39.0"
|
||||||
rmp = "0.8"
|
rmp = "0.8"
|
||||||
rmp-serde = "1.3"
|
rmp-serde = "1.3"
|
||||||
roxmltree = "0.20"
|
roxmltree = "0.20"
|
||||||
@ -161,7 +161,7 @@ syn = "2.0"
|
|||||||
sysinfo = "0.33"
|
sysinfo = "0.33"
|
||||||
tabled = { version = "0.17.0", default-features = false }
|
tabled = { version = "0.17.0", default-features = false }
|
||||||
tempfile = "3.15"
|
tempfile = "3.15"
|
||||||
titlecase = "3.0"
|
titlecase = "3.4"
|
||||||
toml = "0.8"
|
toml = "0.8"
|
||||||
trash = "5.2"
|
trash = "5.2"
|
||||||
update-informer = { version = "1.2.0", default-features = false, features = ["github", "native-tls", "ureq"] }
|
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"
|
unicode-width = "0.2"
|
||||||
ureq = { version = "2.12", default-features = false }
|
ureq = { version = "2.12", default-features = false }
|
||||||
url = "2.2"
|
url = "2.2"
|
||||||
uu_cp = "0.0.29"
|
uu_cp = "0.0.30"
|
||||||
uu_mkdir = "0.0.29"
|
uu_mkdir = "0.0.30"
|
||||||
uu_mktemp = "0.0.29"
|
uu_mktemp = "0.0.30"
|
||||||
uu_mv = "0.0.29"
|
uu_mv = "0.0.30"
|
||||||
uu_touch = "0.0.29"
|
uu_touch = "0.0.30"
|
||||||
uu_whoami = "0.0.29"
|
uu_whoami = "0.0.30"
|
||||||
uu_uname = "0.0.29"
|
uu_uname = "0.0.30"
|
||||||
uucore = "0.0.29"
|
uucore = "0.0.30"
|
||||||
uuid = "1.12.0"
|
uuid = "1.16.0"
|
||||||
v_htmlescape = "0.15.0"
|
v_htmlescape = "0.15.0"
|
||||||
wax = "0.6"
|
wax = "0.6"
|
||||||
web-time = "1.1.0"
|
web-time = "1.1.0"
|
||||||
@ -197,22 +197,22 @@ unchecked_duration_subtraction = "warn"
|
|||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-cli = { path = "./crates/nu-cli", version = "0.102.1" }
|
nu-cli = { path = "./crates/nu-cli", version = "0.103.1" }
|
||||||
nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.102.1" }
|
nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.103.1" }
|
||||||
nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.102.1" }
|
nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.103.1" }
|
||||||
nu-cmd-plugin = { path = "./crates/nu-cmd-plugin", version = "0.102.1", optional = true }
|
nu-cmd-plugin = { path = "./crates/nu-cmd-plugin", version = "0.103.1", optional = true }
|
||||||
nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.102.1" }
|
nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.103.1" }
|
||||||
nu-command = { path = "./crates/nu-command", version = "0.102.1" }
|
nu-command = { path = "./crates/nu-command", version = "0.103.1" }
|
||||||
nu-engine = { path = "./crates/nu-engine", version = "0.102.1" }
|
nu-engine = { path = "./crates/nu-engine", version = "0.103.1" }
|
||||||
nu-explore = { path = "./crates/nu-explore", version = "0.102.1" }
|
nu-explore = { path = "./crates/nu-explore", version = "0.103.1" }
|
||||||
nu-lsp = { path = "./crates/nu-lsp/", version = "0.102.1" }
|
nu-lsp = { path = "./crates/nu-lsp/", version = "0.103.1" }
|
||||||
nu-parser = { path = "./crates/nu-parser", version = "0.102.1" }
|
nu-parser = { path = "./crates/nu-parser", version = "0.103.1" }
|
||||||
nu-path = { path = "./crates/nu-path", version = "0.102.1" }
|
nu-path = { path = "./crates/nu-path", version = "0.103.1" }
|
||||||
nu-plugin-engine = { path = "./crates/nu-plugin-engine", optional = true, version = "0.102.1" }
|
nu-plugin-engine = { path = "./crates/nu-plugin-engine", optional = true, version = "0.103.1" }
|
||||||
nu-protocol = { path = "./crates/nu-protocol", version = "0.102.1" }
|
nu-protocol = { path = "./crates/nu-protocol", version = "0.103.1" }
|
||||||
nu-std = { path = "./crates/nu-std", version = "0.102.1" }
|
nu-std = { path = "./crates/nu-std", version = "0.103.1" }
|
||||||
nu-system = { path = "./crates/nu-system", version = "0.102.1" }
|
nu-system = { path = "./crates/nu-system", version = "0.103.1" }
|
||||||
nu-utils = { path = "./crates/nu-utils", version = "0.102.1" }
|
nu-utils = { path = "./crates/nu-utils", version = "0.103.1" }
|
||||||
reedline = { workspace = true, features = ["bashisms", "sqlite"] }
|
reedline = { workspace = true, features = ["bashisms", "sqlite"] }
|
||||||
|
|
||||||
crossterm = { workspace = true }
|
crossterm = { workspace = true }
|
||||||
@ -220,7 +220,6 @@ ctrlc = { workspace = true }
|
|||||||
dirs = { workspace = true }
|
dirs = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
miette = { workspace = true, features = ["fancy-no-backtrace", "fancy"] }
|
miette = { workspace = true, features = ["fancy-no-backtrace", "fancy"] }
|
||||||
mimalloc = { version = "0.1.42", default-features = false, optional = true }
|
|
||||||
multipart-rs = { workspace = true }
|
multipart-rs = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
simplelog = "0.12"
|
simplelog = "0.12"
|
||||||
@ -242,9 +241,9 @@ nix = { workspace = true, default-features = false, features = [
|
|||||||
] }
|
] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
nu-test-support = { path = "./crates/nu-test-support", 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.102.1" }
|
nu-plugin-protocol = { path = "./crates/nu-plugin-protocol", version = "0.103.1" }
|
||||||
nu-plugin-core = { path = "./crates/nu-plugin-core", version = "0.102.1" }
|
nu-plugin-core = { path = "./crates/nu-plugin-core", version = "0.103.1" }
|
||||||
assert_cmd = "2.0"
|
assert_cmd = "2.0"
|
||||||
dirs = { workspace = true }
|
dirs = { workspace = true }
|
||||||
tango-bench = "0.6"
|
tango-bench = "0.6"
|
||||||
@ -274,7 +273,6 @@ default = [
|
|||||||
"plugin",
|
"plugin",
|
||||||
"trash-support",
|
"trash-support",
|
||||||
"sqlite",
|
"sqlite",
|
||||||
"mimalloc",
|
|
||||||
]
|
]
|
||||||
stable = ["default"]
|
stable = ["default"]
|
||||||
# NOTE: individual features are also passed to `nu-cmd-lang` that uses them to generate the feature matrix in the `version` command
|
# 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
|
# 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"]
|
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.
|
# Optional system clipboard support in `reedline`, this behavior has problematic compatibility with some systems.
|
||||||
# Missing X server/ Wayland can cause issues
|
# Missing X server/ Wayland can cause issues
|
||||||
system-clipboard = [
|
system-clipboard = [
|
||||||
@ -326,7 +323,7 @@ bench = false
|
|||||||
# To use a development version of a dependency please use a global override here
|
# 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
|
# changing versions in each sub-crate of the workspace is tedious
|
||||||
[patch.crates-io]
|
[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"}
|
# nu-ansi-term = {git = "https://github.com/nushell/nu-ansi-term.git", branch = "main"}
|
||||||
|
|
||||||
# Run all benchmarks with `cargo bench`
|
# Run all benchmarks with `cargo bench`
|
||||||
|
@ -5,28 +5,28 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cli"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "nu-cli"
|
name = "nu-cli"
|
||||||
version = "0.102.1"
|
version = "0.103.1"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
bench = false
|
bench = false
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.102.1" }
|
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.103.1" }
|
||||||
nu-command = { path = "../nu-command", version = "0.102.1" }
|
nu-command = { path = "../nu-command", version = "0.103.1" }
|
||||||
nu-test-support = { path = "../nu-test-support", version = "0.102.1" }
|
nu-test-support = { path = "../nu-test-support", version = "0.103.1" }
|
||||||
rstest = { workspace = true, default-features = false }
|
rstest = { workspace = true, default-features = false }
|
||||||
tempfile = { workspace = true }
|
tempfile = { workspace = true }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-cmd-base = { path = "../nu-cmd-base", version = "0.102.1" }
|
nu-cmd-base = { path = "../nu-cmd-base", version = "0.103.1" }
|
||||||
nu-engine = { path = "../nu-engine", version = "0.102.1", features = ["os"] }
|
nu-engine = { path = "../nu-engine", version = "0.103.1", features = ["os"] }
|
||||||
nu-glob = { path = "../nu-glob", version = "0.102.1" }
|
nu-glob = { path = "../nu-glob", version = "0.103.1" }
|
||||||
nu-path = { path = "../nu-path", version = "0.102.1" }
|
nu-path = { path = "../nu-path", version = "0.103.1" }
|
||||||
nu-parser = { path = "../nu-parser", version = "0.102.1" }
|
nu-parser = { path = "../nu-parser", version = "0.103.1" }
|
||||||
nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.102.1", optional = true }
|
nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.103.1", optional = true }
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.102.1", features = ["os"] }
|
nu-protocol = { path = "../nu-protocol", version = "0.103.1", features = ["os"] }
|
||||||
nu-utils = { path = "../nu-utils", version = "0.102.1" }
|
nu-utils = { path = "../nu-utils", version = "0.103.1" }
|
||||||
nu-color-config = { path = "../nu-color-config", version = "0.102.1" }
|
nu-color-config = { path = "../nu-color-config", version = "0.103.1" }
|
||||||
nu-ansi-term = { workspace = true }
|
nu-ansi-term = { workspace = true }
|
||||||
reedline = { workspace = true, features = ["bashisms", "sqlite"] }
|
reedline = { workspace = true, features = ["bashisms", "sqlite"] }
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct CommandlineEdit;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for CommandlineEdit {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"commandline edit"
|
"commandline edit"
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,9 @@ use nu_engine::command_prelude::*;
|
|||||||
use unicode_segmentation::UnicodeSegmentation;
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct CommandlineGetCursor;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for CommandlineGetCursor {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"commandline get-cursor"
|
"commandline get-cursor"
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,6 @@ mod get_cursor;
|
|||||||
mod set_cursor;
|
mod set_cursor;
|
||||||
|
|
||||||
pub use commandline_::Commandline;
|
pub use commandline_::Commandline;
|
||||||
pub use edit::SubCommand as CommandlineEdit;
|
pub use edit::CommandlineEdit;
|
||||||
pub use get_cursor::SubCommand as CommandlineGetCursor;
|
pub use get_cursor::CommandlineGetCursor;
|
||||||
pub use set_cursor::SubCommand as CommandlineSetCursor;
|
pub use set_cursor::CommandlineSetCursor;
|
||||||
|
@ -3,9 +3,9 @@ use nu_engine::command_prelude::*;
|
|||||||
use unicode_segmentation::UnicodeSegmentation;
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct CommandlineSetCursor;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for CommandlineSetCursor {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"commandline set-cursor"
|
"commandline set-cursor"
|
||||||
}
|
}
|
||||||
|
@ -307,9 +307,8 @@ impl NuCompleter {
|
|||||||
let need_externals = !prefix_str.contains(' ');
|
let need_externals = !prefix_str.contains(' ');
|
||||||
let need_internals = !prefix_str.starts_with('^');
|
let need_internals = !prefix_str.starts_with('^');
|
||||||
let mut span = element_expression.span;
|
let mut span = element_expression.span;
|
||||||
span.end = std::cmp::min(span.end, pos + 1);
|
|
||||||
if !need_internals {
|
if !need_internals {
|
||||||
span = Span::new(span.start + 1, span.end)
|
span.start += 1;
|
||||||
};
|
};
|
||||||
suggestions.extend(self.command_completion_helper(
|
suggestions.extend(self.command_completion_helper(
|
||||||
working_set,
|
working_set,
|
||||||
|
@ -65,10 +65,11 @@ fn complete_rec(
|
|||||||
|
|
||||||
for entry in result.filter_map(|e| e.ok()) {
|
for entry in result.filter_map(|e| e.ok()) {
|
||||||
let entry_name = entry.file_name().to_string_lossy().into_owned();
|
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();
|
let mut built = built.clone();
|
||||||
built.parts.push(entry_name.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 {
|
if !want_directory || entry_isdir {
|
||||||
matcher.add(entry_name.clone(), (entry_name, built));
|
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
|
let ls_colors = (engine_state.config.completions.use_ls_colors
|
||||||
&& engine_state.config.use_ansi_coloring.get(engine_state))
|
&& engine_state.config.use_ansi_coloring.get(engine_state))
|
||||||
.then(|| {
|
.then(|| {
|
||||||
let ls_colors_env_str = match stack.get_env_var(engine_state, "LS_COLORS") {
|
let ls_colors_env_str = stack
|
||||||
Some(v) => env_to_string("LS_COLORS", v, engine_state, stack).ok(),
|
.get_env_var(engine_state, "LS_COLORS")
|
||||||
None => None,
|
.and_then(|v| env_to_string("LS_COLORS", v, engine_state, stack).ok());
|
||||||
};
|
|
||||||
get_ls_colors(ls_colors_env_str)
|
get_ls_colors(ls_colors_env_str)
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -263,19 +263,16 @@ pub fn complete_item(
|
|||||||
}
|
}
|
||||||
let is_dir = p.isdir;
|
let is_dir = p.isdir;
|
||||||
let path = original_cwd.apply(p, path_separator);
|
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| {
|
let style = ls_colors.as_ref().map(|lsc| {
|
||||||
lsc.style_for_path_with_metadata(
|
lsc.style_for_path_with_metadata(&real_path, metadata.as_ref())
|
||||||
&path,
|
.map(lscolors::Style::to_nu_ansi_term_style)
|
||||||
std::fs::symlink_metadata(expand_to_real_path(&path))
|
.unwrap_or_default()
|
||||||
.ok()
|
|
||||||
.as_ref(),
|
|
||||||
)
|
|
||||||
.map(lscolors::Style::to_nu_ansi_term_style)
|
|
||||||
.unwrap_or_default()
|
|
||||||
});
|
});
|
||||||
FileSuggestion {
|
FileSuggestion {
|
||||||
span,
|
span,
|
||||||
path: escape_path(path, want_directory),
|
path: escape_path(path),
|
||||||
style,
|
style,
|
||||||
is_dir,
|
is_dir,
|
||||||
}
|
}
|
||||||
@ -284,30 +281,30 @@ pub fn complete_item(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fix files or folders with quotes or hashes
|
// 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.
|
// 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 pathbuf = nu_path::expand_tilde(path);
|
||||||
let path = pathbuf.to_string_lossy();
|
let path = pathbuf.to_string_lossy();
|
||||||
return if path.contains('\'') {
|
if path.contains('\'') {
|
||||||
// decide to use double quote, also need to escape `"` in path
|
// decide to use double quotes
|
||||||
// or else users can't do anything with completed path either.
|
// Path as Debug will do the escaping for `"`, `\`
|
||||||
format!("\"{}\"", path.replace('"', r#"\""#))
|
format!("{:?}", path)
|
||||||
} else {
|
} else {
|
||||||
format!("'{path}'")
|
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 {
|
} 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::{
|
use nu_protocol::{
|
||||||
ast::{Argument, Call, Expr, Expression},
|
ast::{Argument, Call, Expr, Expression},
|
||||||
debugger::WithoutDebug,
|
debugger::WithoutDebug,
|
||||||
engine::{Stack, StateWorkingSet},
|
engine::{EngineState, Stack, StateWorkingSet},
|
||||||
DeclId, PipelineData, Span, Type, Value,
|
DeclId, PipelineData, Span, Type, Value,
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@ -42,28 +42,37 @@ impl<T: Completer> Completer for CustomCompletion<T> {
|
|||||||
) -> Vec<SemanticSuggestion> {
|
) -> Vec<SemanticSuggestion> {
|
||||||
// Call custom declaration
|
// Call custom declaration
|
||||||
let mut stack_mut = stack.clone();
|
let mut stack_mut = stack.clone();
|
||||||
let result = eval_call::<WithoutDebug>(
|
let mut eval = |engine_state: &EngineState| {
|
||||||
working_set.permanent_state,
|
eval_call::<WithoutDebug>(
|
||||||
&mut stack_mut,
|
engine_state,
|
||||||
&Call {
|
&mut stack_mut,
|
||||||
decl_id: self.decl_id,
|
&Call {
|
||||||
head: span,
|
decl_id: self.decl_id,
|
||||||
arguments: vec![
|
head: span,
|
||||||
Argument::Positional(Expression::new_unknown(
|
arguments: vec![
|
||||||
Expr::String(self.line.clone()),
|
Argument::Positional(Expression::new_unknown(
|
||||||
Span::unknown(),
|
Expr::String(self.line.clone()),
|
||||||
Type::String,
|
Span::unknown(),
|
||||||
)),
|
Type::String,
|
||||||
Argument::Positional(Expression::new_unknown(
|
)),
|
||||||
Expr::Int(self.line_pos as i64),
|
Argument::Positional(Expression::new_unknown(
|
||||||
Span::unknown(),
|
Expr::Int(self.line_pos as i64),
|
||||||
Type::Int,
|
Span::unknown(),
|
||||||
)),
|
Type::Int,
|
||||||
],
|
)),
|
||||||
parser_info: HashMap::new(),
|
],
|
||||||
},
|
parser_info: HashMap::new(),
|
||||||
PipelineData::empty(),
|
},
|
||||||
);
|
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 completion_options = orig_options.clone();
|
||||||
let mut should_sort = true;
|
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> {
|
fn collection_comparison_ops() -> Vec<OperatorItem> {
|
||||||
let mut ops = common_comparison_ops();
|
let mut ops = common_comparison_ops();
|
||||||
ops.push(operator_to_item(Comparison::Has));
|
ops.push(operator_to_item(Comparison::Has));
|
||||||
@ -72,6 +81,10 @@ fn bit_ops() -> Vec<OperatorItem> {
|
|||||||
ast::Bits::iter().map(operator_to_item).collect()
|
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> {
|
fn numeric_assignment_ops() -> Vec<OperatorItem> {
|
||||||
ast::Assignment::iter()
|
ast::Assignment::iter()
|
||||||
.filter(|op| !matches!(op, ast::Assignment::ConcatenateAssign))
|
.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::Filesize { .. } | Value::Duration { .. } => valid_value_with_unit_ops(),
|
||||||
Value::Range { .. } | Value::Record { .. } => collection_comparison_ops(),
|
Value::Range { .. } | Value::Record { .. } => collection_comparison_ops(),
|
||||||
Value::List { .. } => valid_list_ops(),
|
Value::List { .. } => valid_list_ops(),
|
||||||
_ => common_comparison_ops(),
|
_ => all_ops_for_immutable(),
|
||||||
};
|
};
|
||||||
if mutable {
|
if mutable {
|
||||||
ops.extend(match value {
|
ops.extend(match value {
|
||||||
@ -165,7 +178,11 @@ fn ops_by_value(value: &Value, mutable: bool) -> Vec<OperatorItem> {
|
|||||||
Value::String { .. } | Value::Binary { .. } | Value::List { .. } => {
|
Value::String { .. } | Value::Binary { .. } | Value::List { .. } => {
|
||||||
concat_assignment_ops()
|
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
|
ops
|
||||||
@ -223,7 +240,7 @@ impl Completer for OperatorCompletion<'_> {
|
|||||||
needs_assignment_ops = false;
|
needs_assignment_ops = false;
|
||||||
ops_by_value(&value, mutable)
|
ops_by_value(&value, mutable)
|
||||||
}
|
}
|
||||||
_ => common_comparison_ops(),
|
_ => all_ops_for_immutable(),
|
||||||
},
|
},
|
||||||
_ => common_comparison_ops(),
|
_ => common_comparison_ops(),
|
||||||
};
|
};
|
||||||
@ -233,6 +250,7 @@ impl Completer for OperatorCompletion<'_> {
|
|||||||
Type::Int | Type::Float | Type::Number => numeric_assignment_ops(),
|
Type::Int | Type::Float | Type::Number => numeric_assignment_ops(),
|
||||||
Type::Filesize | Type::Duration => numeric_assignment_ops(),
|
Type::Filesize | Type::Duration => numeric_assignment_ops(),
|
||||||
Type::String | Type::Binary | Type::List(_) => concat_assignment_ops(),
|
Type::String | Type::Binary | Type::List(_) => concat_assignment_ops(),
|
||||||
|
Type::Any => all_assignment_ops(),
|
||||||
_ => vec![operator_to_item(ast::Assignment::Assign)],
|
_ => vec![operator_to_item(ast::Assignment::Assign)],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,12 @@ fn custom_arguments_and_subcommands() {
|
|||||||
let completion_str = "foo test";
|
let completion_str = "foo test";
|
||||||
let suggestions = completer.complete(completion_str, completion_str.len());
|
let suggestions = completer.complete(completion_str, completion_str.len());
|
||||||
// including both subcommand and directory completions
|
// 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);
|
match_suggestions_by_string(&expected, &suggestions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,6 +350,21 @@ fn custom_arguments_vs_subcommands() {
|
|||||||
match_suggestions(&expected, &suggestions);
|
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 `^`
|
/// External command only if starts with `^`
|
||||||
#[test]
|
#[test]
|
||||||
fn external_commands_only() {
|
fn external_commands_only() {
|
||||||
@ -891,6 +911,7 @@ fn partial_completions() {
|
|||||||
folder(dir.join("partial-a")),
|
folder(dir.join("partial-a")),
|
||||||
folder(dir.join("partial-b")),
|
folder(dir.join("partial-b")),
|
||||||
folder(dir.join("partial-c")),
|
folder(dir.join("partial-c")),
|
||||||
|
format!("`{}`", folder(dir.join("partial-d("))),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Match the results
|
// Match the results
|
||||||
@ -933,6 +954,7 @@ fn partial_completions() {
|
|||||||
file(dir.join("partial-b").join("hello_b")),
|
file(dir.join("partial-b").join("hello_b")),
|
||||||
file(dir.join("partial-b").join("hi_b")),
|
file(dir.join("partial-b").join("hi_b")),
|
||||||
file(dir.join("partial-c").join("hello_c")),
|
file(dir.join("partial-c").join("hello_c")),
|
||||||
|
format!("`{}`", file(dir.join("partial-d(").join(".gitkeep"))),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Match the results
|
// Match the results
|
||||||
@ -980,6 +1002,15 @@ fn partial_completions() {
|
|||||||
.join("final_partial")
|
.join("final_partial")
|
||||||
.join("somefile"),
|
.join("somefile"),
|
||||||
),
|
),
|
||||||
|
format!(
|
||||||
|
"`{}`",
|
||||||
|
file(
|
||||||
|
dir.join("partial-d(")
|
||||||
|
.join("..")
|
||||||
|
.join("final_partial")
|
||||||
|
.join("somefile"),
|
||||||
|
)
|
||||||
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Match the results
|
// Match the results
|
||||||
@ -1060,6 +1091,16 @@ fn partial_completion_with_dot_expansions() {
|
|||||||
.join("final_partial")
|
.join("final_partial")
|
||||||
.join("somefile"),
|
.join("somefile"),
|
||||||
),
|
),
|
||||||
|
format!(
|
||||||
|
"`{}`",
|
||||||
|
file(
|
||||||
|
dir.join("partial-d(")
|
||||||
|
.join("...")
|
||||||
|
.join("partial_completions")
|
||||||
|
.join("final_partial")
|
||||||
|
.join("somefile"),
|
||||||
|
)
|
||||||
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Match the results
|
// Match the results
|
||||||
@ -1384,6 +1425,9 @@ fn file_completion_quoted() {
|
|||||||
"`-inf`",
|
"`-inf`",
|
||||||
"`4.2`",
|
"`4.2`",
|
||||||
"\'[a] bc.txt\'",
|
"\'[a] bc.txt\'",
|
||||||
|
"`curly-bracket_{.txt`",
|
||||||
|
"`semicolon_;.txt`",
|
||||||
|
"'square-bracket_[.txt'",
|
||||||
"`te st.txt`",
|
"`te st.txt`",
|
||||||
"`te#st.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("another")),
|
||||||
folder(dir.join("directory_completion")),
|
folder(dir.join("directory_completion")),
|
||||||
folder(dir.join("test_a")),
|
folder(dir.join("test_a")),
|
||||||
|
file(dir.join("test_a_symlink")),
|
||||||
folder(dir.join("test_b")),
|
folder(dir.join("test_b")),
|
||||||
folder(dir.join(".hidden_folder")),
|
folder(dir.join(".hidden_folder")),
|
||||||
];
|
];
|
||||||
@ -1594,6 +1639,12 @@ fn folder_with_directorycompletions_with_three_trailing_dots() {
|
|||||||
.join("...")
|
.join("...")
|
||||||
.join("test_a"),
|
.join("test_a"),
|
||||||
),
|
),
|
||||||
|
file(
|
||||||
|
dir.join("directory_completion")
|
||||||
|
.join("folder_inside_folder")
|
||||||
|
.join("...")
|
||||||
|
.join("test_a_symlink"),
|
||||||
|
),
|
||||||
folder(
|
folder(
|
||||||
dir.join("directory_completion")
|
dir.join("directory_completion")
|
||||||
.join("folder_inside_folder")
|
.join("folder_inside_folder")
|
||||||
@ -1666,6 +1717,13 @@ fn folder_with_directorycompletions_do_not_collapse_dots() {
|
|||||||
.join("..")
|
.join("..")
|
||||||
.join("test_a"),
|
.join("test_a"),
|
||||||
),
|
),
|
||||||
|
file(
|
||||||
|
dir.join("directory_completion")
|
||||||
|
.join("folder_inside_folder")
|
||||||
|
.join("..")
|
||||||
|
.join("..")
|
||||||
|
.join("test_a_symlink"),
|
||||||
|
),
|
||||||
folder(
|
folder(
|
||||||
dir.join("directory_completion")
|
dir.join("directory_completion")
|
||||||
.join("folder_inside_folder")
|
.join("folder_inside_folder")
|
||||||
@ -2345,6 +2403,13 @@ fn assignment_operator_completions(mut custom_completer: NuCompleter) {
|
|||||||
let expected: Vec<_> = vec!["++", "++="];
|
let expected: Vec<_> = vec!["++", "++="];
|
||||||
let suggestions = custom_completer.complete("$env.config.keybindings +", 25);
|
let suggestions = custom_completer.complete("$env.config.keybindings +", 25);
|
||||||
match_suggestions(&expected, &suggestions);
|
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]
|
#[test]
|
||||||
|
@ -5,7 +5,7 @@ edition = "2021"
|
|||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "nu-cmd-base"
|
name = "nu-cmd-base"
|
||||||
repository = "https://github.com/nushell/nushell/tree/main/crates/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
|
# 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
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-engine = { path = "../nu-engine", 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.102.1" }
|
nu-parser = { path = "../nu-parser", version = "0.103.1" }
|
||||||
nu-path = { path = "../nu-path", version = "0.102.1" }
|
nu-path = { path = "../nu-path", version = "0.103.1" }
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.102.1", default-features = false }
|
nu-protocol = { path = "../nu-protocol", version = "0.103.1", default-features = false }
|
||||||
|
|
||||||
indexmap = { workspace = true }
|
indexmap = { workspace = true }
|
||||||
miette = { workspace = true }
|
miette = { workspace = true }
|
||||||
|
@ -5,7 +5,7 @@ edition = "2021"
|
|||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "nu-cmd-extra"
|
name = "nu-cmd-extra"
|
||||||
repository = "https://github.com/nushell/nushell/tree/main/crates/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
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
@ -16,13 +16,13 @@ bench = false
|
|||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-cmd-base = { path = "../nu-cmd-base", version = "0.102.1" }
|
nu-cmd-base = { path = "../nu-cmd-base", version = "0.103.1" }
|
||||||
nu-engine = { path = "../nu-engine", version = "0.102.1", default-features = false }
|
nu-engine = { path = "../nu-engine", version = "0.103.1", default-features = false }
|
||||||
nu-json = { version = "0.102.1", path = "../nu-json" }
|
nu-json = { version = "0.103.1", path = "../nu-json" }
|
||||||
nu-parser = { path = "../nu-parser", version = "0.102.1" }
|
nu-parser = { path = "../nu-parser", version = "0.103.1" }
|
||||||
nu-pretty-hex = { version = "0.102.1", path = "../nu-pretty-hex" }
|
nu-pretty-hex = { version = "0.103.1", path = "../nu-pretty-hex" }
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.102.1", default-features = false }
|
nu-protocol = { path = "../nu-protocol", version = "0.103.1", default-features = false }
|
||||||
nu-utils = { path = "../nu-utils", version = "0.102.1", default-features = false }
|
nu-utils = { path = "../nu-utils", version = "0.103.1", default-features = false }
|
||||||
|
|
||||||
# Potential dependencies for extras
|
# Potential dependencies for extras
|
||||||
heck = { workspace = true }
|
heck = { workspace = true }
|
||||||
@ -37,6 +37,6 @@ itertools = { workspace = true }
|
|||||||
mime = { workspace = true }
|
mime = { workspace = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.102.1" }
|
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.103.1" }
|
||||||
nu-command = { path = "../nu-command", version = "0.102.1" }
|
nu-command = { path = "../nu-command", version = "0.103.1" }
|
||||||
nu-test-support = { path = "../nu-test-support", version = "0.102.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 and;
|
||||||
mod bits_;
|
mod bits_;
|
||||||
mod into;
|
|
||||||
mod not;
|
mod not;
|
||||||
mod or;
|
mod or;
|
||||||
mod rotate_left;
|
mod rotate_left;
|
||||||
@ -11,7 +10,6 @@ mod xor;
|
|||||||
|
|
||||||
pub use and::BitsAnd;
|
pub use and::BitsAnd;
|
||||||
pub use bits_::Bits;
|
pub use bits_::Bits;
|
||||||
pub use into::BitsInto;
|
|
||||||
pub use not::BitsNot;
|
pub use not::BitsNot;
|
||||||
pub use or::BitsOr;
|
pub use or::BitsOr;
|
||||||
pub use rotate_left::BitsRol;
|
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::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathArcCos;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathArcCos {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math arccos"
|
"math arccos"
|
||||||
}
|
}
|
||||||
@ -114,6 +114,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(MathArcCos {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathArcCosH;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathArcCosH {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math arccosh"
|
"math arccosh"
|
||||||
}
|
}
|
||||||
@ -100,6 +100,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(MathArcCosH {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathArcSin;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathArcSin {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math arcsin"
|
"math arcsin"
|
||||||
}
|
}
|
||||||
@ -115,6 +115,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(MathArcSin {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathArcSinH;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathArcSinH {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math arcsinh"
|
"math arcsinh"
|
||||||
}
|
}
|
||||||
@ -88,6 +88,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(MathArcSinH {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathArcTan;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathArcTan {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math arctan"
|
"math arctan"
|
||||||
}
|
}
|
||||||
@ -102,6 +102,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(MathArcTan {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathArcTanH;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathArcTanH {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math arctanh"
|
"math arctanh"
|
||||||
}
|
}
|
||||||
@ -101,6 +101,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(MathArcTanH {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathCos;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathCos {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math cos"
|
"math cos"
|
||||||
}
|
}
|
||||||
@ -108,6 +108,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(MathCos {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathCosH;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathCosH {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math cosh"
|
"math cosh"
|
||||||
}
|
}
|
||||||
@ -88,6 +88,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(MathCosH {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathExp;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathExp {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math exp"
|
"math exp"
|
||||||
}
|
}
|
||||||
@ -93,6 +93,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(MathExp {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathLn;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathLn {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math ln"
|
"math ln"
|
||||||
}
|
}
|
||||||
@ -100,6 +100,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(MathLn {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,19 +15,19 @@ mod arcsinh;
|
|||||||
mod arctan;
|
mod arctan;
|
||||||
mod arctanh;
|
mod arctanh;
|
||||||
|
|
||||||
pub use cos::SubCommand as MathCos;
|
pub use cos::MathCos;
|
||||||
pub use cosh::SubCommand as MathCosH;
|
pub use cosh::MathCosH;
|
||||||
pub use sin::SubCommand as MathSin;
|
pub use sin::MathSin;
|
||||||
pub use sinh::SubCommand as MathSinH;
|
pub use sinh::MathSinH;
|
||||||
pub use tan::SubCommand as MathTan;
|
pub use tan::MathTan;
|
||||||
pub use tanh::SubCommand as MathTanH;
|
pub use tanh::MathTanH;
|
||||||
|
|
||||||
pub use exp::SubCommand as MathExp;
|
pub use exp::MathExp;
|
||||||
pub use ln::SubCommand as MathLn;
|
pub use ln::MathLn;
|
||||||
|
|
||||||
pub use arccos::SubCommand as MathArcCos;
|
pub use arccos::MathArcCos;
|
||||||
pub use arccosh::SubCommand as MathArcCosH;
|
pub use arccosh::MathArcCosH;
|
||||||
pub use arcsin::SubCommand as MathArcSin;
|
pub use arcsin::MathArcSin;
|
||||||
pub use arcsinh::SubCommand as MathArcSinH;
|
pub use arcsinh::MathArcSinH;
|
||||||
pub use arctan::SubCommand as MathArcTan;
|
pub use arctan::MathArcTan;
|
||||||
pub use arctanh::SubCommand as MathArcTanH;
|
pub use arctanh::MathArcTanH;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathSin;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathSin {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math sin"
|
"math sin"
|
||||||
}
|
}
|
||||||
@ -108,6 +108,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(MathSin {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathSinH;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathSinH {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math sinh"
|
"math sinh"
|
||||||
}
|
}
|
||||||
@ -87,6 +87,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(MathSinH {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathTan;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathTan {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math tan"
|
"math tan"
|
||||||
}
|
}
|
||||||
@ -106,6 +106,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(MathTan {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathTanH;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathTanH {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math tanh"
|
"math tanh"
|
||||||
}
|
}
|
||||||
@ -86,6 +86,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(MathTanH {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
mod bits;
|
mod bits;
|
||||||
mod conversions;
|
|
||||||
mod filters;
|
mod filters;
|
||||||
mod formats;
|
mod formats;
|
||||||
mod math;
|
mod math;
|
||||||
mod platform;
|
mod platform;
|
||||||
mod strings;
|
mod strings;
|
||||||
|
|
||||||
pub use bits::{
|
pub use bits::{Bits, BitsAnd, BitsNot, BitsOr, BitsRol, BitsRor, BitsShl, BitsShr, BitsXor};
|
||||||
Bits, BitsAnd, BitsInto, BitsNot, BitsOr, BitsRol, BitsRor, BitsShl, BitsShr, BitsXor,
|
|
||||||
};
|
|
||||||
pub use formats::ToHtml;
|
pub use formats::ToHtml;
|
||||||
pub use math::{MathArcCos, MathArcCosH, MathArcSin, MathArcSinH, MathArcTan, MathArcTanH};
|
pub use math::{MathArcCos, MathArcCosH, MathArcSin, MathArcSinH, MathArcTan, MathArcTanH};
|
||||||
pub use math::{MathCos, MathCosH, MathSin, MathSinH, MathTan, MathTanH};
|
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!(
|
bind_command!(
|
||||||
filters::UpdateCells,
|
filters::UpdateCells,
|
||||||
filters::EachWhile,
|
filters::EachWhile,
|
||||||
@ -63,7 +58,6 @@ pub fn add_extra_command_context(mut engine_state: EngineState) -> EngineState {
|
|||||||
bind_command! {
|
bind_command! {
|
||||||
Bits,
|
Bits,
|
||||||
BitsAnd,
|
BitsAnd,
|
||||||
BitsInto,
|
|
||||||
BitsNot,
|
BitsNot,
|
||||||
BitsOr,
|
BitsOr,
|
||||||
BitsRol,
|
BitsRol,
|
||||||
|
@ -111,8 +111,7 @@ impl Command for FormatBits {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: crate public only during deprecation
|
fn format_bits(
|
||||||
pub(crate) fn format_bits(
|
|
||||||
engine_state: &EngineState,
|
engine_state: &EngineState,
|
||||||
stack: &mut Stack,
|
stack: &mut Stack,
|
||||||
call: &Call,
|
call: &Call,
|
||||||
|
@ -2,8 +2,6 @@ mod bits;
|
|||||||
mod command;
|
mod command;
|
||||||
mod number;
|
mod number;
|
||||||
|
|
||||||
|
pub(crate) use bits::FormatBits;
|
||||||
pub(crate) use command::FormatPattern;
|
pub(crate) use command::FormatPattern;
|
||||||
// TODO remove `format_bits` visibility after removal of into bits
|
pub(crate) use number::FormatNumber;
|
||||||
pub(crate) use bits::{format_bits, FormatBits};
|
|
||||||
// TODO remove `format_number` visibility after removal of into bits
|
|
||||||
pub(crate) use number::{format_number, FormatNumber};
|
|
||||||
|
@ -3,9 +3,9 @@ use heck::ToLowerCamelCase;
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct StrCamelCase;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for StrCamelCase {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"str camel-case"
|
"str camel-case"
|
||||||
}
|
}
|
||||||
@ -91,6 +91,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(StrCamelCase {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@ use heck::ToKebabCase;
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct StrKebabCase;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for StrKebabCase {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"str kebab-case"
|
"str kebab-case"
|
||||||
}
|
}
|
||||||
@ -90,6 +90,6 @@ mod tests {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(StrKebabCase {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,13 @@ mod snake_case;
|
|||||||
mod str_;
|
mod str_;
|
||||||
mod title_case;
|
mod title_case;
|
||||||
|
|
||||||
pub use camel_case::SubCommand as StrCamelCase;
|
pub use camel_case::StrCamelCase;
|
||||||
pub use kebab_case::SubCommand as StrKebabCase;
|
pub use kebab_case::StrKebabCase;
|
||||||
pub use pascal_case::SubCommand as StrPascalCase;
|
pub use pascal_case::StrPascalCase;
|
||||||
pub use screaming_snake_case::SubCommand as StrScreamingSnakeCase;
|
pub use screaming_snake_case::StrScreamingSnakeCase;
|
||||||
pub use snake_case::SubCommand as StrSnakeCase;
|
pub use snake_case::StrSnakeCase;
|
||||||
pub use str_::Str;
|
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_cmd_base::input_handler::{operate as general_operate, CmdArgument};
|
||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
@ -3,9 +3,9 @@ use heck::ToUpperCamelCase;
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct StrPascalCase;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for StrPascalCase {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"str pascal-case"
|
"str pascal-case"
|
||||||
}
|
}
|
||||||
@ -91,6 +91,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(StrPascalCase {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@ use heck::ToShoutySnakeCase;
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct StrScreamingSnakeCase;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for StrScreamingSnakeCase {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"str screaming-snake-case"
|
"str screaming-snake-case"
|
||||||
}
|
}
|
||||||
@ -91,6 +91,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(StrScreamingSnakeCase {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@ use heck::ToSnakeCase;
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct StrSnakeCase;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for StrSnakeCase {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"str snake-case"
|
"str snake-case"
|
||||||
}
|
}
|
||||||
@ -91,6 +91,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(StrSnakeCase {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@ use heck::ToTitleCase;
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct StrTitleCase;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for StrTitleCase {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"str title-case"
|
"str title-case"
|
||||||
}
|
}
|
||||||
@ -86,6 +86,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::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"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "nu-cmd-lang"
|
name = "nu-cmd-lang"
|
||||||
version = "0.102.1"
|
version = "0.103.1"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
bench = false
|
bench = false
|
||||||
@ -15,10 +15,10 @@ bench = false
|
|||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-engine = { path = "../nu-engine", 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.102.1" }
|
nu-parser = { path = "../nu-parser", version = "0.103.1" }
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.102.1", default-features = false }
|
nu-protocol = { path = "../nu-protocol", version = "0.103.1", default-features = false }
|
||||||
nu-utils = { path = "../nu-utils", version = "0.102.1", default-features = false }
|
nu-utils = { path = "../nu-utils", version = "0.103.1", default-features = false }
|
||||||
|
|
||||||
itertools = { workspace = true }
|
itertools = { workspace = true }
|
||||||
shadow-rs = { version = "0.38", default-features = false }
|
shadow-rs = { version = "0.38", default-features = false }
|
||||||
@ -42,7 +42,6 @@ plugin = [
|
|||||||
"os",
|
"os",
|
||||||
]
|
]
|
||||||
|
|
||||||
mimalloc = []
|
|
||||||
trash-support = []
|
trash-support = []
|
||||||
sqlite = []
|
sqlite = []
|
||||||
static-link-openssl = []
|
static-link-openssl = []
|
||||||
|
@ -103,7 +103,7 @@ impl Command for Describe {
|
|||||||
"category" => Value::test_string("default"),
|
"category" => Value::test_string("default"),
|
||||||
)),
|
)),
|
||||||
)),
|
)),
|
||||||
"first_commit" => Value::test_string("date"),
|
"first_commit" => Value::test_string("datetime"),
|
||||||
"my_duration" => Value::test_string("duration"),
|
"my_duration" => Value::test_string("duration"),
|
||||||
)),
|
)),
|
||||||
))),
|
))),
|
||||||
|
@ -161,11 +161,7 @@ fn push_version_numbers(record: &mut Record, head: Span) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn global_allocator() -> &'static str {
|
fn global_allocator() -> &'static str {
|
||||||
if cfg!(feature = "mimalloc") {
|
"standard"
|
||||||
"mimalloc"
|
|
||||||
} else {
|
|
||||||
"standard"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn features_enabled() -> Vec<String> {
|
fn features_enabled() -> Vec<String> {
|
||||||
|
@ -5,7 +5,7 @@ edition = "2021"
|
|||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "nu-cmd-plugin"
|
name = "nu-cmd-plugin"
|
||||||
repository = "https://github.com/nushell/nushell/tree/main/crates/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
|
# 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
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-engine = { path = "../nu-engine", version = "0.102.1" }
|
nu-engine = { path = "../nu-engine", version = "0.103.1" }
|
||||||
nu-path = { path = "../nu-path", version = "0.102.1" }
|
nu-path = { path = "../nu-path", version = "0.103.1" }
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.102.1", features = ["plugin"] }
|
nu-protocol = { path = "../nu-protocol", version = "0.103.1", features = ["plugin"] }
|
||||||
nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.102.1" }
|
nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.103.1" }
|
||||||
|
|
||||||
itertools = { workspace = true }
|
itertools = { workspace = true }
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-color-confi
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "nu-color-config"
|
name = "nu-color-config"
|
||||||
version = "0.102.1"
|
version = "0.103.1"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
bench = false
|
bench = false
|
||||||
@ -14,12 +14,12 @@ bench = false
|
|||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.102.1", default-features = false }
|
nu-protocol = { path = "../nu-protocol", version = "0.103.1", default-features = false }
|
||||||
nu-engine = { path = "../nu-engine", version = "0.102.1", default-features = false }
|
nu-engine = { path = "../nu-engine", version = "0.103.1", default-features = false }
|
||||||
nu-json = { path = "../nu-json", version = "0.102.1" }
|
nu-json = { path = "../nu-json", version = "0.103.1" }
|
||||||
nu-ansi-term = { workspace = true }
|
nu-ansi-term = { workspace = true }
|
||||||
|
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[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())),
|
("int".to_string(), ComputableStyle::Static(Color::White.normal())),
|
||||||
("filesize".to_string(), ComputableStyle::Static(Color::Cyan.normal())),
|
("filesize".to_string(), ComputableStyle::Static(Color::Cyan.normal())),
|
||||||
("duration".to_string(), ComputableStyle::Static(Color::White.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())),
|
("range".to_string(), ComputableStyle::Static(Color::White.normal())),
|
||||||
("float".to_string(), ComputableStyle::Static(Color::White.normal())),
|
("float".to_string(), ComputableStyle::Static(Color::White.normal())),
|
||||||
("string".to_string(), ComputableStyle::Static(Color::White.normal())),
|
("string".to_string(), ComputableStyle::Static(Color::White.normal())),
|
||||||
|
@ -5,7 +5,7 @@ edition = "2021"
|
|||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "nu-command"
|
name = "nu-command"
|
||||||
repository = "https://github.com/nushell/nushell/tree/main/crates/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
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
@ -16,21 +16,21 @@ bench = false
|
|||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-cmd-base = { path = "../nu-cmd-base", version = "0.102.1" }
|
nu-cmd-base = { path = "../nu-cmd-base", version = "0.103.1" }
|
||||||
nu-color-config = { path = "../nu-color-config", version = "0.102.1" }
|
nu-color-config = { path = "../nu-color-config", version = "0.103.1" }
|
||||||
nu-engine = { path = "../nu-engine", version = "0.102.1", default-features = false }
|
nu-engine = { path = "../nu-engine", version = "0.103.1", default-features = false }
|
||||||
nu-glob = { path = "../nu-glob", version = "0.102.1" }
|
nu-glob = { path = "../nu-glob", version = "0.103.1" }
|
||||||
nu-json = { path = "../nu-json", version = "0.102.1" }
|
nu-json = { path = "../nu-json", version = "0.103.1" }
|
||||||
nu-parser = { path = "../nu-parser", version = "0.102.1" }
|
nu-parser = { path = "../nu-parser", version = "0.103.1" }
|
||||||
nu-path = { path = "../nu-path", version = "0.102.1" }
|
nu-path = { path = "../nu-path", version = "0.103.1" }
|
||||||
nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.102.1" }
|
nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.103.1" }
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.102.1", default-features = false }
|
nu-protocol = { path = "../nu-protocol", version = "0.103.1", default-features = false }
|
||||||
nu-system = { path = "../nu-system", version = "0.102.1" }
|
nu-system = { path = "../nu-system", version = "0.103.1" }
|
||||||
nu-table = { path = "../nu-table", version = "0.102.1" }
|
nu-table = { path = "../nu-table", version = "0.103.1" }
|
||||||
nu-term-grid = { path = "../nu-term-grid", version = "0.102.1" }
|
nu-term-grid = { path = "../nu-term-grid", version = "0.103.1" }
|
||||||
nu-utils = { path = "../nu-utils", version = "0.102.1", default-features = false }
|
nu-utils = { path = "../nu-utils", version = "0.103.1", default-features = false }
|
||||||
nu-ansi-term = { workspace = true }
|
nu-ansi-term = { workspace = true }
|
||||||
nuon = { path = "../nuon", version = "0.102.1" }
|
nuon = { path = "../nuon", version = "0.103.1" }
|
||||||
|
|
||||||
alphanumeric-sort = { workspace = true }
|
alphanumeric-sort = { workspace = true }
|
||||||
base64 = { workspace = true }
|
base64 = { workspace = true }
|
||||||
@ -209,8 +209,8 @@ sqlite = ["rusqlite"]
|
|||||||
trash-support = ["trash"]
|
trash-support = ["trash"]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.102.1" }
|
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.103.1" }
|
||||||
nu-test-support = { path = "../nu-test-support", version = "0.102.1" }
|
nu-test-support = { path = "../nu-test-support", version = "0.103.1" }
|
||||||
|
|
||||||
dirs = { workspace = true }
|
dirs = { workspace = true }
|
||||||
mockito = { workspace = true, default-features = false }
|
mockito = { workspace = true, default-features = false }
|
||||||
|
@ -13,9 +13,9 @@ impl CmdArgument for Arguments {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct IntoBinary;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for IntoBinary {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"into binary"
|
"into binary"
|
||||||
}
|
}
|
||||||
@ -204,7 +204,7 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(IntoBinary {})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
|
@ -2,9 +2,9 @@ use nu_cmd_base::input_handler::{operate, CmdArgument};
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct IntoBool;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for IntoBool {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"into bool"
|
"into bool"
|
||||||
}
|
}
|
||||||
@ -202,7 +202,7 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(IntoBool {})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -49,9 +49,9 @@ impl Zone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct IntoDatetime;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for IntoDatetime {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"into datetime"
|
"into datetime"
|
||||||
}
|
}
|
||||||
@ -408,13 +408,10 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
|||||||
Err(reason) => {
|
Err(reason) => {
|
||||||
match NaiveDateTime::parse_from_str(val, &dt.0) {
|
match NaiveDateTime::parse_from_str(val, &dt.0) {
|
||||||
Ok(d) => {
|
Ok(d) => {
|
||||||
let local_offset = *Local::now().offset();
|
|
||||||
let dt_fixed =
|
let dt_fixed =
|
||||||
TimeZone::from_local_datetime(&local_offset, &d)
|
Local.from_local_datetime(&d).single().unwrap_or_default();
|
||||||
.single()
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
Value::date (dt_fixed,head)
|
Value::date(dt_fixed.into(),head)
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
Value::error (
|
Value::error (
|
||||||
@ -498,14 +495,14 @@ fn list_human_readable_examples(span: Span) -> Value {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use super::{action, DatetimeFormat, SubCommand, Zone};
|
use super::{action, DatetimeFormat, IntoDatetime, Zone};
|
||||||
use nu_protocol::Type::Error;
|
use nu_protocol::Type::Error;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(IntoDatetime {})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -4,9 +4,9 @@ use nu_protocol::{ast::Expr, Unit};
|
|||||||
|
|
||||||
const NS_PER_SEC: i64 = 1_000_000_000;
|
const NS_PER_SEC: i64 = 1_000_000_000;
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct IntoDuration;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for IntoDuration {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"into duration"
|
"into duration"
|
||||||
}
|
}
|
||||||
@ -277,7 +277,7 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(IntoDuration {})
|
||||||
}
|
}
|
||||||
|
|
||||||
const NS_PER_SEC: i64 = 1_000_000_000;
|
const NS_PER_SEC: i64 = 1_000_000_000;
|
||||||
|
@ -4,9 +4,9 @@ use nu_engine::command_prelude::*;
|
|||||||
use nu_utils::get_system_locale;
|
use nu_utils::get_system_locale;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct IntoFilesize;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for IntoFilesize {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"into filesize"
|
"into filesize"
|
||||||
}
|
}
|
||||||
@ -197,6 +197,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::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::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct IntoFloat;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for IntoFloat {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"into float"
|
"into float"
|
||||||
}
|
}
|
||||||
@ -134,7 +134,7 @@ mod tests {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(IntoFloat {})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -12,9 +12,9 @@ impl CmdArgument for Arguments {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct IntoGlob;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for IntoGlob {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"into glob"
|
"into glob"
|
||||||
}
|
}
|
||||||
@ -121,6 +121,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(IntoGlob {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,9 @@ impl CmdArgument for Arguments {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct IntoInt;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for IntoInt {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"into int"
|
"into int"
|
||||||
}
|
}
|
||||||
@ -521,7 +521,7 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(IntoInt {})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -12,16 +12,16 @@ mod record;
|
|||||||
mod string;
|
mod string;
|
||||||
mod value;
|
mod value;
|
||||||
|
|
||||||
pub use self::bool::SubCommand as IntoBool;
|
pub use binary::IntoBinary;
|
||||||
pub use self::filesize::SubCommand as IntoFilesize;
|
pub use bool::IntoBool;
|
||||||
pub use binary::SubCommand as IntoBinary;
|
|
||||||
pub use cell_path::IntoCellPath;
|
pub use cell_path::IntoCellPath;
|
||||||
pub use command::Into;
|
pub use command::Into;
|
||||||
pub use datetime::SubCommand as IntoDatetime;
|
pub use datetime::IntoDatetime;
|
||||||
pub use duration::SubCommand as IntoDuration;
|
pub use duration::IntoDuration;
|
||||||
pub use float::SubCommand as IntoFloat;
|
pub use filesize::IntoFilesize;
|
||||||
pub use glob::SubCommand as IntoGlob;
|
pub use float::IntoFloat;
|
||||||
pub use int::SubCommand as IntoInt;
|
pub use glob::IntoGlob;
|
||||||
pub use record::SubCommand as IntoRecord;
|
pub use int::IntoInt;
|
||||||
pub use string::SubCommand as IntoString;
|
pub use record::IntoRecord;
|
||||||
|
pub use string::IntoString;
|
||||||
pub use value::IntoValue;
|
pub use value::IntoValue;
|
||||||
|
@ -3,9 +3,9 @@ use nu_engine::command_prelude::*;
|
|||||||
use nu_protocol::format_duration_as_timeperiod;
|
use nu_protocol::format_duration_as_timeperiod;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct IntoRecord;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for IntoRecord {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"into record"
|
"into record"
|
||||||
}
|
}
|
||||||
@ -243,6 +243,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::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_cmd_base::input_handler::{operate, CmdArgument};
|
||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
use nu_protocol::{shell_error::into_code, Config};
|
use nu_protocol::Config;
|
||||||
use nu_utils::get_system_locale;
|
use nu_utils::get_system_locale;
|
||||||
use num_format::ToFormattedString;
|
use num_format::ToFormattedString;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -19,9 +19,9 @@ impl CmdArgument for Arguments {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct IntoString;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for IntoString {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"into string"
|
"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::Bool { val, .. } => Value::string(val.to_string(), span),
|
||||||
Value::Date { val, .. } => Value::string(val.format("%c").to_string(), span),
|
Value::Date { val, .. } => Value::string(val.format("%c").to_string(), span),
|
||||||
Value::String { val, .. } => {
|
Value::String { val, .. } => Value::string(val, span),
|
||||||
if group_digits {
|
Value::Glob { val, .. } => Value::string(val, span),
|
||||||
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::Filesize { val, .. } => {
|
Value::Filesize { val, .. } => {
|
||||||
if group_digits {
|
if group_digits {
|
||||||
let decimal_value = digits.unwrap_or(0) as usize;
|
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::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::Nothing { .. } => Value::string("".to_string(), span),
|
||||||
Value::Record { .. } => Value::error(
|
Value::Record { .. } => Value::error(
|
||||||
// Watch out for CantConvert's argument order
|
// 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))
|
.unwrap_or_else(|err| Value::error(err, span))
|
||||||
}
|
}
|
||||||
|
Value::Error { .. } => input.clone(),
|
||||||
x => Value::error(
|
x => Value::error(
|
||||||
ShellError::CantConvert {
|
ShellError::CantConvert {
|
||||||
to_type: String::from("string"),
|
to_type: String::from("string"),
|
||||||
@ -316,6 +306,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::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) {
|
} 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 {
|
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(),
|
from_type: "string".to_string(),
|
||||||
span,
|
span,
|
||||||
help: Some(format!(
|
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))
|
Ok(Value::date(dt, span))
|
||||||
} else if DATETIME_YMD_RE.is_match(&val_str).unwrap_or(false) {
|
} 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 {
|
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(),
|
from_type: "string".to_string(),
|
||||||
span,
|
span,
|
||||||
help: Some(format!(
|
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))
|
Ok(Value::date(dt, span))
|
||||||
} else if DATETIME_YMDZ_RE.is_match(&val_str).unwrap_or(false) {
|
} 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 {
|
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(),
|
from_type: "string".to_string(),
|
||||||
span,
|
span,
|
||||||
help: Some(format!(
|
help: Some(format!(
|
||||||
|
@ -4,4 +4,4 @@ mod split_cell_path;
|
|||||||
|
|
||||||
pub use fill::Fill;
|
pub use fill::Fill;
|
||||||
pub use into::*;
|
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};
|
use nu_protocol::{ast::PathMember, IntoValue};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct SplitCellPath;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for SplitCellPath {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"split cell-path"
|
"split cell-path"
|
||||||
}
|
}
|
||||||
@ -150,6 +150,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::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::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct DateHumanize;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for DateHumanize {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"date humanize"
|
"date humanize"
|
||||||
}
|
}
|
||||||
@ -101,6 +101,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::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::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct DateListTimezones;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for DateListTimezones {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"date list-timezone"
|
"date list-timezone"
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ mod to_timezone;
|
|||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
pub use date_::Date;
|
pub use date_::Date;
|
||||||
pub use humanize::SubCommand as DateHumanize;
|
pub use humanize::DateHumanize;
|
||||||
pub use list_timezone::SubCommand as DateListTimezones;
|
pub use list_timezone::DateListTimezones;
|
||||||
pub use now::SubCommand as DateNow;
|
pub use now::DateNow;
|
||||||
pub use to_timezone::SubCommand as DateToTimezone;
|
pub use to_timezone::DateToTimezone;
|
||||||
pub(crate) use utils::{generate_strftime_list, parse_date_from_string};
|
pub(crate) use utils::{generate_strftime_list, parse_date_from_string};
|
||||||
|
@ -2,9 +2,9 @@ use chrono::Local;
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct DateNow;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for DateNow {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"date now"
|
"date now"
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,9 @@ use chrono::{DateTime, FixedOffset, Local, LocalResult, TimeZone};
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct DateToTimezone;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for DateToTimezone {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"date to-timezone"
|
"date to-timezone"
|
||||||
}
|
}
|
||||||
@ -147,6 +147,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::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,
|
ParEach,
|
||||||
ChunkBy,
|
ChunkBy,
|
||||||
Prepend,
|
Prepend,
|
||||||
Range,
|
|
||||||
Reduce,
|
Reduce,
|
||||||
Reject,
|
Reject,
|
||||||
Rename,
|
Rename,
|
||||||
@ -455,7 +454,7 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
|
|||||||
Job,
|
Job,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(all(unix, feature = "os"))]
|
||||||
bind_command! {
|
bind_command! {
|
||||||
JobUnfreeze,
|
JobUnfreeze,
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ fn convert_string_to_value(
|
|||||||
Err(x) => match x {
|
Err(x) => match x {
|
||||||
nu_json::Error::Syntax(_, row, col) => {
|
nu_json::Error::Syntax(_, row, col) => {
|
||||||
let label = x.to_string();
|
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 {
|
Err(ShellError::GenericError {
|
||||||
error: "Error while parsing JSON text".into(),
|
error: "Error while parsing JSON text".into(),
|
||||||
msg: "error parsing JSON text".into(),
|
msg: "error parsing JSON text".into(),
|
||||||
@ -173,23 +173,3 @@ fn expand_closure(
|
|||||||
_ => None,
|
_ => 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_engine::{command_prelude::*, ClosureEvalOnce};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
engine::{Closure, Job, ThreadJob},
|
engine::{Closure, Job, Redirection, ThreadJob},
|
||||||
report_shell_error, Signals,
|
report_shell_error, OutDest, Signals,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -76,15 +76,18 @@ impl Command for JobSpawn {
|
|||||||
let result = thread::Builder::new()
|
let result = thread::Builder::new()
|
||||||
.name(format!("background job {}", id.get()))
|
.name(format!("background job {}", id.get()))
|
||||||
.spawn(move || {
|
.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())
|
.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| {
|
.unwrap_or_else(|err| {
|
||||||
if !job_state.signals().interrupted() {
|
if !job_state.signals().interrupted() {
|
||||||
report_shell_error(&job_state, &err);
|
report_shell_error(&job_state, &err);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::nothing(head)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,7 @@ mod job_kill;
|
|||||||
mod job_list;
|
mod job_list;
|
||||||
mod job_spawn;
|
mod job_spawn;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(all(unix, feature = "os"))]
|
||||||
mod job_unfreeze;
|
mod job_unfreeze;
|
||||||
|
|
||||||
pub use is_admin::IsAdmin;
|
pub use is_admin::IsAdmin;
|
||||||
@ -14,5 +14,5 @@ pub use job_list::JobList;
|
|||||||
|
|
||||||
pub use job_spawn::JobSpawn;
|
pub use job_spawn::JobSpawn;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(all(unix, feature = "os"))]
|
||||||
pub use job_unfreeze::JobUnfreeze;
|
pub use job_unfreeze::JobUnfreeze;
|
||||||
|
@ -802,7 +802,7 @@ mod windows_helper {
|
|||||||
use std::os::windows::prelude::OsStrExt;
|
use std::os::windows::prelude::OsStrExt;
|
||||||
use windows::Win32::Foundation::FILETIME;
|
use windows::Win32::Foundation::FILETIME;
|
||||||
use windows::Win32::Storage::FileSystem::{
|
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,
|
FILE_ATTRIBUTE_REPARSE_POINT, WIN32_FIND_DATAW,
|
||||||
};
|
};
|
||||||
use windows::Win32::System::SystemServices::{
|
use windows::Win32::System::SystemServices::{
|
||||||
@ -925,7 +925,14 @@ mod windows_helper {
|
|||||||
windows::core::PCWSTR(filename_wide.as_ptr()),
|
windows::core::PCWSTR(filename_wide.as_ptr()),
|
||||||
&mut find_data,
|
&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(
|
Err(e) => Err(ShellError::Io(IoError::new_with_additional_context(
|
||||||
std::io::ErrorKind::Other,
|
std::io::ErrorKind::Other,
|
||||||
span,
|
span,
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
use nu_engine::{command_prelude::*, current_dir, get_eval_block};
|
use nu_engine::{command_prelude::*, current_dir, eval_call};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast,
|
ast,
|
||||||
|
debugger::{WithDebug, WithoutDebug},
|
||||||
shell_error::{self, io::IoError},
|
shell_error::{self, io::IoError},
|
||||||
DataSource, NuGlob, PipelineMetadata,
|
DataSource, NuGlob, PipelineMetadata,
|
||||||
};
|
};
|
||||||
use std::path::{Path, PathBuf};
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(feature = "sqlite")]
|
#[cfg(feature = "sqlite")]
|
||||||
use crate::database::SQLiteDatabase;
|
use crate::database::SQLiteDatabase;
|
||||||
@ -63,7 +67,6 @@ impl Command for Open {
|
|||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
let cwd = current_dir(engine_state, stack)?;
|
let cwd = current_dir(engine_state, stack)?;
|
||||||
let mut paths = call.rest::<Spanned<NuGlob>>(engine_state, stack, 0)?;
|
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) {
|
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
|
// 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 {
|
match converter {
|
||||||
Some((converter_id, ext)) => {
|
Some((converter_id, ext)) => {
|
||||||
let decl = engine_state.get_decl(converter_id);
|
let open_call = ast::Call {
|
||||||
let command_output = if let Some(block_id) = decl.block_id() {
|
decl_id: converter_id,
|
||||||
let block = engine_state.get_block(block_id);
|
head: call_span,
|
||||||
eval_block(engine_state, stack, block, stream)
|
arguments: vec![],
|
||||||
|
parser_info: HashMap::new(),
|
||||||
|
};
|
||||||
|
let command_output = if engine_state.is_debugging() {
|
||||||
|
eval_call::<WithDebug>(engine_state, stack, &open_call, stream)
|
||||||
} else {
|
} else {
|
||||||
let call = ast::Call::new(call_span);
|
eval_call::<WithoutDebug>(engine_state, stack, &open_call, stream)
|
||||||
decl.run(engine_state, stack, &(&call).into(), stream)
|
|
||||||
};
|
};
|
||||||
output.push(command_output.map_err(|inner| {
|
output.push(command_output.map_err(|inner| {
|
||||||
ShellError::GenericError{
|
ShellError::GenericError{
|
||||||
|
@ -158,17 +158,15 @@ impl Command for UTouch {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut expanded_globs = glob(
|
let mut expanded_globs =
|
||||||
&file_path.to_string_lossy(),
|
glob(&file_path.to_string_lossy(), engine_state.signals().clone())
|
||||||
Some(engine_state.signals().clone()),
|
.unwrap_or_else(|_| {
|
||||||
)
|
panic!(
|
||||||
.unwrap_or_else(|_| {
|
"Failed to process file path: {}",
|
||||||
panic!(
|
&file_path.to_string_lossy()
|
||||||
"Failed to process file path: {}",
|
)
|
||||||
&file_path.to_string_lossy()
|
})
|
||||||
)
|
.peekable();
|
||||||
})
|
|
||||||
.peekable();
|
|
||||||
|
|
||||||
if expanded_globs.peek().is_none() {
|
if expanded_globs.peek().is_none() {
|
||||||
let file_name = file_path.file_name().unwrap_or_else(|| {
|
let file_name = file_path.file_name().unwrap_or_else(|| {
|
||||||
|
@ -23,6 +23,11 @@ impl Command for Default {
|
|||||||
SyntaxShape::String,
|
SyntaxShape::String,
|
||||||
"The name of the column.",
|
"The name of the column.",
|
||||||
)
|
)
|
||||||
|
.switch(
|
||||||
|
"empty",
|
||||||
|
"also replace empty items like \"\", {}, and []",
|
||||||
|
Some('e'),
|
||||||
|
)
|
||||||
.category(Category::Filters)
|
.category(Category::Filters)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +42,8 @@ impl Command for Default {
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> 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> {
|
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,
|
stack: &mut Stack,
|
||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
|
default_when_empty: bool,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let metadata = input.metadata();
|
let metadata = input.metadata();
|
||||||
let value: Value = call.req(engine_state, stack, 0)?;
|
let value: Value = call.req(engine_state, stack, 0)?;
|
||||||
@ -104,7 +125,9 @@ fn default(
|
|||||||
} => {
|
} => {
|
||||||
let record = record.to_mut();
|
let record = record.to_mut();
|
||||||
if let Some(val) = record.get_mut(&column.item) {
|
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();
|
*val = value.clone();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -118,7 +141,10 @@ fn default(
|
|||||||
engine_state.signals(),
|
engine_state.signals(),
|
||||||
)
|
)
|
||||||
.map(|x| x.set_metadata(metadata))
|
.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())
|
Ok(value.into_pipeline_data())
|
||||||
} else {
|
} else {
|
||||||
Ok(input)
|
Ok(input)
|
||||||
|
@ -31,7 +31,6 @@ mod merge;
|
|||||||
mod move_;
|
mod move_;
|
||||||
mod par_each;
|
mod par_each;
|
||||||
mod prepend;
|
mod prepend;
|
||||||
mod range;
|
|
||||||
mod reduce;
|
mod reduce;
|
||||||
mod reject;
|
mod reject;
|
||||||
mod rename;
|
mod rename;
|
||||||
@ -91,7 +90,6 @@ pub use merge::MergeDeep;
|
|||||||
pub use move_::Move;
|
pub use move_::Move;
|
||||||
pub use par_each::ParEach;
|
pub use par_each::ParEach;
|
||||||
pub use prepend::Prepend;
|
pub use prepend::Prepend;
|
||||||
pub use range::Range;
|
|
||||||
pub use reduce::Reduce;
|
pub use reduce::Reduce;
|
||||||
pub use reject::Reject;
|
pub use reject::Reject;
|
||||||
pub use rename::Rename;
|
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> {
|
fn convert_string_to_value(string_input: &str, span: Span) -> Result<Value, ShellError> {
|
||||||
match nu_json::from_str(string_input) {
|
match nu_json::from_str(string_input) {
|
||||||
Ok(value) => Ok(convert_nujson_to_value(value, span)),
|
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 {
|
Err(x) => match x {
|
||||||
nu_json::Error::Syntax(_, row, col) => {
|
nu_json::Error::Syntax(_, row, col) => {
|
||||||
let label = x.to_string();
|
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 {
|
Err(ShellError::GenericError {
|
||||||
error: "Error while parsing JSON text".into(),
|
error: "Error while parsing JSON text".into(),
|
||||||
msg: "error 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)),
|
Ok(value) => Ok(convert_nujson_to_value(value, span)),
|
||||||
Err(err) => Err(if err.is_syntax() {
|
Err(err) => Err(if err.is_syntax() {
|
||||||
let label = err.to_string();
|
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 {
|
ShellError::GenericError {
|
||||||
error: "Error while parsing JSON text".into(),
|
error: "Error while parsing JSON text".into(),
|
||||||
msg: "error 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 indexmap::IndexMap;
|
||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
use roxmltree::NodeType;
|
use roxmltree::{NodeType, ParsingOptions, TextPos};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct FromXml;
|
pub struct FromXml;
|
||||||
@ -16,6 +16,11 @@ impl Command for FromXml {
|
|||||||
Signature::build("from xml")
|
Signature::build("from xml")
|
||||||
.input_output_types(vec![(Type::String, Type::record())])
|
.input_output_types(vec![(Type::String, Type::record())])
|
||||||
.switch("keep-comments", "add comment nodes to result", None)
|
.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(
|
.switch(
|
||||||
"keep-pi",
|
"keep-pi",
|
||||||
"add processing instruction nodes to result",
|
"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 head = call.head;
|
||||||
let keep_comments = call.has_flag(engine_state, stack, "keep-comments")?;
|
let keep_comments = call.has_flag(engine_state, stack, "keep-comments")?;
|
||||||
let keep_processing_instructions = call.has_flag(engine_state, stack, "keep-pi")?;
|
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 {
|
let info = ParsingInfo {
|
||||||
span: head,
|
span: head,
|
||||||
keep_comments,
|
keep_comments,
|
||||||
keep_processing_instructions,
|
keep_processing_instructions,
|
||||||
|
allow_dtd,
|
||||||
};
|
};
|
||||||
from_xml(input, &info)
|
from_xml(input, &info)
|
||||||
}
|
}
|
||||||
@ -90,6 +97,7 @@ struct ParsingInfo {
|
|||||||
span: Span,
|
span: Span,
|
||||||
keep_comments: bool,
|
keep_comments: bool,
|
||||||
keep_processing_instructions: bool,
|
keep_processing_instructions: bool,
|
||||||
|
allow_dtd: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_attributes_to_value(attributes: &[roxmltree::Attribute], info: &ParsingInfo) -> Value {
|
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> {
|
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))
|
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) => {
|
||||||
Ok(x.into_pipeline_data_with_metadata(metadata.map(|md| md.with_content_type(None))))
|
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 {
|
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.",
|
"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.",
|
"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.",
|
"The http://www.w3.org/2000/xmlns/ URI must not be declared.",
|
||||||
span,
|
source, pos,
|
||||||
),
|
),
|
||||||
roxmltree::Error::InvalidElementNamePrefix(_) => {
|
roxmltree::Error::InvalidElementNamePrefix(pos) => {
|
||||||
make_cant_convert_error("xmlns can't be used as an element prefix.", span)
|
make_xml_error_spanned("xmlns can't be used as an element prefix.", source, pos)
|
||||||
}
|
}
|
||||||
roxmltree::Error::DuplicatedNamespace(_, _) => {
|
roxmltree::Error::DuplicatedNamespace(namespace, pos) => {
|
||||||
make_cant_convert_error("A namespace was already defined on this element.", span)
|
make_xml_error_spanned(format!("Namespace {namespace} was already defined on this element."), source, pos)
|
||||||
}
|
}
|
||||||
roxmltree::Error::UnknownNamespace(prefix, _) => {
|
roxmltree::Error::UnknownNamespace(prefix, pos) => {
|
||||||
make_cant_convert_error(format!("Unknown prefix {}", prefix), span)
|
make_xml_error_spanned(format!("Unknown prefix {}", prefix), source, pos)
|
||||||
}
|
}
|
||||||
roxmltree::Error::UnexpectedCloseTag { .. } => {
|
roxmltree::Error::UnexpectedCloseTag(expected, actual, pos) => {
|
||||||
make_cant_convert_error("Unexpected close tag", span)
|
make_xml_error_spanned(format!("Unexpected close tag {actual}, expected {expected}"), source, pos)
|
||||||
}
|
}
|
||||||
roxmltree::Error::UnexpectedEntityCloseTag(_) => {
|
roxmltree::Error::UnexpectedEntityCloseTag(pos) => {
|
||||||
make_cant_convert_error("Entity value starts with a close tag.", span)
|
make_xml_error_spanned("Entity value starts with a close tag.", source, pos)
|
||||||
}
|
}
|
||||||
roxmltree::Error::UnknownEntityReference(_, _) => make_cant_convert_error(
|
roxmltree::Error::UnknownEntityReference(entity, pos) => make_xml_error_spanned(
|
||||||
"A reference to an entity that was not defined in the DTD.",
|
format!("Reference to unknown entity {entity} (was not defined in the DTD)"),
|
||||||
span,
|
source, pos,
|
||||||
),
|
),
|
||||||
roxmltree::Error::MalformedEntityReference(_) => {
|
roxmltree::Error::MalformedEntityReference(pos) => {
|
||||||
make_cant_convert_error("A malformed entity reference.", span)
|
make_xml_error_spanned("Malformed entity reference.", source, pos)
|
||||||
}
|
}
|
||||||
roxmltree::Error::EntityReferenceLoop(_) => {
|
roxmltree::Error::EntityReferenceLoop(pos) => {
|
||||||
make_cant_convert_error("A possible entity reference loop.", span)
|
make_xml_error_spanned("Possible entity reference loop.", source, pos)
|
||||||
}
|
}
|
||||||
roxmltree::Error::InvalidAttributeValue(_) => {
|
roxmltree::Error::InvalidAttributeValue(pos) => {
|
||||||
make_cant_convert_error("Attribute value cannot have a < character.", span)
|
make_xml_error_spanned("Attribute value cannot have a < character.", source, pos)
|
||||||
}
|
}
|
||||||
roxmltree::Error::DuplicatedAttribute(_, _) => {
|
roxmltree::Error::DuplicatedAttribute(attribute, pos) => {
|
||||||
make_cant_convert_error("An element has a duplicated attributes.", span)
|
make_xml_error_spanned(format!("Element has a duplicated attribute: {attribute}"), source, pos)
|
||||||
}
|
}
|
||||||
roxmltree::Error::NoRootNode => {
|
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 => {
|
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(
|
roxmltree::Error::DtdDetected => make_xml_error(
|
||||||
"An XML with DTD detected. DTDs are currently disabled due to security reasons.",
|
"XML document with DTD detected.\nDTDs are disabled by default to prevent denial-of-service attacks (use --allow-dtd to parse anyway)",
|
||||||
span,
|
span
|
||||||
),
|
),
|
||||||
roxmltree::Error::NodesLimitReached => {
|
roxmltree::Error::NodesLimitReached => {
|
||||||
make_cant_convert_error("Node limit was reached.", span)
|
make_xml_error("Node limit was reached.", span)
|
||||||
}
|
}
|
||||||
roxmltree::Error::AttributesLimitReached => {
|
roxmltree::Error::AttributesLimitReached => {
|
||||||
make_cant_convert_error("Attribute limit reached", span)
|
make_xml_error("Attribute limit reached", span)
|
||||||
}
|
}
|
||||||
roxmltree::Error::NamespacesLimitReached => {
|
roxmltree::Error::NamespacesLimitReached => {
|
||||||
make_cant_convert_error("Namespace limit reached", span)
|
make_xml_error("Namespace limit reached", span)
|
||||||
}
|
}
|
||||||
roxmltree::Error::UnexpectedDeclaration(_) => {
|
roxmltree::Error::UnexpectedDeclaration(pos) => {
|
||||||
make_cant_convert_error("An XML document can have only one XML declaration and it must be at the start of the document.", span)
|
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(_) => {
|
roxmltree::Error::InvalidName(pos) => {
|
||||||
make_cant_convert_error("Invalid name found.", span)
|
make_xml_error_spanned("Invalid name.", source, pos)
|
||||||
}
|
}
|
||||||
roxmltree::Error::NonXmlChar(_, _) => {
|
roxmltree::Error::NonXmlChar(_, pos) => {
|
||||||
make_cant_convert_error("A non-XML character has occurred. Valid characters are: <https://www.w3.org/TR/xml/#char32>", span)
|
make_xml_error_spanned("Non-XML character found. Valid characters are: <https://www.w3.org/TR/xml/#char32>", source, pos)
|
||||||
}
|
}
|
||||||
roxmltree::Error::InvalidChar(_, _, _) => {
|
roxmltree::Error::InvalidChar(expected, actual, pos) => {
|
||||||
make_cant_convert_error("An invalid/unexpected character in XML.", span)
|
make_xml_error_spanned(
|
||||||
|
format!("Unexpected character {}, expected {}", actual as char, expected as char),
|
||||||
|
source,
|
||||||
|
pos
|
||||||
|
)
|
||||||
}
|
}
|
||||||
roxmltree::Error::InvalidChar2(_, _, _) => {
|
roxmltree::Error::InvalidChar2(expected, actual, pos) => {
|
||||||
make_cant_convert_error("An invalid/unexpected character in XML.", span)
|
make_xml_error_spanned(
|
||||||
|
format!("Unexpected character {}, expected {}", actual as char, expected),
|
||||||
|
source,
|
||||||
|
pos
|
||||||
|
)
|
||||||
}
|
}
|
||||||
roxmltree::Error::InvalidString(_, _) => {
|
roxmltree::Error::InvalidString(_, pos) => {
|
||||||
make_cant_convert_error("An invalid/unexpected string in XML.", span)
|
make_xml_error_spanned("Invalid/unexpected string in XML.", source, pos)
|
||||||
}
|
}
|
||||||
roxmltree::Error::InvalidExternalID(_) => {
|
roxmltree::Error::InvalidExternalID(pos) => {
|
||||||
make_cant_convert_error("An invalid ExternalID in the DTD.", span)
|
make_xml_error_spanned("Invalid ExternalID in the DTD.", source, pos)
|
||||||
}
|
}
|
||||||
roxmltree::Error::InvalidComment(_) => {
|
roxmltree::Error::InvalidComment(pos) => {
|
||||||
make_cant_convert_error("A comment cannot contain `--` or end with `-`.", span)
|
make_xml_error_spanned("A comment cannot contain `--` or end with `-`.", source, pos)
|
||||||
}
|
}
|
||||||
roxmltree::Error::InvalidCharacterData(_) => {
|
roxmltree::Error::InvalidCharacterData(pos) => {
|
||||||
make_cant_convert_error("A Character Data node contains an invalid data. Currently, only `]]>` is not allowed.", span)
|
make_xml_error_spanned("Character Data node contains an invalid data. Currently, only `]]>` is not allowed.", source, pos)
|
||||||
}
|
}
|
||||||
roxmltree::Error::UnknownToken(_) => {
|
roxmltree::Error::UnknownToken(pos) => {
|
||||||
make_cant_convert_error("Unknown token in XML.", span)
|
make_xml_error_spanned("Unknown token in XML.", source, pos)
|
||||||
}
|
}
|
||||||
roxmltree::Error::UnexpectedEndOfStream => {
|
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 {
|
fn make_xml_error(msg: impl Into<String>, span: Span) -> ShellError {
|
||||||
ShellError::CantConvert {
|
ShellError::GenericError {
|
||||||
from_type: Type::String.to_string(),
|
error: "Failed to parse XML".into(),
|
||||||
to_type: "XML".to_string(),
|
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,
|
span,
|
||||||
help: Some(help.into()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,6 +407,7 @@ mod tests {
|
|||||||
span: Span::test_data(),
|
span: Span::test_data(),
|
||||||
keep_comments: false,
|
keep_comments: false,
|
||||||
keep_processing_instructions: false,
|
keep_processing_instructions: false,
|
||||||
|
allow_dtd: false,
|
||||||
};
|
};
|
||||||
from_xml_string_to_value(xml, &info)
|
from_xml_string_to_value(xml, &info)
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ impl Command for ToJson {
|
|||||||
// allow ranges to expand and turn into array
|
// allow ranges to expand and turn into array
|
||||||
let input = input.try_expand_range()?;
|
let input = input.try_expand_range()?;
|
||||||
let value = input.into_value(span)?;
|
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 {
|
let json_result = if raw {
|
||||||
nu_json::to_string_raw(&json_value)
|
nu_json::to_string_raw(&json_value)
|
||||||
@ -78,16 +78,12 @@ impl Command for ToJson {
|
|||||||
};
|
};
|
||||||
Ok(PipelineData::Value(res, Some(metadata)))
|
Ok(PipelineData::Value(res, Some(metadata)))
|
||||||
}
|
}
|
||||||
_ => Ok(Value::error(
|
_ => Err(ShellError::CantConvert {
|
||||||
ShellError::CantConvert {
|
to_type: "JSON".into(),
|
||||||
to_type: "JSON".into(),
|
from_type: value.get_type().to_string(),
|
||||||
from_type: value.get_type().to_string(),
|
|
||||||
span,
|
|
||||||
help: None,
|
|
||||||
},
|
|
||||||
span,
|
span,
|
||||||
)
|
help: None,
|
||||||
.into_pipeline_data()),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,6 +114,7 @@ impl Command for ToJson {
|
|||||||
pub fn value_to_json_value(
|
pub fn value_to_json_value(
|
||||||
engine_state: &EngineState,
|
engine_state: &EngineState,
|
||||||
v: &Value,
|
v: &Value,
|
||||||
|
call_span: Span,
|
||||||
serialize_types: bool,
|
serialize_types: bool,
|
||||||
) -> Result<nu_json::Value, ShellError> {
|
) -> Result<nu_json::Value, ShellError> {
|
||||||
let span = v.span();
|
let span = v.span();
|
||||||
@ -142,24 +139,20 @@ pub fn value_to_json_value(
|
|||||||
),
|
),
|
||||||
|
|
||||||
Value::List { vals, .. } => {
|
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::Error { error, .. } => return Err(*error.clone()),
|
||||||
Value::Closure { val, .. } => {
|
Value::Closure { val, .. } => {
|
||||||
if serialize_types {
|
if serialize_types {
|
||||||
let block = engine_state.get_block(val.block_id);
|
let closure_string = val.coerce_into_string(engine_state, span)?;
|
||||||
if let Some(span) = block.span {
|
nu_json::Value::String(closure_string.to_string())
|
||||||
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()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
} else {
|
} 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,
|
Value::Range { .. } => nu_json::Value::Null,
|
||||||
@ -171,14 +164,14 @@ pub fn value_to_json_value(
|
|||||||
for (k, v) in &**val {
|
for (k, v) in &**val {
|
||||||
m.insert(
|
m.insert(
|
||||||
k.clone(),
|
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)
|
nu_json::Value::Object(m)
|
||||||
}
|
}
|
||||||
Value::Custom { val, .. } => {
|
Value::Custom { val, .. } => {
|
||||||
let collected = val.to_base_value(span)?;
|
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(
|
fn json_list(
|
||||||
engine_state: &EngineState,
|
engine_state: &EngineState,
|
||||||
input: &[Value],
|
input: &[Value],
|
||||||
|
call_span: Span,
|
||||||
serialize_types: bool,
|
serialize_types: bool,
|
||||||
) -> Result<Vec<nu_json::Value>, ShellError> {
|
) -> Result<Vec<nu_json::Value>, ShellError> {
|
||||||
let mut out = vec![];
|
let mut out = vec![];
|
||||||
|
|
||||||
for value in input {
|
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)
|
Ok(out)
|
||||||
|
@ -22,6 +22,11 @@ impl Command for ToMsgpack {
|
|||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build(self.name())
|
Signature::build(self.name())
|
||||||
.input_output_type(Type::Any, Type::Binary)
|
.input_output_type(Type::Any, Type::Binary)
|
||||||
|
.switch(
|
||||||
|
"serialize",
|
||||||
|
"serialize nushell types that cannot be deserialized",
|
||||||
|
Some('s'),
|
||||||
|
)
|
||||||
.category(Category::Formats)
|
.category(Category::Formats)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,8 +74,8 @@ MessagePack: https://msgpack.org/
|
|||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
&self,
|
&self,
|
||||||
_engine_state: &EngineState,
|
engine_state: &EngineState,
|
||||||
_stack: &mut Stack,
|
stack: &mut Stack,
|
||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
@ -83,7 +88,16 @@ MessagePack: https://msgpack.org/
|
|||||||
let value = input.into_value(value_span)?;
|
let value = input.into_value(value_span)?;
|
||||||
let mut out = vec![];
|
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)))
|
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,
|
out: &mut impl io::Write,
|
||||||
value: &Value,
|
value: &Value,
|
||||||
depth: usize,
|
depth: usize,
|
||||||
|
engine_state: &EngineState,
|
||||||
|
call_span: Span,
|
||||||
|
serialize_types: bool,
|
||||||
) -> Result<(), WriteError> {
|
) -> Result<(), WriteError> {
|
||||||
use mp::ValueWriteError::InvalidMarkerWrite;
|
use mp::ValueWriteError::InvalidMarkerWrite;
|
||||||
let span = value.span();
|
let span = value.span();
|
||||||
@ -196,6 +213,9 @@ pub(crate) fn write_value(
|
|||||||
out,
|
out,
|
||||||
&Value::list(val.into_range_iter(span, Signals::empty()).collect(), span),
|
&Value::list(val.into_range_iter(span, Signals::empty()).collect(), span),
|
||||||
depth,
|
depth,
|
||||||
|
engine_state,
|
||||||
|
call_span,
|
||||||
|
serialize_types,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Value::String { val, .. } => {
|
Value::String { val, .. } => {
|
||||||
@ -208,13 +228,20 @@ pub(crate) fn write_value(
|
|||||||
mp::write_map_len(out, convert(val.len(), span)?).err_span(span)?;
|
mp::write_map_len(out, convert(val.len(), span)?).err_span(span)?;
|
||||||
for (k, v) in val.iter() {
|
for (k, v) in val.iter() {
|
||||||
mp::write_str(out, k).err_span(span)?;
|
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, .. } => {
|
Value::List { vals, .. } => {
|
||||||
mp::write_array_len(out, convert(vals.len(), span)?).err_span(span)?;
|
mp::write_array_len(out, convert(vals.len(), span)?).err_span(span)?;
|
||||||
for val in vals {
|
for val in vals {
|
||||||
write_value(out, val, depth + 1)?;
|
write_value(
|
||||||
|
out,
|
||||||
|
val,
|
||||||
|
depth + 1,
|
||||||
|
engine_state,
|
||||||
|
call_span,
|
||||||
|
serialize_types,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Value::Nothing { .. } => {
|
Value::Nothing { .. } => {
|
||||||
@ -222,11 +249,20 @@ pub(crate) fn write_value(
|
|||||||
.map_err(InvalidMarkerWrite)
|
.map_err(InvalidMarkerWrite)
|
||||||
.err_span(span)?;
|
.err_span(span)?;
|
||||||
}
|
}
|
||||||
Value::Closure { .. } => {
|
Value::Closure { val, .. } => {
|
||||||
// Closures can't be converted
|
if serialize_types {
|
||||||
mp::write_nil(out)
|
let closure_string = val
|
||||||
.map_err(InvalidMarkerWrite)
|
.coerce_into_string(engine_state, span)
|
||||||
.err_span(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, .. } => {
|
Value::Error { error, .. } => {
|
||||||
return Err(WriteError::Shell(error.clone()));
|
return Err(WriteError::Shell(error.clone()));
|
||||||
@ -249,7 +285,14 @@ pub(crate) fn write_value(
|
|||||||
mp::write_bin(out, val).err_span(span)?;
|
mp::write_bin(out, val).err_span(span)?;
|
||||||
}
|
}
|
||||||
Value::Custom { val, .. } => {
|
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(())
|
Ok(())
|
||||||
|
@ -32,6 +32,11 @@ impl Command for ToMsgpackz {
|
|||||||
"Window size for brotli compression (default 20)",
|
"Window size for brotli compression (default 20)",
|
||||||
Some('w'),
|
Some('w'),
|
||||||
)
|
)
|
||||||
|
.switch(
|
||||||
|
"serialize",
|
||||||
|
"serialize nushell types that cannot be deserialized",
|
||||||
|
Some('s'),
|
||||||
|
)
|
||||||
.category(Category::Formats)
|
.category(Category::Formats)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,6 +74,7 @@ impl Command for ToMsgpackz {
|
|||||||
.get_flag(engine_state, stack, "window-size")?
|
.get_flag(engine_state, stack, "window-size")?
|
||||||
.map(to_u32)
|
.map(to_u32)
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
let serialize_types = call.has_flag(engine_state, stack, "serialize")?;
|
||||||
|
|
||||||
let value_span = input.span().unwrap_or(call.head);
|
let value_span = input.span().unwrap_or(call.head);
|
||||||
let value = input.into_value(value_span)?;
|
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),
|
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()
|
out.flush()
|
||||||
.map_err(|err| IoError::new(err.kind(), call.head, None))?;
|
.map_err(|err| IoError::new(err.kind(), call.head, None))?;
|
||||||
drop(out);
|
drop(out);
|
||||||
|
@ -69,16 +69,9 @@ impl Command for ToNuon {
|
|||||||
match nuon::to_nuon(engine_state, &value, style, Some(span), serialize_types) {
|
match nuon::to_nuon(engine_state, &value, style, Some(span), serialize_types) {
|
||||||
Ok(serde_nuon_string) => Ok(Value::string(serde_nuon_string, span)
|
Ok(serde_nuon_string) => Ok(Value::string(serde_nuon_string, span)
|
||||||
.into_pipeline_data_with_metadata(Some(metadata))),
|
.into_pipeline_data_with_metadata(Some(metadata))),
|
||||||
_ => Ok(Value::error(
|
Err(error) => {
|
||||||
ShellError::CantConvert {
|
Ok(Value::error(error, span).into_pipeline_data_with_metadata(Some(metadata)))
|
||||||
to_type: "NUON".into(),
|
}
|
||||||
from_type: value.get_type().to_string(),
|
|
||||||
span,
|
|
||||||
help: None,
|
|
||||||
},
|
|
||||||
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_engine::command_prelude::*;
|
||||||
|
use nu_protocol::Range;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathAbs;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathAbs {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math abs"
|
"math abs"
|
||||||
}
|
}
|
||||||
@ -21,6 +23,7 @@ impl Command for SubCommand {
|
|||||||
Type::List(Box::new(Type::Duration)),
|
Type::List(Box::new(Type::Duration)),
|
||||||
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)
|
.allow_variants_without_examples(true)
|
||||||
.category(Category::Math)
|
.category(Category::Math)
|
||||||
@ -46,6 +49,19 @@ impl Command for SubCommand {
|
|||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let head = call.head;
|
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())
|
input.map(move |value| abs_helper(value, head), engine_state.signals())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +72,19 @@ impl Command for SubCommand {
|
|||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let head = call.head;
|
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(
|
input.map(
|
||||||
move |value| abs_helper(value, head),
|
move |value| abs_helper(value, head),
|
||||||
working_set.permanent().signals(),
|
working_set.permanent().signals(),
|
||||||
@ -105,6 +134,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::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;
|
const NS_PER_SEC: i64 = 1_000_000_000;
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathAvg;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathAvg {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math avg"
|
"math avg"
|
||||||
}
|
}
|
||||||
@ -104,6 +104,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::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_engine::command_prelude::*;
|
||||||
|
use nu_protocol::Range;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathCeil;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathCeil {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math ceil"
|
"math ceil"
|
||||||
}
|
}
|
||||||
@ -16,6 +18,7 @@ impl Command for SubCommand {
|
|||||||
Type::List(Box::new(Type::Number)),
|
Type::List(Box::new(Type::Number)),
|
||||||
Type::List(Box::new(Type::Int)),
|
Type::List(Box::new(Type::Int)),
|
||||||
),
|
),
|
||||||
|
(Type::Range, Type::List(Box::new(Type::Number))),
|
||||||
])
|
])
|
||||||
.allow_variants_without_examples(true)
|
.allow_variants_without_examples(true)
|
||||||
.category(Category::Math)
|
.category(Category::Math)
|
||||||
@ -45,6 +48,19 @@ impl Command for SubCommand {
|
|||||||
if matches!(input, PipelineData::Empty) {
|
if matches!(input, PipelineData::Empty) {
|
||||||
return Err(ShellError::PipelineEmpty { dst_span: head });
|
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())
|
input.map(move |value| operate(value, head), engine_state.signals())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +75,19 @@ impl Command for SubCommand {
|
|||||||
if matches!(input, PipelineData::Empty) {
|
if matches!(input, PipelineData::Empty) {
|
||||||
return Err(ShellError::PipelineEmpty { dst_span: head });
|
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(
|
input.map(
|
||||||
move |value| operate(value, head),
|
move |value| operate(value, head),
|
||||||
working_set.permanent().signals(),
|
working_set.permanent().signals(),
|
||||||
@ -103,6 +132,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::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_engine::command_prelude::*;
|
||||||
|
use nu_protocol::Range;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathFloor;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathFloor {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math floor"
|
"math floor"
|
||||||
}
|
}
|
||||||
@ -16,6 +18,7 @@ impl Command for SubCommand {
|
|||||||
Type::List(Box::new(Type::Number)),
|
Type::List(Box::new(Type::Number)),
|
||||||
Type::List(Box::new(Type::Int)),
|
Type::List(Box::new(Type::Int)),
|
||||||
),
|
),
|
||||||
|
(Type::Range, Type::List(Box::new(Type::Number))),
|
||||||
])
|
])
|
||||||
.allow_variants_without_examples(true)
|
.allow_variants_without_examples(true)
|
||||||
.category(Category::Math)
|
.category(Category::Math)
|
||||||
@ -45,6 +48,19 @@ impl Command for SubCommand {
|
|||||||
if matches!(input, PipelineData::Empty) {
|
if matches!(input, PipelineData::Empty) {
|
||||||
return Err(ShellError::PipelineEmpty { dst_span: head });
|
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())
|
input.map(move |value| operate(value, head), engine_state.signals())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +75,19 @@ impl Command for SubCommand {
|
|||||||
if matches!(input, PipelineData::Empty) {
|
if matches!(input, PipelineData::Empty) {
|
||||||
return Err(ShellError::PipelineEmpty { dst_span: head });
|
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(
|
input.map(
|
||||||
move |value| operate(value, head),
|
move |value| operate(value, head),
|
||||||
working_set.permanent().signals(),
|
working_set.permanent().signals(),
|
||||||
@ -103,6 +132,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::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_engine::command_prelude::*;
|
||||||
|
use nu_protocol::Range;
|
||||||
use nu_protocol::Signals;
|
use nu_protocol::Signals;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathLog;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathLog {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math log"
|
"math log"
|
||||||
}
|
}
|
||||||
@ -22,6 +24,7 @@ impl Command for SubCommand {
|
|||||||
Type::List(Box::new(Type::Number)),
|
Type::List(Box::new(Type::Number)),
|
||||||
Type::List(Box::new(Type::Float)),
|
Type::List(Box::new(Type::Float)),
|
||||||
),
|
),
|
||||||
|
(Type::Range, Type::List(Box::new(Type::Number))),
|
||||||
])
|
])
|
||||||
.allow_variants_without_examples(true)
|
.allow_variants_without_examples(true)
|
||||||
.category(Category::Math)
|
.category(Category::Math)
|
||||||
@ -46,7 +49,21 @@ impl Command for SubCommand {
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
|
let head = call.head;
|
||||||
let base: Spanned<f64> = call.req(engine_state, stack, 0)?;
|
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())
|
log(base, call.head, input, engine_state.signals())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +73,21 @@ impl Command for SubCommand {
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
|
let head = call.head;
|
||||||
let base: Spanned<f64> = call.req_const(working_set, 0)?;
|
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())
|
log(base, call.head, input, working_set.permanent().signals())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,6 +190,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(MathLog {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,9 @@ use crate::math::{
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathMax;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathMax {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math max"
|
"math max"
|
||||||
}
|
}
|
||||||
@ -97,6 +97,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::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;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathMedian;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathMedian {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math median"
|
"math median"
|
||||||
}
|
}
|
||||||
@ -151,6 +151,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(MathMedian {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,9 @@ use crate::math::{
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathMin;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathMin {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math min"
|
"math min"
|
||||||
}
|
}
|
||||||
@ -95,6 +95,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(MathMin {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,20 +17,20 @@ mod sum;
|
|||||||
mod utils;
|
mod utils;
|
||||||
mod variance;
|
mod variance;
|
||||||
|
|
||||||
pub use abs::SubCommand as MathAbs;
|
pub use abs::MathAbs;
|
||||||
pub use avg::SubCommand as MathAvg;
|
pub use avg::MathAvg;
|
||||||
pub use ceil::SubCommand as MathCeil;
|
pub use ceil::MathCeil;
|
||||||
pub use floor::SubCommand as MathFloor;
|
pub use floor::MathFloor;
|
||||||
pub use math_::MathCommand as Math;
|
pub use math_::MathCommand as Math;
|
||||||
pub use max::SubCommand as MathMax;
|
pub use max::MathMax;
|
||||||
pub use median::SubCommand as MathMedian;
|
pub use median::MathMedian;
|
||||||
pub use min::SubCommand as MathMin;
|
pub use min::MathMin;
|
||||||
pub use mode::SubCommand as MathMode;
|
pub use mode::MathMode;
|
||||||
pub use product::SubCommand as MathProduct;
|
pub use product::MathProduct;
|
||||||
pub use round::SubCommand as MathRound;
|
pub use round::MathRound;
|
||||||
pub use sqrt::SubCommand as MathSqrt;
|
pub use sqrt::MathSqrt;
|
||||||
pub use stddev::SubCommand as MathStddev;
|
pub use stddev::MathStddev;
|
||||||
pub use sum::SubCommand as MathSum;
|
pub use sum::MathSum;
|
||||||
pub use variance::SubCommand as MathVariance;
|
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};
|
use std::{cmp::Ordering, collections::HashMap};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathMode;
|
||||||
|
|
||||||
#[derive(Hash, Eq, PartialEq, Debug)]
|
#[derive(Hash, Eq, PartialEq, Debug)]
|
||||||
enum NumberTypes {
|
enum NumberTypes {
|
||||||
@ -28,7 +28,7 @@ impl HashableType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathMode {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math mode"
|
"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
|
//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
|
// But f64 doesn't implement Hash, so we get the binary representation to use as
|
||||||
// key in the HashMap
|
// key in the HashMap
|
||||||
@ -130,11 +130,11 @@ pub fn mode(values: &[Value], _span: Span, head: Span) -> Result<Value, ShellErr
|
|||||||
NumberTypes::Filesize,
|
NumberTypes::Filesize,
|
||||||
)),
|
)),
|
||||||
Value::Error { error, .. } => Err(*error.clone()),
|
Value::Error { error, .. } => Err(*error.clone()),
|
||||||
other => Err(ShellError::UnsupportedInput {
|
_ => Err(ShellError::UnsupportedInput {
|
||||||
msg: "Unable to give a result with this input".to_string(),
|
msg: "Unable to give a result with this input".to_string(),
|
||||||
input: "value originates from here".into(),
|
input: "value originates from here".into(),
|
||||||
msg_span: head,
|
msg_span: head,
|
||||||
input_span: other.span(),
|
input_span: span,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<HashableType>, ShellError>>()?;
|
.collect::<Result<Vec<HashableType>, ShellError>>()?;
|
||||||
@ -183,6 +183,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::test_examples;
|
use crate::test_examples;
|
||||||
|
|
||||||
test_examples(SubCommand {})
|
test_examples(MathMode {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,9 @@ use crate::math::{
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathProduct;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathProduct {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math product"
|
"math product"
|
||||||
}
|
}
|
||||||
@ -88,6 +88,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::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_engine::command_prelude::*;
|
||||||
|
use nu_protocol::Range;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathRound;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathRound {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math round"
|
"math round"
|
||||||
}
|
}
|
||||||
@ -16,6 +18,7 @@ impl Command for SubCommand {
|
|||||||
Type::List(Box::new(Type::Number)),
|
Type::List(Box::new(Type::Number)),
|
||||||
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)
|
.allow_variants_without_examples(true)
|
||||||
.named(
|
.named(
|
||||||
@ -52,6 +55,19 @@ impl Command for SubCommand {
|
|||||||
if matches!(input, PipelineData::Empty) {
|
if matches!(input, PipelineData::Empty) {
|
||||||
return Err(ShellError::PipelineEmpty { dst_span: head });
|
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(
|
input.map(
|
||||||
move |value| operate(value, head, precision_param),
|
move |value| operate(value, head, precision_param),
|
||||||
engine_state.signals(),
|
engine_state.signals(),
|
||||||
@ -70,6 +86,19 @@ impl Command for SubCommand {
|
|||||||
if matches!(input, PipelineData::Empty) {
|
if matches!(input, PipelineData::Empty) {
|
||||||
return Err(ShellError::PipelineEmpty { dst_span: head });
|
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(
|
input.map(
|
||||||
move |value| operate(value, head, precision_param),
|
move |value| operate(value, head, precision_param),
|
||||||
working_set.permanent().signals(),
|
working_set.permanent().signals(),
|
||||||
@ -153,6 +182,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::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_engine::command_prelude::*;
|
||||||
|
use nu_protocol::Range;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathSqrt;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathSqrt {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math sqrt"
|
"math sqrt"
|
||||||
}
|
}
|
||||||
@ -16,6 +18,7 @@ impl Command for SubCommand {
|
|||||||
Type::List(Box::new(Type::Number)),
|
Type::List(Box::new(Type::Number)),
|
||||||
Type::List(Box::new(Type::Float)),
|
Type::List(Box::new(Type::Float)),
|
||||||
),
|
),
|
||||||
|
(Type::Range, Type::List(Box::new(Type::Number))),
|
||||||
])
|
])
|
||||||
.allow_variants_without_examples(true)
|
.allow_variants_without_examples(true)
|
||||||
.category(Category::Math)
|
.category(Category::Math)
|
||||||
@ -45,6 +48,19 @@ impl Command for SubCommand {
|
|||||||
if matches!(input, PipelineData::Empty) {
|
if matches!(input, PipelineData::Empty) {
|
||||||
return Err(ShellError::PipelineEmpty { dst_span: head });
|
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())
|
input.map(move |value| operate(value, head), engine_state.signals())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +75,19 @@ impl Command for SubCommand {
|
|||||||
if matches!(input, PipelineData::Empty) {
|
if matches!(input, PipelineData::Empty) {
|
||||||
return Err(ShellError::PipelineEmpty { dst_span: head });
|
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(
|
input.map(
|
||||||
move |value| operate(value, head),
|
move |value| operate(value, head),
|
||||||
working_set.permanent().signals(),
|
working_set.permanent().signals(),
|
||||||
@ -127,6 +156,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::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::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SubCommand;
|
pub struct MathStddev;
|
||||||
|
|
||||||
impl Command for SubCommand {
|
impl Command for MathStddev {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"math stddev"
|
"math stddev"
|
||||||
}
|
}
|
||||||
@ -14,6 +14,7 @@ impl Command for SubCommand {
|
|||||||
Signature::build("math stddev")
|
Signature::build("math stddev")
|
||||||
.input_output_types(vec![
|
.input_output_types(vec![
|
||||||
(Type::List(Box::new(Type::Number)), Type::Number),
|
(Type::List(Box::new(Type::Number)), Type::Number),
|
||||||
|
(Type::Range, Type::Number),
|
||||||
(Type::table(), Type::record()),
|
(Type::table(), Type::record()),
|
||||||
(Type::record(), Type::record()),
|
(Type::record(), Type::record()),
|
||||||
])
|
])
|
||||||
@ -53,6 +54,18 @@ impl Command for SubCommand {
|
|||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let sample = call.has_flag(engine_state, stack, "sample")?;
|
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))
|
run_with_function(call, input, compute_stddev(sample))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,6 +76,18 @@ impl Command for SubCommand {
|
|||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let sample = call.has_flag_const(working_set, "sample")?;
|
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))
|
run_with_function(call, input, compute_stddev(sample))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,6 +136,6 @@ mod test {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
use crate::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