From db37bead643ae3c0b7b6dd3942f3eb6e80b8f4d2 Mon Sep 17 00:00:00 2001 From: Stefan Holderbach Date: Tue, 21 May 2024 03:09:28 +0200 Subject: [PATCH 001/113] Remove unused dependencies (#12917) - **Remove unused `pathdiff` dep in `nu-cli`** - **Remove unused `serde_json` dep on `nu-protocol`** - Unnecessary after moving the plugin file to msgpack (still a dev-dependency) --- Cargo.lock | 1 - crates/nu-cli/Cargo.toml | 1 - crates/nu-protocol/Cargo.toml | 2 -- 3 files changed, 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fb792cbd2a..38d640ab5f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2846,7 +2846,6 @@ dependencies = [ "nu-test-support", "nu-utils", "once_cell", - "pathdiff", "percent-encoding", "reedline", "rstest", diff --git a/crates/nu-cli/Cargo.toml b/crates/nu-cli/Cargo.toml index e631f7ccf6..d9cd728f19 100644 --- a/crates/nu-cli/Cargo.toml +++ b/crates/nu-cli/Cargo.toml @@ -39,7 +39,6 @@ miette = { workspace = true, features = ["fancy-no-backtrace"] } lscolors = { workspace = true, default-features = false, features = ["nu-ansi-term"] } once_cell = { workspace = true } percent-encoding = { workspace = true } -pathdiff = { workspace = true } sysinfo = { workspace = true } unicode-segmentation = { workspace = true } uuid = { workspace = true, features = ["v4"] } diff --git a/crates/nu-protocol/Cargo.toml b/crates/nu-protocol/Cargo.toml index ae04c20ddb..84e76b3f5a 100644 --- a/crates/nu-protocol/Cargo.toml +++ b/crates/nu-protocol/Cargo.toml @@ -28,7 +28,6 @@ miette = { workspace = true, features = ["fancy-no-backtrace"] } num-format = { workspace = true } rmp-serde = { workspace = true, optional = true } serde = { workspace = true, default-features = false } -serde_json = { workspace = true, optional = true } thiserror = "1.0" typetag = "0.2" os_pipe = { workspace = true, features = ["io_safety"] } @@ -40,7 +39,6 @@ nix = { workspace = true, default-features = false, features = ["signal"] } plugin = [ "brotli", "rmp-serde", - "serde_json", ] [dev-dependencies] From 1cdc39bc2a616fde4c2b58b45893653517725643 Mon Sep 17 00:00:00 2001 From: Devyn Cairns Date: Mon, 20 May 2024 22:47:24 -0700 Subject: [PATCH 002/113] Update mimalloc to 0.1.42 (#12919) # Description This update fixes mimalloc for NetBSD # Tests + Formatting Tests are passing just fine --- Cargo.lock | 10 +++++----- Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 38d640ab5f..59948fbc51 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -377,7 +377,7 @@ dependencies = [ "bitflags 2.5.0", "cexpr", "clang-sys", - "itertools 0.11.0", + "itertools 0.12.1", "lazy_static", "lazycell", "proc-macro2", @@ -2326,9 +2326,9 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libmimalloc-sys" -version = "0.1.37" +version = "0.1.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81eb4061c0582dedea1cbc7aff2240300dd6982e0239d1c99e65c1dbf4a30ba7" +checksum = "0e7bb23d733dfcc8af652a78b7bf232f0e967710d044732185e561e47c0336b6" dependencies = [ "cc", "libc", @@ -2582,9 +2582,9 @@ dependencies = [ [[package]] name = "mimalloc" -version = "0.1.41" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f41a2280ded0da56c8cf898babb86e8f10651a34adcfff190ae9a1159c6908d" +checksum = "e9186d86b79b52f4a77af65604b51225e8db1d6ee7e3f41aec1e40829c71a176" dependencies = [ "libmimalloc-sys", ] diff --git a/Cargo.toml b/Cargo.toml index afc31383f9..665fd21747 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -197,7 +197,7 @@ crossterm = { workspace = true } ctrlc = { workspace = true } log = { workspace = true } miette = { workspace = true, features = ["fancy-no-backtrace", "fancy"] } -mimalloc = { version = "0.1.37", default-features = false, optional = true } +mimalloc = { version = "0.1.42", default-features = false, optional = true } serde_json = { workspace = true } simplelog = "0.12" time = "0.3" From f83439fdda33975f803dca653b08c9210d83826c Mon Sep 17 00:00:00 2001 From: NotTheDr01ds <32344964+NotTheDr01ds@users.noreply.github.com> Date: Tue, 21 May 2024 11:31:14 -0400 Subject: [PATCH 003/113] Add completer for std help (#12929) # Description While each of the `help ` in `std` had completers, there wasn't one for the main `help` command. This adds all internals and custom commands (as with `help commands`) as possible completions. # User-Facing Changes `help ` + Tab will now suggest completions for both the `help ` as well as all internal and custom commands. # Tests + Formatting Note: Cannot add tests for completion functions since they are module-internal and not visible to test cases, that I can see. - :green_circle: `toolkit fmt` - :green_circle: `toolkit clippy` - :green_circle: `toolkit test` - :green_circle: `toolkit test stdlib` --- crates/nu-std/std/help.nu | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/crates/nu-std/std/help.nu b/crates/nu-std/std/help.nu index 4e08597691..20a672dd90 100644 --- a/crates/nu-std/std/help.nu +++ b/crates/nu-std/std/help.nu @@ -93,6 +93,18 @@ def "nu-complete list-commands" [] { scope commands | select name usage | rename value description } +def "nu-complete main-help" [] { + [ + { value: "commands", description: "Show help on Nushell commands." } + { value: "aliases", description: "Show help on Nushell aliases." } + { value: "modules", description: "Show help on Nushell modules." } + { value: "externs", description: "Show help on Nushell externs." } + { value: "operators", description: "Show help on Nushell operators." } + { value: "escapes", description: "Show help on Nushell string escapes." } + ] + | append (nu-complete list-commands) +} + def "nu-complete list-externs" [] { scope commands | where is_extern | select name usage | rename value description } @@ -720,7 +732,7 @@ def pretty-cmd [] { # search for string in command names, usage and search terms # > help --find char export def main [ - ...item: string # the name of the help item to get help on + ...item: string@"nu-complete main-help" # the name of the help item to get help on --find (-f): string # string to find in help items names and usage ] { if ($item | is-empty) and ($find | is-empty) { From 3cf150727c0491ede29f0902bfbd0d410a589184 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 May 2024 11:22:02 +0800 Subject: [PATCH 004/113] Bump actions/checkout from 4.1.5 to 4.1.6 (#12934) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.5 to 4.1.6.
Release notes

Sourced from actions/checkout's releases.

v4.1.6

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.5...v4.1.6

Changelog

Sourced from actions/checkout's changelog.

v4.1.6

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.5&new-version=4.1.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/audit.yml | 2 +- .github/workflows/ci.yml | 8 ++++---- .github/workflows/nightly-build.yml | 6 +++--- .github/workflows/release.yml | 2 +- .github/workflows/typos.yml | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index e8a7f55817..a0295b3b4d 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -19,7 +19,7 @@ jobs: # Prevent sudden announcement of a new advisory from failing ci: continue-on-error: true steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 - uses: rustsec/audit-check@v1.4.1 with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3acdfa71d1..9cb92b0902 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: runs-on: ${{ matrix.platform }} steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 - name: Setup Rust toolchain and cache uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 @@ -66,7 +66,7 @@ jobs: runs-on: ${{ matrix.platform }} steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 - name: Setup Rust toolchain and cache uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 @@ -95,7 +95,7 @@ jobs: runs-on: ${{ matrix.platform }} steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 - name: Setup Rust toolchain and cache uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 @@ -146,7 +146,7 @@ jobs: runs-on: ${{ matrix.platform }} steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 - name: Setup Rust toolchain and cache uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index 418b392fce..d95ddd438a 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -27,7 +27,7 @@ jobs: # if: github.repository == 'nushell/nightly' steps: - name: Checkout - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 if: github.repository == 'nushell/nightly' with: ref: main @@ -112,7 +112,7 @@ jobs: runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 with: ref: main fetch-depth: 0 @@ -181,7 +181,7 @@ jobs: - name: Waiting for Release run: sleep 1800 - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 with: ref: main diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fb1b384d54..7d58501044 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -62,7 +62,7 @@ jobs: runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 - name: Update Rust Toolchain Target run: | diff --git a/.github/workflows/typos.yml b/.github/workflows/typos.yml index dacfb83928..709f09c2e7 100644 --- a/.github/workflows/typos.yml +++ b/.github/workflows/typos.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Actions Repository - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Check spelling uses: crate-ci/typos@v1.21.0 From d7e75c0b70570096cbaa20e61adc174ef5a135b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 May 2024 15:59:33 +0800 Subject: [PATCH 005/113] Bump shadow-rs from 0.27.1 to 0.28.0 (#12932) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [shadow-rs](https://github.com/baoyachi/shadow-rs) from 0.27.1 to 0.28.0.
Release notes

Sourced from shadow-rs's releases.

fix cargo clippy

#160

Thx @​qartik

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=shadow-rs&package-manager=cargo&previous-version=0.27.1&new-version=0.28.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- crates/nu-cmd-lang/Cargo.toml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 59948fbc51..2bc6f891ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5401,9 +5401,9 @@ dependencies = [ [[package]] name = "shadow-rs" -version = "0.27.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7960cbd6ba74691bb15e7ebf97f7136bd02d1115f5695a58c1f31d5645750128" +checksum = "1d75516bdaee8f640543ad1f6e292448c23ce57143f812c3736ab4b0874383df" dependencies = [ "const_format", "is_debug", diff --git a/crates/nu-cmd-lang/Cargo.toml b/crates/nu-cmd-lang/Cargo.toml index abb89a6991..45f5b9bc8f 100644 --- a/crates/nu-cmd-lang/Cargo.toml +++ b/crates/nu-cmd-lang/Cargo.toml @@ -18,10 +18,10 @@ nu-protocol = { path = "../nu-protocol", version = "0.93.1" } nu-utils = { path = "../nu-utils", version = "0.93.1" } itertools = { workspace = true } -shadow-rs = { version = "0.27", default-features = false } +shadow-rs = { version = "0.28", default-features = false } [build-dependencies] -shadow-rs = { version = "0.27", default-features = false } +shadow-rs = { version = "0.28", default-features = false } [features] mimalloc = [] From 758c5d447aeccdf75fa95dd85b6c661113935df0 Mon Sep 17 00:00:00 2001 From: Devyn Cairns Date: Wed, 22 May 2024 08:13:45 -0700 Subject: [PATCH 006/113] Add support for the `ps` command on FreeBSD, NetBSD, and OpenBSD (#12892) # Description I feel like it's a little sad that BSDs get to enjoy almost everything other than the `ps` command, and there are some tests that rely on this command, so I figured it would be fun to patch that and make it work. The different BSDs have diverged from each other somewhat, but generally have a similar enough API for reading process information via `sysctl()`, with some slightly different args. This supports FreeBSD with the `freebsd` module, and NetBSD and OpenBSD with the `netbsd` module. OpenBSD is a fork of NetBSD and the interface has some minor differences but many things are the same. I had wanted to try to support DragonFlyBSD too, but their Rust version in the latest release is only 1.72.0, which is too old for me to want to try to compile rustc up to 1.77.2... but I will revisit this whenever they do update it. Dragonfly is a fork of FreeBSD, so it's likely to be more or less the same - I just don't want to enable it without testing it. Fixes #6862 (partially, we probably won't be adding `zfs list`) # User-Facing Changes `ps` added for FreeBSD, NetBSD, and OpenBSD. # Tests + Formatting The CI doesn't run tests for BSDs, so I'm not entirely sure if everything was already passing before. (Frankly, it's unlikely.) But nothing appears to be broken. # After Submitting - [ ] release notes? - [ ] DragonflyBSD, whenever they do update Rust to something close enough for me to try it --- Cargo.lock | 1 + crates/nu-command/src/default_context.rs | 3 + crates/nu-command/src/system/mod.rs | 4 + crates/nu-command/src/system/ps.rs | 17 +- crates/nu-system/Cargo.toml | 1 + crates/nu-system/src/freebsd.rs | 305 ++++++++++++++++++++ crates/nu-system/src/lib.rs | 10 + crates/nu-system/src/netbsd.rs | 336 +++++++++++++++++++++++ 8 files changed, 662 insertions(+), 15 deletions(-) create mode 100644 crates/nu-system/src/freebsd.rs create mode 100644 crates/nu-system/src/netbsd.rs diff --git a/Cargo.lock b/Cargo.lock index 2bc6f891ba..362d64ba99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3264,6 +3264,7 @@ name = "nu-system" version = "0.93.1" dependencies = [ "chrono", + "itertools 0.12.1", "libc", "libproc", "log", diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index ba55472e15..a23f9c4ef4 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -164,6 +164,9 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState { #[cfg(any( target_os = "android", target_os = "linux", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd", target_os = "macos", target_os = "windows" ))] diff --git a/crates/nu-command/src/system/mod.rs b/crates/nu-command/src/system/mod.rs index 788e1b7740..c0f890232d 100644 --- a/crates/nu-command/src/system/mod.rs +++ b/crates/nu-command/src/system/mod.rs @@ -5,6 +5,8 @@ mod nu_check; target_os = "android", target_os = "linux", target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd", target_os = "macos", target_os = "windows" ))] @@ -23,6 +25,8 @@ pub use nu_check::NuCheck; target_os = "android", target_os = "linux", target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd", target_os = "macos", target_os = "windows" ))] diff --git a/crates/nu-command/src/system/ps.rs b/crates/nu-command/src/system/ps.rs index 922bf7915b..c64549a44d 100644 --- a/crates/nu-command/src/system/ps.rs +++ b/crates/nu-command/src/system/ps.rs @@ -2,20 +2,13 @@ use itertools::Itertools; use nu_engine::command_prelude::*; -#[cfg(all( - unix, - not(target_os = "freebsd"), - not(target_os = "macos"), - not(target_os = "windows"), - not(target_os = "android"), -))] +#[cfg(target_os = "linux")] use procfs::WithCurrentSystemInfo; use std::time::Duration; #[derive(Clone)] pub struct Ps; -#[cfg(not(target_os = "freebsd"))] impl Command for Ps { fn name(&self) -> &str { "ps" @@ -82,7 +75,6 @@ impl Command for Ps { } } -#[cfg(not(target_os = "freebsd"))] fn run_ps( engine_state: &EngineState, stack: &mut Stack, @@ -111,12 +103,7 @@ fn run_ps( if long { record.push("command", Value::string(proc.command(), span)); - #[cfg(all( - unix, - not(target_os = "macos"), - not(target_os = "windows"), - not(target_os = "android"), - ))] + #[cfg(target_os = "linux")] { let proc_stat = proc .curr_proc diff --git a/crates/nu-system/Cargo.toml b/crates/nu-system/Cargo.toml index 771f4417ca..88d6b28b05 100644 --- a/crates/nu-system/Cargo.toml +++ b/crates/nu-system/Cargo.toml @@ -16,6 +16,7 @@ bench = false libc = { workspace = true } log = { workspace = true } sysinfo = { workspace = true } +itertools = { workspace = true } [target.'cfg(target_family = "unix")'.dependencies] nix = { workspace = true, default-features = false, features = ["fs", "term", "process", "signal"] } diff --git a/crates/nu-system/src/freebsd.rs b/crates/nu-system/src/freebsd.rs new file mode 100644 index 0000000000..ff0f67dd10 --- /dev/null +++ b/crates/nu-system/src/freebsd.rs @@ -0,0 +1,305 @@ +use itertools::{EitherOrBoth, Itertools}; +use libc::{ + kinfo_proc, sysctl, CTL_HW, CTL_KERN, KERN_PROC, KERN_PROC_ALL, KERN_PROC_ARGS, TDF_IDLETD, +}; +use std::{ + ffi::CStr, + io, + mem::{self, MaybeUninit}, + ptr, + time::{Duration, Instant}, +}; + +#[derive(Debug)] +pub struct ProcessInfo { + pub pid: i32, + pub ppid: i32, + pub name: String, + pub argv: Vec, + pub stat: i8, + pub percent_cpu: f64, + pub mem_resident: u64, // in bytes + pub mem_virtual: u64, // in bytes +} + +pub fn collect_proc(interval: Duration, _with_thread: bool) -> Vec { + compare_procs(interval).unwrap_or_else(|err| { + log::warn!("Failed to get processes: {}", err); + vec![] + }) +} + +fn compare_procs(interval: Duration) -> io::Result> { + let pagesize = get_pagesize()? as u64; + + // Compare two full snapshots of all of the processes over the interval + let now = Instant::now(); + let procs_a = get_procs()?; + std::thread::sleep(interval); + let procs_b = get_procs()?; + let true_interval = Instant::now().saturating_duration_since(now); + let true_interval_sec = true_interval.as_secs_f64(); + + // Group all of the threads in each process together + let a_grouped = procs_a.into_iter().group_by(|proc| proc.ki_pid); + let b_grouped = procs_b.into_iter().group_by(|proc| proc.ki_pid); + + // Join the processes between the two snapshots + Ok(a_grouped + .into_iter() + .merge_join_by(b_grouped.into_iter(), |(pid_a, _), (pid_b, _)| { + pid_a.cmp(pid_b) + }) + .map(|threads| { + // Join the threads between the two snapshots for the process + let mut threads = { + let (left, right) = threads.left_and_right(); + left.into_iter() + .flat_map(|(_, threads)| threads) + .merge_join_by( + right.into_iter().flat_map(|(_, threads)| threads), + |thread_a, thread_b| thread_a.ki_tid.cmp(&thread_b.ki_tid), + ) + .peekable() + }; + + // Pick the later process entry of the first thread to use for basic process information + let proc = match threads.peek().ok_or(io::ErrorKind::NotFound)? { + EitherOrBoth::Both(_, b) => b, + EitherOrBoth::Left(a) => a, + EitherOrBoth::Right(b) => b, + } + .clone(); + + // Skip over the idle process. It always appears with high CPU usage when the + // system is idle + if proc.ki_tdflags as u64 & TDF_IDLETD as u64 != 0 { + return Err(io::ErrorKind::NotFound.into()); + } + + // Aggregate all of the threads that exist in both snapshots and sum their runtime. + let (runtime_a, runtime_b) = + threads + .flat_map(|t| t.both()) + .fold((0., 0.), |(runtime_a, runtime_b), (a, b)| { + let runtime_in_seconds = + |proc: &kinfo_proc| proc.ki_runtime as f64 /* µsec */ / 1_000_000.0; + ( + runtime_a + runtime_in_seconds(&a), + runtime_b + runtime_in_seconds(&b), + ) + }); + + // The percentage CPU is the ratio of how much runtime occurred for the process out of + // the true measured interval that occurred. + let percent_cpu = 100. * (runtime_b - runtime_a).max(0.) / true_interval_sec; + + let info = ProcessInfo { + pid: proc.ki_pid, + ppid: proc.ki_ppid, + name: read_cstr(&proc.ki_comm).to_string_lossy().into_owned(), + argv: get_proc_args(proc.ki_pid)?, + stat: proc.ki_stat, + percent_cpu, + mem_resident: proc.ki_rssize.max(0) as u64 * pagesize, + mem_virtual: proc.ki_size.max(0) as u64, + }; + Ok(info) + }) + // Remove errors from the list - probably just processes that are gone now + .flat_map(|result: io::Result<_>| result.ok()) + .collect()) +} + +fn check(err: libc::c_int) -> std::io::Result<()> { + if err < 0 { + Err(io::Error::last_os_error()) + } else { + Ok(()) + } +} + +/// This is a bounds-checked way to read a `CStr` from a slice of `c_char` +fn read_cstr(slice: &[libc::c_char]) -> &CStr { + unsafe { + // SAFETY: ensure that c_char and u8 are the same size + mem::transmute::(0); + let slice: &[u8] = mem::transmute(slice); + CStr::from_bytes_until_nul(slice).unwrap_or_default() + } +} + +fn get_procs() -> io::Result> { + // To understand what's going on here, see the sysctl(3) manpage for FreeBSD. + unsafe { + const STRUCT_SIZE: usize = mem::size_of::(); + let ctl_name = [CTL_KERN, KERN_PROC, KERN_PROC_ALL]; + + // First, try to figure out how large a buffer we need to allocate + // (calling with NULL just tells us that) + let mut data_len = 0; + check(sysctl( + ctl_name.as_ptr(), + ctl_name.len() as u32, + ptr::null_mut(), + &mut data_len, + ptr::null(), + 0, + ))?; + + // data_len will be set in bytes, so divide by the size of the structure + let expected_len = data_len.div_ceil(STRUCT_SIZE); + + // Now allocate the Vec and set data_len to the real number of bytes allocated + let mut vec: Vec = Vec::with_capacity(expected_len); + data_len = vec.capacity() * STRUCT_SIZE; + + // Call sysctl() again to put the result in the vec + check(sysctl( + ctl_name.as_ptr(), + ctl_name.len() as u32, + vec.as_mut_ptr() as *mut libc::c_void, + &mut data_len, + ptr::null(), + 0, + ))?; + + // If that was ok, we can set the actual length of the vec to whatever + // data_len was changed to, since that should now all be properly initialized data. + let true_len = data_len.div_ceil(STRUCT_SIZE); + vec.set_len(true_len); + + // Sort the procs by pid and then tid before using them + vec.sort_by_key(|p| (p.ki_pid, p.ki_tid)); + Ok(vec) + } +} + +fn get_proc_args(pid: i32) -> io::Result> { + unsafe { + let ctl_name = [CTL_KERN, KERN_PROC, KERN_PROC_ARGS, pid]; + + // First, try to figure out how large a buffer we need to allocate + // (calling with NULL just tells us that) + let mut data_len = 0; + check(sysctl( + ctl_name.as_ptr(), + ctl_name.len() as u32, + ptr::null_mut(), + &mut data_len, + ptr::null(), + 0, + ))?; + + // Now allocate the Vec and set data_len to the real number of bytes allocated + let mut vec: Vec = Vec::with_capacity(data_len); + data_len = vec.capacity(); + + // Call sysctl() again to put the result in the vec + check(sysctl( + ctl_name.as_ptr(), + ctl_name.len() as u32, + vec.as_mut_ptr() as *mut libc::c_void, + &mut data_len, + ptr::null(), + 0, + ))?; + + // If that was ok, we can set the actual length of the vec to whatever + // data_len was changed to, since that should now all be properly initialized data. + vec.set_len(data_len); + Ok(vec) + } +} + +// For getting simple values from the sysctl interface +unsafe fn get_ctl(ctl_name: &[i32]) -> io::Result { + let mut value: MaybeUninit = MaybeUninit::uninit(); + let mut value_len = mem::size_of_val(&value); + check(sysctl( + ctl_name.as_ptr(), + ctl_name.len() as u32, + value.as_mut_ptr() as *mut libc::c_void, + &mut value_len, + ptr::null(), + 0, + ))?; + Ok(value.assume_init()) +} + +fn get_pagesize() -> io::Result { + // not in libc for some reason + const HW_PAGESIZE: i32 = 7; + unsafe { get_ctl(&[CTL_HW, HW_PAGESIZE]) } +} + +impl ProcessInfo { + /// PID of process + pub fn pid(&self) -> i32 { + self.pid + } + + /// Parent PID of process + pub fn ppid(&self) -> i32 { + self.ppid + } + + /// Name of command + pub fn name(&self) -> String { + let argv_name = self + .argv + .split(|b| *b == 0) + .next() + .map(String::from_utf8_lossy) + .unwrap_or_default() + .into_owned(); + + if !argv_name.is_empty() { + argv_name + } else { + // Just use the command name alone. + self.name.clone() + } + } + + /// Full name of command, with arguments + pub fn command(&self) -> String { + if let Some(last_nul) = self.argv.iter().rposition(|b| *b == 0) { + // The command string is NUL separated + // Take the string up to the last NUL, then replace the NULs with spaces + String::from_utf8_lossy(&self.argv[0..last_nul]).replace("\0", " ") + } else { + // The argv is empty, so use the name instead + self.name() + } + } + + /// Get the status of the process + pub fn status(&self) -> String { + match self.stat { + libc::SIDL | libc::SRUN => "Running", + libc::SSLEEP => "Sleeping", + libc::SSTOP => "Stopped", + libc::SWAIT => "Waiting", + libc::SLOCK => "Locked", + libc::SZOMB => "Zombie", + _ => "Unknown", + } + .into() + } + + /// CPU usage as a percent of total + pub fn cpu_usage(&self) -> f64 { + self.percent_cpu + } + + /// Memory size in number of bytes + pub fn mem_size(&self) -> u64 { + self.mem_resident + } + + /// Virtual memory size in bytes + pub fn virtual_size(&self) -> u64 { + self.mem_virtual + } +} diff --git a/crates/nu-system/src/lib.rs b/crates/nu-system/src/lib.rs index 6058ed4fcf..2fc97d2e7e 100644 --- a/crates/nu-system/src/lib.rs +++ b/crates/nu-system/src/lib.rs @@ -1,8 +1,13 @@ mod foreground; + +#[cfg(target_os = "freebsd")] +mod freebsd; #[cfg(any(target_os = "android", target_os = "linux"))] mod linux; #[cfg(target_os = "macos")] mod macos; +#[cfg(any(target_os = "netbsd", target_os = "openbsd"))] +mod netbsd; pub mod os_info; #[cfg(target_os = "windows")] mod windows; @@ -10,9 +15,14 @@ mod windows; #[cfg(unix)] pub use self::foreground::stdin_fd; pub use self::foreground::{ForegroundChild, ForegroundGuard}; + +#[cfg(target_os = "freebsd")] +pub use self::freebsd::*; #[cfg(any(target_os = "android", target_os = "linux"))] pub use self::linux::*; #[cfg(target_os = "macos")] pub use self::macos::*; +#[cfg(any(target_os = "netbsd", target_os = "openbsd"))] +pub use self::netbsd::*; #[cfg(target_os = "windows")] pub use self::windows::*; diff --git a/crates/nu-system/src/netbsd.rs b/crates/nu-system/src/netbsd.rs new file mode 100644 index 0000000000..04f69b35fe --- /dev/null +++ b/crates/nu-system/src/netbsd.rs @@ -0,0 +1,336 @@ +//! This is used for both NetBSD and OpenBSD, because they are fairly similar. + +use itertools::{EitherOrBoth, Itertools}; +use libc::{sysctl, CTL_HW, CTL_KERN, KERN_PROC_ALL, KERN_PROC_ARGS, KERN_PROC_ARGV}; +use std::{ + io, + mem::{self, MaybeUninit}, + ptr, + time::{Duration, Instant}, +}; + +#[cfg(target_os = "netbsd")] +type KInfoProc = libc::kinfo_proc2; +#[cfg(target_os = "openbsd")] +type KInfoProc = libc::kinfo_proc; + +#[derive(Debug)] +pub struct ProcessInfo { + pub pid: i32, + pub ppid: i32, + pub argv: Vec, + pub stat: i8, + pub percent_cpu: f64, + pub mem_resident: u64, // in bytes + pub mem_virtual: u64, // in bytes +} + +pub fn collect_proc(interval: Duration, _with_thread: bool) -> Vec { + compare_procs(interval).unwrap_or_else(|err| { + log::warn!("Failed to get processes: {}", err); + vec![] + }) +} + +fn compare_procs(interval: Duration) -> io::Result> { + let pagesize = get_pagesize()? as u64; + + // Compare two full snapshots of all of the processes over the interval + let now = Instant::now(); + let procs_a = get_procs()?; + std::thread::sleep(interval); + let procs_b = get_procs()?; + let true_interval = Instant::now().saturating_duration_since(now); + let true_interval_sec = true_interval.as_secs_f64(); + + // Join the processes between the two snapshots + Ok(procs_a + .into_iter() + .merge_join_by(procs_b.into_iter(), |a, b| a.p_pid.cmp(&b.p_pid)) + .map(|proc| { + // Take both snapshotted processes if we can, but if not then just keep the one that + // exists and set prev_proc to None + let (prev_proc, proc) = match proc { + EitherOrBoth::Both(a, b) => (Some(a), b), + EitherOrBoth::Left(a) => (None, a), + EitherOrBoth::Right(b) => (None, b), + }; + + // The percentage CPU is the ratio of how much runtime occurred for the process out of + // the true measured interval that occurred. + let percent_cpu = if let Some(prev_proc) = prev_proc { + let prev_rtime = + prev_proc.p_rtime_sec as f64 + prev_proc.p_rtime_usec as f64 / 1_000_000.0; + let rtime = proc.p_rtime_sec as f64 + proc.p_rtime_usec as f64 / 1_000_000.0; + 100. * (rtime - prev_rtime).max(0.) / true_interval_sec + } else { + 0.0 + }; + + Ok(ProcessInfo { + pid: proc.p_pid, + ppid: proc.p_ppid, + argv: get_proc_args(proc.p_pid, KERN_PROC_ARGV)?, + stat: proc.p_stat, + percent_cpu, + mem_resident: proc.p_vm_rssize.max(0) as u64 * pagesize, + #[cfg(target_os = "netbsd")] + mem_virtual: proc.p_vm_msize.max(0) as u64 * pagesize, + #[cfg(target_os = "openbsd")] + mem_virtual: proc.p_vm_map_size.max(0) as u64 * pagesize, + }) + }) + // Remove errors from the list - probably just processes that are gone now + .flat_map(|result: io::Result<_>| result.ok()) + .collect()) +} + +fn check(err: libc::c_int) -> std::io::Result<()> { + if err < 0 { + Err(io::Error::last_os_error()) + } else { + Ok(()) + } +} + +/// Call `sysctl()` in read mode (i.e. the last two arguments are NULL and zero) +unsafe fn sysctl_get( + name: *const i32, + name_len: u32, + data: *mut libc::c_void, + data_len: *mut usize, +) -> i32 { + sysctl( + name, + name_len, + data, + data_len, + // NetBSD and OpenBSD differ in mutability for this pointer, but it's null anyway + #[cfg(target_os = "netbsd")] + ptr::null(), + #[cfg(target_os = "openbsd")] + ptr::null_mut(), + 0, + ) +} + +fn get_procs() -> io::Result> { + // To understand what's going on here, see the sysctl(3) and sysctl(7) manpages for NetBSD. + unsafe { + const STRUCT_SIZE: usize = mem::size_of::(); + + #[cfg(target_os = "netbsd")] + const TGT_KERN_PROC: i32 = libc::KERN_PROC2; + #[cfg(target_os = "openbsd")] + const TGT_KERN_PROC: i32 = libc::KERN_PROC; + + let mut ctl_name = [ + CTL_KERN, + TGT_KERN_PROC, + KERN_PROC_ALL, + 0, + STRUCT_SIZE as i32, + 0, + ]; + + // First, try to figure out how large a buffer we need to allocate + // (calling with NULL just tells us that) + let mut data_len = 0; + check(sysctl_get( + ctl_name.as_ptr(), + ctl_name.len() as u32, + ptr::null_mut(), + &mut data_len, + ))?; + + // data_len will be set in bytes, so divide by the size of the structure + let expected_len = data_len.div_ceil(STRUCT_SIZE); + + // Now allocate the Vec and set data_len to the real number of bytes allocated + let mut vec: Vec = Vec::with_capacity(expected_len); + data_len = vec.capacity() * STRUCT_SIZE; + + // We are also supposed to set ctl_name[5] to the number of structures we want + ctl_name[5] = expected_len.try_into().expect("expected_len too big"); + + // Call sysctl() again to put the result in the vec + check(sysctl_get( + ctl_name.as_ptr(), + ctl_name.len() as u32, + vec.as_mut_ptr() as *mut libc::c_void, + &mut data_len, + ))?; + + // If that was ok, we can set the actual length of the vec to whatever + // data_len was changed to, since that should now all be properly initialized data. + let true_len = data_len.div_ceil(STRUCT_SIZE); + vec.set_len(true_len); + + // Sort the procs by pid before using them + vec.sort_by_key(|p| p.p_pid); + Ok(vec) + } +} + +fn get_proc_args(pid: i32, what: i32) -> io::Result> { + unsafe { + let ctl_name = [CTL_KERN, KERN_PROC_ARGS, pid, what]; + + // First, try to figure out how large a buffer we need to allocate + // (calling with NULL just tells us that) + let mut data_len = 0; + check(sysctl_get( + ctl_name.as_ptr(), + ctl_name.len() as u32, + ptr::null_mut(), + &mut data_len, + ))?; + + // Now allocate the Vec and set data_len to the real number of bytes allocated + let mut vec: Vec = Vec::with_capacity(data_len); + data_len = vec.capacity(); + + // Call sysctl() again to put the result in the vec + check(sysctl_get( + ctl_name.as_ptr(), + ctl_name.len() as u32, + vec.as_mut_ptr() as *mut libc::c_void, + &mut data_len, + ))?; + + // If that was ok, we can set the actual length of the vec to whatever + // data_len was changed to, since that should now all be properly initialized data. + vec.set_len(data_len); + + // On OpenBSD we have to do an extra step, because it fills the buffer with pointers to the + // strings first, even though the strings are within the buffer as well. + #[cfg(target_os = "openbsd")] + let vec = { + use std::ffi::CStr; + + // Set up some bounds checking. We assume there will be some pointers at the base until + // we reach NULL, but we want to make sure we only ever read data within the range of + // min_ptr..max_ptr. + let ptrs = vec.as_ptr() as *const *const u8; + let min_ptr = vec.as_ptr() as *const u8; + let max_ptr = vec.as_ptr().add(vec.len()) as *const u8; + let max_index: isize = (vec.len() / mem::size_of::<*const u8>()) + .try_into() + .expect("too big for isize"); + + let mut new_vec = Vec::with_capacity(vec.len()); + for index in 0..max_index { + let ptr = ptrs.offset(index); + if *ptr == ptr::null() { + break; + } else { + // Make sure it's within the bounds of the buffer + assert!( + *ptr >= min_ptr && *ptr < max_ptr, + "pointer out of bounds of the buffer returned by sysctl()" + ); + // Also bounds-check the C strings, to make sure we don't overrun the buffer + new_vec.extend( + CStr::from_bytes_until_nul(std::slice::from_raw_parts( + *ptr, + max_ptr.offset_from(*ptr) as usize, + )) + .expect("invalid C string") + .to_bytes_with_nul(), + ); + } + } + new_vec + }; + + Ok(vec) + } +} + +// For getting simple values from the sysctl interface +unsafe fn get_ctl(ctl_name: &[i32]) -> io::Result { + let mut value: MaybeUninit = MaybeUninit::uninit(); + let mut value_len = mem::size_of_val(&value); + check(sysctl_get( + ctl_name.as_ptr(), + ctl_name.len() as u32, + value.as_mut_ptr() as *mut libc::c_void, + &mut value_len, + ))?; + Ok(value.assume_init()) +} + +fn get_pagesize() -> io::Result { + // not in libc for some reason + const HW_PAGESIZE: i32 = 7; + unsafe { get_ctl(&[CTL_HW, HW_PAGESIZE]) } +} + +impl ProcessInfo { + /// PID of process + pub fn pid(&self) -> i32 { + self.pid + } + + /// Parent PID of process + pub fn ppid(&self) -> i32 { + self.ppid + } + + /// Name of command + pub fn name(&self) -> String { + self.argv + .split(|b| *b == 0) + .next() + .map(String::from_utf8_lossy) + .unwrap_or_default() + .into_owned() + } + + /// Full name of command, with arguments + pub fn command(&self) -> String { + if let Some(last_nul) = self.argv.iter().rposition(|b| *b == 0) { + // The command string is NUL separated + // Take the string up to the last NUL, then replace the NULs with spaces + String::from_utf8_lossy(&self.argv[0..last_nul]).replace("\0", " ") + } else { + "".into() + } + } + + /// Get the status of the process + pub fn status(&self) -> String { + // see sys/proc.h (OpenBSD), sys/lwp.h (NetBSD) + // the names given here are the NetBSD ones, starting with LS*, but the OpenBSD ones are + // the same, just starting with S* instead + match self.stat { + 1 /* LSIDL */ => "", + 2 /* LSRUN */ => "Waiting", + 3 /* LSSLEEP */ => "Sleeping", + 4 /* LSSTOP */ => "Stopped", + 5 /* LSZOMB */ => "Zombie", + #[cfg(target_os = "openbsd")] // removed in NetBSD + 6 /* LSDEAD */ => "Dead", + 7 /* LSONPROC */ => "Running", + #[cfg(target_os = "netbsd")] // doesn't exist in OpenBSD + 8 /* LSSUSPENDED */ => "Suspended", + _ => "Unknown", + } + .into() + } + + /// CPU usage as a percent of total + pub fn cpu_usage(&self) -> f64 { + self.percent_cpu + } + + /// Memory size in number of bytes + pub fn mem_size(&self) -> u64 { + self.mem_resident + } + + /// Virtual memory size in bytes + pub fn virtual_size(&self) -> u64 { + self.mem_virtual + } +} From 7de513a4e04d4654314a02c60a1a415fc5f348a0 Mon Sep 17 00:00:00 2001 From: Devyn Cairns Date: Wed, 22 May 2024 09:55:24 -0700 Subject: [PATCH 007/113] Implement streaming I/O for CSV and TSV commands (#12918) # Description Implements streaming for: - `from csv` - `from tsv` - `to csv` - `to tsv` via the new string-typed ByteStream support. # User-Facing Changes Commands above. Also: - `to csv` and `to tsv` now have `--columns `, to provide the exact columns desired in the output. This is required for them to have streaming output, because otherwise collecting the entire list is necessary to determine the output columns. If we introduce `TableStream`, this may become less necessary. # Tests + Formatting - :green_circle: `toolkit fmt` - :green_circle: `toolkit clippy` - :green_circle: `toolkit test` - :green_circle: `toolkit test stdlib` # After Submitting - [ ] release notes --------- Co-authored-by: Ian Manske --- .../nu-command/src/formats/from/delimited.rs | 78 ++++-- crates/nu-command/src/formats/to/csv.rs | 41 ++- crates/nu-command/src/formats/to/delimited.rs | 252 +++++++++--------- crates/nu-command/src/formats/to/tsv.rs | 31 ++- 4 files changed, 235 insertions(+), 167 deletions(-) diff --git a/crates/nu-command/src/formats/from/delimited.rs b/crates/nu-command/src/formats/from/delimited.rs index 1fdea19482..853f3bd83e 100644 --- a/crates/nu-command/src/formats/from/delimited.rs +++ b/crates/nu-command/src/formats/from/delimited.rs @@ -1,7 +1,14 @@ use csv::{ReaderBuilder, Trim}; -use nu_protocol::{IntoPipelineData, PipelineData, ShellError, Span, Value}; +use nu_protocol::{ByteStream, ListStream, PipelineData, ShellError, Span, Value}; -fn from_delimited_string_to_value( +fn from_csv_error(err: csv::Error, span: Span) -> ShellError { + ShellError::DelimiterError { + msg: err.to_string(), + span, + } +} + +fn from_delimited_stream( DelimitedReaderConfig { separator, comment, @@ -12,9 +19,15 @@ fn from_delimited_string_to_value( no_infer, trim, }: DelimitedReaderConfig, - s: String, + input: ByteStream, span: Span, -) -> Result { +) -> Result { + let input_reader = if let Some(stream) = input.reader() { + stream + } else { + return Ok(ListStream::new(std::iter::empty(), span, None)); + }; + let mut reader = ReaderBuilder::new() .has_headers(!noheaders) .flexible(flexible) @@ -23,19 +36,29 @@ fn from_delimited_string_to_value( .quote(quote as u8) .escape(escape.map(|c| c as u8)) .trim(trim) - .from_reader(s.as_bytes()); + .from_reader(input_reader); let headers = if noheaders { - (1..=reader.headers()?.len()) + (1..=reader + .headers() + .map_err(|err| from_csv_error(err, span))? + .len()) .map(|i| format!("column{i}")) .collect::>() } else { - reader.headers()?.iter().map(String::from).collect() + reader + .headers() + .map_err(|err| from_csv_error(err, span))? + .iter() + .map(String::from) + .collect() }; - let mut rows = vec![]; - for row in reader.records() { - let row = row?; + let iter = reader.into_records().map(move |row| { + let row = match row { + Ok(row) => row, + Err(err) => return Value::error(from_csv_error(err, span), span), + }; let columns = headers.iter().cloned(); let values = row .into_iter() @@ -57,10 +80,10 @@ fn from_delimited_string_to_value( // // Otherwise, if there are less values than headers, // then `Value::nothing(span)` is used to fill the remaining columns. - rows.push(Value::record(columns.zip(values).collect(), span)); - } + Value::record(columns.zip(values).collect(), span) + }); - Ok(Value::list(rows, span)) + Ok(ListStream::new(iter, span, None)) } pub(super) struct DelimitedReaderConfig { @@ -79,14 +102,27 @@ pub(super) fn from_delimited_data( input: PipelineData, name: Span, ) -> Result { - let (concat_string, _span, metadata) = input.collect_string_strict(name)?; - - Ok(from_delimited_string_to_value(config, concat_string, name) - .map_err(|x| ShellError::DelimiterError { - msg: x.to_string(), - span: name, - })? - .into_pipeline_data_with_metadata(metadata)) + match input { + PipelineData::Empty => Ok(PipelineData::Empty), + PipelineData::Value(value, metadata) => { + let string = value.into_string()?; + let byte_stream = ByteStream::read_string(string, name, None); + Ok(PipelineData::ListStream( + from_delimited_stream(config, byte_stream, name)?, + metadata, + )) + } + PipelineData::ListStream(list_stream, _) => Err(ShellError::OnlySupportsThisInputType { + exp_input_type: "string".into(), + wrong_type: "list".into(), + dst_span: name, + src_span: list_stream.span(), + }), + PipelineData::ByteStream(byte_stream, metadata) => Ok(PipelineData::ListStream( + from_delimited_stream(config, byte_stream, name)?, + metadata, + )), + } } pub fn trim_from_str(trim: Option) -> Result { diff --git a/crates/nu-command/src/formats/to/csv.rs b/crates/nu-command/src/formats/to/csv.rs index 173c6fbd6b..e7786e60cc 100644 --- a/crates/nu-command/src/formats/to/csv.rs +++ b/crates/nu-command/src/formats/to/csv.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use crate::formats::to::delimited::to_delimited_data; use nu_engine::command_prelude::*; use nu_protocol::Config; @@ -27,26 +29,37 @@ impl Command for ToCsv { "do not output the columns names as the first row", Some('n'), ) + .named( + "columns", + SyntaxShape::List(SyntaxShape::String.into()), + "the names (in order) of the columns to use", + None, + ) .category(Category::Formats) } fn examples(&self) -> Vec { vec![ Example { - description: "Outputs an CSV string representing the contents of this table", + description: "Outputs a CSV string representing the contents of this table", example: "[[foo bar]; [1 2]] | to csv", result: Some(Value::test_string("foo,bar\n1,2\n")), }, Example { - description: "Outputs an CSV string representing the contents of this table", + description: "Outputs a CSV string representing the contents of this table", example: "[[foo bar]; [1 2]] | to csv --separator ';' ", result: Some(Value::test_string("foo;bar\n1;2\n")), }, Example { - description: "Outputs an CSV string representing the contents of this record", + description: "Outputs a CSV string representing the contents of this record", example: "{a: 1 b: 2} | to csv", result: Some(Value::test_string("a,b\n1,2\n")), }, + Example { + description: "Outputs a CSV stream with column names pre-determined", + example: "[[foo bar baz]; [1 2 3]] | to csv --columns [baz foo]", + result: Some(Value::test_string("baz,foo\n3,1\n")), + }, ] } @@ -64,8 +77,9 @@ impl Command for ToCsv { let head = call.head; let noheaders = call.has_flag(engine_state, stack, "noheaders")?; let separator: Option> = call.get_flag(engine_state, stack, "separator")?; - let config = engine_state.get_config(); - to_csv(input, noheaders, separator, head, config) + let columns: Option> = call.get_flag(engine_state, stack, "columns")?; + let config = engine_state.config.clone(); + to_csv(input, noheaders, separator, columns, head, config) } } @@ -73,13 +87,14 @@ fn to_csv( input: PipelineData, noheaders: bool, separator: Option>, + columns: Option>, head: Span, - config: &Config, + config: Arc, ) -> Result { let sep = match separator { Some(Spanned { item: s, span, .. }) => { if s == r"\t" { - '\t' + Spanned { item: '\t', span } } else { let vec_s: Vec = s.chars().collect(); if vec_s.len() != 1 { @@ -89,13 +104,19 @@ fn to_csv( span, }); }; - vec_s[0] + Spanned { + item: vec_s[0], + span: head, + } } } - _ => ',', + _ => Spanned { + item: ',', + span: head, + }, }; - to_delimited_data(noheaders, sep, "CSV", input, head, config) + to_delimited_data(noheaders, sep, columns, "CSV", input, head, config) } #[cfg(test)] diff --git a/crates/nu-command/src/formats/to/delimited.rs b/crates/nu-command/src/formats/to/delimited.rs index 490983d67b..a7a2480a34 100644 --- a/crates/nu-command/src/formats/to/delimited.rs +++ b/crates/nu-command/src/formats/to/delimited.rs @@ -1,113 +1,31 @@ -use csv::{Writer, WriterBuilder}; +use csv::WriterBuilder; use nu_cmd_base::formats::to::delimited::merge_descriptors; -use nu_protocol::{Config, IntoPipelineData, PipelineData, Record, ShellError, Span, Value}; -use std::{collections::VecDeque, error::Error}; +use nu_protocol::{ + ByteStream, ByteStreamType, Config, PipelineData, ShellError, Span, Spanned, Value, +}; +use std::{iter, sync::Arc}; -fn from_value_to_delimited_string( - value: &Value, - separator: char, - config: &Config, - head: Span, -) -> Result { - let span = value.span(); - match value { - Value::Record { val, .. } => record_to_delimited(val, span, separator, config, head), - Value::List { vals, .. } => table_to_delimited(vals, span, separator, config, head), - // Propagate errors by explicitly matching them before the final case. - Value::Error { error, .. } => Err(*error.clone()), - v => Err(make_unsupported_input_error(v, head, v.span())), - } -} - -fn record_to_delimited( - record: &Record, - span: Span, - separator: char, - config: &Config, - head: Span, -) -> Result { - let mut wtr = WriterBuilder::new() - .delimiter(separator as u8) - .from_writer(vec![]); - let mut fields: VecDeque = VecDeque::new(); - let mut values: VecDeque = VecDeque::new(); - - for (k, v) in record { - fields.push_back(k.clone()); - - values.push_back(to_string_tagged_value(v, config, head, span)?); - } - - wtr.write_record(fields).expect("can not write."); - wtr.write_record(values).expect("can not write."); - - writer_to_string(wtr).map_err(|_| make_conversion_error("record", span)) -} - -fn table_to_delimited( - vals: &[Value], - span: Span, - separator: char, - config: &Config, - head: Span, -) -> Result { - if let Some(val) = find_non_record(vals) { - return Err(make_unsupported_input_error(val, head, span)); - } - - let mut wtr = WriterBuilder::new() - .delimiter(separator as u8) - .from_writer(vec![]); - - let merged_descriptors = merge_descriptors(vals); - - if merged_descriptors.is_empty() { - let vals = vals - .iter() - .map(|ele| { - to_string_tagged_value(ele, config, head, span).unwrap_or_else(|_| String::new()) - }) - .collect::>(); - wtr.write_record(vals).expect("can not write"); - } else { - wtr.write_record(merged_descriptors.iter().map(|item| &item[..])) - .expect("can not write."); - - for l in vals { - // should always be true because of `find_non_record` above - if let Value::Record { val: l, .. } = l { - let mut row = vec![]; - for desc in &merged_descriptors { - row.push(match l.get(desc) { - Some(s) => to_string_tagged_value(s, config, head, span)?, - None => String::new(), - }); - } - wtr.write_record(&row).expect("can not write"); - } +fn make_csv_error(error: csv::Error, format_name: &str, head: Span) -> ShellError { + if let csv::ErrorKind::Io(error) = error.kind() { + ShellError::IOErrorSpanned { + msg: error.to_string(), + span: head, + } + } else { + ShellError::GenericError { + error: format!("Failed to generate {format_name} data"), + msg: error.to_string(), + span: Some(head), + help: None, + inner: vec![], } - } - writer_to_string(wtr).map_err(|_| make_conversion_error("table", span)) -} - -fn writer_to_string(writer: Writer>) -> Result> { - Ok(String::from_utf8(writer.into_inner()?)?) -} - -fn make_conversion_error(type_from: &str, span: Span) -> ShellError { - ShellError::CantConvert { - to_type: type_from.to_string(), - from_type: "string".to_string(), - span, - help: None, } } fn to_string_tagged_value( v: &Value, config: &Config, - span: Span, - head: Span, + format_name: &'static str, ) -> Result { match &v { Value::String { .. } @@ -123,50 +41,124 @@ fn to_string_tagged_value( Value::Nothing { .. } => Ok(String::new()), // Propagate existing errors Value::Error { error, .. } => Err(*error.clone()), - _ => Err(make_unsupported_input_error(v, head, span)), + _ => Err(make_cant_convert_error(v, format_name)), } } -fn make_unsupported_input_error(value: &Value, head: Span, span: Span) -> ShellError { +fn make_unsupported_input_error( + r#type: impl std::fmt::Display, + head: Span, + span: Span, +) -> ShellError { ShellError::UnsupportedInput { - msg: "Unexpected type".to_string(), - input: format!("input type: {:?}", value.get_type()), + msg: "expected table or record".to_string(), + input: format!("input type: {}", r#type), msg_span: head, input_span: span, } } -pub fn find_non_record(values: &[Value]) -> Option<&Value> { - values - .iter() - .find(|val| !matches!(val, Value::Record { .. })) +fn make_cant_convert_error(value: &Value, format_name: &'static str) -> ShellError { + ShellError::CantConvert { + to_type: "string".into(), + from_type: value.get_type().to_string(), + span: value.span(), + help: Some(format!( + "only simple values are supported for {format_name} output" + )), + } } pub fn to_delimited_data( noheaders: bool, - sep: char, + separator: Spanned, + columns: Option>, format_name: &'static str, input: PipelineData, - span: Span, - config: &Config, + head: Span, + config: Arc, ) -> Result { - let value = input.into_value(span)?; - let output = match from_value_to_delimited_string(&value, sep, config, span) { - Ok(mut x) => { - if noheaders { - if let Some(second_line) = x.find('\n') { - let start = second_line + 1; - x.replace_range(0..start, ""); - } - } - Ok(x) + let mut input = input; + let span = input.span().unwrap_or(head); + let metadata = input.metadata(); + + let separator = u8::try_from(separator.item).map_err(|_| ShellError::IncorrectValue { + msg: "separator must be an ASCII character".into(), + val_span: separator.span, + call_span: head, + })?; + + // Check to ensure the input is likely one of our supported types first. We can't check a stream + // without consuming it though + match input { + PipelineData::Value(Value::List { .. } | Value::Record { .. }, _) => (), + PipelineData::Value(Value::Error { error, .. }, _) => return Err(*error), + PipelineData::Value(other, _) => { + return Err(make_unsupported_input_error(other.get_type(), head, span)) } - Err(_) => Err(ShellError::CantConvert { - to_type: format_name.into(), - from_type: value.get_type().to_string(), - span: value.span(), - help: None, - }), - }?; - Ok(Value::string(output, span).into_pipeline_data()) + PipelineData::ByteStream(..) => { + return Err(make_unsupported_input_error("byte stream", head, span)) + } + PipelineData::ListStream(..) => (), + PipelineData::Empty => (), + } + + // Determine the columns we'll use. This is necessary even if we don't write the header row, + // because we need to write consistent columns. + let columns = match columns { + Some(columns) => columns, + None => { + // The columns were not provided. We need to detect them, and in order to do so, we have + // to convert the input into a value first, so that we can find all of them + let value = input.into_value(span)?; + let columns = match &value { + Value::List { vals, .. } => merge_descriptors(vals), + Value::Record { val, .. } => val.columns().cloned().collect(), + _ => return Err(make_unsupported_input_error(value.get_type(), head, span)), + }; + input = PipelineData::Value(value, metadata.clone()); + columns + } + }; + + // Generate a byte stream of all of the values in the pipeline iterator, with a non-strict + // iterator so we can still accept plain records. + let mut iter = input.into_iter(); + + // If we're configured to generate a header, we generate it first, then set this false + let mut is_header = !noheaders; + + let stream = ByteStream::from_fn(head, None, ByteStreamType::String, move |buffer| { + let mut wtr = WriterBuilder::new() + .delimiter(separator) + .from_writer(buffer); + + if is_header { + // Unless we are configured not to write a header, we write the header row now, once, + // before everything else. + wtr.write_record(&columns) + .map_err(|err| make_csv_error(err, format_name, head))?; + is_header = false; + Ok(true) + } else if let Some(row) = iter.next() { + // Write each column of a normal row, in order + let record = row.into_record()?; + for column in &columns { + let field = record + .get(column) + .map(|v| to_string_tagged_value(v, &config, format_name)) + .unwrap_or(Ok(String::new()))?; + wtr.write_field(field) + .map_err(|err| make_csv_error(err, format_name, head))?; + } + // End the row + wtr.write_record(iter::empty::()) + .map_err(|err| make_csv_error(err, format_name, head))?; + Ok(true) + } else { + Ok(false) + } + }); + + Ok(PipelineData::ByteStream(stream, metadata)) } diff --git a/crates/nu-command/src/formats/to/tsv.rs b/crates/nu-command/src/formats/to/tsv.rs index eeaeb6b401..edc9592409 100644 --- a/crates/nu-command/src/formats/to/tsv.rs +++ b/crates/nu-command/src/formats/to/tsv.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use crate::formats::to::delimited::to_delimited_data; use nu_engine::command_prelude::*; use nu_protocol::Config; @@ -21,6 +23,12 @@ impl Command for ToTsv { "do not output the column names as the first row", Some('n'), ) + .named( + "columns", + SyntaxShape::List(SyntaxShape::String.into()), + "the names (in order) of the columns to use", + None, + ) .category(Category::Formats) } @@ -31,15 +39,20 @@ impl Command for ToTsv { fn examples(&self) -> Vec { vec![ Example { - description: "Outputs an TSV string representing the contents of this table", + description: "Outputs a TSV string representing the contents of this table", example: "[[foo bar]; [1 2]] | to tsv", result: Some(Value::test_string("foo\tbar\n1\t2\n")), }, Example { - description: "Outputs an TSV string representing the contents of this record", + description: "Outputs a TSV string representing the contents of this record", example: "{a: 1 b: 2} | to tsv", result: Some(Value::test_string("a\tb\n1\t2\n")), }, + Example { + description: "Outputs a TSV stream with column names pre-determined", + example: "[[foo bar baz]; [1 2 3]] | to tsv --columns [baz foo]", + result: Some(Value::test_string("baz\tfoo\n3\t1\n")), + }, ] } @@ -52,18 +65,24 @@ impl Command for ToTsv { ) -> Result { let head = call.head; let noheaders = call.has_flag(engine_state, stack, "noheaders")?; - let config = engine_state.get_config(); - to_tsv(input, noheaders, head, config) + let columns: Option> = call.get_flag(engine_state, stack, "columns")?; + let config = engine_state.config.clone(); + to_tsv(input, noheaders, columns, head, config) } } fn to_tsv( input: PipelineData, noheaders: bool, + columns: Option>, head: Span, - config: &Config, + config: Arc, ) -> Result { - to_delimited_data(noheaders, '\t', "TSV", input, head, config) + let sep = Spanned { + item: '\t', + span: head, + }; + to_delimited_data(noheaders, sep, columns, "TSV", input, head, config) } #[cfg(test)] From 75689ec98aa7037f1101844ea16f1934c51ff706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20=C5=BD=C3=A1dn=C3=ADk?= Date: Wed, 22 May 2024 19:56:51 +0300 Subject: [PATCH 008/113] Small improvements to `debug profile` (#12930) # Description 1. With the `-l` flag, `debug profile` now collects files and line numbers of profiled pipeline elements ![profiler_lines](https://github.com/nushell/nushell/assets/25571562/b400a956-d958-4aff-aa4c-7e65da3f78fa) 2. Error from the profiled closure will be reported instead of silently ignored. ![profiler_lines_error](https://github.com/nushell/nushell/assets/25571562/54f7ad7a-06a3-4d56-92c2-c3466917bee8) # User-Facing Changes New `--lines(-l)` flag to `debug profile`. The command will also fail if the profiled closure fails, so technically it is a breaking change. # Tests + Formatting # After Submitting --------- Co-authored-by: Ian Manske --- crates/nu-command/src/debug/profile.rs | 16 ++++----- crates/nu-protocol/src/debugger/profiler.rs | 40 +++++++++++++++++++++ 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/crates/nu-command/src/debug/profile.rs b/crates/nu-command/src/debug/profile.rs index bd5de6041a..0cef979094 100644 --- a/crates/nu-command/src/debug/profile.rs +++ b/crates/nu-command/src/debug/profile.rs @@ -28,6 +28,7 @@ impl Command for DebugProfile { Some('v'), ) .switch("expr", "Collect expression types", Some('x')) + .switch("lines", "Collect line numbers", Some('l')) .named( "max-depth", SyntaxShape::Int, @@ -90,6 +91,7 @@ confusing the id/parent_id hierarchy. The --expr flag is helpful for investigati let collect_expanded_source = call.has_flag(engine_state, stack, "expanded-source")?; let collect_values = call.has_flag(engine_state, stack, "values")?; let collect_exprs = call.has_flag(engine_state, stack, "expr")?; + let collect_lines = call.has_flag(engine_state, stack, "lines")?; let max_depth = call .get_flag(engine_state, stack, "max-depth")? .unwrap_or(2); @@ -101,6 +103,7 @@ confusing the id/parent_id hierarchy. The --expr flag is helpful for investigati collect_expanded_source, collect_values, collect_exprs, + collect_lines, call.span(), ); @@ -118,14 +121,11 @@ confusing the id/parent_id hierarchy. The --expr flag is helpful for investigati let result = ClosureEvalOnce::new(engine_state, stack, closure).run_with_input(input); - // TODO: See eval_source() - match result { - Ok(pipeline_data) => { - let _ = pipeline_data.into_value(call.span()); - // pipeline_data.print(engine_state, caller_stack, true, false) - } - Err(_e) => (), // TODO: Report error - } + // Return potential errors + let pipeline_data = result?; + + // Collect the output + let _ = pipeline_data.into_value(call.span()); Ok(engine_state .deactivate_debugger() diff --git a/crates/nu-protocol/src/debugger/profiler.rs b/crates/nu-protocol/src/debugger/profiler.rs index 53b9d0555a..b95bf571b4 100644 --- a/crates/nu-protocol/src/debugger/profiler.rs +++ b/crates/nu-protocol/src/debugger/profiler.rs @@ -9,6 +9,7 @@ use crate::{ engine::EngineState, record, PipelineData, ShellError, Span, Value, }; +use std::io::BufRead; use std::time::Instant; #[derive(Debug, Clone, Copy)] @@ -50,11 +51,13 @@ pub struct Profiler { collect_expanded_source: bool, collect_values: bool, collect_exprs: bool, + collect_lines: bool, elements: Vec, element_stack: Vec, } impl Profiler { + #[allow(clippy::too_many_arguments)] pub fn new( max_depth: i64, collect_spans: bool, @@ -62,6 +65,7 @@ impl Profiler { collect_expanded_source: bool, collect_values: bool, collect_exprs: bool, + collect_lines: bool, span: Span, ) -> Self { let first = ElementInfo { @@ -82,6 +86,7 @@ impl Profiler { collect_expanded_source, collect_values, collect_exprs, + collect_lines, elements: vec![first], element_stack: vec![ElementId(0)], } @@ -262,6 +267,31 @@ fn expr_to_string(engine_state: &EngineState, expr: &Expr) -> String { } } +// Find a file name and a line number (indexed from 1) of a span +fn find_file_of_span(engine_state: &EngineState, span: Span) -> Option<(&str, usize)> { + for file in engine_state.files() { + if file.covered_span.contains_span(span) { + // count the number of lines between file start and the searched span start + let chunk = + engine_state.get_span_contents(Span::new(file.covered_span.start, span.start)); + let nlines = chunk.lines().count(); + // account for leading part of current line being counted as a separate line + let line_num = if chunk.last() == Some(&b'\n') { + nlines + 1 + } else { + nlines + }; + + // first line has no previous line, clamp up to `1` + let line_num = usize::max(line_num, 1); + + return Some((&file.name, line_num)); + } + } + + None +} + fn collect_data( engine_state: &EngineState, profiler: &Profiler, @@ -277,6 +307,16 @@ fn collect_data( "parent_id" => Value::int(parent_id.0 as i64, profiler_span), }; + if profiler.collect_lines { + if let Some((fname, line_num)) = find_file_of_span(engine_state, element.element_span) { + row.push("file", Value::string(fname, profiler_span)); + row.push("line_num", Value::int(line_num as i64, profiler_span)); + } else { + row.push("file", Value::nothing(profiler_span)); + row.push("line", Value::nothing(profiler_span)); + } + } + if profiler.collect_spans { let span_start = i64::try_from(element.element_span.start) .map_err(|_| profiler_error("error converting span start to i64", profiler_span))?; From 7ede90cba50e4dad62a2ff503a2566c82a4935ea Mon Sep 17 00:00:00 2001 From: YizhePKU Date: Thu, 23 May 2024 00:58:27 +0800 Subject: [PATCH 009/113] Remove `std::env::set_current_dir()` call from `EngineState::merge_env()` (#12922) As discussed in https://github.com/nushell/nushell/pull/12749, we no longer need to call `std::env::set_current_dir()` to sync `$env.PWD` with the actual working directory. This PR removes the call from `EngineState::merge_env()`. --- crates/nu-cli/src/config_files.rs | 11 +---- crates/nu-cli/src/repl.rs | 12 ++--- crates/nu-cli/tests/completions/mod.rs | 46 +++++++++---------- .../support/completions_helpers.rs | 9 ++-- crates/nu-cmd-base/src/hook.rs | 4 +- crates/nu-cmd-lang/src/example_support.rs | 2 +- crates/nu-protocol/src/engine/engine_state.rs | 9 +--- crates/nu-std/src/lib.rs | 3 +- src/config_files.rs | 22 ++------- src/test_bins.rs | 6 +-- 10 files changed, 41 insertions(+), 83 deletions(-) diff --git a/crates/nu-cli/src/config_files.rs b/crates/nu-cli/src/config_files.rs index ec7ad2f412..0684623226 100644 --- a/crates/nu-cli/src/config_files.rs +++ b/crates/nu-cli/src/config_files.rs @@ -235,15 +235,8 @@ pub fn eval_config_contents( engine_state.file = prev_file; // Merge the environment in case env vars changed in the config - match engine_state.cwd(Some(stack)) { - Ok(cwd) => { - if let Err(e) = engine_state.merge_env(stack, cwd) { - report_error_new(engine_state, &e); - } - } - Err(e) => { - report_error_new(engine_state, &e); - } + if let Err(e) = engine_state.merge_env(stack) { + report_error_new(engine_state, &e); } } } diff --git a/crates/nu-cli/src/repl.rs b/crates/nu-cli/src/repl.rs index 29c2f62734..e79f41eb21 100644 --- a/crates/nu-cli/src/repl.rs +++ b/crates/nu-cli/src/repl.rs @@ -15,10 +15,7 @@ use crate::{ use crossterm::cursor::SetCursorStyle; use log::{error, trace, warn}; use miette::{ErrReport, IntoDiagnostic, Result}; -use nu_cmd_base::{ - hook::eval_hook, - util::{get_editor, get_guaranteed_cwd}, -}; +use nu_cmd_base::{hook::eval_hook, util::get_editor}; use nu_color_config::StyleComputer; #[allow(deprecated)] use nu_engine::{convert_env_values, current_dir_str, env_to_strings}; @@ -118,8 +115,7 @@ pub fn evaluate_repl( PipelineData::empty(), false, ); - let cwd = get_guaranteed_cwd(engine_state, &unique_stack); - engine_state.merge_env(&mut unique_stack, cwd)?; + engine_state.merge_env(&mut unique_stack)?; } let hostname = System::host_name(); @@ -281,12 +277,10 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) { hostname, } = ctx; - let cwd = get_guaranteed_cwd(engine_state, &stack); - let mut start_time = std::time::Instant::now(); // Before doing anything, merge the environment from the previous REPL iteration into the // permanent state. - if let Err(err) = engine_state.merge_env(&mut stack, cwd) { + if let Err(err) = engine_state.merge_env(&mut stack) { report_error_new(engine_state, &err); } perf( diff --git a/crates/nu-cli/tests/completions/mod.rs b/crates/nu-cli/tests/completions/mod.rs index cb883b67db..a3eb692adf 100644 --- a/crates/nu-cli/tests/completions/mod.rs +++ b/crates/nu-cli/tests/completions/mod.rs @@ -18,11 +18,11 @@ use support::{ #[fixture] fn completer() -> NuCompleter { // Create a new engine - let (dir, _, mut engine, mut stack) = new_engine(); + let (_, _, mut engine, mut stack) = new_engine(); // Add record value as example let record = "def tst [--mod -s] {}"; - assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); + assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack).is_ok()); // Instantiate a new completer NuCompleter::new(Arc::new(engine), Arc::new(stack)) @@ -31,12 +31,12 @@ fn completer() -> NuCompleter { #[fixture] fn completer_strings() -> NuCompleter { // Create a new engine - let (dir, _, mut engine, mut stack) = new_engine(); + let (_, _, mut engine, mut stack) = new_engine(); // Add record value as example let record = r#"def animals [] { ["cat", "dog", "eel" ] } def my-command [animal: string@animals] { print $animal }"#; - assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); + assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack).is_ok()); // Instantiate a new completer NuCompleter::new(Arc::new(engine), Arc::new(stack)) @@ -45,7 +45,7 @@ fn completer_strings() -> NuCompleter { #[fixture] fn extern_completer() -> NuCompleter { // Create a new engine - let (dir, _, mut engine, mut stack) = new_engine(); + let (_, _, mut engine, mut stack) = new_engine(); // Add record value as example let record = r#" @@ -56,7 +56,7 @@ fn extern_completer() -> NuCompleter { -b: string@animals ] "#; - assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); + assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack).is_ok()); // Instantiate a new completer NuCompleter::new(Arc::new(engine), Arc::new(stack)) @@ -65,7 +65,7 @@ fn extern_completer() -> NuCompleter { #[fixture] fn custom_completer() -> NuCompleter { // Create a new engine - let (dir, _, mut engine, mut stack) = new_engine(); + let (_, _, mut engine, mut stack) = new_engine(); // Add record value as example let record = r#" @@ -79,7 +79,7 @@ fn custom_completer() -> NuCompleter { completer: $external_completer } "#; - assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); + assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack).is_ok()); // Instantiate a new completer NuCompleter::new(Arc::new(engine), Arc::new(stack)) @@ -705,11 +705,11 @@ fn folder_with_directorycompletions() { #[test] fn variables_completions() { // Create a new engine - let (dir, _, mut engine, mut stack) = new_engine(); + let (_, _, mut engine, mut stack) = new_engine(); // Add record value as example let record = "let actor = { name: 'Tom Hardy', age: 44 }"; - assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); + assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack).is_ok()); // Instantiate a new completer let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack)); @@ -812,11 +812,11 @@ fn variables_completions() { #[test] fn alias_of_command_and_flags() { - let (dir, _, mut engine, mut stack) = new_engine(); + let (_, _, mut engine, mut stack) = new_engine(); // Create an alias let alias = r#"alias ll = ls -l"#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack).is_ok()); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack)); @@ -831,11 +831,11 @@ fn alias_of_command_and_flags() { #[test] fn alias_of_basic_command() { - let (dir, _, mut engine, mut stack) = new_engine(); + let (_, _, mut engine, mut stack) = new_engine(); // Create an alias let alias = r#"alias ll = ls "#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack).is_ok()); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack)); @@ -850,14 +850,14 @@ fn alias_of_basic_command() { #[test] fn alias_of_another_alias() { - let (dir, _, mut engine, mut stack) = new_engine(); + let (_, _, mut engine, mut stack) = new_engine(); // Create an alias let alias = r#"alias ll = ls -la"#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir.clone()).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack).is_ok()); // Create the second alias let alias = r#"alias lf = ll -f"#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack).is_ok()); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack)); @@ -874,7 +874,7 @@ fn run_external_completion(completer: &str, input: &str) -> Vec { let completer = format!("$env.config.completions.external.completer = {completer}"); // Create a new engine - let (dir, _, mut engine_state, mut stack) = new_engine(); + let (_, _, mut engine_state, mut stack) = new_engine(); let (block, delta) = { let mut working_set = StateWorkingSet::new(&engine_state); let block = parse(&mut working_set, None, completer.as_bytes(), false); @@ -890,7 +890,7 @@ fn run_external_completion(completer: &str, input: &str) -> Vec { ); // Merge environment into the permanent state - assert!(engine_state.merge_env(&mut stack, &dir).is_ok()); + assert!(engine_state.merge_env(&mut stack).is_ok()); // Instantiate a new completer let mut completer = NuCompleter::new(Arc::new(engine_state), Arc::new(stack)); @@ -1068,11 +1068,11 @@ fn custom_completer_triggers_cursor_after_word(mut custom_completer: NuCompleter #[ignore = "was reverted, still needs fixing"] #[rstest] fn alias_offset_bug_7648() { - let (dir, _, mut engine, mut stack) = new_engine(); + let (_, _, mut engine, mut stack) = new_engine(); // Create an alias let alias = r#"alias ea = ^$env.EDITOR /tmp/test.s"#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack).is_ok()); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack)); @@ -1087,11 +1087,11 @@ fn alias_offset_bug_7648() { #[ignore = "was reverted, still needs fixing"] #[rstest] fn alias_offset_bug_7754() { - let (dir, _, mut engine, mut stack) = new_engine(); + let (_, _, mut engine, mut stack) = new_engine(); // Create an alias let alias = r#"alias ll = ls -l"#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack).is_ok()); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack)); diff --git a/crates/nu-cli/tests/completions/support/completions_helpers.rs b/crates/nu-cli/tests/completions/support/completions_helpers.rs index 47f46ab00e..df92979e23 100644 --- a/crates/nu-cli/tests/completions/support/completions_helpers.rs +++ b/crates/nu-cli/tests/completions/support/completions_helpers.rs @@ -62,7 +62,7 @@ pub fn new_engine() -> (PathBuf, String, EngineState, Stack) { ); // Merge environment into the permanent state - let merge_result = engine_state.merge_env(&mut stack, &dir); + let merge_result = engine_state.merge_env(&mut stack); assert!(merge_result.is_ok()); (dir, dir_str, engine_state, stack) @@ -97,7 +97,7 @@ pub fn new_quote_engine() -> (PathBuf, String, EngineState, Stack) { ); // Merge environment into the permanent state - let merge_result = engine_state.merge_env(&mut stack, &dir); + let merge_result = engine_state.merge_env(&mut stack); assert!(merge_result.is_ok()); (dir, dir_str, engine_state, stack) @@ -132,7 +132,7 @@ pub fn new_partial_engine() -> (PathBuf, String, EngineState, Stack) { ); // Merge environment into the permanent state - let merge_result = engine_state.merge_env(&mut stack, &dir); + let merge_result = engine_state.merge_env(&mut stack); assert!(merge_result.is_ok()); (dir, dir_str, engine_state, stack) @@ -173,7 +173,6 @@ pub fn merge_input( input: &[u8], engine_state: &mut EngineState, stack: &mut Stack, - dir: PathBuf, ) -> Result<(), ShellError> { let (block, delta) = { let mut working_set = StateWorkingSet::new(engine_state); @@ -196,5 +195,5 @@ pub fn merge_input( .is_ok()); // Merge environment into the permanent state - engine_state.merge_env(stack, &dir) + engine_state.merge_env(stack) } diff --git a/crates/nu-cmd-base/src/hook.rs b/crates/nu-cmd-base/src/hook.rs index 76c13bd5c3..9133cf4167 100644 --- a/crates/nu-cmd-base/src/hook.rs +++ b/crates/nu-cmd-base/src/hook.rs @@ -1,4 +1,3 @@ -use crate::util::get_guaranteed_cwd; use miette::Result; use nu_engine::{eval_block, eval_block_with_early_return}; use nu_parser::parse; @@ -284,8 +283,7 @@ pub fn eval_hook( } } - let cwd = get_guaranteed_cwd(engine_state, stack); - engine_state.merge_env(stack, cwd)?; + engine_state.merge_env(stack)?; Ok(output) } diff --git a/crates/nu-cmd-lang/src/example_support.rs b/crates/nu-cmd-lang/src/example_support.rs index bb03bbaf8c..d938729fef 100644 --- a/crates/nu-cmd-lang/src/example_support.rs +++ b/crates/nu-cmd-lang/src/example_support.rs @@ -138,7 +138,7 @@ pub fn check_example_evaluates_to_expected_output( stack.add_env_var("PWD".to_string(), Value::test_string(cwd.to_string_lossy())); engine_state - .merge_env(&mut stack, cwd) + .merge_env(&mut stack) .expect("Error merging environment"); let empty_input = PipelineData::empty(); diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index 710ca77d4c..10c96b7463 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -277,11 +277,7 @@ impl EngineState { } /// Merge the environment from the runtime Stack into the engine state - pub fn merge_env( - &mut self, - stack: &mut Stack, - cwd: impl AsRef, - ) -> Result<(), ShellError> { + pub fn merge_env(&mut self, stack: &mut Stack) -> Result<(), ShellError> { let mut config_updated = false; for mut scope in stack.env_vars.drain(..) { @@ -311,9 +307,6 @@ impl EngineState { } } - // TODO: better error - std::env::set_current_dir(cwd)?; - if config_updated { // Make plugin GC config changes take effect immediately. #[cfg(feature = "plugin")] diff --git a/crates/nu-std/src/lib.rs b/crates/nu-std/src/lib.rs index a20e3fc5da..e6c8f30556 100644 --- a/crates/nu-std/src/lib.rs +++ b/crates/nu-std/src/lib.rs @@ -98,8 +98,7 @@ use std pwd eval_block::(engine_state, &mut stack, &block, pipeline_data)?; - let cwd = engine_state.cwd(Some(&stack))?; - engine_state.merge_env(&mut stack, cwd)?; + engine_state.merge_env(&mut stack)?; Ok(()) } diff --git a/src/config_files.rs b/src/config_files.rs index ec4511860f..3df076045f 100644 --- a/src/config_files.rs +++ b/src/config_files.rs @@ -164,15 +164,8 @@ pub(crate) fn read_default_env_file(engine_state: &mut EngineState, stack: &mut ); // Merge the environment in case env vars changed in the config - match engine_state.cwd(Some(stack)) { - Ok(cwd) => { - if let Err(e) = engine_state.merge_env(stack, cwd) { - report_error_new(engine_state, &e); - } - } - Err(e) => { - report_error_new(engine_state, &e); - } + if let Err(e) = engine_state.merge_env(stack) { + report_error_new(engine_state, &e); } } @@ -202,15 +195,8 @@ fn eval_default_config( ); // Merge the environment in case env vars changed in the config - match engine_state.cwd(Some(stack)) { - Ok(cwd) => { - if let Err(e) = engine_state.merge_env(stack, cwd) { - report_error_new(engine_state, &e); - } - } - Err(e) => { - report_error_new(engine_state, &e); - } + if let Err(e) = engine_state.merge_env(stack) { + report_error_new(engine_state, &e); } } diff --git a/src/test_bins.rs b/src/test_bins.rs index 73a760ada1..d96c74a911 100644 --- a/src/test_bins.rs +++ b/src/test_bins.rs @@ -250,13 +250,9 @@ pub fn nu_repl() { for (i, line) in source_lines.iter().enumerate() { let mut stack = Stack::with_parent(top_stack.clone()); - let cwd = engine_state - .cwd(Some(&stack)) - .unwrap_or_else(|err| outcome_err(&engine_state, &err)); - // Before doing anything, merge the environment from the previous REPL iteration into the // permanent state. - if let Err(err) = engine_state.merge_env(&mut stack, &cwd) { + if let Err(err) = engine_state.merge_env(&mut stack) { outcome_err(&engine_state, &err); } From ac4125f8edd5b8f3f68aa653d03d57b2d25f1da1 Mon Sep 17 00:00:00 2001 From: Wind Date: Thu, 23 May 2024 01:00:58 +0800 Subject: [PATCH 010/113] fix range semantic in detect_columns, str substring, str index-of (#12894) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Fixes: https://github.com/nushell/nushell/issues/7761 It's still unsure if we want to change the `range semantic` itself, but it's good to keep range semantic consistent between nushell commands. # User-Facing Changes ### Before ```nushell ❯ "abc" | str substring 1..=2 b ``` ### After ```nushell ❯ "abc" | str substring 1..=2 bc ``` # Tests + Formatting Adjust tests to fit new behavior --- crates/nu-cmd-base/src/util.rs | 4 ++-- crates/nu-command/src/strings/str_/index_of.rs | 2 +- crates/nu-command/src/strings/str_/substring.rs | 6 +++--- crates/nu-command/tests/commands/detect_columns.rs | 6 +++--- crates/nu-command/tests/commands/str_/mod.rs | 4 ++-- tests/repl/test_strings.rs | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/crates/nu-cmd-base/src/util.rs b/crates/nu-cmd-base/src/util.rs index 9c63dec836..559161329b 100644 --- a/crates/nu-cmd-base/src/util.rs +++ b/crates/nu-cmd-base/src/util.rs @@ -25,8 +25,8 @@ pub fn process_range(range: &Range) -> Result<(isize, isize), MakeRangeError> { Range::IntRange(range) => { let start = range.start().try_into().unwrap_or(0); let end = match range.end() { - Bound::Included(v) => v as isize, - Bound::Excluded(v) => (v - 1) as isize, + Bound::Included(v) => (v + 1) as isize, + Bound::Excluded(v) => v as isize, Bound::Unbounded => isize::MAX, }; Ok((start, end)) diff --git a/crates/nu-command/src/strings/str_/index_of.rs b/crates/nu-command/src/strings/str_/index_of.rs index 457713c2df..df26df7493 100644 --- a/crates/nu-command/src/strings/str_/index_of.rs +++ b/crates/nu-command/src/strings/str_/index_of.rs @@ -405,7 +405,7 @@ mod tests { let range = Range::new( Value::int(0, Span::test_data()), Value::int(1, Span::test_data()), - Value::int(3, Span::test_data()), + Value::int(2, Span::test_data()), RangeInclusion::Inclusive, Span::test_data(), ) diff --git a/crates/nu-command/src/strings/str_/substring.rs b/crates/nu-command/src/strings/str_/substring.rs index 55871401ef..4f5c953dda 100644 --- a/crates/nu-command/src/strings/str_/substring.rs +++ b/crates/nu-command/src/strings/str_/substring.rs @@ -70,7 +70,7 @@ impl Command for SubCommand { } fn usage(&self) -> &str { - "Get part of a string. Note that the start is included but the end is excluded, and that the first character of a string is index 0." + "Get part of a string. Note that the first character of a string is index 0." } fn search_terms(&self) -> Vec<&str> { @@ -108,12 +108,12 @@ impl Command for SubCommand { Example { description: "Get a substring \"nushell\" from the text \"good nushell\" using a range", - example: " 'good nushell' | str substring 5..12", + example: " 'good nushell' | str substring 5..11", result: Some(Value::test_string("nushell")), }, Example { description: "Count indexes and split using grapheme clusters", - example: " '🇯🇵ほげ ふが ぴよ' | str substring --grapheme-clusters 4..6", + example: " '🇯🇵ほげ ふが ぴよ' | str substring --grapheme-clusters 4..5", result: Some(Value::test_string("ふが")), }, ] diff --git a/crates/nu-command/tests/commands/detect_columns.rs b/crates/nu-command/tests/commands/detect_columns.rs index d605eb4aa1..5bc057fa18 100644 --- a/crates/nu-command/tests/commands/detect_columns.rs +++ b/crates/nu-command/tests/commands/detect_columns.rs @@ -31,12 +31,12 @@ fn detect_columns_with_legacy_and_flag_c() { ( "$\"c1 c2 c3 c4 c5(char nl)a b c d e\"", "[[c1,c3,c4,c5]; ['a b',c,d,e]]", - "0..1", + "0..0", ), ( "$\"c1 c2 c3 c4 c5(char nl)a b c d e\"", "[[c1,c2,c3,c4]; [a,b,c,'d e']]", - "(-2)..(-1)", + "(-2)..(-2)", ), ( "$\"c1 c2 c3 c4 c5(char nl)a b c d e\"", @@ -77,7 +77,7 @@ drwxr-xr-x 4 root root 4.0K Mar 20 08:18 ~(char nl) ['drwxr-xr-x', '4', 'root', 'root', '4.0K', 'Mar 20 08:18', '~'], ['-rw-r--r--', '1', 'root', 'root', '3.0K', 'Mar 20 07:23', '~asdf'] ]"; - let range = "5..7"; + let range = "5..6"; let cmd = format!( "({} | detect columns -c {} -s 1 --no-headers) == {}", pipeline(body), diff --git a/crates/nu-command/tests/commands/str_/mod.rs b/crates/nu-command/tests/commands/str_/mod.rs index 9efa28b1ef..43f59b3e10 100644 --- a/crates/nu-command/tests/commands/str_/mod.rs +++ b/crates/nu-command/tests/commands/str_/mod.rs @@ -269,7 +269,7 @@ fn substring_errors_if_start_index_is_greater_than_end_index() { cwd: dirs.test(), pipeline( r#" open sample.toml - | str substring 6..5 fortune.teller.phone + | str substring 6..4 fortune.teller.phone "# )); @@ -342,7 +342,7 @@ fn substrings_the_input_and_treats_start_index_as_zero_if_blank_start_index_give cwd: dirs.test(), pipeline( r#" open sample.toml - | str substring ..2 package.name + | str substring ..1 package.name | get package.name "# )); diff --git a/tests/repl/test_strings.rs b/tests/repl/test_strings.rs index fa6c419e23..62960fed13 100644 --- a/tests/repl/test_strings.rs +++ b/tests/repl/test_strings.rs @@ -3,7 +3,7 @@ use crate::repl::tests::{fail_test, run_test, TestResult}; #[test] fn cjk_in_substrings() -> TestResult { run_test( - r#"let s = '[Rust 程序设计语言](title-page.md)'; let start = ($s | str index-of '('); let end = ($s | str index-of ')'); $s | str substring ($start + 1)..($end)"#, + r#"let s = '[Rust 程序设计语言](title-page.md)'; let start = ($s | str index-of '('); let end = ($s | str index-of ')'); $s | str substring ($start + 1)..<($end)"#, "title-page.md", ) } From 64afb52ffaa68ac761b5f5d05d51d3fb1547084b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20=C5=BD=C3=A1dn=C3=ADk?= Date: Thu, 23 May 2024 00:24:22 +0300 Subject: [PATCH 011/113] Fix leftover wrong column name (#12937) # Description Small fixup for https://github.com/nushell/nushell/pull/12930 --- crates/nu-protocol/src/debugger/profiler.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/nu-protocol/src/debugger/profiler.rs b/crates/nu-protocol/src/debugger/profiler.rs index b95bf571b4..0fa2d4f3aa 100644 --- a/crates/nu-protocol/src/debugger/profiler.rs +++ b/crates/nu-protocol/src/debugger/profiler.rs @@ -310,7 +310,7 @@ fn collect_data( if profiler.collect_lines { if let Some((fname, line_num)) = find_file_of_span(engine_state, element.element_span) { row.push("file", Value::string(fname, profiler_span)); - row.push("line_num", Value::int(line_num as i64, profiler_span)); + row.push("line", Value::int(line_num as i64, profiler_span)); } else { row.push("file", Value::nothing(profiler_span)); row.push("line", Value::nothing(profiler_span)); From 6c649809d38a687cd63b59ab028b7f30207e5663 Mon Sep 17 00:00:00 2001 From: YizhePKU Date: Thu, 23 May 2024 10:05:27 +0800 Subject: [PATCH 012/113] Rewrite run_external.rs (#12921) This PR is a complete rewrite of `run_external.rs`. The main goal of the rewrite is improving readability, but it also fixes some bugs related to argument handling and the PATH variable (fixes https://github.com/nushell/nushell/issues/6011). I'll discuss some technical details to make reviewing easier. ## Argument handling Quoting arguments for external commands is hard. Like, *really* hard. We've had more than a dozen issues and PRs dedicated to quoting arguments (see Appendix) but the current implementation is still buggy. Here's a demonstration of the buggy behavior: ```nu let foo = "'bar'" ^touch $foo # This creates a file named `bar`, but it should be `'bar'` ^touch ...[ "'bar'" ] # Same ``` I'll describe how this PR deals with argument handling. First, we'll introduce the concept of **bare strings**. Bare strings are **string literals** that are either **unquoted** or **quoted by backticks** [^1]. Strings within a list literal are NOT considered bare strings, even if they are unquoted or quoted by backticks. When a bare string is used as an argument to external process, we need to perform tilde-expansion, glob-expansion, and inner-quotes-removal, in that order. "Inner-quotes-removal" means transforming from `--option="value"` into `--option=value`. ## `.bat` files and CMD built-ins On Windows, `.bat` files and `.cmd` files are considered executable, but they need `CMD.exe` as the interpreter. The Rust standard library supports running `.bat` files directly and will spawn `CMD.exe` under the hood (see [documentation](https://doc.rust-lang.org/std/process/index.html#windows-argument-splitting)). However, other extensions are not supported [^2]. Nushell also supports a selected number of CMD built-ins. The problem with CMD is that it uses a different set of quoting rules. Correctly quoting for CMD requires using [Command::raw_arg()](https://doc.rust-lang.org/std/os/windows/process/trait.CommandExt.html#tymethod.raw_arg) and manually quoting CMD special characters, on top of quoting from the Nushell side. ~~I decided that this is too complex and chose to reject special characters in CMD built-ins instead [^3]. Hopefully this will not affact real-world use cases.~~ I've implemented escaping that works reasonably well. ## `which-support` feature The `which` crate is now a hard dependency of `nu-command`, making the `which-support` feature essentially useless. The `which` crate is already a hard dependency of `nu-cli`, and we should consider removing the `which-support` feature entirely. ## Appendix Here's a list of quoting-related issues and PRs in rough chronological order. * https://github.com/nushell/nushell/issues/4609 * https://github.com/nushell/nushell/issues/4631 * https://github.com/nushell/nushell/issues/4601 * https://github.com/nushell/nushell/pull/5846 * https://github.com/nushell/nushell/issues/5978 * https://github.com/nushell/nushell/pull/6014 * https://github.com/nushell/nushell/issues/6154 * https://github.com/nushell/nushell/pull/6161 * https://github.com/nushell/nushell/issues/6399 * https://github.com/nushell/nushell/pull/6420 * https://github.com/nushell/nushell/pull/6426 * https://github.com/nushell/nushell/issues/6465 * https://github.com/nushell/nushell/issues/6559 * https://github.com/nushell/nushell/pull/6560 [^1]: The idea that backtick-quoted strings act like bare strings was introduced by Kubouch and briefly mentioned in [the language reference](https://www.nushell.sh/lang-guide/chapters/strings_and_text.html#backtick-quotes). [^2]: The documentation also said "running .bat scripts in this way may be removed in the future and so should not be relied upon", which is another reason to move away from this. But again, quoting for CMD is hard. [^3]: If anyone wants to try, the best resource I found on the topic is [this](https://daviddeley.com/autohotkey/parameters/parameters.htm). --- Cargo.lock | 1 + crates/nu-command/Cargo.toml | 5 +- .../nu-command/src/env/config/config_env.rs | 75 +- crates/nu-command/src/env/config/config_nu.rs | 75 +- crates/nu-command/src/env/config/mod.rs | 1 - crates/nu-command/src/env/config/utils.rs | 36 - crates/nu-command/src/system/exec.rs | 120 +- crates/nu-command/src/system/mod.rs | 2 +- crates/nu-command/src/system/run_external.rs | 1217 ++++++++--------- crates/nu-command/tests/commands/all.rs | 4 +- crates/nu-command/tests/commands/any.rs | 4 +- crates/nu-command/tests/commands/complete.rs | 2 +- .../nu-command/tests/commands/source_env.rs | 8 +- crates/nu-command/tests/commands/use_.rs | 10 +- src/test_bins.rs | 1 + tests/repl/test_known_external.rs | 12 +- tests/repl/test_parser.rs | 4 +- tests/repl/test_spread.rs | 7 +- tests/shell/pipeline/commands/external.rs | 6 +- tests/shell/pipeline/commands/internal.rs | 11 +- 20 files changed, 803 insertions(+), 798 deletions(-) delete mode 100644 crates/nu-command/src/env/config/utils.rs diff --git a/Cargo.lock b/Cargo.lock index 362d64ba99..e074e772a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3012,6 +3012,7 @@ dependencies = [ "sha2", "sysinfo", "tabled", + "tempfile", "terminal_size", "titlecase", "toml 0.8.12", diff --git a/crates/nu-command/Cargo.toml b/crates/nu-command/Cargo.toml index 6010e16285..d3456764fd 100644 --- a/crates/nu-command/Cargo.toml +++ b/crates/nu-command/Cargo.toml @@ -99,7 +99,7 @@ uu_whoami = { workspace = true } uuid = { workspace = true, features = ["v4"] } v_htmlescape = { workspace = true } wax = { workspace = true } -which = { workspace = true, optional = true } +which = { workspace = true } unicode-width = { workspace = true } [target.'cfg(windows)'.dependencies] @@ -134,7 +134,7 @@ workspace = true plugin = ["nu-parser/plugin"] sqlite = ["rusqlite"] trash-support = ["trash"] -which-support = ["which"] +which-support = [] [dev-dependencies] nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.93.1" } @@ -146,3 +146,4 @@ quickcheck = { workspace = true } quickcheck_macros = { workspace = true } rstest = { workspace = true, default-features = false } pretty_assertions = { workspace = true } +tempfile = { workspace = true } diff --git a/crates/nu-command/src/env/config/config_env.rs b/crates/nu-command/src/env/config/config_env.rs index 3c8dff487e..32bd7bba90 100644 --- a/crates/nu-command/src/env/config/config_env.rs +++ b/crates/nu-command/src/env/config/config_env.rs @@ -1,6 +1,7 @@ -use super::utils::gen_command; use nu_cmd_base::util::get_editor; use nu_engine::{command_prelude::*, env_to_strings}; +use nu_protocol::{process::ChildProcess, ByteStream}; +use nu_system::ForegroundChild; #[derive(Clone)] pub struct ConfigEnv; @@ -47,7 +48,7 @@ impl Command for ConfigEnv { engine_state: &EngineState, stack: &mut Stack, call: &Call, - input: PipelineData, + _input: PipelineData, ) -> Result { // `--default` flag handling if call.has_flag(engine_state, stack, "default")? { @@ -55,27 +56,59 @@ impl Command for ConfigEnv { return Ok(Value::string(nu_utils::get_default_env(), head).into_pipeline_data()); } - let env_vars_str = env_to_strings(engine_state, stack)?; - let nu_config = match engine_state.get_config_path("env-path") { - Some(path) => path, - None => { - return Err(ShellError::GenericError { - error: "Could not find $nu.env-path".into(), - msg: "Could not find $nu.env-path".into(), - span: None, - help: None, - inner: vec![], - }); - } + // Find the editor executable. + let (editor_name, editor_args) = get_editor(engine_state, stack, call.head)?; + let paths = nu_engine::env::path_str(engine_state, stack, call.head)?; + let cwd = engine_state.cwd(Some(stack))?; + let editor_executable = + crate::which(&editor_name, &paths, &cwd).ok_or(ShellError::ExternalCommand { + label: format!("`{editor_name}` not found"), + help: "Failed to find the editor executable".into(), + span: call.head, + })?; + + let Some(env_path) = engine_state.get_config_path("env-path") else { + return Err(ShellError::GenericError { + error: "Could not find $nu.env-path".into(), + msg: "Could not find $nu.env-path".into(), + span: None, + help: None, + inner: vec![], + }); }; + let env_path = env_path.to_string_lossy().to_string(); - let (item, config_args) = get_editor(engine_state, stack, call.head)?; + // Create the command. + let mut command = std::process::Command::new(editor_executable); - gen_command(call.head, nu_config, item, config_args, env_vars_str).run_with_input( - engine_state, - stack, - input, - true, - ) + // Configure PWD. + command.current_dir(cwd); + + // Configure environment variables. + let envs = env_to_strings(engine_state, stack)?; + command.env_clear(); + command.envs(envs); + + // Configure args. + command.arg(env_path); + command.args(editor_args); + + // Spawn the child process. On Unix, also put the child process to + // foreground if we're in an interactive session. + #[cfg(windows)] + let child = ForegroundChild::spawn(command)?; + #[cfg(unix)] + let child = ForegroundChild::spawn( + command, + engine_state.is_interactive, + &engine_state.pipeline_externals_state, + )?; + + // Wrap the output into a `PipelineData::ByteStream`. + let child = ChildProcess::new(child, None, false, call.head)?; + Ok(PipelineData::ByteStream( + ByteStream::child(child, call.head), + None, + )) } } diff --git a/crates/nu-command/src/env/config/config_nu.rs b/crates/nu-command/src/env/config/config_nu.rs index c43d8d0726..08695ca5bb 100644 --- a/crates/nu-command/src/env/config/config_nu.rs +++ b/crates/nu-command/src/env/config/config_nu.rs @@ -1,6 +1,7 @@ -use super::utils::gen_command; use nu_cmd_base::util::get_editor; use nu_engine::{command_prelude::*, env_to_strings}; +use nu_protocol::{process::ChildProcess, ByteStream}; +use nu_system::ForegroundChild; #[derive(Clone)] pub struct ConfigNu; @@ -51,7 +52,7 @@ impl Command for ConfigNu { engine_state: &EngineState, stack: &mut Stack, call: &Call, - input: PipelineData, + _input: PipelineData, ) -> Result { // `--default` flag handling if call.has_flag(engine_state, stack, "default")? { @@ -59,27 +60,59 @@ impl Command for ConfigNu { return Ok(Value::string(nu_utils::get_default_config(), head).into_pipeline_data()); } - let env_vars_str = env_to_strings(engine_state, stack)?; - let nu_config = match engine_state.get_config_path("config-path") { - Some(path) => path, - None => { - return Err(ShellError::GenericError { - error: "Could not find $nu.config-path".into(), - msg: "Could not find $nu.config-path".into(), - span: None, - help: None, - inner: vec![], - }); - } + // Find the editor executable. + let (editor_name, editor_args) = get_editor(engine_state, stack, call.head)?; + let paths = nu_engine::env::path_str(engine_state, stack, call.head)?; + let cwd = engine_state.cwd(Some(stack))?; + let editor_executable = + crate::which(&editor_name, &paths, &cwd).ok_or(ShellError::ExternalCommand { + label: format!("`{editor_name}` not found"), + help: "Failed to find the editor executable".into(), + span: call.head, + })?; + + let Some(config_path) = engine_state.get_config_path("config-path") else { + return Err(ShellError::GenericError { + error: "Could not find $nu.config-path".into(), + msg: "Could not find $nu.config-path".into(), + span: None, + help: None, + inner: vec![], + }); }; + let config_path = config_path.to_string_lossy().to_string(); - let (item, config_args) = get_editor(engine_state, stack, call.head)?; + // Create the command. + let mut command = std::process::Command::new(editor_executable); - gen_command(call.head, nu_config, item, config_args, env_vars_str).run_with_input( - engine_state, - stack, - input, - true, - ) + // Configure PWD. + command.current_dir(cwd); + + // Configure environment variables. + let envs = env_to_strings(engine_state, stack)?; + command.env_clear(); + command.envs(envs); + + // Configure args. + command.arg(config_path); + command.args(editor_args); + + // Spawn the child process. On Unix, also put the child process to + // foreground if we're in an interactive session. + #[cfg(windows)] + let child = ForegroundChild::spawn(command)?; + #[cfg(unix)] + let child = ForegroundChild::spawn( + command, + engine_state.is_interactive, + &engine_state.pipeline_externals_state, + )?; + + // Wrap the output into a `PipelineData::ByteStream`. + let child = ChildProcess::new(child, None, false, call.head)?; + Ok(PipelineData::ByteStream( + ByteStream::child(child, call.head), + None, + )) } } diff --git a/crates/nu-command/src/env/config/mod.rs b/crates/nu-command/src/env/config/mod.rs index 9cd93d2491..fa6a3b4ca3 100644 --- a/crates/nu-command/src/env/config/mod.rs +++ b/crates/nu-command/src/env/config/mod.rs @@ -2,7 +2,6 @@ mod config_; mod config_env; mod config_nu; mod config_reset; -mod utils; pub use config_::ConfigMeta; pub use config_env::ConfigEnv; pub use config_nu::ConfigNu; diff --git a/crates/nu-command/src/env/config/utils.rs b/crates/nu-command/src/env/config/utils.rs deleted file mode 100644 index 4b3ea43483..0000000000 --- a/crates/nu-command/src/env/config/utils.rs +++ /dev/null @@ -1,36 +0,0 @@ -use crate::ExternalCommand; -use nu_protocol::{OutDest, Span, Spanned}; -use std::{collections::HashMap, path::Path}; - -pub(crate) fn gen_command( - span: Span, - config_path: &Path, - item: String, - config_args: Vec, - env_vars_str: HashMap, -) -> ExternalCommand { - let name = Spanned { item, span }; - - let mut args = vec![Spanned { - item: config_path.to_string_lossy().to_string(), - span: Span::unknown(), - }]; - - let number_of_args = config_args.len() + 1; - - for arg in config_args { - args.push(Spanned { - item: arg, - span: Span::unknown(), - }) - } - - ExternalCommand { - name, - args, - arg_keep_raw: vec![false; number_of_args], - out: OutDest::Inherit, - err: OutDest::Inherit, - env_vars: env_vars_str, - } -} diff --git a/crates/nu-command/src/system/exec.rs b/crates/nu-command/src/system/exec.rs index 21c98f121b..35ab9428be 100644 --- a/crates/nu-command/src/system/exec.rs +++ b/crates/nu-command/src/system/exec.rs @@ -1,7 +1,4 @@ -use super::run_external::create_external_command; -#[allow(deprecated)] -use nu_engine::{command_prelude::*, current_dir}; -use nu_protocol::OutDest; +use nu_engine::{command_prelude::*, env_to_strings}; #[derive(Clone)] pub struct Exec; @@ -35,7 +32,66 @@ On Windows based systems, Nushell will wait for the command to finish and then e call: &Call, _input: PipelineData, ) -> Result { - exec(engine_state, stack, call) + let cwd = engine_state.cwd(Some(stack))?; + + // Find the absolute path to the executable. If the command is not + // found, display a helpful error message. + let name: Spanned = call.req(engine_state, stack, 0)?; + let executable = { + let paths = nu_engine::env::path_str(engine_state, stack, call.head)?; + let Some(executable) = crate::which(&name.item, &paths, &cwd) else { + return Err(crate::command_not_found( + &name.item, + call.head, + engine_state, + stack, + )); + }; + executable + }; + + // Create the command. + let mut command = std::process::Command::new(executable); + + // Configure PWD. + command.current_dir(cwd); + + // Configure environment variables. + let envs = env_to_strings(engine_state, stack)?; + command.env_clear(); + command.envs(envs); + + // Configure args. + let args = crate::eval_arguments_from_call(engine_state, stack, call)?; + command.args(args.into_iter().map(|s| s.item)); + + // Execute the child process, replacing/terminating the current process + // depending on platform. + #[cfg(unix)] + { + use std::os::unix::process::CommandExt; + + let err = command.exec(); + Err(ShellError::ExternalCommand { + label: "Failed to exec into new process".into(), + help: err.to_string(), + span: call.head, + }) + } + #[cfg(windows)] + { + let mut child = command.spawn().map_err(|err| ShellError::ExternalCommand { + label: "Failed to exec into new process".into(), + help: err.to_string(), + span: call.head, + })?; + let status = child.wait().map_err(|err| ShellError::ExternalCommand { + label: "Failed to wait for child process".into(), + help: err.to_string(), + span: call.head, + })?; + std::process::exit(status.code().expect("status.code() succeeds on Windows")) + } } fn examples(&self) -> Vec { @@ -53,57 +109,3 @@ On Windows based systems, Nushell will wait for the command to finish and then e ] } } - -fn exec( - engine_state: &EngineState, - stack: &mut Stack, - call: &Call, -) -> Result { - let mut external_command = create_external_command(engine_state, stack, call)?; - external_command.out = OutDest::Inherit; - external_command.err = OutDest::Inherit; - - #[allow(deprecated)] - let cwd = current_dir(engine_state, stack)?; - let mut command = external_command.spawn_simple_command(&cwd.to_string_lossy())?; - command.current_dir(cwd); - command.envs(external_command.env_vars); - - // this either replaces our process and should not return, - // or the exec fails and we get an error back - exec_impl(command, call.head) -} - -#[cfg(unix)] -fn exec_impl(mut command: std::process::Command, span: Span) -> Result { - use std::os::unix::process::CommandExt; - - let error = command.exec(); - - Err(ShellError::GenericError { - error: "Error on exec".into(), - msg: error.to_string(), - span: Some(span), - help: None, - inner: vec![], - }) -} - -#[cfg(windows)] -fn exec_impl(mut command: std::process::Command, span: Span) -> Result { - match command.spawn() { - Ok(mut child) => match child.wait() { - Ok(status) => std::process::exit(status.code().unwrap_or(0)), - Err(e) => Err(ShellError::ExternalCommand { - label: "Error in external command".into(), - help: e.to_string(), - span, - }), - }, - Err(e) => Err(ShellError::ExternalCommand { - label: "Error spawning external command".into(), - help: e.to_string(), - span, - }), - } -} diff --git a/crates/nu-command/src/system/mod.rs b/crates/nu-command/src/system/mod.rs index c0f890232d..a87aac8a07 100644 --- a/crates/nu-command/src/system/mod.rs +++ b/crates/nu-command/src/system/mod.rs @@ -33,7 +33,7 @@ pub use nu_check::NuCheck; pub use ps::Ps; #[cfg(windows)] pub use registry_query::RegistryQuery; -pub use run_external::{External, ExternalCommand}; +pub use run_external::{command_not_found, eval_arguments_from_call, which, External}; pub use sys::*; pub use uname::UName; pub use which_::Which; diff --git a/crates/nu-command/src/system/run_external.rs b/crates/nu-command/src/system/run_external.rs index b37d3a2fcb..873cee19b1 100644 --- a/crates/nu-command/src/system/run_external.rs +++ b/crates/nu-command/src/system/run_external.rs @@ -1,15 +1,18 @@ use nu_cmd_base::hook::eval_hook; use nu_engine::{command_prelude::*, env_to_strings, get_eval_expression}; -use nu_protocol::{ast::Expr, did_you_mean, process::ChildProcess, ByteStream, NuGlob, OutDest}; +use nu_protocol::{ + ast::{Expr, Expression}, + did_you_mean, + process::ChildProcess, + ByteStream, OutDest, +}; use nu_system::ForegroundChild; use nu_utils::IgnoreCaseExt; -use os_pipe::PipeReader; -use pathdiff::diff_paths; use std::{ - collections::HashMap, + borrow::Cow, io::Write, path::{Path, PathBuf}, - process::{Command as CommandSys, Stdio}, + process::Stdio, sync::Arc, thread, }; @@ -41,8 +44,131 @@ impl Command for External { call: &Call, input: PipelineData, ) -> Result { - let command = create_external_command(engine_state, stack, call)?; - command.run_with_input(engine_state, stack, input, false) + let cwd = engine_state.cwd(Some(stack))?; + + // Find the absolute path to the executable. On Windows, set the + // executable to "cmd.exe" if it's is a CMD internal command. If the + // command is not found, display a helpful error message. + let name: Spanned = call.req(engine_state, stack, 0)?; + let executable = if cfg!(windows) && is_cmd_internal_command(&name.item) { + PathBuf::from("cmd.exe") + } else { + let paths = nu_engine::env::path_str(engine_state, stack, call.head)?; + let Some(executable) = which(&name.item, &paths, &cwd) else { + return Err(command_not_found( + &name.item, + call.head, + engine_state, + stack, + )); + }; + executable + }; + + // Create the command. + let mut command = std::process::Command::new(executable); + + // Configure PWD. + command.current_dir(cwd); + + // Configure environment variables. + let envs = env_to_strings(engine_state, stack)?; + command.env_clear(); + command.envs(envs); + + // Configure args. + let args = eval_arguments_from_call(engine_state, stack, call)?; + #[cfg(windows)] + if is_cmd_internal_command(&name.item) { + use std::os::windows::process::CommandExt; + + // The /D flag disables execution of AutoRun commands from registry. + // The /C flag followed by a command name instructs CMD to execute + // that command and quit. + command.args(["/D", "/C", &name.item]); + for arg in &args { + command.raw_arg(escape_cmd_argument(arg)?.as_ref()); + } + } else { + command.args(args.into_iter().map(|s| s.item)); + } + #[cfg(not(windows))] + command.args(args.into_iter().map(|s| s.item)); + + // Configure stdout and stderr. If both are set to `OutDest::Pipe`, + // we'll setup a pipe that merge two streams into one. + let stdout = stack.stdout(); + let stderr = stack.stderr(); + let merged_stream = if matches!(stdout, OutDest::Pipe) && matches!(stderr, OutDest::Pipe) { + let (reader, writer) = os_pipe::pipe()?; + command.stdout(writer.try_clone()?); + command.stderr(writer); + Some(reader) + } else { + command.stdout(Stdio::try_from(stdout)?); + command.stderr(Stdio::try_from(stderr)?); + None + }; + + // Configure stdin. We'll try connecting input to the child process + // directly. If that's not possible, we'll setup a pipe and spawn a + // thread to copy data into the child process. + let data_to_copy_into_stdin = match input { + PipelineData::ByteStream(stream, metadata) => match stream.into_stdio() { + Ok(stdin) => { + command.stdin(stdin); + None + } + Err(stream) => { + command.stdin(Stdio::piped()); + Some(PipelineData::ByteStream(stream, metadata)) + } + }, + PipelineData::Empty => { + command.stdin(Stdio::inherit()); + None + } + value => { + command.stdin(Stdio::piped()); + Some(value) + } + }; + + // Spawn the child process. On Unix, also put the child process to + // foreground if we're in an interactive session. + #[cfg(windows)] + let mut child = ForegroundChild::spawn(command)?; + #[cfg(unix)] + let mut child = ForegroundChild::spawn( + command, + engine_state.is_interactive, + &engine_state.pipeline_externals_state, + )?; + + // If we need to copy data into the child process, do it now. + if let Some(data) = data_to_copy_into_stdin { + let stdin = child.as_mut().stdin.take().expect("stdin is piped"); + let engine_state = engine_state.clone(); + let stack = stack.clone(); + thread::Builder::new() + .name("external stdin worker".into()) + .spawn(move || { + let _ = write_pipeline_data(engine_state, stack, data, stdin); + }) + .err_span(call.head)?; + } + + // Wrap the output into a `PipelineData::ByteStream`. + let child = ChildProcess::new( + child, + merged_stream, + matches!(stderr, OutDest::Pipe), + call.head, + )?; + Ok(PipelineData::ByteStream( + ByteStream::child(child, call.head), + None, + )) } fn examples(&self) -> Vec { @@ -66,679 +192,514 @@ impl Command for External { } } -/// Creates ExternalCommand from a call -pub fn create_external_command( +/// Removes surrounding quotes from a string. Doesn't remove quotes from raw +/// strings. Returns the original string if it doesn't have matching quotes. +fn remove_quotes(s: &str) -> &str { + let quoted_by_double_quotes = s.len() >= 2 && s.starts_with('"') && s.ends_with('"'); + let quoted_by_single_quotes = s.len() >= 2 && s.starts_with('\'') && s.ends_with('\''); + let quoted_by_backticks = s.len() >= 2 && s.starts_with('`') && s.ends_with('`'); + if quoted_by_double_quotes || quoted_by_single_quotes || quoted_by_backticks { + &s[1..s.len() - 1] + } else { + s + } +} + +/// Evaluate all arguments from a call, performing expansions when necessary. +pub fn eval_arguments_from_call( engine_state: &EngineState, stack: &mut Stack, call: &Call, -) -> Result { - let name: Spanned = call.req(engine_state, stack, 0)?; - - // Translate environment variables from Values to Strings - let env_vars_str = env_to_strings(engine_state, stack)?; - - fn value_as_spanned(value: Value) -> Result, ShellError> { - let span = value.span(); - - value - .coerce_string() - .map(|item| Spanned { item, span }) - .map_err(|_| ShellError::ExternalCommand { - label: format!("Cannot convert {} to a string", value.get_type()), - help: "All arguments to an external command need to be string-compatible".into(), - span, - }) - } - - let eval_expression = get_eval_expression(engine_state); - - let mut spanned_args = vec![]; - let mut arg_keep_raw = vec![]; - for (arg, spread) in call.rest_iter(1) { - match eval_expression(engine_state, stack, arg)? { - Value::List { vals, .. } => { - if spread { - // turn all the strings in the array into params. - // Example: one_arg may be something like ["ls" "-a"] - // convert it to "ls" "-a" - for v in vals { - spanned_args.push(value_as_spanned(v)?); - // for arguments in list, it's always treated as a whole arguments - arg_keep_raw.push(true); - } - } else { - return Err(ShellError::CannotPassListToExternal { - arg: String::from_utf8_lossy(engine_state.get_span_contents(arg.span)) - .into(), - span: arg.span, - }); +) -> Result>, ShellError> { + let cwd = engine_state.cwd(Some(stack))?; + let mut args: Vec> = vec![]; + for (expr, spread) in call.rest_iter(1) { + if is_bare_string(expr) { + // If `expr` is a bare string, perform tilde-expansion, + // glob-expansion, and inner-quotes-removal, in that order. + for arg in eval_argument(engine_state, stack, expr, spread)? { + let tilde_expanded = expand_tilde(&arg); + for glob_expanded in expand_glob(&tilde_expanded, &cwd, expr.span)? { + let inner_quotes_removed = remove_inner_quotes(&glob_expanded); + args.push(inner_quotes_removed.into_owned().into_spanned(expr.span)); } } - val => { - if spread { - return Err(ShellError::CannotSpreadAsList { span: arg.span }); - } else { - spanned_args.push(value_as_spanned(val)?); - match arg.expr { - // refer to `parse_dollar_expr` function - // the expression type of $variable_name, $"($variable_name)" - // will be Expr::StringInterpolation, Expr::FullCellPath - Expr::StringInterpolation(_) | Expr::FullCellPath(_) => { - arg_keep_raw.push(true) - } - _ => arg_keep_raw.push(false), - } - } + } else { + for arg in eval_argument(engine_state, stack, expr, spread)? { + args.push(arg.into_spanned(expr.span)); } } } - - Ok(ExternalCommand { - name, - args: spanned_args, - arg_keep_raw, - out: stack.stdout().clone(), - err: stack.stderr().clone(), - env_vars: env_vars_str, - }) + Ok(args) } -#[derive(Clone)] -pub struct ExternalCommand { - pub name: Spanned, - pub args: Vec>, - pub arg_keep_raw: Vec, - pub out: OutDest, - pub err: OutDest, - pub env_vars: HashMap, -} - -impl ExternalCommand { - pub fn run_with_input( - &self, - engine_state: &EngineState, - stack: &mut Stack, - input: PipelineData, - reconfirm_command_name: bool, - ) -> Result { - let head = self.name.span; - - #[cfg(windows)] - let (child, reader, input) = { - // We may need to run `create_process` again, so we have to clone the underlying - // file or pipe in `input` here first. - let (input_consumed, stdin) = match &input { - PipelineData::ByteStream(stream, ..) => match stream.source() { - nu_protocol::ByteStreamSource::Read(_) => (false, Stdio::piped()), - nu_protocol::ByteStreamSource::File(file) => { - (true, file.try_clone().err_span(head)?.into()) - } - nu_protocol::ByteStreamSource::Child(child) => { - if let Some(nu_protocol::process::ChildPipe::Pipe(pipe)) = &child.stdout { - (true, pipe.try_clone().err_span(head)?.into()) - } else { - (false, Stdio::piped()) - } - } - }, - PipelineData::Empty => (false, Stdio::inherit()), - _ => (false, Stdio::piped()), - }; - - let mut input = input; - let (cmd, mut reader) = self.create_process(stdin, false, head)?; - let child = match ForegroundChild::spawn(cmd) { - Ok(child) => { - if input_consumed { - input = PipelineData::Empty; - } - Ok(child) - } - Err(err) => { - // Running external commands on Windows has 2 points of complication: - // 1. Some common Windows commands are actually built in to cmd.exe, not executables in their own right. - // 2. We need to let users run batch scripts etc. (.bat, .cmd) without typing their extension - - // To support these situations, we have a fallback path that gets run if a command - // fails to be run as a normal executable: - // 1. "shell out" to cmd.exe if the command is a known cmd.exe internal command - // 2. Otherwise, use `which-rs` to look for batch files etc. then run those in cmd.exe - - // set the default value, maybe we'll override it later - let mut child = Err(err); - - // This has the full list of cmd.exe "internal" commands: https://ss64.com/nt/syntax-internal.html - // I (Reilly) went through the full list and whittled it down to ones that are potentially useful: - const CMD_INTERNAL_COMMANDS: [&str; 9] = [ - "ASSOC", "CLS", "ECHO", "FTYPE", "MKLINK", "PAUSE", "START", "VER", "VOL", - ]; - let command_name = &self.name.item; - let looks_like_cmd_internal = CMD_INTERNAL_COMMANDS - .iter() - .any(|&cmd| command_name.eq_ignore_ascii_case(cmd)); - - let (data, stdin) = extract_stdio(input); - input = data; - - if looks_like_cmd_internal { - let (cmd, new_reader) = self.create_process(stdin, true, head)?; - reader = new_reader; - child = ForegroundChild::spawn(cmd); - } else { - #[cfg(feature = "which-support")] - { - // maybe it's a batch file (foo.cmd) and the user typed `foo`. Try to find it with `which-rs` - // TODO: clean this up with an if-let chain once those are stable - if let Ok(path) = - nu_engine::env::path_str(engine_state, stack, self.name.span) - { - if let Some(cwd) = self.env_vars.get("PWD") { - // append cwd to PATH so `which-rs` looks in the cwd too. - // this approximates what cmd.exe does. - let path_with_cwd = format!("{};{}", cwd, path); - if let Ok(which_path) = - which::which_in(&self.name.item, Some(path_with_cwd), cwd) - { - if let Some(file_name) = which_path.file_name() { - if !file_name - .to_string_lossy() - .eq_ignore_case(command_name) - { - // which-rs found an executable file with a slightly different name - // than the one the user tried. Let's try running it - let mut new_command = self.clone(); - new_command.name = Spanned { - item: file_name.to_string_lossy().to_string(), - span: self.name.span, - }; - let (cmd, new_reader) = new_command - .create_process(stdin, true, head)?; - reader = new_reader; - child = ForegroundChild::spawn(cmd); - } - } - } - } - } - } - } - - child - } - }; - - (child, reader, input) - }; - - #[cfg(unix)] - let (child, reader, input) = { - let (input, stdin) = extract_stdio(input); - let (cmd, reader) = self.create_process(stdin, false, head)?; - let child = ForegroundChild::spawn( - cmd, - engine_state.is_interactive, - &engine_state.pipeline_externals_state, - ); - (child, reader, input) - }; - - match child { - Err(err) => { - match err.kind() { - // If file not found, try suggesting alternative commands to the user - std::io::ErrorKind::NotFound => { - // recommend a replacement if the user tried a removed command - let command_name_lower = self.name.item.to_lowercase(); - let removed_from_nu = crate::removed_commands(); - if removed_from_nu.contains_key(&command_name_lower) { - let replacement = match removed_from_nu.get(&command_name_lower) { - Some(s) => s.clone(), - None => "".to_string(), - }; - return Err(ShellError::RemovedCommand { - removed: command_name_lower, - replacement, - span: self.name.span, - }); - } - - let suggestion = suggest_command(&self.name.item, engine_state); - let label = match suggestion { - Some(s) => { - if reconfirm_command_name { - format!( - "'{}' was not found; did you mean '{s}'?", - self.name.item - ) - } else { - let cmd_name = &self.name.item; - let maybe_module = engine_state - .which_module_has_decl(cmd_name.as_bytes(), &[]); - if let Some(module_name) = maybe_module { - let module_name = String::from_utf8_lossy(module_name); - let new_name = &[module_name.as_ref(), cmd_name].join(" "); - - if engine_state - .find_decl(new_name.as_bytes(), &[]) - .is_some() - { - format!("command '{cmd_name}' was not found but it was imported from module '{module_name}'; try using `{new_name}`") - } else { - format!("command '{cmd_name}' was not found but it exists in module '{module_name}'; try importing it with `use`") - } - } else { - // If command and suggestion are the same, display not found - if cmd_name == &s { - format!("'{cmd_name}' was not found") - } else { - format!("did you mean '{s}'?") - } - } - } - } - None => { - if reconfirm_command_name { - format!("executable '{}' was not found", self.name.item) - } else { - "executable was not found".into() - } - } - }; - - let mut err_str = err.to_string(); - if engine_state.is_interactive { - let mut engine_state = engine_state.clone(); - if let Some(hook) = engine_state.config.hooks.command_not_found.clone() - { - let canary = "ENTERED_COMMAND_NOT_FOUND"; - let stack = &mut stack.start_capture(); - if stack.has_env_var(&engine_state, canary) { - return Err(ShellError::ExternalCommand { - label: "command_not_found handler could not be run".into(), - help: "make sure the command_not_found closure itself does not use unknown commands".to_string(), - span: self.name.span, - }); - } - stack.add_env_var( - canary.to_string(), - Value::bool(true, Span::unknown()), - ); - match eval_hook( - &mut engine_state, - stack, - None, - vec![( - "cmd_name".into(), - Value::string(self.name.item.to_string(), self.name.span), - )], - &hook, - "command_not_found", - ) { - Ok(PipelineData::Value(Value::String { val, .. }, ..)) => { - err_str = format!("{}\n{}", err_str, val); - } - - Err(err) => { - stack.remove_env_var(&engine_state, canary); - return Err(err); - } - _ => {} - } - stack.remove_env_var(&engine_state, canary); - } - } - - Err(ShellError::ExternalCommand { - label, - help: err_str, - span: self.name.span, - }) - } - // otherwise, a default error message - _ => Err(ShellError::ExternalCommand { - label: "can't run executable".into(), - help: err.to_string(), - span: self.name.span, - }), - } - } - Ok(mut child) => { - if !input.is_nothing() { - let mut engine_state = engine_state.clone(); - let mut stack = stack.clone(); - - // Turn off color as we pass data through - Arc::make_mut(&mut engine_state.config).use_ansi_coloring = false; - - // Pipe input into the external command's stdin - if let Some(mut stdin_write) = child.as_mut().stdin.take() { - thread::Builder::new() - .name("external stdin worker".to_string()) - .spawn(move || { - let input = match input { - // Don't touch binary input or byte streams - input @ PipelineData::ByteStream(..) => input, - input @ PipelineData::Value(Value::Binary { .. }, ..) => input, - input => { - let stack = &mut stack.start_capture(); - // Attempt to render the input as a table before piping it to the external. - // This is important for pagers like `less`; - // they need to get Nu data rendered for display to users. - // - // TODO: should we do something different for list inputs? - // Users often expect those to be piped to *nix tools as raw strings separated by newlines - crate::Table.run( - &engine_state, - stack, - &Call::new(head), - input, - )? - } - }; - - if let PipelineData::ByteStream(stream, ..) = input { - stream.write_to(&mut stdin_write)?; - } else { - for value in input.into_iter() { - let buf = value.coerce_into_binary()?; - stdin_write.write_all(&buf)?; - } - } - - Ok::<_, ShellError>(()) - }) - .err_span(head)?; - } - } - - let child = - ChildProcess::new(child, reader, matches!(self.err, OutDest::Pipe), head)?; - - Ok(PipelineData::ByteStream( - ByteStream::child(child, head), - None, - )) - } - } +/// Evaluates an expression, coercing the values to strings. +/// +/// Note: The parser currently has a special hack that retains surrounding +/// quotes for string literals in `Expression`, so that we can decide whether +/// the expression is considered a bare string. The hack doesn't affect string +/// literals within lists or records. This function will remove the quotes +/// before evaluating the expression. +fn eval_argument( + engine_state: &EngineState, + stack: &mut Stack, + expr: &Expression, + spread: bool, +) -> Result, ShellError> { + // Remove quotes from string literals. + let mut expr = expr.clone(); + if let Expr::String(s) = &expr.expr { + expr.expr = Expr::String(remove_quotes(s).into()); } - pub fn create_process( - &self, - stdin: Stdio, - use_cmd: bool, - span: Span, - ) -> Result<(CommandSys, Option), ShellError> { - let mut process = if let Some(d) = self.env_vars.get("PWD") { - let mut process = if use_cmd { - self.spawn_cmd_command(d) + let eval = get_eval_expression(engine_state); + match eval(engine_state, stack, &expr)? { + Value::List { vals, .. } => { + if spread { + vals.into_iter() + .map(|val| val.coerce_into_string()) + .collect() } else { - self.create_command(d)? - }; - - // do not try to set current directory if cwd does not exist - if Path::new(&d).exists() { - process.current_dir(d); + Err(ShellError::CannotPassListToExternal { + arg: String::from_utf8_lossy(engine_state.get_span_contents(expr.span)).into(), + span: expr.span, + }) } - process - } else { - return Err(ShellError::GenericError{ - error: "Current directory not found".into(), - msg: "did not find PWD environment variable".into(), - span: Some(span), - help: Some(concat!( - "The environment variable 'PWD' was not found. ", - "It is required to define the current directory when running an external command." - ).into()), - inner:Vec::new(), - }); - }; - - process.envs(&self.env_vars); - - // If the external is not the last command, its output will get piped - // either as a string or binary - let reader = if matches!(self.out, OutDest::Pipe) && matches!(self.err, OutDest::Pipe) { - let (reader, writer) = os_pipe::pipe()?; - let writer_clone = writer.try_clone()?; - process.stdout(writer); - process.stderr(writer_clone); - Some(reader) - } else { - process.stdout(Stdio::try_from(&self.out)?); - process.stderr(Stdio::try_from(&self.err)?); - None - }; - - process.stdin(stdin); - - Ok((process, reader)) - } - - fn create_command(&self, cwd: &str) -> Result { - // in all the other cases shell out - if cfg!(windows) { - //TODO. This should be modifiable from the config file. - // We could give the option to call from powershell - // for minimal builds cwd is unused - if self.name.item.ends_with(".cmd") || self.name.item.ends_with(".bat") { - Ok(self.spawn_cmd_command(cwd)) + } + value => { + if spread { + Err(ShellError::CannotSpreadAsList { span: expr.span }) } else { - self.spawn_simple_command(cwd) + Ok(vec![value.coerce_into_string()?]) } - } else { - self.spawn_simple_command(cwd) } } - - /// Spawn a command without shelling out to an external shell - /// - /// Note that this function will not set the cwd or environment variables. - /// It only creates the command and adds arguments. - pub fn spawn_simple_command(&self, cwd: &str) -> Result { - let (head, _, _) = trim_enclosing_quotes(&self.name.item); - let head = nu_path::expand_to_real_path(head) - .to_string_lossy() - .to_string(); - - let mut process = std::process::Command::new(head); - process.env_clear(); - - for (arg, arg_keep_raw) in self.args.iter().zip(self.arg_keep_raw.iter()) { - trim_expand_and_apply_arg(&mut process, arg, arg_keep_raw, cwd); - } - - Ok(process) - } - - /// Spawn a cmd command with `cmd /c args...` - pub fn spawn_cmd_command(&self, cwd: &str) -> std::process::Command { - let mut process = std::process::Command::new("cmd"); - - // Disable AutoRun - // TODO: There should be a config option to enable/disable this - // Alternatively (even better) a config option to specify all the arguments to pass to cmd - process.arg("/D"); - - process.arg("/c"); - process.arg(&self.name.item); - for (arg, arg_keep_raw) in self.args.iter().zip(self.arg_keep_raw.iter()) { - // https://stackoverflow.com/questions/1200235/how-to-pass-a-quoted-pipe-character-to-cmd-exe - // cmd.exe needs to have a caret to escape a pipe - let arg = Spanned { - item: arg.item.replace('|', "^|"), - span: arg.span, - }; - - trim_expand_and_apply_arg(&mut process, &arg, arg_keep_raw, cwd) - } - - process - } } -fn trim_expand_and_apply_arg( - process: &mut CommandSys, - arg: &Spanned, - arg_keep_raw: &bool, - cwd: &str, -) { - // if arg is quoted, like "aa", 'aa', `aa`, or: - // if arg is a variable or String interpolation, like: $variable_name, $"($variable_name)" - // `as_a_whole` will be true, so nu won't remove the inner quotes. - let (trimmed_args, mut run_glob_expansion, mut keep_raw) = trim_enclosing_quotes(&arg.item); - if *arg_keep_raw { - keep_raw = true; - // it's a list or a variable, don't run glob expansion either - run_glob_expansion = false; - } - let mut arg = Spanned { - item: if keep_raw { - trimmed_args - } else { - remove_quotes(trimmed_args) - }, - span: arg.span, +/// Returns whether an expression is considered a bare string. +/// +/// Bare strings are defined as string literals that are either unquoted or +/// quoted by backticks. Raw strings or string interpolations don't count. +fn is_bare_string(expr: &Expression) -> bool { + let Expr::String(s) = &expr.expr else { + return false; }; - if !keep_raw { - arg.item = nu_path::expand_tilde(arg.item) - .to_string_lossy() - .to_string(); - } - let cwd = PathBuf::from(cwd); - if arg.item.contains('*') && run_glob_expansion { - // we need to run glob expansion, so it's NeedExpand. - let path = Spanned { - item: NuGlob::Expand(arg.item.clone()), - span: arg.span, - }; - if let Ok((prefix, matches)) = nu_engine::glob_from(&path, &cwd, arg.span, None) { - let matches: Vec<_> = matches.collect(); - - // FIXME: do we want to special-case this further? We might accidentally expand when they don't - // intend to - if matches.is_empty() { - process.arg(&arg.item); - } - for m in matches { - if let Ok(arg) = m { - let arg = if let Some(prefix) = &prefix { - if let Ok(remainder) = arg.strip_prefix(prefix) { - let new_prefix = if let Some(pfx) = diff_paths(prefix, &cwd) { - pfx - } else { - prefix.to_path_buf() - }; - - new_prefix.join(remainder).to_string_lossy().to_string() - } else { - arg.to_string_lossy().to_string() - } - } else { - arg.to_string_lossy().to_string() - }; - - process.arg(&arg); - } else { - process.arg(&arg.item); - } - } - } - } else { - process.arg(&arg.item); - } + let quoted_by_double_quotes = s.len() >= 2 && s.starts_with('"') && s.ends_with('"'); + let quoted_by_single_quotes = s.len() >= 2 && s.starts_with('\'') && s.ends_with('\''); + !quoted_by_double_quotes && !quoted_by_single_quotes } -/// Given an invalid command name, try to suggest an alternative -fn suggest_command(attempted_command: &str, engine_state: &EngineState) -> Option { - let commands = engine_state.get_signatures(false); - let command_folded_case = attempted_command.to_folded_case(); - let search_term_match = commands.iter().find(|sig| { +/// Performs tilde expansion on `arg`. Returns the original string if `arg` +/// doesn't start with tilde. +fn expand_tilde(arg: &str) -> String { + nu_path::expand_tilde(arg).to_string_lossy().to_string() +} + +/// Performs glob expansion on `arg`. If the expansion found no matches, returns +/// the original string as the expansion result. +/// +/// Note: This matches the default behavior of Bash, but is known to be +/// error-prone. We might want to change this behavior in the future. +fn expand_glob(arg: &str, cwd: &Path, span: Span) -> Result, ShellError> { + let paths = + nu_glob::glob_with_parent(arg, nu_glob::MatchOptions::default(), cwd).map_err(|err| { + ShellError::InvalidGlobPattern { + msg: err.msg.to_string(), + span, + } + })?; + + let mut result = vec![]; + for path in paths { + let path = path.map_err(|err| ShellError::IOErrorSpanned { + msg: format!("{}: {:?}", err.path().display(), err.error()), + span, + })?; + // Strip PWD from the resulting paths if possible. + let path_stripped = path.strip_prefix(cwd).unwrap_or(&path); + let path_string = path_stripped.to_string_lossy().to_string(); + result.push(path_string); + } + + if result.is_empty() { + result.push(arg.to_string()); + } + + Ok(result) +} + +/// Transforms `--option="value"` into `--option=value`. `value` can be quoted +/// with double quotes, single quotes, or backticks. Only removes the outermost +/// pair of quotes after the equal sign. +fn remove_inner_quotes(arg: &str) -> Cow<'_, str> { + // Check that `arg` is a long option. + if !arg.starts_with("--") { + return Cow::Borrowed(arg); + } + // Split `arg` on the first `=`. + let Some((option, value)) = arg.split_once('=') else { + return Cow::Borrowed(arg); + }; + // Check that `option` doesn't contain quotes. + if option.contains('"') || option.contains('\'') || option.contains('`') { + return Cow::Borrowed(arg); + } + // Remove the outermost pair of quotes from `value`. + let value = remove_quotes(value); + Cow::Owned(format!("{option}={value}")) +} + +/// Write `PipelineData` into `writer`. If `PipelineData` is not binary, it is +/// first rendered using the `table` command. +/// +/// Note: Avoid using this function when piping data from an external command to +/// another external command, because it copies data unnecessarily. Instead, +/// extract the pipe from the `PipelineData::ByteStream` of the first command +/// and hand it to the second command directly. +fn write_pipeline_data( + mut engine_state: EngineState, + mut stack: Stack, + data: PipelineData, + mut writer: impl Write, +) -> Result<(), ShellError> { + if let PipelineData::ByteStream(stream, ..) = data { + stream.write_to(writer)?; + } else if let PipelineData::Value(Value::Binary { val, .. }, ..) = data { + writer.write_all(&val)?; + } else { + stack.start_capture(); + + // Turn off color as we pass data through + Arc::make_mut(&mut engine_state.config).use_ansi_coloring = false; + + // Invoke the `table` command. + let output = + crate::Table.run(&engine_state, &mut stack, &Call::new(Span::unknown()), data)?; + + // Write the output. + for value in output { + let bytes = value.coerce_into_binary()?; + writer.write_all(&bytes)?; + } + } + Ok(()) +} + +/// Returns a helpful error message given an invalid command name, +pub fn command_not_found( + name: &str, + span: Span, + engine_state: &EngineState, + stack: &mut Stack, +) -> ShellError { + // Run the `command_not_found` hook if there is one. + if let Some(hook) = &engine_state.config.hooks.command_not_found { + let mut stack = stack.start_capture(); + // Set a special environment variable to avoid infinite loops when the + // `command_not_found` hook triggers itself. + let canary = "ENTERED_COMMAND_NOT_FOUND"; + if stack.has_env_var(engine_state, canary) { + return ShellError::ExternalCommand { + label: format!( + "Command {name} not found while running the `command_not_found` hook" + ), + help: "Make sure the `command_not_found` hook itself does not use unknown commands" + .into(), + span, + }; + } + stack.add_env_var(canary.into(), Value::bool(true, Span::unknown())); + + let output = eval_hook( + &mut engine_state.clone(), + &mut stack, + None, + vec![("cmd_name".into(), Value::string(name, span))], + hook, + "command_not_found", + ); + + // Remove the special environment variable that we just set. + stack.remove_env_var(engine_state, canary); + + match output { + Ok(PipelineData::Value(Value::String { val, .. }, ..)) => { + return ShellError::ExternalCommand { + label: format!("Command `{name}` not found"), + help: val, + span, + }; + } + Err(err) => { + return err; + } + _ => { + // The hook did not return a string, so ignore it. + } + } + } + + // If the name is one of the removed commands, recommend a replacement. + if let Some(replacement) = crate::removed_commands().get(&name.to_lowercase()) { + return ShellError::RemovedCommand { + removed: name.to_lowercase(), + replacement: replacement.clone(), + span, + }; + } + + // The command might be from another module. Try to find it. + if let Some(module) = engine_state.which_module_has_decl(name.as_bytes(), &[]) { + let module = String::from_utf8_lossy(module); + // Is the command already imported? + let full_name = format!("{module} {name}"); + if engine_state.find_decl(full_name.as_bytes(), &[]).is_some() { + return ShellError::ExternalCommand { + label: format!("Command `{name}` not found"), + help: format!("Did you mean `{full_name}`?"), + span, + }; + } else { + return ShellError::ExternalCommand { + label: format!("Command `{name}` not found"), + help: format!("A command with that name exists in module `{module}`. Try importing it with `use`"), + span, + }; + } + } + + // Try to match the name with the search terms of existing commands. + let signatures = engine_state.get_signatures(false); + if let Some(sig) = signatures.iter().find(|sig| { sig.search_terms .iter() - .any(|term| term.to_folded_case() == command_folded_case) - }); - match search_term_match { - Some(sig) => Some(sig.name.clone()), - None => { - let command_names: Vec = commands.iter().map(|sig| sig.name.clone()).collect(); - did_you_mean(&command_names, attempted_command) + .any(|term| term.to_folded_case() == name.to_folded_case()) + }) { + return ShellError::ExternalCommand { + label: format!("Command `{name}` not found"), + help: format!("Did you mean `{}`?", sig.name), + span, + }; + } + + // Try a fuzzy search on the names of all existing commands. + if let Some(cmd) = did_you_mean(signatures.iter().map(|sig| &sig.name), name) { + // The user is invoking an external command with the same name as a + // built-in command. Remind them of this. + if cmd == name { + return ShellError::ExternalCommand { + label: format!("Command `{name}` not found"), + help: "There is a built-in command with the same name".into(), + span, + }; } + return ShellError::ExternalCommand { + label: format!("Command `{name}` not found"), + help: format!("Did you mean `{cmd}`?"), + span, + }; + } + + // We found nothing useful. Give up and return a generic error message. + ShellError::ExternalCommand { + label: format!("Command `{name}` not found"), + help: format!("`{name}` is neither a Nushell built-in or a known external command"), + span, } } -/// This function returns a tuple with 3 items: -/// 1st item: trimmed string. -/// 2nd item: a boolean value indicate if it's ok to run glob expansion. -/// 3rd item: a boolean value indicate if we need to keep raw string. -fn trim_enclosing_quotes(input: &str) -> (String, bool, bool) { - let mut chars = input.chars(); - - match (chars.next(), chars.next_back()) { - (Some('"'), Some('"')) => (chars.collect(), false, true), - (Some('\''), Some('\'')) => (chars.collect(), false, true), - // We treat back-quoted strings as bare words, so there's no need to keep them as raw strings - (Some('`'), Some('`')) => (chars.collect(), true, false), - _ => (input.to_string(), true, false), - } +/// Searches for the absolute path of an executable by name. `.bat` and `.cmd` +/// files are recognized as executables on Windows. +/// +/// This is a wrapper around `which::which_in()` except that, on Windows, it +/// also searches the current directory before any PATH entries. +/// +/// Note: the `which.rs` crate always uses PATHEXT from the environment. As +/// such, changing PATHEXT within Nushell doesn't work without updating the +/// actual environment of the Nushell process. +pub fn which(name: &str, paths: &str, cwd: &Path) -> Option { + #[cfg(windows)] + let paths = format!("{};{}", cwd.display(), paths); + which::which_in(name, Some(paths), cwd).ok() } -fn remove_quotes(input: String) -> String { - let mut chars = input.chars(); - - match (chars.next_back(), input.contains('=')) { - (Some('"'), true) => chars - .collect::() - .replacen('"', "", 1) - .replace(r#"\""#, "\""), - (Some('\''), true) => chars.collect::().replacen('\'', "", 1), - _ => input, - } +/// Returns true if `name` is a (somewhat useful) CMD internal command. The full +/// list can be found at https://ss64.com/nt/syntax-internal.html +fn is_cmd_internal_command(name: &str) -> bool { + const COMMANDS: &[&str] = &[ + "ASSOC", "CLS", "ECHO", "FTYPE", "MKLINK", "PAUSE", "START", "VER", "VOL", + ]; + COMMANDS.iter().any(|cmd| cmd.eq_ignore_ascii_case(name)) } -fn extract_stdio(pipeline: PipelineData) -> (PipelineData, Stdio) { - match pipeline { - PipelineData::ByteStream(stream, metadata) => match stream.into_stdio() { - Ok(pipe) => (PipelineData::Empty, pipe), - Err(stream) => (PipelineData::ByteStream(stream, metadata), Stdio::piped()), - }, - PipelineData::Empty => (PipelineData::Empty, Stdio::inherit()), - data => (data, Stdio::piped()), +/// Returns true if a string contains CMD special characters. +#[cfg(windows)] +fn has_cmd_special_character(s: &str) -> bool { + const SPECIAL_CHARS: &[char] = &['<', '>', '&', '|', '^']; + SPECIAL_CHARS.iter().any(|c| s.contains(*c)) +} + +/// Escape an argument for CMD internal commands. The result can be safely +/// passed to `raw_arg()`. +#[cfg(windows)] +fn escape_cmd_argument(arg: &Spanned) -> Result, ShellError> { + let Spanned { item: arg, span } = arg; + if arg.contains('"') { + // If `arg` is already quoted by double quotes, confirm there's no + // embedded double quotes, then leave it as is. + if arg.chars().filter(|c| *c == '"').count() == 2 + && arg.starts_with('"') + && arg.ends_with('"') + { + Ok(Cow::Borrowed(arg)) + } else { + Err(ShellError::ExternalCommand { + label: "Arguments to CMD internal commands cannot contain embedded double quotes" + .into(), + help: "CMD doesn't support escaping double quotes inside double quotes".into(), + span: *span, + }) + } + } else if arg.contains(' ') || has_cmd_special_character(arg) { + // If `arg` contains space or special characters, quote the entire argument by double quotes. + Ok(Cow::Owned(format!("\"{arg}\""))) + } else { + Ok(Cow::Borrowed(arg)) } } #[cfg(test)] mod test { use super::*; + use nu_protocol::ast::ListItem; #[test] - fn remove_quotes_argument_with_equal_test() { - let input = r#"--file="my_file.txt""#.into(); - let res = remove_quotes(input); - - assert_eq!("--file=my_file.txt", res) + fn test_remove_quotes() { + assert_eq!(remove_quotes(r#""#), r#""#); + assert_eq!(remove_quotes(r#"'"#), r#"'"#); + assert_eq!(remove_quotes(r#"''"#), r#""#); + assert_eq!(remove_quotes(r#""foo""#), r#"foo"#); + assert_eq!(remove_quotes(r#"`foo '"' bar`"#), r#"foo '"' bar"#); + assert_eq!(remove_quotes(r#"'foo' bar"#), r#"'foo' bar"#); + assert_eq!(remove_quotes(r#"r#'foo'#"#), r#"r#'foo'#"#); } #[test] - fn argument_without_equal_test() { - let input = r#"--file "my_file.txt""#.into(); - let res = remove_quotes(input); + fn test_eval_argument() { + fn expression(expr: Expr) -> Expression { + Expression { + expr, + span: Span::unknown(), + ty: Type::Any, + custom_completion: None, + } + } - assert_eq!(r#"--file "my_file.txt""#, res) + fn eval(expr: Expr, spread: bool) -> Result, ShellError> { + let engine_state = EngineState::new(); + let mut stack = Stack::new(); + eval_argument(&engine_state, &mut stack, &expression(expr), spread) + } + + let actual = eval(Expr::String("".into()), false).unwrap(); + let expected = &[""]; + assert_eq!(actual, expected); + + let actual = eval(Expr::String("'foo'".into()), false).unwrap(); + let expected = &["foo"]; + assert_eq!(actual, expected); + + let actual = eval(Expr::RawString("'foo'".into()), false).unwrap(); + let expected = &["'foo'"]; + assert_eq!(actual, expected); + + let actual = eval(Expr::List(vec![]), true).unwrap(); + let expected: &[&str] = &[]; + assert_eq!(actual, expected); + + let actual = eval( + Expr::List(vec![ + ListItem::Item(expression(Expr::String("'foo'".into()))), + ListItem::Item(expression(Expr::String("bar".into()))), + ]), + true, + ) + .unwrap(); + let expected = &["'foo'", "bar"]; + assert_eq!(actual, expected); + + eval(Expr::String("".into()), true).unwrap_err(); + eval(Expr::List(vec![]), false).unwrap_err(); } #[test] - fn remove_quotes_argument_with_single_quotes_test() { - let input = r#"--file='my_file.txt'"#.into(); - let res = remove_quotes(input); + fn test_expand_glob() { + let tempdir = tempfile::tempdir().unwrap(); + let cwd = tempdir.path(); + std::fs::File::create(cwd.join("a.txt")).unwrap(); + std::fs::File::create(cwd.join("b.txt")).unwrap(); - assert_eq!("--file=my_file.txt", res) + let actual = expand_glob("*.txt", cwd, Span::unknown()).unwrap(); + let expected = &["a.txt", "b.txt"]; + assert_eq!(actual, expected); + + let actual = expand_glob("'*.txt'", cwd, Span::unknown()).unwrap(); + let expected = &["'*.txt'"]; + assert_eq!(actual, expected); + + expand_glob("[*.txt", cwd, Span::unknown()).unwrap_err(); } #[test] - fn argument_with_inner_quotes_test() { - let input = r#"sh -c 'echo a'"#.into(); - let res = remove_quotes(input); + fn test_remove_inner_quotes() { + let actual = remove_inner_quotes(r#"--option=value"#); + let expected = r#"--option=value"#; + assert_eq!(actual, expected); - assert_eq!("sh -c 'echo a'", res) + let actual = remove_inner_quotes(r#"--option="value""#); + let expected = r#"--option=value"#; + assert_eq!(actual, expected); + + let actual = remove_inner_quotes(r#"--option='value'"#); + let expected = r#"--option=value"#; + assert_eq!(actual, expected); + + let actual = remove_inner_quotes(r#"--option "value""#); + let expected = r#"--option "value""#; + assert_eq!(actual, expected); + } + + #[test] + fn test_write_pipeline_data() { + let engine_state = EngineState::new(); + let stack = Stack::new(); + + let mut buf = vec![]; + let input = PipelineData::Empty; + write_pipeline_data(engine_state.clone(), stack.clone(), input, &mut buf).unwrap(); + assert_eq!(buf, b""); + + let mut buf = vec![]; + let input = PipelineData::Value(Value::string("foo", Span::unknown()), None); + write_pipeline_data(engine_state.clone(), stack.clone(), input, &mut buf).unwrap(); + assert_eq!(buf, b"foo"); + + let mut buf = vec![]; + let input = PipelineData::Value(Value::binary(b"foo", Span::unknown()), None); + write_pipeline_data(engine_state.clone(), stack.clone(), input, &mut buf).unwrap(); + assert_eq!(buf, b"foo"); + + let mut buf = vec![]; + let input = PipelineData::ByteStream( + ByteStream::read( + b"foo".as_slice(), + Span::unknown(), + None, + ByteStreamType::Unknown, + ), + None, + ); + write_pipeline_data(engine_state.clone(), stack.clone(), input, &mut buf).unwrap(); + assert_eq!(buf, b"foo"); } } diff --git a/crates/nu-command/tests/commands/all.rs b/crates/nu-command/tests/commands/all.rs index bcf6f86a45..8ed5a6f34f 100644 --- a/crates/nu-command/tests/commands/all.rs +++ b/crates/nu-command/tests/commands/all.rs @@ -55,7 +55,9 @@ fn checks_if_all_returns_error_with_invalid_command() { "# )); - assert!(actual.err.contains("can't run executable") || actual.err.contains("did you mean")); + assert!( + actual.err.contains("Command `st` not found") && actual.err.contains("Did you mean `ast`?") + ); } #[test] diff --git a/crates/nu-command/tests/commands/any.rs b/crates/nu-command/tests/commands/any.rs index 0e43f26cfd..f8af25eb61 100644 --- a/crates/nu-command/tests/commands/any.rs +++ b/crates/nu-command/tests/commands/any.rs @@ -41,7 +41,9 @@ fn checks_if_any_returns_error_with_invalid_command() { "# )); - assert!(actual.err.contains("can't run executable") || actual.err.contains("did you mean")); + assert!( + actual.err.contains("Command `st` not found") && actual.err.contains("Did you mean `ast`?") + ); } #[test] diff --git a/crates/nu-command/tests/commands/complete.rs b/crates/nu-command/tests/commands/complete.rs index a5a8b6a256..329e95ad71 100644 --- a/crates/nu-command/tests/commands/complete.rs +++ b/crates/nu-command/tests/commands/complete.rs @@ -24,7 +24,7 @@ fn basic_exit_code() { #[test] fn error() { let actual = nu!("not-found | complete"); - assert!(actual.err.contains("executable was not found")); + assert!(actual.err.contains("Command `not-found` not found")); } #[test] diff --git a/crates/nu-command/tests/commands/source_env.rs b/crates/nu-command/tests/commands/source_env.rs index 4e8da55c78..9dd0320a45 100644 --- a/crates/nu-command/tests/commands/source_env.rs +++ b/crates/nu-command/tests/commands/source_env.rs @@ -283,13 +283,17 @@ fn source_env_is_scoped() { let actual = nu!(cwd: dirs.test(), &inp.join("; ")); - assert!(actual.err.contains("executable was not found")); + assert!(actual + .err + .contains("Command `no-name-similar-to-this` not found")); let inp = &[r#"source-env spam.nu"#, r#"nor-similar-to-this"#]; let actual = nu!(cwd: dirs.test(), &inp.join("; ")); - assert!(actual.err.contains("executable was not found")); + assert!(actual + .err + .contains("Command `nor-similar-to-this` not found")); }) } diff --git a/crates/nu-command/tests/commands/use_.rs b/crates/nu-command/tests/commands/use_.rs index 8cb783f96b..63b1f8391a 100644 --- a/crates/nu-command/tests/commands/use_.rs +++ b/crates/nu-command/tests/commands/use_.rs @@ -189,9 +189,7 @@ fn use_module_creates_accurate_did_you_mean_1() { let actual = nu!(r#" module spam { export def foo [] { "foo" } }; use spam; foo "#); - assert!(actual.err.contains( - "command 'foo' was not found but it was imported from module 'spam'; try using `spam foo`" - )); + assert!(actual.err.contains("Did you mean `spam foo`")); } #[test] @@ -199,9 +197,9 @@ fn use_module_creates_accurate_did_you_mean_2() { let actual = nu!(r#" module spam { export def foo [] { "foo" } }; foo "#); - assert!(actual.err.contains( - "command 'foo' was not found but it exists in module 'spam'; try importing it with `use`" - )); + assert!(actual + .err + .contains("A command with that name exists in module `spam`")); } #[test] diff --git a/src/test_bins.rs b/src/test_bins.rs index d96c74a911..7cd542e732 100644 --- a/src/test_bins.rs +++ b/src/test_bins.rs @@ -242,6 +242,7 @@ pub fn nu_repl() { let mut top_stack = Arc::new(Stack::new()); engine_state.add_env_var("PWD".into(), Value::test_string(cwd.to_string_lossy())); + engine_state.add_env_var("PATH".into(), Value::test_string("")); let mut last_output = String::new(); diff --git a/tests/repl/test_known_external.rs b/tests/repl/test_known_external.rs index c140f4ee90..96ea677d37 100644 --- a/tests/repl/test_known_external.rs +++ b/tests/repl/test_known_external.rs @@ -108,14 +108,14 @@ fn known_external_misc_values() -> TestResult { /// GitHub issue #7822 #[test] fn known_external_subcommand_from_module() -> TestResult { - let output = Command::new("cargo").arg("check").arg("-h").output()?; + let output = Command::new("cargo").arg("add").arg("-h").output()?; run_test( r#" module cargo { - export extern check [] + export extern add [] }; use cargo; - cargo check -h + cargo add -h "#, String::from_utf8(output.stdout)?.trim(), ) @@ -124,14 +124,14 @@ fn known_external_subcommand_from_module() -> TestResult { /// GitHub issue #7822 #[test] fn known_external_aliased_subcommand_from_module() -> TestResult { - let output = Command::new("cargo").arg("check").arg("-h").output()?; + let output = Command::new("cargo").arg("add").arg("-h").output()?; run_test( r#" module cargo { - export extern check [] + export extern add [] }; use cargo; - alias cc = cargo check; + alias cc = cargo add; cc -h "#, String::from_utf8(output.stdout)?.trim(), diff --git a/tests/repl/test_parser.rs b/tests/repl/test_parser.rs index c0e7279b7b..9d743b175d 100644 --- a/tests/repl/test_parser.rs +++ b/tests/repl/test_parser.rs @@ -647,7 +647,7 @@ fn duration_with_underscores_2() -> TestResult { #[test] fn duration_with_underscores_3() -> TestResult { - fail_test("1_000_d_ay", "executable was not found") + fail_test("1_000_d_ay", "Command `1_000_d_ay` not found") } #[test] @@ -667,7 +667,7 @@ fn filesize_with_underscores_2() -> TestResult { #[test] fn filesize_with_underscores_3() -> TestResult { - fail_test("42m_b", "executable was not found") + fail_test("42m_b", "Command `42m_b` not found") } #[test] diff --git a/tests/repl/test_spread.rs b/tests/repl/test_spread.rs index 419188be33..f0ce84d393 100644 --- a/tests/repl/test_spread.rs +++ b/tests/repl/test_spread.rs @@ -183,17 +183,14 @@ fn explain_spread_args() -> TestResult { #[test] fn disallow_implicit_spread_for_externals() -> TestResult { - fail_test( - r#"nu --testbin cococo [1 2]"#, - "Lists are not automatically spread", - ) + fail_test(r#"^echo [1 2]"#, "Lists are not automatically spread") } #[test] fn respect_shape() -> TestResult { fail_test( "def foo [...rest] { ...$rest }; foo bar baz", - "executable was not found", + "Command `...$rest` not found", ) .unwrap(); fail_test("module foo { ...$bar }", "expected_keyword").unwrap(); diff --git a/tests/shell/pipeline/commands/external.rs b/tests/shell/pipeline/commands/external.rs index 3cbed5a124..8557e9e327 100644 --- a/tests/shell/pipeline/commands/external.rs +++ b/tests/shell/pipeline/commands/external.rs @@ -72,7 +72,9 @@ fn correctly_escape_external_arguments() { fn escape_also_escapes_equals() { let actual = nu!("^MYFOONAME=MYBARVALUE"); - assert!(actual.err.contains("executable was not found")); + assert!(actual + .err + .contains("Command `MYFOONAME=MYBARVALUE` not found")); } #[test] @@ -127,7 +129,7 @@ fn command_not_found_error_shows_not_found_1() { export extern "foo" []; foo "#); - assert!(actual.err.contains("'foo' was not found")); + assert!(actual.err.contains("Command `foo` not found")); } #[test] diff --git a/tests/shell/pipeline/commands/internal.rs b/tests/shell/pipeline/commands/internal.rs index 6c2226ff65..67d4ee31a9 100644 --- a/tests/shell/pipeline/commands/internal.rs +++ b/tests/shell/pipeline/commands/internal.rs @@ -989,7 +989,9 @@ fn hide_alias_hides_alias() { " )); - assert!(actual.err.contains("did you mean 'all'?")); + assert!( + actual.err.contains("Command `ll` not found") && actual.err.contains("Did you mean `all`?") + ); } mod parse { @@ -1035,7 +1037,7 @@ mod parse { fn ensure_backticks_are_bareword_command() { let actual = nu!("`8abc123`"); - assert!(actual.err.contains("was not found"),); + assert!(actual.err.contains("Command `8abc123` not found"),); } } @@ -1146,5 +1148,8 @@ fn command_not_found_error_shows_not_found_2() { export def --wrapped my-foo [...rest] { foo }; my-foo "#); - assert!(actual.err.contains("did you mean")); + assert!( + actual.err.contains("Command `foo` not found") + && actual.err.contains("Did you mean `for`?") + ); } From 58cf0c56f8cefc3c1bf9d4a39d3fdb19890b8681 Mon Sep 17 00:00:00 2001 From: Wind Date: Thu, 23 May 2024 10:47:06 +0800 Subject: [PATCH 013/113] add some completion tests (#12908) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description ```nushell ❯ ls ╭───┬───────┬──────┬──────┬──────────╮ │ # │ name │ type │ size │ modified │ ├───┼───────┼──────┼──────┼──────────┤ │ 0 │ a.txt │ file │ 0 B │ now │ ╰───┴───────┴──────┴──────┴──────────╯ ❯ ls a. NO RECORDS FOUND ``` There is a completion issue on previous version, I think @amtoine have reproduced it before. But currently I can't reproduce it on latest main. To avoid such regression, I added some tests for completion. --------- Co-authored-by: Antoine Stevan <44101798+amtoine@users.noreply.github.com> --- crates/nu-cli/tests/completions/mod.rs | 46 +++++++++++++++++++ .../partial_a/have_ext.exe | 0 .../partial_a/have_ext.txt | 0 3 files changed, 46 insertions(+) create mode 100644 tests/fixtures/partial_completions/partial_a/have_ext.exe create mode 100644 tests/fixtures/partial_completions/partial_a/have_ext.txt diff --git a/crates/nu-cli/tests/completions/mod.rs b/crates/nu-cli/tests/completions/mod.rs index a3eb692adf..eb245e2fb2 100644 --- a/crates/nu-cli/tests/completions/mod.rs +++ b/crates/nu-cli/tests/completions/mod.rs @@ -292,6 +292,8 @@ fn partial_completions() { // Create the expected values let expected_paths: Vec = vec![ + file(dir.join("partial_a").join("have_ext.exe")), + file(dir.join("partial_a").join("have_ext.txt")), file(dir.join("partial_a").join("hello")), file(dir.join("partial_a").join("hola")), file(dir.join("partial_b").join("hello_b")), @@ -310,6 +312,8 @@ fn partial_completions() { // Create the expected values let expected_paths: Vec = vec![ file(dir.join("partial_a").join("anotherfile")), + file(dir.join("partial_a").join("have_ext.exe")), + file(dir.join("partial_a").join("have_ext.txt")), file(dir.join("partial_a").join("hello")), file(dir.join("partial_a").join("hola")), file(dir.join("partial_b").join("hello_b")), @@ -360,6 +364,34 @@ fn partial_completions() { // Match the results match_suggestions(expected_paths, suggestions); + + // Test completion for all files under directories whose names begin with "pa" + let file_str = file(dir.join("partial_a").join("have")); + let target_file = format!("rm {file_str}"); + let suggestions = completer.complete(&target_file, target_file.len()); + + // Create the expected values + let expected_paths: Vec = vec![ + file(dir.join("partial_a").join("have_ext.exe")), + file(dir.join("partial_a").join("have_ext.txt")), + ]; + + // Match the results + match_suggestions(expected_paths, suggestions); + + // Test completion for all files under directories whose names begin with "pa" + let file_str = file(dir.join("partial_a").join("have_ext.")); + let file_dir = format!("rm {file_str}"); + let suggestions = completer.complete(&file_dir, file_dir.len()); + + // Create the expected values + let expected_paths: Vec = vec![ + file(dir.join("partial_a").join("have_ext.exe")), + file(dir.join("partial_a").join("have_ext.txt")), + ]; + + // Match the results + match_suggestions(expected_paths, suggestions); } #[test] @@ -394,6 +426,13 @@ fn command_ls_with_filecompletion() { ".hidden_folder/".to_string(), ]; + match_suggestions(expected_paths, suggestions); + + let target_dir = "ls custom_completion."; + let suggestions = completer.complete(target_dir, target_dir.len()); + + let expected_paths: Vec = vec!["custom_completion.nu".to_string()]; + match_suggestions(expected_paths, suggestions) } #[test] @@ -428,6 +467,13 @@ fn command_open_with_filecompletion() { ".hidden_folder/".to_string(), ]; + match_suggestions(expected_paths, suggestions); + + let target_dir = "open custom_completion."; + let suggestions = completer.complete(target_dir, target_dir.len()); + + let expected_paths: Vec = vec!["custom_completion.nu".to_string()]; + match_suggestions(expected_paths, suggestions) } diff --git a/tests/fixtures/partial_completions/partial_a/have_ext.exe b/tests/fixtures/partial_completions/partial_a/have_ext.exe new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/fixtures/partial_completions/partial_a/have_ext.txt b/tests/fixtures/partial_completions/partial_a/have_ext.txt new file mode 100644 index 0000000000..e69de29bb2 From c7097ca93761ea2062fef2271ebbdc4a10d67bce Mon Sep 17 00:00:00 2001 From: Reilly Wood <26268125+rgwood@users.noreply.github.com> Date: Wed, 22 May 2024 20:06:14 -0700 Subject: [PATCH 014/113] `explore` cleanup: remove+move binary viewer config (#12920) Small change, removing 4 more configuration options from `explore`'s binary viewer: 1. `show_index` 2. `show_data` 3. `show_ascii` 4. `show_split` These controlled whether the 3 columns in the binary viewer (index, hex data, ASCII) and the pipe separator (`|`) in between them are shown. I don't think we need this level of configurability until the `explore` command is more mature, and maybe even not then; we can just show them all. I think it's very unlikely that anyone is using these configuration points. Also, the row offset (e.g. how many rows we have scrolled down) was being stored in config/settings when it's arguably not config; more like internal state of the binary viewer. I moved it to a more appropriate location and renamed it. --- .../src/views/binary/binary_widget.rs | 135 +++++++----------- crates/nu-explore/src/views/binary/mod.rs | 14 +- 2 files changed, 52 insertions(+), 97 deletions(-) diff --git a/crates/nu-explore/src/views/binary/binary_widget.rs b/crates/nu-explore/src/views/binary/binary_widget.rs index bee4e9d854..d100774be5 100644 --- a/crates/nu-explore/src/views/binary/binary_widget.rs +++ b/crates/nu-explore/src/views/binary/binary_widget.rs @@ -20,11 +20,17 @@ pub struct BinaryWidget<'a> { data: &'a [u8], opts: BinarySettings, style: BinaryStyle, + row_offset: usize, } impl<'a> BinaryWidget<'a> { pub fn new(data: &'a [u8], opts: BinarySettings, style: BinaryStyle) -> Self { - Self { data, opts, style } + Self { + data, + opts, + style, + row_offset: 0, + } } pub fn count_lines(&self) -> usize { @@ -35,37 +41,22 @@ impl<'a> BinaryWidget<'a> { self.opts.count_segments * self.opts.segment_size } - pub fn set_index_offset(&mut self, offset: usize) { - self.opts.index_offset = offset; + pub fn set_row_offset(&mut self, offset: usize) { + self.row_offset = offset; } } #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] pub struct BinarySettings { - disable_index: bool, - disable_ascii: bool, - disable_data: bool, segment_size: usize, count_segments: usize, - index_offset: usize, } impl BinarySettings { - pub fn new( - disable_index: bool, - disable_ascii: bool, - disable_data: bool, - segment_size: usize, - count_segments: usize, - index_offset: usize, - ) -> Self { + pub fn new(segment_size: usize, count_segments: usize) -> Self { Self { - disable_index, - disable_ascii, - disable_data, segment_size, count_segments, - index_offset, } } } @@ -75,7 +66,6 @@ pub struct BinaryStyle { color_index: Option, column_padding_left: u16, column_padding_right: u16, - show_split: bool, } impl BinaryStyle { @@ -83,13 +73,11 @@ impl BinaryStyle { color_index: Option, column_padding_left: u16, column_padding_right: u16, - show_split: bool, ) -> Self { Self { color_index, column_padding_left, column_padding_right, - show_split, } } } @@ -102,10 +90,6 @@ impl Widget for BinaryWidget<'_> { return; } - if self.opts.disable_index && self.opts.disable_data && self.opts.disable_ascii { - return; - } - render_hexdump(area, buf, self); } } @@ -114,11 +98,6 @@ impl Widget for BinaryWidget<'_> { fn render_hexdump(area: Rect, buf: &mut Buffer, w: BinaryWidget) { const MIN_INDEX_SIZE: usize = 8; - let show_index = !w.opts.disable_index; - let show_data = !w.opts.disable_data; - let show_ascii = !w.opts.disable_ascii; - let show_split = w.style.show_split; - let index_width = get_max_index_size(&w).max(MIN_INDEX_SIZE) as u16; // safe as it's checked before hand that we have enough space let mut last_line = None; @@ -126,7 +105,7 @@ fn render_hexdump(area: Rect, buf: &mut Buffer, w: BinaryWidget) { for line in 0..area.height { let data_line_length = w.opts.count_segments * w.opts.segment_size; let start_index = line as usize * data_line_length; - let address = w.opts.index_offset + start_index; + let address = w.row_offset + start_index; if start_index > w.data.len() { last_line = Some(line); @@ -137,31 +116,24 @@ fn render_hexdump(area: Rect, buf: &mut Buffer, w: BinaryWidget) { let y = line; let line = &w.data[start_index..]; - if show_index { - x += render_space(buf, x, y, 1, w.style.column_padding_left); - x += render_hex_usize(buf, x, y, address, index_width, get_index_style(&w)); - x += render_space(buf, x, y, 1, w.style.column_padding_right); - } + // index column + x += render_space(buf, x, y, 1, w.style.column_padding_left); + x += render_hex_usize(buf, x, y, address, index_width, get_index_style(&w)); + x += render_space(buf, x, y, 1, w.style.column_padding_right); - if show_split { - x += render_split(buf, x, y); - } + x += render_vertical_split(buf, x, y); - if show_data { - x += render_space(buf, x, y, 1, w.style.column_padding_left); - x += render_data_line(buf, x, y, line, &w); - x += render_space(buf, x, y, 1, w.style.column_padding_right); - } + // data/hex column + x += render_space(buf, x, y, 1, w.style.column_padding_left); + x += render_data_line(buf, x, y, line, &w); + x += render_space(buf, x, y, 1, w.style.column_padding_right); - if show_split { - x += render_split(buf, x, y); - } + x += render_vertical_split(buf, x, y); - if show_ascii { - x += render_space(buf, x, y, 1, w.style.column_padding_left); - x += render_ascii_line(buf, x, y, line, &w); - render_space(buf, x, y, 1, w.style.column_padding_right); - } + // ASCII column + x += render_space(buf, x, y, 1, w.style.column_padding_left); + x += render_ascii_line(buf, x, y, line, &w); + render_space(buf, x, y, 1, w.style.column_padding_right); } let data_line_size = (w.opts.count_segments * (w.opts.segment_size * 2) @@ -172,36 +144,29 @@ fn render_hexdump(area: Rect, buf: &mut Buffer, w: BinaryWidget) { for line in last_line..area.height { let data_line_length = w.opts.count_segments * w.opts.segment_size; let start_index = line as usize * data_line_length; - let address = w.opts.index_offset + start_index; + let address = w.row_offset + start_index; let mut x = 0; let y = line; - if show_index { - x += render_space(buf, x, y, 1, w.style.column_padding_left); - x += render_hex_usize(buf, x, y, address, index_width, get_index_style(&w)); - x += render_space(buf, x, y, 1, w.style.column_padding_right); - } + // index column + x += render_space(buf, x, y, 1, w.style.column_padding_left); + x += render_hex_usize(buf, x, y, address, index_width, get_index_style(&w)); + x += render_space(buf, x, y, 1, w.style.column_padding_right); - if show_split { - x += render_split(buf, x, y); - } + x += render_vertical_split(buf, x, y); - if show_data { - x += render_space(buf, x, y, 1, w.style.column_padding_left); - x += render_space(buf, x, y, 1, data_line_size); - x += render_space(buf, x, y, 1, w.style.column_padding_right); - } + // data/hex column + x += render_space(buf, x, y, 1, w.style.column_padding_left); + x += render_space(buf, x, y, 1, data_line_size); + x += render_space(buf, x, y, 1, w.style.column_padding_right); - if show_split { - x += render_split(buf, x, y); - } + x += render_vertical_split(buf, x, y); - if show_ascii { - x += render_space(buf, x, y, 1, w.style.column_padding_left); - x += render_space(buf, x, y, 1, ascii_line_size); - render_space(buf, x, y, 1, w.style.column_padding_right); - } + // ASCII column + x += render_space(buf, x, y, 1, w.style.column_padding_left); + x += render_space(buf, x, y, 1, ascii_line_size); + render_space(buf, x, y, 1, w.style.column_padding_right); } } } @@ -336,12 +301,15 @@ fn get_index_style(w: &BinaryWidget) -> Option { w.style.color_index } -fn render_space(buf: &mut Buffer, x: u16, y: u16, height: u16, padding: u16) -> u16 { - repeat_vertical(buf, x, y, padding, height, ' ', TextStyle::default()); - padding +/// Render blank characters starting at the given position, going right `width` characters and down `height` characters. +/// Returns `width` for convenience. +fn render_space(buf: &mut Buffer, x: u16, y: u16, height: u16, width: u16) -> u16 { + repeat_vertical(buf, x, y, width, height, ' ', TextStyle::default()); + width } -fn render_split(buf: &mut Buffer, x: u16, y: u16) -> u16 { +/// Render a vertical split (│) at the given position. Returns the width of the split (always 1) for convenience. +fn render_vertical_split(buf: &mut Buffer, x: u16, y: u16) -> u16 { repeat_vertical(buf, x, y, 1, 1, '│', TextStyle::default()); 1 } @@ -369,7 +337,7 @@ fn repeat_vertical( fn get_max_index_size(w: &BinaryWidget) -> usize { let line_size = w.opts.count_segments * (w.opts.segment_size * 2); let count_lines = w.data.len() / line_size; - let max_index = w.opts.index_offset + count_lines * line_size; + let max_index = w.row_offset + count_lines * line_size; usize_to_hex(max_index, 0).len() } @@ -379,7 +347,7 @@ fn get_widget_width(w: &BinaryWidget) -> usize { let line_size = w.opts.count_segments * (w.opts.segment_size * 2); let count_lines = w.data.len() / line_size; - let max_index = w.opts.index_offset + count_lines * line_size; + let max_index = w.row_offset + count_lines * line_size; let index_size = usize_to_hex(max_index, 0).len(); let index_size = index_size.max(MIN_INDEX_SIZE); @@ -388,17 +356,16 @@ fn get_widget_width(w: &BinaryWidget) -> usize { let ascii_size = w.opts.count_segments * w.opts.segment_size; - let split = w.style.show_split as usize; #[allow(clippy::identity_op)] let min_width = 0 + w.style.column_padding_left as usize + index_size + w.style.column_padding_right as usize - + split + + 1 // split + w.style.column_padding_left as usize + data_size + w.style.column_padding_right as usize - + split + + 1 //split + w.style.column_padding_left as usize + ascii_size + w.style.column_padding_right as usize; diff --git a/crates/nu-explore/src/views/binary/mod.rs b/crates/nu-explore/src/views/binary/mod.rs index 31ea0d6eaf..7e44a3985e 100644 --- a/crates/nu-explore/src/views/binary/mod.rs +++ b/crates/nu-explore/src/views/binary/mod.rs @@ -107,7 +107,7 @@ fn create_binary_widget(v: &BinaryView) -> BinaryWidget<'_> { let data = &v.data[index..]; let mut w = BinaryWidget::new(data, v.settings.opts, v.settings.style.clone()); - w.set_index_offset(index); + w.set_row_offset(index); w } @@ -184,29 +184,17 @@ fn settings_from_config(config: &ConfigMap) -> Settings { Settings { opts: BinarySettings::new( - !config_get_bool(config, "show_index", true), - !config_get_bool(config, "show_ascii", true), - !config_get_bool(config, "show_data", true), config_get_usize(config, "segment_size", 2), config_get_usize(config, "count_segments", 8), - 0, ), style: BinaryStyle::new( colors.get("color_index").cloned(), config_get_usize(config, "column_padding_left", 1) as u16, config_get_usize(config, "column_padding_right", 1) as u16, - config_get_bool(config, "split", false), ), } } -fn config_get_bool(config: &ConfigMap, key: &str, default: bool) -> bool { - config - .get(key) - .and_then(|v| v.as_bool().ok()) - .unwrap_or(default) -} - fn config_get_usize(config: &ConfigMap, key: &str, default: usize) -> usize { config .get(key) From 2612a167e31fce874a7faaaecf2222a38c03c6c8 Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Thu, 23 May 2024 05:53:55 +0000 Subject: [PATCH 015/113] Remove list support in `with-env` (#12939) # Description Following from #12523, this PR removes support for lists of environments variables in the `with-env` command. Rather, only records will be supported now. # After Submitting Update examples using the list form in the docs and book. --- crates/nu-command/src/env/with_env.rs | 69 +-------------------------- 1 file changed, 2 insertions(+), 67 deletions(-) diff --git a/crates/nu-command/src/env/with_env.rs b/crates/nu-command/src/env/with_env.rs index ff66d21f49..46f7d1eb6e 100644 --- a/crates/nu-command/src/env/with_env.rs +++ b/crates/nu-command/src/env/with_env.rs @@ -1,6 +1,5 @@ use nu_engine::{command_prelude::*, eval_block}; use nu_protocol::{debugger::WithoutDebug, engine::Closure}; -use std::collections::HashMap; #[derive(Clone)] pub struct WithEnv; @@ -58,78 +57,14 @@ fn with_env( call: &Call, input: PipelineData, ) -> Result { - let variable: Value = call.req(engine_state, stack, 0)?; - + let env: Record = call.req(engine_state, stack, 0)?; let capture_block: Closure = call.req(engine_state, stack, 1)?; let block = engine_state.get_block(capture_block.block_id); let mut stack = stack.captures_to_stack_preserve_out_dest(capture_block.captures); - let mut env: HashMap = HashMap::new(); - - match &variable { - Value::List { vals: table, .. } => { - nu_protocol::report_error_new( - engine_state, - &ShellError::GenericError { - error: "Deprecated argument type".into(), - msg: "providing the variables to `with-env` as a list or single row table has been deprecated".into(), - span: Some(variable.span()), - help: Some("use the record form instead".into()), - inner: vec![], - }, - ); - if table.len() == 1 { - // single row([[X W]; [Y Z]]) - match &table[0] { - Value::Record { val, .. } => { - for (k, v) in &**val { - env.insert(k.to_string(), v.clone()); - } - } - x => { - return Err(ShellError::CantConvert { - to_type: "record".into(), - from_type: x.get_type().to_string(), - span: x.span(), - help: None, - }); - } - } - } else { - // primitive values([X Y W Z]) - for row in table.chunks(2) { - if row.len() == 2 { - env.insert(row[0].coerce_string()?, row[1].clone()); - } - if row.len() == 1 { - return Err(ShellError::IncorrectValue { - msg: format!("Missing value for $env.{}", row[0].coerce_string()?), - val_span: row[0].span(), - call_span: call.head, - }); - } - } - } - } - // when get object by `open x.json` or `from json` - Value::Record { val, .. } => { - for (k, v) in &**val { - env.insert(k.clone(), v.clone()); - } - } - x => { - return Err(ShellError::CantConvert { - to_type: "record".into(), - from_type: x.get_type().to_string(), - span: x.span(), - help: None, - }); - } - }; - // TODO: factor list of prohibited env vars into common place for prohibited in ["PWD", "FILE_PWD", "CURRENT_FILE"] { - if env.contains_key(prohibited) { + if env.contains(prohibited) { return Err(ShellError::AutomaticEnvVarSetManually { envvar_name: prohibited.into(), span: call.head, From f53aa6fcbfe53563d8e04d5f3717c5890860f5da Mon Sep 17 00:00:00 2001 From: Wind Date: Thu, 23 May 2024 21:51:02 +0800 Subject: [PATCH 016/113] fix std help (#12943) # Description Fixes: #12941 ~~The issue is cause by some columns(is_builtin, is_plugin, is_custom, is_keyword) are removed in #10023~~ Edit: I'm wrong # Tests + Formatting Added one test for `std help` --- crates/nu-std/std/help.nu | 10 +++++----- crates/nu-std/tests/test_help.nu | 9 +++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 crates/nu-std/tests/test_help.nu diff --git a/crates/nu-std/std/help.nu b/crates/nu-std/std/help.nu index 20a672dd90..df6c4c6ca6 100644 --- a/crates/nu-std/std/help.nu +++ b/crates/nu-std/std/help.nu @@ -515,7 +515,7 @@ def build-command-page [command: record] { $"- (ansi cyan)does not create(ansi reset) a scope." } ) | append ( - if ($command.is_builtin) { + if ($command.type == "built-in") { $"- (ansi cyan)is(ansi reset) a built-in command." } else { $"- (ansi cyan)is not(ansi reset) a built-in command." @@ -527,19 +527,19 @@ def build-command-page [command: record] { $"- (ansi cyan)is not(ansi reset) a subcommand." } ) | append ( - if ($command.is_plugin) { + if ($command.type == "plugin") { $"- (ansi cyan)is part(ansi reset) of a plugin." } else { $"- (ansi cyan)is not part(ansi reset) of a plugin." } ) | append ( - if ($command.is_custom) { + if ($command.type == "custom") { $"- (ansi cyan)is(ansi reset) a custom command." } else { $"- (ansi cyan)is not(ansi reset) a custom command." } ) | append ( - if ($command.is_keyword) { + if ($command.type == "keyword") { $"- (ansi cyan)is(ansi reset) a keyword." } else { $"- (ansi cyan)is not(ansi reset) a keyword." @@ -689,7 +689,7 @@ export def commands [ ...command: string@"nu-complete list-commands" # the name of command to get help on --find (-f): string # string to find in command names and usage ] { - let commands = (scope commands | where not is_extern | reject is_extern | sort-by name) + let commands = (scope commands | sort-by name) if not ($find | is-empty) { # TODO: impl find for external commands diff --git a/crates/nu-std/tests/test_help.nu b/crates/nu-std/tests/test_help.nu new file mode 100644 index 0000000000..1608950886 --- /dev/null +++ b/crates/nu-std/tests/test_help.nu @@ -0,0 +1,9 @@ +use std assert +use std help + +#[test] +def show_help_on_commands [] { + let help_result = (help alias) + assert ("item not found" not-in $help_result) +} + From 0b5a4c0d951622e60c318ecaa66f15ab2c80eeaa Mon Sep 17 00:00:00 2001 From: Reilly Wood <26268125+rgwood@users.noreply.github.com> Date: Thu, 23 May 2024 06:51:39 -0700 Subject: [PATCH 017/113] `explore` refactoring+clarification (#12940) Another very boring PR cleaning up and documenting some of `explore`'s innards. Mostly renaming things that I found confusing or vague when reading through the code, also adding some comments. --- ...coloredtextw.rs => colored_text_widget.rs} | 13 ++-- crates/nu-explore/src/views/mod.rs | 2 +- crates/nu-explore/src/views/preview.rs | 11 +-- crates/nu-explore/src/views/record/mod.rs | 12 ++-- .../record/{tablew.rs => table_widget.rs} | 68 +++++++++---------- 5 files changed, 55 insertions(+), 51 deletions(-) rename crates/nu-explore/src/views/{coloredtextw.rs => colored_text_widget.rs} (89%) rename crates/nu-explore/src/views/record/{tablew.rs => table_widget.rs} (92%) diff --git a/crates/nu-explore/src/views/coloredtextw.rs b/crates/nu-explore/src/views/colored_text_widget.rs similarity index 89% rename from crates/nu-explore/src/views/coloredtextw.rs rename to crates/nu-explore/src/views/colored_text_widget.rs index 93ef68f38f..4b1398e713 100644 --- a/crates/nu-explore/src/views/coloredtextw.rs +++ b/crates/nu-explore/src/views/colored_text_widget.rs @@ -8,24 +8,27 @@ use ratatui::{ widgets::Widget, }; -pub struct ColoredTextW<'a> { +/// A widget that represents a single line of text with ANSI styles. +pub struct ColoredTextWidget<'a> { text: &'a str, + /// Column to start rendering from col: usize, } -impl<'a> ColoredTextW<'a> { +impl<'a> ColoredTextWidget<'a> { pub fn new(text: &'a str, col: usize) -> Self { Self { text, col } } - pub fn what(&self, area: Rect) -> String { - cut_string(self.text, self.col, area.width as usize) + /// Return a window of the text that fits into the given width, with ANSI styles stripped. + pub fn get_plain_text(&self, max_width: usize) -> String { + cut_string(self.text, self.col, max_width) .ansi_strip() .into_owned() } } -impl Widget for ColoredTextW<'_> { +impl Widget for ColoredTextWidget<'_> { fn render(self, area: Rect, buf: &mut ratatui::buffer::Buffer) { let text = cut_string(self.text, self.col, area.width as usize); diff --git a/crates/nu-explore/src/views/mod.rs b/crates/nu-explore/src/views/mod.rs index 3226f546d2..dd0a4a3339 100644 --- a/crates/nu-explore/src/views/mod.rs +++ b/crates/nu-explore/src/views/mod.rs @@ -1,5 +1,5 @@ mod binary; -mod coloredtextw; +mod colored_text_widget; mod cursor; mod interactive; mod preview; diff --git a/crates/nu-explore/src/views/preview.rs b/crates/nu-explore/src/views/preview.rs index 2bd495144b..360cfbd226 100644 --- a/crates/nu-explore/src/views/preview.rs +++ b/crates/nu-explore/src/views/preview.rs @@ -1,4 +1,4 @@ -use super::{coloredtextw::ColoredTextW, cursor::XYCursor, Layout, View, ViewConfig}; +use super::{colored_text_widget::ColoredTextWidget, cursor::XYCursor, Layout, View, ViewConfig}; use crate::{ nu_common::{NuSpan, NuText}, pager::{report::Report, Frame, Transition, ViewInfo}, @@ -43,13 +43,14 @@ impl View for Preview { let lines = &self.lines[self.cursor.row_starts_at()..]; for (i, line) in lines.iter().enumerate().take(area.height as usize) { - let text = ColoredTextW::new(line, self.cursor.column()); - let s = text.what(area); + let text_widget = ColoredTextWidget::new(line, self.cursor.column()); + let plain_text = text_widget.get_plain_text(area.width as usize); let area = Rect::new(area.x, area.y + i as u16, area.width, 1); - f.render_widget(text, area); + f.render_widget(text_widget, area); - layout.push(&s, area.x, area.y, area.width, area.height); + // push the plain text to layout so it can be searched + layout.push(&plain_text, area.x, area.y, area.width, area.height); } } diff --git a/crates/nu-explore/src/views/record/mod.rs b/crates/nu-explore/src/views/record/mod.rs index 2ad3140bf4..5bd74c2329 100644 --- a/crates/nu-explore/src/views/record/mod.rs +++ b/crates/nu-explore/src/views/record/mod.rs @@ -1,6 +1,6 @@ -mod tablew; +mod table_widget; -use self::tablew::{TableStyle, TableW, TableWState}; +use self::table_widget::{TableStyle, TableWidget, TableWidgetState}; use super::{ cursor::XYCursor, util::{make_styled_string, nu_style_to_tui}, @@ -25,7 +25,7 @@ use nu_protocol::{ use ratatui::{layout::Rect, widgets::Block}; use std::{borrow::Cow, collections::HashMap}; -pub use self::tablew::Orientation; +pub use self::table_widget::Orientation; #[derive(Debug, Clone)] pub struct RecordView<'a> { @@ -175,7 +175,7 @@ impl<'a> RecordView<'a> { } } - fn create_tablew(&'a self, cfg: ViewConfig<'a>) -> TableW<'a> { + fn create_tablew(&'a self, cfg: ViewConfig<'a>) -> TableWidget<'a> { let layer = self.get_layer_last(); let mut data = convert_records_to_string(&layer.records, cfg.nu_config, cfg.style_computer); @@ -185,7 +185,7 @@ impl<'a> RecordView<'a> { let style_computer = cfg.style_computer; let (row, column) = self.get_current_offset(); - TableW::new( + TableWidget::new( headers, data, style_computer, @@ -225,7 +225,7 @@ impl<'a> RecordView<'a> { impl View for RecordView<'_> { fn draw(&mut self, f: &mut Frame, area: Rect, cfg: ViewConfig<'_>, layout: &mut Layout) { - let mut table_layout = TableWState::default(); + let mut table_layout = TableWidgetState::default(); let table = self.create_tablew(cfg); f.render_stateful_widget(table, area, &mut table_layout); diff --git a/crates/nu-explore/src/views/record/tablew.rs b/crates/nu-explore/src/views/record/table_widget.rs similarity index 92% rename from crates/nu-explore/src/views/record/tablew.rs rename to crates/nu-explore/src/views/record/table_widget.rs index b4b4fe4514..70debfd888 100644 --- a/crates/nu-explore/src/views/record/tablew.rs +++ b/crates/nu-explore/src/views/record/table_widget.rs @@ -18,13 +18,13 @@ use std::{ }; #[derive(Debug, Clone)] -pub struct TableW<'a> { +pub struct TableWidget<'a> { columns: Cow<'a, [String]>, data: Cow<'a, [Vec]>, index_row: usize, index_column: usize, style: TableStyle, - head_position: Orientation, + header_position: Orientation, style_computer: &'a StyleComputer<'a>, } @@ -38,14 +38,13 @@ pub enum Orientation { #[derive(Debug, Default, Clone, Copy)] pub struct TableStyle { pub splitline_style: NuStyle, - pub shift_line_style: NuStyle, pub show_index: bool, pub show_header: bool, pub column_padding_left: usize, pub column_padding_right: usize, } -impl<'a> TableW<'a> { +impl<'a> TableWidget<'a> { #[allow(clippy::too_many_arguments)] pub fn new( columns: impl Into>, @@ -54,7 +53,7 @@ impl<'a> TableW<'a> { index_row: usize, index_column: usize, style: TableStyle, - head_position: Orientation, + header_position: Orientation, ) -> Self { Self { columns: columns.into(), @@ -63,21 +62,21 @@ impl<'a> TableW<'a> { index_row, index_column, style, - head_position, + header_position, } } } #[derive(Debug, Default)] -pub struct TableWState { +pub struct TableWidgetState { pub layout: Layout, pub count_rows: usize, pub count_columns: usize, pub data_height: u16, } -impl StatefulWidget for TableW<'_> { - type State = TableWState; +impl StatefulWidget for TableWidget<'_> { + type State = TableWidgetState; fn render( self, @@ -89,7 +88,7 @@ impl StatefulWidget for TableW<'_> { return; } - let is_horizontal = matches!(self.head_position, Orientation::Top); + let is_horizontal = matches!(self.header_position, Orientation::Top); if is_horizontal { self.render_table_horizontal(area, buf, state); } else { @@ -99,8 +98,8 @@ impl StatefulWidget for TableW<'_> { } // todo: refactoring these to methods as they have quite a bit in common. -impl<'a> TableW<'a> { - fn render_table_horizontal(self, area: Rect, buf: &mut Buffer, state: &mut TableWState) { +impl<'a> TableWidget<'a> { + fn render_table_horizontal(self, area: Rect, buf: &mut Buffer, state: &mut TableWidgetState) { let padding_l = self.style.column_padding_left as u16; let padding_r = self.style.column_padding_right as u16; @@ -108,7 +107,6 @@ impl<'a> TableW<'a> { let show_head = self.style.show_header; let splitline_s = self.style.splitline_style; - let shift_column_s = self.style.shift_line_style; let mut data_height = area.height; let mut data_y = area.y; @@ -164,7 +162,8 @@ impl<'a> TableW<'a> { ); } - let mut do_render_shift_column = false; + // if there is more data than we can show, add an ellipsis to the column headers to hint at that + let mut show_overflow_indicator = false; state.count_rows = data.len(); state.count_columns = 0; state.data_height = data_height; @@ -191,11 +190,11 @@ impl<'a> TableW<'a> { let pad = padding_l + padding_r; let head = show_head.then_some(&mut head); - let (w, ok, shift) = + let (w, ok, overflow) = truncate_column_width(space, 1, use_space, pad, is_last, &mut column, head); - if shift { - do_render_shift_column = true; + if overflow { + show_overflow_indicator = true; } if w == 0 && !ok { @@ -232,14 +231,14 @@ impl<'a> TableW<'a> { state.count_columns += 1; - if do_render_shift_column { + if show_overflow_indicator { break; } } - if do_render_shift_column && show_head { + if show_overflow_indicator && show_head { width += render_space(buf, width, data_y, data_height, padding_l); - width += render_shift_column(buf, width, head_y, 1, shift_column_s); + width += render_overflow_column(buf, width, head_y, 1); width += render_space(buf, width, data_y, data_height, padding_r); } @@ -264,7 +263,7 @@ impl<'a> TableW<'a> { } } - fn render_table_vertical(self, area: Rect, buf: &mut Buffer, state: &mut TableWState) { + fn render_table_vertical(self, area: Rect, buf: &mut Buffer, state: &mut TableWidgetState) { if area.width == 0 || area.height == 0 { return; } @@ -275,7 +274,6 @@ impl<'a> TableW<'a> { let show_index = self.style.show_index; let show_head = self.style.show_header; let splitline_s = self.style.splitline_style; - let shift_column_s = self.style.shift_line_style; let mut left_w = 0; @@ -358,7 +356,8 @@ impl<'a> TableW<'a> { ); } - let mut do_render_shift_column = false; + // if there is more data than we can show, add an ellipsis to the column headers to hint at that + let mut show_overflow_indicator = false; state.count_rows = columns.len(); state.count_columns = 0; @@ -375,11 +374,11 @@ impl<'a> TableW<'a> { let available = area.width - left_w; let is_last = col + 1 == self.data.len(); let pad = padding_l + padding_r; - let (column_width, ok, shift) = + let (column_width, ok, overflow) = truncate_column_width(available, 1, column_width, pad, is_last, &mut column, None); - if shift { - do_render_shift_column = true; + if overflow { + show_overflow_indicator = true; } if column_width == 0 && !ok { @@ -403,16 +402,16 @@ impl<'a> TableW<'a> { state.count_columns += 1; } - if do_render_shift_column { + if show_overflow_indicator { break; } } - if do_render_shift_column { + if show_overflow_indicator { let x = area.x + left_w; left_w += render_space(buf, x, area.y, area.height, padding_l); let x = area.x + left_w; - left_w += render_shift_column(buf, x, area.y, area.height, shift_column_s); + left_w += render_overflow_column(buf, x, area.y, area.height); let x = area.x + left_w; left_w += render_space(buf, x, area.y, area.height, padding_r); } @@ -433,13 +432,13 @@ fn truncate_column_width( ) -> (u16, bool, bool) { let result = check_column_width(space, min, w, pad, is_last); - let (width, shift_column) = match result { + let (width, overflow) = match result { Some(result) => result, None => return (w, true, false), }; if width == 0 { - return (0, false, shift_column); + return (0, false, overflow); } truncate_list(column, width as usize); @@ -447,7 +446,7 @@ fn truncate_column_width( truncate_str(head, width as usize); } - (width, false, shift_column) + (width, false, overflow) } fn check_column_width( @@ -652,10 +651,11 @@ fn truncate_list(list: &mut [NuText], width: usize) { } } -fn render_shift_column(buf: &mut Buffer, x: u16, y: u16, height: u16, style: NuStyle) -> u16 { +/// Render a column with an ellipsis in the header to indicate that there is more data than can be displayed +fn render_overflow_column(buf: &mut Buffer, x: u16, y: u16, height: u16) -> u16 { let style = TextStyle { alignment: Alignment::Left, - color_style: Some(style), + color_style: None, }; repeat_vertical(buf, x, y, 1, height, '…', style); From bf07806b1bc96eebcaa57456c97035a6bce68ef7 Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Thu, 23 May 2024 20:38:47 +0000 Subject: [PATCH 018/113] Use `cwd` in `grid` (#12947) # Description Fixes #12946. The `grid` command does not use the cwd when trying to get the icon or color for a file/path. --- crates/nu-command/src/viewers/griddle.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/crates/nu-command/src/viewers/griddle.rs b/crates/nu-command/src/viewers/griddle.rs index e0856e0a70..8b39bf5649 100644 --- a/crates/nu-command/src/viewers/griddle.rs +++ b/crates/nu-command/src/viewers/griddle.rs @@ -5,6 +5,7 @@ use nu_engine::{command_prelude::*, env_to_string}; use nu_protocol::Config; use nu_term_grid::grid::{Alignment, Cell, Direction, Filling, Grid, GridOptions}; use nu_utils::get_ls_colors; +use std::path::Path; use terminal_size::{Height, Width}; #[derive(Clone)] @@ -67,6 +68,7 @@ prints out the list properly."# }; let use_grid_icons = config.use_grid_icons; let use_color: bool = color_param && config.use_ansi_coloring; + let cwd = engine_state.cwd(Some(stack))?; match input { PipelineData::Value(Value::List { vals, .. }, ..) => { @@ -81,6 +83,7 @@ prints out the list properly."# separator_param, env_str, use_grid_icons, + &cwd, )?) } else { Ok(PipelineData::empty()) @@ -98,6 +101,7 @@ prints out the list properly."# separator_param, env_str, use_grid_icons, + &cwd, )?) } else { // dbg!(data); @@ -120,6 +124,7 @@ prints out the list properly."# separator_param, env_str, use_grid_icons, + &cwd, )?) } x => { @@ -161,6 +166,7 @@ prints out the list properly."# } } +#[allow(clippy::too_many_arguments)] fn create_grid_output( items: Vec<(usize, String, String)>, call: &Call, @@ -169,6 +175,7 @@ fn create_grid_output( separator_param: Option, env_str: Option, use_grid_icons: bool, + cwd: &Path, ) -> Result { let ls_colors = get_ls_colors(env_str); @@ -196,8 +203,8 @@ fn create_grid_output( if use_color { if use_grid_icons { let no_ansi = nu_utils::strip_ansi_unlikely(&value); - let path = std::path::Path::new(no_ansi.as_ref()); - let icon = icon_for_file(path, call.head)?; + let path = cwd.join(no_ansi.as_ref()); + let icon = icon_for_file(&path, call.head)?; let ls_colors_style = ls_colors.style_for_path(path); let icon_style = match ls_colors_style { From 7d11c28eea72b940a1babc11fc17072b532f9a03 Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Fri, 24 May 2024 11:09:59 -0500 Subject: [PATCH 019/113] Revert "Remove `std::env::set_current_dir()` call from `EngineState::merge_env()`" (#12954) Reverts nushell/nushell#12922 --- crates/nu-cli/src/config_files.rs | 11 ++++- crates/nu-cli/src/repl.rs | 12 +++-- crates/nu-cli/tests/completions/mod.rs | 46 +++++++++---------- .../support/completions_helpers.rs | 9 ++-- crates/nu-cmd-base/src/hook.rs | 4 +- crates/nu-cmd-lang/src/example_support.rs | 2 +- crates/nu-protocol/src/engine/engine_state.rs | 9 +++- crates/nu-std/src/lib.rs | 3 +- src/config_files.rs | 22 +++++++-- src/test_bins.rs | 6 ++- 10 files changed, 83 insertions(+), 41 deletions(-) diff --git a/crates/nu-cli/src/config_files.rs b/crates/nu-cli/src/config_files.rs index 0684623226..ec7ad2f412 100644 --- a/crates/nu-cli/src/config_files.rs +++ b/crates/nu-cli/src/config_files.rs @@ -235,8 +235,15 @@ pub fn eval_config_contents( engine_state.file = prev_file; // Merge the environment in case env vars changed in the config - if let Err(e) = engine_state.merge_env(stack) { - report_error_new(engine_state, &e); + match engine_state.cwd(Some(stack)) { + Ok(cwd) => { + if let Err(e) = engine_state.merge_env(stack, cwd) { + report_error_new(engine_state, &e); + } + } + Err(e) => { + report_error_new(engine_state, &e); + } } } } diff --git a/crates/nu-cli/src/repl.rs b/crates/nu-cli/src/repl.rs index e79f41eb21..29c2f62734 100644 --- a/crates/nu-cli/src/repl.rs +++ b/crates/nu-cli/src/repl.rs @@ -15,7 +15,10 @@ use crate::{ use crossterm::cursor::SetCursorStyle; use log::{error, trace, warn}; use miette::{ErrReport, IntoDiagnostic, Result}; -use nu_cmd_base::{hook::eval_hook, util::get_editor}; +use nu_cmd_base::{ + hook::eval_hook, + util::{get_editor, get_guaranteed_cwd}, +}; use nu_color_config::StyleComputer; #[allow(deprecated)] use nu_engine::{convert_env_values, current_dir_str, env_to_strings}; @@ -115,7 +118,8 @@ pub fn evaluate_repl( PipelineData::empty(), false, ); - engine_state.merge_env(&mut unique_stack)?; + let cwd = get_guaranteed_cwd(engine_state, &unique_stack); + engine_state.merge_env(&mut unique_stack, cwd)?; } let hostname = System::host_name(); @@ -277,10 +281,12 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) { hostname, } = ctx; + let cwd = get_guaranteed_cwd(engine_state, &stack); + let mut start_time = std::time::Instant::now(); // Before doing anything, merge the environment from the previous REPL iteration into the // permanent state. - if let Err(err) = engine_state.merge_env(&mut stack) { + if let Err(err) = engine_state.merge_env(&mut stack, cwd) { report_error_new(engine_state, &err); } perf( diff --git a/crates/nu-cli/tests/completions/mod.rs b/crates/nu-cli/tests/completions/mod.rs index eb245e2fb2..a5b0b13aa8 100644 --- a/crates/nu-cli/tests/completions/mod.rs +++ b/crates/nu-cli/tests/completions/mod.rs @@ -18,11 +18,11 @@ use support::{ #[fixture] fn completer() -> NuCompleter { // Create a new engine - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Add record value as example let record = "def tst [--mod -s] {}"; - assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); // Instantiate a new completer NuCompleter::new(Arc::new(engine), Arc::new(stack)) @@ -31,12 +31,12 @@ fn completer() -> NuCompleter { #[fixture] fn completer_strings() -> NuCompleter { // Create a new engine - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Add record value as example let record = r#"def animals [] { ["cat", "dog", "eel" ] } def my-command [animal: string@animals] { print $animal }"#; - assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); // Instantiate a new completer NuCompleter::new(Arc::new(engine), Arc::new(stack)) @@ -45,7 +45,7 @@ fn completer_strings() -> NuCompleter { #[fixture] fn extern_completer() -> NuCompleter { // Create a new engine - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Add record value as example let record = r#" @@ -56,7 +56,7 @@ fn extern_completer() -> NuCompleter { -b: string@animals ] "#; - assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); // Instantiate a new completer NuCompleter::new(Arc::new(engine), Arc::new(stack)) @@ -65,7 +65,7 @@ fn extern_completer() -> NuCompleter { #[fixture] fn custom_completer() -> NuCompleter { // Create a new engine - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Add record value as example let record = r#" @@ -79,7 +79,7 @@ fn custom_completer() -> NuCompleter { completer: $external_completer } "#; - assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); // Instantiate a new completer NuCompleter::new(Arc::new(engine), Arc::new(stack)) @@ -751,11 +751,11 @@ fn folder_with_directorycompletions() { #[test] fn variables_completions() { // Create a new engine - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Add record value as example let record = "let actor = { name: 'Tom Hardy', age: 44 }"; - assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); // Instantiate a new completer let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack)); @@ -858,11 +858,11 @@ fn variables_completions() { #[test] fn alias_of_command_and_flags() { - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Create an alias let alias = r#"alias ll = ls -l"#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack)); @@ -877,11 +877,11 @@ fn alias_of_command_and_flags() { #[test] fn alias_of_basic_command() { - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Create an alias let alias = r#"alias ll = ls "#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack)); @@ -896,14 +896,14 @@ fn alias_of_basic_command() { #[test] fn alias_of_another_alias() { - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Create an alias let alias = r#"alias ll = ls -la"#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir.clone()).is_ok()); // Create the second alias let alias = r#"alias lf = ll -f"#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack)); @@ -920,7 +920,7 @@ fn run_external_completion(completer: &str, input: &str) -> Vec { let completer = format!("$env.config.completions.external.completer = {completer}"); // Create a new engine - let (_, _, mut engine_state, mut stack) = new_engine(); + let (dir, _, mut engine_state, mut stack) = new_engine(); let (block, delta) = { let mut working_set = StateWorkingSet::new(&engine_state); let block = parse(&mut working_set, None, completer.as_bytes(), false); @@ -936,7 +936,7 @@ fn run_external_completion(completer: &str, input: &str) -> Vec { ); // Merge environment into the permanent state - assert!(engine_state.merge_env(&mut stack).is_ok()); + assert!(engine_state.merge_env(&mut stack, &dir).is_ok()); // Instantiate a new completer let mut completer = NuCompleter::new(Arc::new(engine_state), Arc::new(stack)); @@ -1114,11 +1114,11 @@ fn custom_completer_triggers_cursor_after_word(mut custom_completer: NuCompleter #[ignore = "was reverted, still needs fixing"] #[rstest] fn alias_offset_bug_7648() { - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Create an alias let alias = r#"alias ea = ^$env.EDITOR /tmp/test.s"#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack)); @@ -1133,11 +1133,11 @@ fn alias_offset_bug_7648() { #[ignore = "was reverted, still needs fixing"] #[rstest] fn alias_offset_bug_7754() { - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Create an alias let alias = r#"alias ll = ls -l"#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack)); diff --git a/crates/nu-cli/tests/completions/support/completions_helpers.rs b/crates/nu-cli/tests/completions/support/completions_helpers.rs index df92979e23..47f46ab00e 100644 --- a/crates/nu-cli/tests/completions/support/completions_helpers.rs +++ b/crates/nu-cli/tests/completions/support/completions_helpers.rs @@ -62,7 +62,7 @@ pub fn new_engine() -> (PathBuf, String, EngineState, Stack) { ); // Merge environment into the permanent state - let merge_result = engine_state.merge_env(&mut stack); + let merge_result = engine_state.merge_env(&mut stack, &dir); assert!(merge_result.is_ok()); (dir, dir_str, engine_state, stack) @@ -97,7 +97,7 @@ pub fn new_quote_engine() -> (PathBuf, String, EngineState, Stack) { ); // Merge environment into the permanent state - let merge_result = engine_state.merge_env(&mut stack); + let merge_result = engine_state.merge_env(&mut stack, &dir); assert!(merge_result.is_ok()); (dir, dir_str, engine_state, stack) @@ -132,7 +132,7 @@ pub fn new_partial_engine() -> (PathBuf, String, EngineState, Stack) { ); // Merge environment into the permanent state - let merge_result = engine_state.merge_env(&mut stack); + let merge_result = engine_state.merge_env(&mut stack, &dir); assert!(merge_result.is_ok()); (dir, dir_str, engine_state, stack) @@ -173,6 +173,7 @@ pub fn merge_input( input: &[u8], engine_state: &mut EngineState, stack: &mut Stack, + dir: PathBuf, ) -> Result<(), ShellError> { let (block, delta) = { let mut working_set = StateWorkingSet::new(engine_state); @@ -195,5 +196,5 @@ pub fn merge_input( .is_ok()); // Merge environment into the permanent state - engine_state.merge_env(stack) + engine_state.merge_env(stack, &dir) } diff --git a/crates/nu-cmd-base/src/hook.rs b/crates/nu-cmd-base/src/hook.rs index 9133cf4167..76c13bd5c3 100644 --- a/crates/nu-cmd-base/src/hook.rs +++ b/crates/nu-cmd-base/src/hook.rs @@ -1,3 +1,4 @@ +use crate::util::get_guaranteed_cwd; use miette::Result; use nu_engine::{eval_block, eval_block_with_early_return}; use nu_parser::parse; @@ -283,7 +284,8 @@ pub fn eval_hook( } } - engine_state.merge_env(stack)?; + let cwd = get_guaranteed_cwd(engine_state, stack); + engine_state.merge_env(stack, cwd)?; Ok(output) } diff --git a/crates/nu-cmd-lang/src/example_support.rs b/crates/nu-cmd-lang/src/example_support.rs index d938729fef..bb03bbaf8c 100644 --- a/crates/nu-cmd-lang/src/example_support.rs +++ b/crates/nu-cmd-lang/src/example_support.rs @@ -138,7 +138,7 @@ pub fn check_example_evaluates_to_expected_output( stack.add_env_var("PWD".to_string(), Value::test_string(cwd.to_string_lossy())); engine_state - .merge_env(&mut stack) + .merge_env(&mut stack, cwd) .expect("Error merging environment"); let empty_input = PipelineData::empty(); diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index 10c96b7463..710ca77d4c 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -277,7 +277,11 @@ impl EngineState { } /// Merge the environment from the runtime Stack into the engine state - pub fn merge_env(&mut self, stack: &mut Stack) -> Result<(), ShellError> { + pub fn merge_env( + &mut self, + stack: &mut Stack, + cwd: impl AsRef, + ) -> Result<(), ShellError> { let mut config_updated = false; for mut scope in stack.env_vars.drain(..) { @@ -307,6 +311,9 @@ impl EngineState { } } + // TODO: better error + std::env::set_current_dir(cwd)?; + if config_updated { // Make plugin GC config changes take effect immediately. #[cfg(feature = "plugin")] diff --git a/crates/nu-std/src/lib.rs b/crates/nu-std/src/lib.rs index e6c8f30556..a20e3fc5da 100644 --- a/crates/nu-std/src/lib.rs +++ b/crates/nu-std/src/lib.rs @@ -98,7 +98,8 @@ use std pwd eval_block::(engine_state, &mut stack, &block, pipeline_data)?; - engine_state.merge_env(&mut stack)?; + let cwd = engine_state.cwd(Some(&stack))?; + engine_state.merge_env(&mut stack, cwd)?; Ok(()) } diff --git a/src/config_files.rs b/src/config_files.rs index 3df076045f..ec4511860f 100644 --- a/src/config_files.rs +++ b/src/config_files.rs @@ -164,8 +164,15 @@ pub(crate) fn read_default_env_file(engine_state: &mut EngineState, stack: &mut ); // Merge the environment in case env vars changed in the config - if let Err(e) = engine_state.merge_env(stack) { - report_error_new(engine_state, &e); + match engine_state.cwd(Some(stack)) { + Ok(cwd) => { + if let Err(e) = engine_state.merge_env(stack, cwd) { + report_error_new(engine_state, &e); + } + } + Err(e) => { + report_error_new(engine_state, &e); + } } } @@ -195,8 +202,15 @@ fn eval_default_config( ); // Merge the environment in case env vars changed in the config - if let Err(e) = engine_state.merge_env(stack) { - report_error_new(engine_state, &e); + match engine_state.cwd(Some(stack)) { + Ok(cwd) => { + if let Err(e) = engine_state.merge_env(stack, cwd) { + report_error_new(engine_state, &e); + } + } + Err(e) => { + report_error_new(engine_state, &e); + } } } diff --git a/src/test_bins.rs b/src/test_bins.rs index 7cd542e732..b20c01f997 100644 --- a/src/test_bins.rs +++ b/src/test_bins.rs @@ -251,9 +251,13 @@ pub fn nu_repl() { for (i, line) in source_lines.iter().enumerate() { let mut stack = Stack::with_parent(top_stack.clone()); + let cwd = engine_state + .cwd(Some(&stack)) + .unwrap_or_else(|err| outcome_err(&engine_state, &err)); + // Before doing anything, merge the environment from the previous REPL iteration into the // permanent state. - if let Err(err) = engine_state.merge_env(&mut stack) { + if let Err(err) = engine_state.merge_env(&mut stack, &cwd) { outcome_err(&engine_state, &err); } From 84b7a99adfb5a5cde24f29d81c86f503e7f0e815 Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Fri, 24 May 2024 23:09:26 +0000 Subject: [PATCH 020/113] Revert "Polars lazy refactor (#12669)" (#12962) This reverts commit 68adc4657f9c57bb7090df3984a5d2931f8e7358. # Description Reverts the lazyframe refactor (#12669) for the next release, since there are still a few lingering issues. This temporarily solves #12863 and #12828. After the release, the lazyframes can be added back and cleaned up. --- Cargo.lock | 1 - crates/nu_plugin_polars/Cargo.toml | 1 - .../src/dataframe/{lazy => eager}/cast.rs | 48 ++- .../src/dataframe/{lazy => eager}/drop.rs | 47 ++- .../{lazy => eager}/drop_duplicates.rs | 25 +- .../dataframe/{lazy => eager}/drop_nulls.rs | 32 +- .../src/dataframe/eager/filter_with.rs | 162 +++++++++ .../src/dataframe/{lazy => eager}/first.rs | 17 +- .../src/dataframe/{lazy => eager}/get.rs | 27 +- .../src/dataframe/{lazy => eager}/last.rs | 14 +- .../src/dataframe/{lazy => eager}/melt.rs | 132 +++++-- .../src/dataframe/eager/mod.rs | 36 ++ .../src/dataframe/eager/open.rs | 343 ++++++++++++------ .../src/dataframe/eager/query_df.rs | 2 +- .../src/dataframe/{lazy => eager}/rename.rs | 50 ++- .../src/dataframe/eager/sample.rs | 2 +- .../src/dataframe/{lazy => eager}/slice.rs | 16 +- .../src/dataframe/eager/summary.rs | 2 +- .../src/dataframe/eager/take.rs | 2 +- .../src/dataframe/eager/with_column.rs | 196 ++++++++++ .../expressions/expressions_macro.rs | 2 + .../src/dataframe/expressions/is_in.rs | 3 +- .../src/dataframe/expressions/otherwise.rs | 2 +- .../src/dataframe/expressions/when.rs | 2 +- .../src/dataframe/lazy/aggregate.rs | 4 +- .../src/dataframe/lazy/collect.rs | 8 +- .../src/dataframe/lazy/fetch.rs | 4 +- .../src/dataframe/lazy/fill_null.rs | 4 +- .../src/dataframe/lazy/filter.rs | 7 +- .../src/dataframe/lazy/filter_with.rs | 97 ----- .../src/dataframe/lazy/groupby.rs | 4 +- .../src/dataframe/lazy/join.rs | 9 +- .../src/dataframe/lazy/macro_commands.rs | 2 +- .../src/dataframe/lazy/median.rs | 2 +- .../src/dataframe/lazy/mod.rs | 27 +- .../src/dataframe/lazy/quantile.rs | 1 + .../src/dataframe/lazy/select.rs | 2 +- .../src/dataframe/lazy/sort_by_expr.rs | 5 +- .../src/dataframe/lazy/to_lazy.rs | 90 +++++ .../src/dataframe/lazy/with_column.rs | 114 ------ .../src/dataframe/series/shift.rs | 33 +- .../src/dataframe/series/unique.rs | 43 ++- .../src/dataframe/values/mod.rs | 14 +- .../values/nu_dataframe/conversion.rs | 2 +- .../src/dataframe/values/nu_dataframe/mod.rs | 14 +- .../values/nu_dataframe/operations.rs | 4 +- .../values/nu_expression/custom_value.rs | 49 ++- .../src/dataframe/values/nu_lazyframe/mod.rs | 12 +- .../dataframe/values/nu_lazygroupby/mod.rs | 4 +- .../src/dataframe/values/utils.rs | 2 + 50 files changed, 1210 insertions(+), 511 deletions(-) rename crates/nu_plugin_polars/src/dataframe/{lazy => eager}/cast.rs (79%) rename crates/nu_plugin_polars/src/dataframe/{lazy => eager}/drop.rs (62%) rename crates/nu_plugin_polars/src/dataframe/{lazy => eager}/drop_duplicates.rs (82%) rename crates/nu_plugin_polars/src/dataframe/{lazy => eager}/drop_nulls.rs (84%) create mode 100644 crates/nu_plugin_polars/src/dataframe/eager/filter_with.rs rename crates/nu_plugin_polars/src/dataframe/{lazy => eager}/first.rs (91%) rename crates/nu_plugin_polars/src/dataframe/{lazy => eager}/get.rs (77%) rename crates/nu_plugin_polars/src/dataframe/{lazy => eager}/last.rs (90%) rename crates/nu_plugin_polars/src/dataframe/{lazy => eager}/melt.rs (56%) rename crates/nu_plugin_polars/src/dataframe/{lazy => eager}/rename.rs (77%) rename crates/nu_plugin_polars/src/dataframe/{lazy => eager}/slice.rs (87%) create mode 100644 crates/nu_plugin_polars/src/dataframe/eager/with_column.rs delete mode 100644 crates/nu_plugin_polars/src/dataframe/lazy/filter_with.rs create mode 100644 crates/nu_plugin_polars/src/dataframe/lazy/to_lazy.rs delete mode 100644 crates/nu_plugin_polars/src/dataframe/lazy/with_column.rs diff --git a/Cargo.lock b/Cargo.lock index e074e772a3..2ee4c6fc25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3399,7 +3399,6 @@ dependencies = [ "polars", "polars-arrow", "polars-io", - "polars-lazy", "polars-ops", "polars-plan", "polars-utils", diff --git a/crates/nu_plugin_polars/Cargo.toml b/crates/nu_plugin_polars/Cargo.toml index df30c71c52..6a2a980383 100644 --- a/crates/nu_plugin_polars/Cargo.toml +++ b/crates/nu_plugin_polars/Cargo.toml @@ -34,7 +34,6 @@ polars-arrow = { version = "0.39"} polars-ops = { version = "0.39"} polars-plan = { version = "0.39", features = ["regex"]} polars-utils = { version = "0.39"} -polars-lazy = { version = "0.39"} typetag = "0.2" uuid = { version = "1.7", features = ["v4", "serde"] } diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/cast.rs b/crates/nu_plugin_polars/src/dataframe/eager/cast.rs similarity index 79% rename from crates/nu_plugin_polars/src/dataframe/lazy/cast.rs rename to crates/nu_plugin_polars/src/dataframe/eager/cast.rs index 9348a9ec82..d676fb04ea 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/cast.rs +++ b/crates/nu_plugin_polars/src/dataframe/eager/cast.rs @@ -4,6 +4,7 @@ use crate::{ PolarsPlugin, }; +use super::super::values::NuDataFrame; use nu_plugin::{EngineInterface, EvaluatedCall, PluginCommand}; use nu_protocol::{ record, Category, Example, LabeledError, PipelineData, ShellError, Signature, Span, @@ -66,7 +67,7 @@ impl PluginCommand for CastDF { Example { description: "Cast a column in a lazy dataframe to a different dtype", example: - "[[a b]; [1 2] [3 4]] | polars into-df | polars cast u8 a | polars schema", + "[[a b]; [1 2] [3 4]] | polars into-df | polars into-lazy | polars cast u8 a | polars schema", result: Some(Value::record( record! { "a" => Value::string("u8", Span::test_data()), @@ -98,7 +99,7 @@ impl PluginCommand for CastDF { } PolarsPluginObject::NuDataFrame(df) => { let (dtype, column_nm) = df_args(call)?; - command_lazy(plugin, engine, call, column_nm, dtype, df.lazy()) + command_eager(plugin, engine, call, column_nm, dtype, df) } PolarsPluginObject::NuExpression(expr) => { let dtype: String = call.req(0)?; @@ -143,10 +144,51 @@ fn command_lazy( ) -> Result { let column = col(&column_nm).cast(dtype); let lazy = lazy.to_polars().with_columns(&[column]); - let lazy = NuLazyFrame::new(lazy); + let lazy = NuLazyFrame::new(false, lazy); lazy.to_pipeline_data(plugin, engine, call.head) } +fn command_eager( + plugin: &PolarsPlugin, + engine: &EngineInterface, + call: &EvaluatedCall, + column_nm: String, + dtype: DataType, + nu_df: NuDataFrame, +) -> Result { + let mut df = (*nu_df.df).clone(); + let column = df + .column(&column_nm) + .map_err(|e| ShellError::GenericError { + error: format!("{e}"), + msg: "".into(), + span: Some(call.head), + help: None, + inner: vec![], + })?; + + let casted = column.cast(&dtype).map_err(|e| ShellError::GenericError { + error: format!("{e}"), + msg: "".into(), + span: Some(call.head), + help: None, + inner: vec![], + })?; + + let _ = df + .with_column(casted) + .map_err(|e| ShellError::GenericError { + error: format!("{e}"), + msg: "".into(), + span: Some(call.head), + help: None, + inner: vec![], + })?; + + let df = NuDataFrame::new(false, df); + df.to_pipeline_data(plugin, engine, call.head) +} + #[cfg(test)] mod test { diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/drop.rs b/crates/nu_plugin_polars/src/dataframe/eager/drop.rs similarity index 62% rename from crates/nu_plugin_polars/src/dataframe/lazy/drop.rs rename to crates/nu_plugin_polars/src/dataframe/eager/drop.rs index 6a0bd5b58a..812a77b048 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/drop.rs +++ b/crates/nu_plugin_polars/src/dataframe/eager/drop.rs @@ -4,7 +4,7 @@ use nu_protocol::{ Value, }; -use crate::values::{CustomValueSupport, NuLazyFrame}; +use crate::values::CustomValueSupport; use crate::PolarsPlugin; use super::super::values::utils::convert_columns; @@ -37,7 +37,7 @@ impl PluginCommand for DropDF { fn examples(&self) -> Vec { vec![Example { description: "drop column a", - example: "[[a b]; [1 2] [3 4]] | polars into-df | polars drop a | polars collect", + example: "[[a b]; [1 2] [3 4]] | polars into-df | polars drop a", result: Some( NuDataFrame::try_from_columns( vec![Column::new( @@ -70,11 +70,46 @@ fn command( input: PipelineData, ) -> Result { let columns: Vec = call.rest(0)?; - let (col_string, _col_span) = convert_columns(columns, call.head)?; + let (col_string, col_span) = convert_columns(columns, call.head)?; - let df = NuLazyFrame::try_from_pipeline_coerce(plugin, input, call.head)?; - let polars_df = df.to_polars().drop(col_string.iter().map(|s| &s.item)); - let final_df = NuLazyFrame::new(polars_df); + let df = NuDataFrame::try_from_pipeline_coerce(plugin, input, call.head)?; + + let new_df = col_string + .first() + .ok_or_else(|| ShellError::GenericError { + error: "Empty names list".into(), + msg: "No column names were found".into(), + span: Some(col_span), + help: None, + inner: vec![], + }) + .and_then(|col| { + df.as_ref() + .drop(&col.item) + .map_err(|e| ShellError::GenericError { + error: "Error dropping column".into(), + msg: e.to_string(), + span: Some(col.span), + help: None, + inner: vec![], + }) + })?; + + // If there are more columns in the drop selection list, these + // are added from the resulting dataframe + let polars_df = col_string.iter().skip(1).try_fold(new_df, |new_df, col| { + new_df + .drop(&col.item) + .map_err(|e| ShellError::GenericError { + error: "Error dropping column".into(), + msg: e.to_string(), + span: Some(col.span), + help: None, + inner: vec![], + }) + })?; + + let final_df = NuDataFrame::new(df.from_lazy, polars_df); final_df.to_pipeline_data(plugin, engine, call.head) } diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/drop_duplicates.rs b/crates/nu_plugin_polars/src/dataframe/eager/drop_duplicates.rs similarity index 82% rename from crates/nu_plugin_polars/src/dataframe/lazy/drop_duplicates.rs rename to crates/nu_plugin_polars/src/dataframe/eager/drop_duplicates.rs index f3cf569a3b..3eb6311637 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/drop_duplicates.rs +++ b/crates/nu_plugin_polars/src/dataframe/eager/drop_duplicates.rs @@ -5,11 +5,11 @@ use nu_protocol::{ }; use polars::prelude::UniqueKeepStrategy; -use crate::values::{CustomValueSupport, NuDataFrame}; +use crate::values::CustomValueSupport; use crate::PolarsPlugin; use super::super::values::utils::convert_columns_string; -use super::super::values::{Column, NuLazyFrame}; +use super::super::values::{Column, NuDataFrame}; #[derive(Clone)] pub struct DropDuplicates; @@ -48,7 +48,7 @@ impl PluginCommand for DropDuplicates { fn examples(&self) -> Vec { vec![Example { description: "drop duplicates", - example: "[[a b]; [1 2] [3 4] [1 2]] | polars into-df | polars drop-duplicates | polars collect", + example: "[[a b]; [1 2] [3 4] [1 2]] | polars into-df | polars drop-duplicates", result: Some( NuDataFrame::try_from_columns( vec![ @@ -87,7 +87,7 @@ fn command( input: PipelineData, ) -> Result { let columns: Option> = call.opt(0)?; - let (subset, _col_span) = match columns { + let (subset, col_span) = match columns { Some(cols) => { let (agg_string, col_span) = convert_columns_string(cols, call.head)?; (Some(agg_string), col_span) @@ -95,7 +95,9 @@ fn command( None => (None, call.head), }; - let df = NuLazyFrame::try_from_pipeline_coerce(plugin, input, call.head)?; + let df = NuDataFrame::try_from_pipeline_coerce(plugin, input, call.head)?; + + let subset_slice = subset.as_ref().map(|cols| &cols[..]); let keep_strategy = if call.has_flag("last")? { UniqueKeepStrategy::Last @@ -103,9 +105,18 @@ fn command( UniqueKeepStrategy::First }; - let polars_df = df.to_polars().unique(subset, keep_strategy); + let polars_df = df + .as_ref() + .unique(subset_slice, keep_strategy, None) + .map_err(|e| ShellError::GenericError { + error: "Error dropping duplicates".into(), + msg: e.to_string(), + span: Some(col_span), + help: None, + inner: vec![], + })?; - let df = NuLazyFrame::new(polars_df); + let df = NuDataFrame::new(df.from_lazy, polars_df); df.to_pipeline_data(plugin, engine, call.head) } diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/drop_nulls.rs b/crates/nu_plugin_polars/src/dataframe/eager/drop_nulls.rs similarity index 84% rename from crates/nu_plugin_polars/src/dataframe/lazy/drop_nulls.rs rename to crates/nu_plugin_polars/src/dataframe/eager/drop_nulls.rs index ba03429359..4d1b41e2fa 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/drop_nulls.rs +++ b/crates/nu_plugin_polars/src/dataframe/eager/drop_nulls.rs @@ -4,13 +4,11 @@ use nu_protocol::{ Value, }; -use polars_lazy::dsl::col; - -use crate::values::{CustomValueSupport, NuDataFrame}; +use crate::values::CustomValueSupport; use crate::PolarsPlugin; use super::super::values::utils::convert_columns_string; -use super::super::values::{Column, NuLazyFrame}; +use super::super::values::{Column, NuDataFrame}; #[derive(Clone)] pub struct DropNulls; @@ -45,7 +43,8 @@ impl PluginCommand for DropNulls { Example { description: "drop null values in dataframe", example: r#"let df = ([[a b]; [1 2] [3 0] [1 2]] | polars into-df); - let a = ($df | polars with-column [((polars col b) / (polars col b) | polars as res)]); + let res = ($df.b / $df.b); + let a = ($df | polars with-column $res --name res); $a | polars drop-nulls"#, result: Some( NuDataFrame::try_from_columns( @@ -110,20 +109,31 @@ fn command( call: &EvaluatedCall, input: PipelineData, ) -> Result { - let df = NuLazyFrame::try_from_pipeline_coerce(plugin, input, call.head)?; + let df = NuDataFrame::try_from_pipeline_coerce(plugin, input, call.head)?; + let columns: Option> = call.opt(0)?; - let (subset, _col_span) = match columns { + let (subset, col_span) = match columns { Some(cols) => { let (agg_string, col_span) = convert_columns_string(cols, call.head)?; - let agg_expr = agg_string.iter().map(|s| col(s)).collect(); - (Some(agg_expr), col_span) + (Some(agg_string), col_span) } None => (None, call.head), }; - let polars_df = df.to_polars().drop_nulls(subset); - let df = NuLazyFrame::new(polars_df); + let subset_slice = subset.as_ref().map(|cols| &cols[..]); + + let polars_df = df + .as_ref() + .drop_nulls(subset_slice) + .map_err(|e| ShellError::GenericError { + error: "Error dropping nulls".into(), + msg: e.to_string(), + span: Some(col_span), + help: None, + inner: vec![], + })?; + let df = NuDataFrame::new(df.from_lazy, polars_df); df.to_pipeline_data(plugin, engine, call.head) } diff --git a/crates/nu_plugin_polars/src/dataframe/eager/filter_with.rs b/crates/nu_plugin_polars/src/dataframe/eager/filter_with.rs new file mode 100644 index 0000000000..b95f646edd --- /dev/null +++ b/crates/nu_plugin_polars/src/dataframe/eager/filter_with.rs @@ -0,0 +1,162 @@ +use nu_plugin::{EngineInterface, EvaluatedCall, PluginCommand}; +use nu_protocol::{ + Category, Example, LabeledError, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, + Value, +}; +use polars::prelude::LazyFrame; + +use crate::{ + dataframe::values::{NuExpression, NuLazyFrame}, + values::{cant_convert_err, CustomValueSupport, PolarsPluginObject, PolarsPluginType}, + PolarsPlugin, +}; + +use super::super::values::{Column, NuDataFrame}; + +#[derive(Clone)] +pub struct FilterWith; + +impl PluginCommand for FilterWith { + type Plugin = PolarsPlugin; + + fn name(&self) -> &str { + "polars filter-with" + } + + fn usage(&self) -> &str { + "Filters dataframe using a mask or expression as reference." + } + + fn signature(&self) -> Signature { + Signature::build(self.name()) + .required( + "mask or expression", + SyntaxShape::Any, + "boolean mask used to filter data", + ) + .input_output_type( + Type::Custom("dataframe".into()), + Type::Custom("dataframe".into()), + ) + .category(Category::Custom("dataframe or lazyframe".into())) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Filter dataframe using a bool mask", + example: r#"let mask = ([true false] | polars into-df); + [[a b]; [1 2] [3 4]] | polars into-df | polars filter-with $mask"#, + result: Some( + NuDataFrame::try_from_columns( + vec![ + Column::new("a".to_string(), vec![Value::test_int(1)]), + Column::new("b".to_string(), vec![Value::test_int(2)]), + ], + None, + ) + .expect("simple df for test should not fail") + .into_value(Span::test_data()), + ), + }, + Example { + description: "Filter dataframe using an expression", + example: "[[a b]; [1 2] [3 4]] | polars into-df | polars filter-with ((polars col a) > 1)", + result: Some( + NuDataFrame::try_from_columns( + vec![ + Column::new("a".to_string(), vec![Value::test_int(3)]), + Column::new("b".to_string(), vec![Value::test_int(4)]), + ], + None, + ) + .expect("simple df for test should not fail") + .into_value(Span::test_data()), + ), + }, + ] + } + + fn run( + &self, + plugin: &Self::Plugin, + engine: &EngineInterface, + call: &EvaluatedCall, + input: PipelineData, + ) -> Result { + let value = input.into_value(call.head)?; + match PolarsPluginObject::try_from_value(plugin, &value)? { + PolarsPluginObject::NuDataFrame(df) => command_eager(plugin, engine, call, df), + PolarsPluginObject::NuLazyFrame(lazy) => command_lazy(plugin, engine, call, lazy), + _ => Err(cant_convert_err( + &value, + &[PolarsPluginType::NuDataFrame, PolarsPluginType::NuLazyFrame], + )), + } + .map_err(LabeledError::from) + } +} + +fn command_eager( + plugin: &PolarsPlugin, + engine: &EngineInterface, + call: &EvaluatedCall, + df: NuDataFrame, +) -> Result { + let mask_value: Value = call.req(0)?; + let mask_span = mask_value.span(); + + if NuExpression::can_downcast(&mask_value) { + let expression = NuExpression::try_from_value(plugin, &mask_value)?; + let lazy = df.lazy(); + let lazy = lazy.apply_with_expr(expression, LazyFrame::filter); + + lazy.to_pipeline_data(plugin, engine, call.head) + } else { + let mask = NuDataFrame::try_from_value_coerce(plugin, &mask_value, mask_span)? + .as_series(mask_span)?; + let mask = mask.bool().map_err(|e| ShellError::GenericError { + error: "Error casting to bool".into(), + msg: e.to_string(), + span: Some(mask_span), + help: Some("Perhaps you want to use a series with booleans as mask".into()), + inner: vec![], + })?; + + let polars_df = df + .as_ref() + .filter(mask) + .map_err(|e| ShellError::GenericError { + error: "Error filtering dataframe".into(), + msg: e.to_string(), + span: Some(call.head), + help: Some("The only allowed column types for dummies are String or Int".into()), + inner: vec![], + })?; + let df = NuDataFrame::new(df.from_lazy, polars_df); + df.to_pipeline_data(plugin, engine, call.head) + } +} + +fn command_lazy( + plugin: &PolarsPlugin, + engine: &EngineInterface, + call: &EvaluatedCall, + lazy: NuLazyFrame, +) -> Result { + let expr: Value = call.req(0)?; + let expr = NuExpression::try_from_value(plugin, &expr)?; + let lazy = lazy.apply_with_expr(expr, LazyFrame::filter); + lazy.to_pipeline_data(plugin, engine, call.head) +} + +#[cfg(test)] +mod test { + use super::*; + use crate::test::test_polars_plugin_command; + + #[test] + fn test_examples() -> Result<(), ShellError> { + test_polars_plugin_command(&FilterWith) + } +} diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/first.rs b/crates/nu_plugin_polars/src/dataframe/eager/first.rs similarity index 91% rename from crates/nu_plugin_polars/src/dataframe/lazy/first.rs rename to crates/nu_plugin_polars/src/dataframe/eager/first.rs index 4692a933b0..a35ea7dd16 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/first.rs +++ b/crates/nu_plugin_polars/src/dataframe/eager/first.rs @@ -48,7 +48,7 @@ impl PluginCommand for FirstDF { vec![ Example { description: "Return the first row of a dataframe", - example: "[[a b]; [1 2] [3 4]] | polars into-df | polars first | polars collect", + example: "[[a b]; [1 2] [3 4]] | polars into-df | polars first", result: Some( NuDataFrame::try_from_columns( vec![ @@ -63,7 +63,7 @@ impl PluginCommand for FirstDF { }, Example { description: "Return the first two rows of a dataframe", - example: "[[a b]; [1 2] [3 4]] | polars into-df | polars first 2 | polars collect", + example: "[[a b]; [1 2] [3 4]] | polars into-df | polars first 2", result: Some( NuDataFrame::try_from_columns( vec![ @@ -98,12 +98,13 @@ impl PluginCommand for FirstDF { input: PipelineData, ) -> Result { let value = input.into_value(call.head)?; - if NuLazyFrame::can_downcast(&value) || NuDataFrame::can_downcast(&value) { - let lazy = NuLazyFrame::try_from_value_coerce(plugin, &value)?; - command(plugin, engine, call, lazy).map_err(LabeledError::from) + if NuDataFrame::can_downcast(&value) || NuLazyFrame::can_downcast(&value) { + let df = NuDataFrame::try_from_value_coerce(plugin, &value, call.head)?; + command(plugin, engine, call, df).map_err(|e| e.into()) } else { let expr = NuExpression::try_from_value(plugin, &value)?; let expr: NuExpression = expr.into_polars().first().into(); + expr.to_pipeline_data(plugin, engine, call.head) .map_err(LabeledError::from) } @@ -114,13 +115,13 @@ fn command( plugin: &PolarsPlugin, engine: &EngineInterface, call: &EvaluatedCall, - df: NuLazyFrame, + df: NuDataFrame, ) -> Result { let rows: Option = call.opt(0)?; let rows = rows.unwrap_or(1); - let res = df.to_polars().slice(0, rows as u32); - let res: NuLazyFrame = res.into(); + let res = df.as_ref().head(Some(rows)); + let res = NuDataFrame::new(false, res); res.to_pipeline_data(plugin, engine, call.head) } diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/get.rs b/crates/nu_plugin_polars/src/dataframe/eager/get.rs similarity index 77% rename from crates/nu_plugin_polars/src/dataframe/lazy/get.rs rename to crates/nu_plugin_polars/src/dataframe/eager/get.rs index a56978f917..34ba98154f 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/get.rs +++ b/crates/nu_plugin_polars/src/dataframe/eager/get.rs @@ -5,13 +5,10 @@ use nu_protocol::{ }; use crate::{ - dataframe::values::utils::convert_columns_string, - values::{CustomValueSupport, NuDataFrame}, - PolarsPlugin, + dataframe::values::utils::convert_columns_string, values::CustomValueSupport, PolarsPlugin, }; -use super::super::values::{Column, NuLazyFrame}; -use polars::prelude::{col, Expr}; +use super::super::values::{Column, NuDataFrame}; #[derive(Clone)] pub struct GetDF; @@ -40,7 +37,7 @@ impl PluginCommand for GetDF { fn examples(&self) -> Vec { vec![Example { description: "Returns the selected column", - example: "[[a b]; [1 2] [3 4]] | polars into-df | polars get a | polars collect", + example: "[[a b]; [1 2] [3 4]] | polars into-df | polars get a", result: Some( NuDataFrame::try_from_columns( vec![Column::new( @@ -73,13 +70,21 @@ fn command( input: PipelineData, ) -> Result { let columns: Vec = call.rest(0)?; - let (col_string, _col_span) = convert_columns_string(columns, call.head)?; - let col_expr: Vec = col_string.iter().map(|s| col(s)).collect(); + let (col_string, col_span) = convert_columns_string(columns, call.head)?; - let df = NuLazyFrame::try_from_pipeline_coerce(plugin, input, call.head)?; + let df = NuDataFrame::try_from_pipeline_coerce(plugin, input, call.head)?; - let df = df.to_polars().select(col_expr); - let df = NuLazyFrame::new(df); + let df = df + .as_ref() + .select(col_string) + .map_err(|e| ShellError::GenericError { + error: "Error selecting columns".into(), + msg: e.to_string(), + span: Some(col_span), + help: None, + inner: vec![], + })?; + let df = NuDataFrame::new(false, df); df.to_pipeline_data(plugin, engine, call.head) } diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/last.rs b/crates/nu_plugin_polars/src/dataframe/eager/last.rs similarity index 90% rename from crates/nu_plugin_polars/src/dataframe/lazy/last.rs rename to crates/nu_plugin_polars/src/dataframe/eager/last.rs index 0453c71d1e..23b44eb473 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/last.rs +++ b/crates/nu_plugin_polars/src/dataframe/eager/last.rs @@ -3,7 +3,7 @@ use crate::{ PolarsPlugin, }; -use super::super::values::{NuDataFrame, NuExpression}; +use super::super::values::{utils::DEFAULT_ROWS, NuDataFrame, NuExpression}; use nu_plugin::{EngineInterface, EvaluatedCall, PluginCommand}; use nu_protocol::{ Category, Example, LabeledError, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, @@ -44,7 +44,7 @@ impl PluginCommand for LastDF { vec![ Example { description: "Create new dataframe with last rows", - example: "[[a b]; [1 2] [3 4]] | polars into-df | polars last | polars collect", + example: "[[a b]; [1 2] [3 4]] | polars into-df | polars last 1", result: Some( NuDataFrame::try_from_columns( vec![ @@ -74,7 +74,7 @@ impl PluginCommand for LastDF { ) -> Result { let value = input.into_value(call.head)?; if NuDataFrame::can_downcast(&value) || NuLazyFrame::can_downcast(&value) { - let df = NuLazyFrame::try_from_value_coerce(plugin, &value)?; + let df = NuDataFrame::try_from_value_coerce(plugin, &value, call.head)?; command(plugin, engine, call, df).map_err(|e| e.into()) } else { let expr = NuExpression::try_from_value(plugin, &value)?; @@ -90,13 +90,13 @@ fn command( plugin: &PolarsPlugin, engine: &EngineInterface, call: &EvaluatedCall, - df: NuLazyFrame, + df: NuDataFrame, ) -> Result { let rows: Option = call.opt(0)?; - let rows = rows.unwrap_or(1); + let rows = rows.unwrap_or(DEFAULT_ROWS); - let res = df.to_polars().tail(rows as u32); - let res = NuLazyFrame::new(res); + let res = df.as_ref().tail(Some(rows)); + let res = NuDataFrame::new(false, res); res.to_pipeline_data(plugin, engine, call.head) } diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/melt.rs b/crates/nu_plugin_polars/src/dataframe/eager/melt.rs similarity index 56% rename from crates/nu_plugin_polars/src/dataframe/lazy/melt.rs rename to crates/nu_plugin_polars/src/dataframe/eager/melt.rs index 3f0b77e2f4..b69389ed24 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/melt.rs +++ b/crates/nu_plugin_polars/src/dataframe/eager/melt.rs @@ -1,14 +1,11 @@ use nu_plugin::{EngineInterface, EvaluatedCall, PluginCommand}; use nu_protocol::{ - Category, Example, LabeledError, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, - Value, + Category, Example, LabeledError, PipelineData, ShellError, Signature, Span, Spanned, + SyntaxShape, Type, Value, }; -use polars::frame::explode::MeltArgs; use crate::{ - dataframe::values::utils::convert_columns_string, - values::{CustomValueSupport, NuLazyFrame}, - PolarsPlugin, + dataframe::values::utils::convert_columns_string, values::CustomValueSupport, PolarsPlugin, }; use super::super::values::{Column, NuDataFrame}; @@ -53,11 +50,6 @@ impl PluginCommand for MeltDF { "optional name for value column", Some('l'), ) - .switch( - "streamable", - "Use polar's streaming engine. Results will not have a stable ordering.", - Some('s'), - ) .input_output_type( Type::Custom("dataframe".into()), Type::Custom("dataframe".into()), @@ -69,7 +61,7 @@ impl PluginCommand for MeltDF { vec![Example { description: "melt dataframe", example: - "[[a b c d]; [x 1 4 a] [y 2 5 b] [z 3 6 c]] | polars into-df | polars melt -c [b c] -v [a d] | polars collect", + "[[a b c d]; [x 1 4 a] [y 2 5 b] [z 3 6 c]] | polars into-df | polars melt -c [b c] -v [a d]", result: Some( NuDataFrame::try_from_columns(vec![ Column::new( @@ -143,31 +135,111 @@ fn command( let id_col: Vec = call.get_flag("columns")?.expect("required value"); let val_col: Vec = call.get_flag("values")?.expect("required value"); - let value_name = call.get_flag("value-name")?.map(|v: String| v.into()); - let variable_name = call.get_flag("variable-name")?.map(|v: String| v.into()); - let streamable = call.has_flag("streamable")?; + let value_name: Option> = call.get_flag("value-name")?; + let variable_name: Option> = call.get_flag("variable-name")?; - let (id_vars, _id_col_span) = convert_columns_string(id_col, call.head)?; - let id_vars = id_vars.into_iter().map(Into::into).collect(); - let (value_vars, _val_col_span) = convert_columns_string(val_col, call.head)?; - let value_vars = value_vars.into_iter().map(Into::into).collect(); + let (id_col_string, id_col_span) = convert_columns_string(id_col, call.head)?; + let (val_col_string, val_col_span) = convert_columns_string(val_col, call.head)?; - let df = NuLazyFrame::try_from_pipeline_coerce(plugin, input, call.head)?; - let polars_df = df.to_polars(); + let df = NuDataFrame::try_from_pipeline_coerce(plugin, input, call.head)?; - let args = MeltArgs { - id_vars, - value_vars, - variable_name, - value_name, - streamable, - }; + check_column_datatypes(df.as_ref(), &id_col_string, id_col_span)?; + check_column_datatypes(df.as_ref(), &val_col_string, val_col_span)?; - let res = polars_df.melt(args); - let res = NuLazyFrame::new(res); + let mut res = df + .as_ref() + .melt(&id_col_string, &val_col_string) + .map_err(|e| ShellError::GenericError { + error: "Error calculating melt".into(), + msg: e.to_string(), + span: Some(call.head), + help: None, + inner: vec![], + })?; + + if let Some(name) = &variable_name { + res.rename("variable", &name.item) + .map_err(|e| ShellError::GenericError { + error: "Error renaming column".into(), + msg: e.to_string(), + span: Some(name.span), + help: None, + inner: vec![], + })?; + } + + if let Some(name) = &value_name { + res.rename("value", &name.item) + .map_err(|e| ShellError::GenericError { + error: "Error renaming column".into(), + msg: e.to_string(), + span: Some(name.span), + help: None, + inner: vec![], + })?; + } + + let res = NuDataFrame::new(false, res); res.to_pipeline_data(plugin, engine, call.head) } +fn check_column_datatypes>( + df: &polars::prelude::DataFrame, + cols: &[T], + col_span: Span, +) -> Result<(), ShellError> { + if cols.is_empty() { + return Err(ShellError::GenericError { + error: "Merge error".into(), + msg: "empty column list".into(), + span: Some(col_span), + help: None, + inner: vec![], + }); + } + + // Checking if they are same type + if cols.len() > 1 { + for w in cols.windows(2) { + let l_series = df + .column(w[0].as_ref()) + .map_err(|e| ShellError::GenericError { + error: "Error selecting columns".into(), + msg: e.to_string(), + span: Some(col_span), + help: None, + inner: vec![], + })?; + + let r_series = df + .column(w[1].as_ref()) + .map_err(|e| ShellError::GenericError { + error: "Error selecting columns".into(), + msg: e.to_string(), + span: Some(col_span), + help: None, + inner: vec![], + })?; + + if l_series.dtype() != r_series.dtype() { + return Err(ShellError::GenericError { + error: "Merge error".into(), + msg: "found different column types in list".into(), + span: Some(col_span), + help: Some(format!( + "datatypes {} and {} are incompatible", + l_series.dtype(), + r_series.dtype() + )), + inner: vec![], + }); + } + } + } + + Ok(()) +} + #[cfg(test)] mod test { use crate::test::test_polars_plugin_command; diff --git a/crates/nu_plugin_polars/src/dataframe/eager/mod.rs b/crates/nu_plugin_polars/src/dataframe/eager/mod.rs index 28c99f1fed..dc50ba7cd2 100644 --- a/crates/nu_plugin_polars/src/dataframe/eager/mod.rs +++ b/crates/nu_plugin_polars/src/dataframe/eager/mod.rs @@ -1,11 +1,22 @@ mod append; +mod cast; mod columns; +mod drop; +mod drop_duplicates; +mod drop_nulls; mod dummies; +mod filter_with; +mod first; +mod get; +mod last; +mod melt; mod open; mod query_df; +mod rename; mod sample; mod schema; mod shape; +mod slice; mod sql_context; mod sql_expr; mod summary; @@ -17,18 +28,30 @@ mod to_df; mod to_json_lines; mod to_nu; mod to_parquet; +mod with_column; use crate::PolarsPlugin; pub use self::open::OpenDataFrame; pub use append::AppendDF; +pub use cast::CastDF; pub use columns::ColumnsDF; +pub use drop::DropDF; +pub use drop_duplicates::DropDuplicates; +pub use drop_nulls::DropNulls; pub use dummies::Dummies; +pub use filter_with::FilterWith; +pub use first::FirstDF; +pub use get::GetDF; +pub use last::LastDF; +pub use melt::MeltDF; use nu_plugin::PluginCommand; pub use query_df::QueryDf; +pub use rename::RenameDF; pub use sample::SampleDF; pub use schema::SchemaCmd; pub use shape::ShapeDF; +pub use slice::SliceDF; pub use sql_context::SQLContext; pub use summary::Summary; pub use take::TakeDF; @@ -39,16 +62,28 @@ pub use to_df::ToDataFrame; pub use to_json_lines::ToJsonLines; pub use to_nu::ToNu; pub use to_parquet::ToParquet; +pub use with_column::WithColumn; pub(crate) fn eager_commands() -> Vec>> { vec![ Box::new(AppendDF), + Box::new(CastDF), Box::new(ColumnsDF), + Box::new(DropDF), + Box::new(DropDuplicates), + Box::new(DropNulls), Box::new(Dummies), + Box::new(FilterWith), + Box::new(GetDF), Box::new(OpenDataFrame), + Box::new(MeltDF), Box::new(Summary), + Box::new(FirstDF), + Box::new(LastDF), + Box::new(RenameDF), Box::new(SampleDF), Box::new(ShapeDF), + Box::new(SliceDF), Box::new(SchemaCmd), Box::new(TakeDF), Box::new(ToNu), @@ -59,5 +94,6 @@ pub(crate) fn eager_commands() -> Vec Result { - let args = ScanArgsParquet { - n_rows: None, - cache: true, - parallel: ParallelStrategy::Auto, - rechunk: false, - row_index: None, - low_memory: false, - cloud_options: None, - use_statistics: false, - hive_options: HiveOptions::default(), - }; + if call.has_flag("lazy")? { + let file: String = call.req(0)?; + let args = ScanArgsParquet { + n_rows: None, + cache: true, + parallel: ParallelStrategy::Auto, + rechunk: false, + row_index: None, + low_memory: false, + cloud_options: None, + use_statistics: false, + hive_options: HiveOptions::default(), + }; - let maybe_columns: Option> = call - .get_flag::>("columns")? - .map(|cols| cols.iter().map(|s| col(s)).collect()); + let df: NuLazyFrame = LazyFrame::scan_parquet(file, args) + .map_err(|e| ShellError::GenericError { + error: "Parquet reader error".into(), + msg: format!("{e:?}"), + span: Some(call.head), + help: None, + inner: vec![], + })? + .into(); - let mut polars_df = - LazyFrame::scan_parquet(file_path, args).map_err(|e| ShellError::GenericError { - error: "Parquet reader error".into(), - msg: format!("{e:?}"), - span: Some(call.head), + df.cache_and_to_value(plugin, engine, call.head) + } else { + let columns: Option> = call.get_flag("columns")?; + + let r = File::open(file_path).map_err(|e| ShellError::GenericError { + error: "Error opening file".into(), + msg: e.to_string(), + span: Some(file_span), help: None, inner: vec![], })?; + let reader = ParquetReader::new(r); - if let Some(columns) = maybe_columns { - polars_df = polars_df.select(columns); + let reader = match columns { + None => reader, + Some(columns) => reader.with_columns(Some(columns)), + }; + + let df: NuDataFrame = reader + .finish() + .map_err(|e| ShellError::GenericError { + error: "Parquet reader error".into(), + msg: format!("{e:?}"), + span: Some(call.head), + help: None, + inner: vec![], + })? + .into(); + + df.cache_and_to_value(plugin, engine, call.head) } - - let df: NuLazyFrame = polars_df.into(); - df.cache_and_to_value(plugin, engine, call.head) } fn from_avro( @@ -238,36 +262,60 @@ fn from_ipc( engine: &nu_plugin::EngineInterface, call: &nu_plugin::EvaluatedCall, file_path: &Path, - _file_span: Span, + file_span: Span, ) -> Result { - let args = ScanArgsIpc { - n_rows: None, - cache: true, - rechunk: false, - row_index: None, - memory_map: true, - cloud_options: None, - }; + if call.has_flag("lazy")? { + let file: String = call.req(0)?; + let args = ScanArgsIpc { + n_rows: None, + cache: true, + rechunk: false, + row_index: None, + memory_map: true, + cloud_options: None, + }; - let maybe_columns: Option> = call - .get_flag::>("columns")? - .map(|cols| cols.iter().map(|s| col(s)).collect()); + let df: NuLazyFrame = LazyFrame::scan_ipc(file, args) + .map_err(|e| ShellError::GenericError { + error: "IPC reader error".into(), + msg: format!("{e:?}"), + span: Some(call.head), + help: None, + inner: vec![], + })? + .into(); - let mut polars_df = - LazyFrame::scan_ipc(file_path, args).map_err(|e| ShellError::GenericError { - error: "IPC reader error".into(), - msg: format!("{e:?}"), - span: Some(call.head), + df.cache_and_to_value(plugin, engine, call.head) + } else { + let columns: Option> = call.get_flag("columns")?; + + let r = File::open(file_path).map_err(|e| ShellError::GenericError { + error: "Error opening file".into(), + msg: e.to_string(), + span: Some(file_span), help: None, inner: vec![], })?; + let reader = IpcReader::new(r); - if let Some(columns) = maybe_columns { - polars_df = polars_df.select(columns); + let reader = match columns { + None => reader, + Some(columns) => reader.with_columns(Some(columns)), + }; + + let df: NuDataFrame = reader + .finish() + .map_err(|e| ShellError::GenericError { + error: "IPC reader error".into(), + msg: format!("{e:?}"), + span: Some(call.head), + help: None, + inner: vec![], + })? + .into(); + + df.cache_and_to_value(plugin, engine, call.head) } - - let df: NuLazyFrame = polars_df.into(); - df.cache_and_to_value(plugin, engine, call.head) } fn from_json( @@ -316,21 +364,32 @@ fn from_jsonl( engine: &nu_plugin::EngineInterface, call: &nu_plugin::EvaluatedCall, file_path: &Path, - _file_span: Span, + file_span: Span, ) -> Result { let infer_schema: Option = call.get_flag("infer-schema")?; let maybe_schema = call .get_flag("schema")? .map(|schema| NuSchema::try_from(&schema)) .transpose()?; + let file = File::open(file_path).map_err(|e| ShellError::GenericError { + error: "Error opening file".into(), + msg: e.to_string(), + span: Some(file_span), + help: None, + inner: vec![], + })?; - let maybe_columns: Option> = call - .get_flag::>("columns")? - .map(|cols| cols.iter().map(|s| col(s)).collect()); + let buf_reader = BufReader::new(file); + let reader = JsonReader::new(buf_reader) + .with_json_format(JsonFormat::JsonLines) + .infer_schema_len(infer_schema); - let mut polars_df = LazyJsonLineReader::new(file_path) - .with_infer_schema_length(infer_schema) - .with_schema(maybe_schema.map(|s| s.into())) + let reader = match maybe_schema { + Some(schema) => reader.with_schema(schema.into()), + None => reader, + }; + + let df: NuDataFrame = reader .finish() .map_err(|e| ShellError::GenericError { error: "Json lines reader error".into(), @@ -338,13 +397,9 @@ fn from_jsonl( span: Some(call.head), help: None, inner: vec![], - })?; + })? + .into(); - if let Some(columns) = maybe_columns { - polars_df = polars_df.select(columns); - } - - let df: NuLazyFrame = polars_df.into(); df.cache_and_to_value(plugin, engine, call.head) } @@ -353,73 +408,137 @@ fn from_csv( engine: &nu_plugin::EngineInterface, call: &nu_plugin::EvaluatedCall, file_path: &Path, - _file_span: Span, + file_span: Span, ) -> Result { let delimiter: Option> = call.get_flag("delimiter")?; let no_header: bool = call.has_flag("no-header")?; let infer_schema: Option = call.get_flag("infer-schema")?; let skip_rows: Option = call.get_flag("skip-rows")?; - let maybe_columns: Option> = call - .get_flag::>("columns")? - .map(|cols| cols.iter().map(|s| col(s)).collect()); + let columns: Option> = call.get_flag("columns")?; let maybe_schema = call .get_flag("schema")? .map(|schema| NuSchema::try_from(&schema)) .transpose()?; - let csv_reader = LazyCsvReader::new(file_path); + if call.has_flag("lazy")? { + let csv_reader = LazyCsvReader::new(file_path); - let csv_reader = match delimiter { - None => csv_reader, - Some(d) => { - if d.item.len() != 1 { - return Err(ShellError::GenericError { - error: "Incorrect delimiter".into(), - msg: "Delimiter has to be one character".into(), - span: Some(d.span), - help: None, - inner: vec![], - }); - } else { - let delimiter = match d.item.chars().next() { - Some(d) => d as u8, - None => unreachable!(), - }; - csv_reader.with_separator(delimiter) + let csv_reader = match delimiter { + None => csv_reader, + Some(d) => { + if d.item.len() != 1 { + return Err(ShellError::GenericError { + error: "Incorrect delimiter".into(), + msg: "Delimiter has to be one character".into(), + span: Some(d.span), + help: None, + inner: vec![], + }); + } else { + let delimiter = match d.item.chars().next() { + Some(d) => d as u8, + None => unreachable!(), + }; + csv_reader.with_separator(delimiter) + } } - } - }; + }; - let csv_reader = csv_reader.has_header(!no_header); + let csv_reader = csv_reader.has_header(!no_header); - let csv_reader = match maybe_schema { - Some(schema) => csv_reader.with_schema(Some(schema.into())), - None => csv_reader, - }; + let csv_reader = match maybe_schema { + Some(schema) => csv_reader.with_schema(Some(schema.into())), + None => csv_reader, + }; - let csv_reader = match infer_schema { - None => csv_reader, - Some(r) => csv_reader.with_infer_schema_length(Some(r)), - }; + let csv_reader = match infer_schema { + None => csv_reader, + Some(r) => csv_reader.with_infer_schema_length(Some(r)), + }; - let csv_reader = match skip_rows { - None => csv_reader, - Some(r) => csv_reader.with_skip_rows(r), - }; + let csv_reader = match skip_rows { + None => csv_reader, + Some(r) => csv_reader.with_skip_rows(r), + }; - let mut polars_df = csv_reader.finish().map_err(|e| ShellError::GenericError { - error: "CSV reader error".into(), - msg: format!("{e:?}"), - span: Some(call.head), - help: None, - inner: vec![], - })?; + let df: NuLazyFrame = csv_reader + .finish() + .map_err(|e| ShellError::GenericError { + error: "Parquet reader error".into(), + msg: format!("{e:?}"), + span: Some(call.head), + help: None, + inner: vec![], + })? + .into(); - if let Some(columns) = maybe_columns { - polars_df = polars_df.select(columns); + df.cache_and_to_value(plugin, engine, call.head) + } else { + let csv_reader = CsvReader::from_path(file_path) + .map_err(|e| ShellError::GenericError { + error: "Error creating CSV reader".into(), + msg: e.to_string(), + span: Some(file_span), + help: None, + inner: vec![], + })? + .with_encoding(CsvEncoding::LossyUtf8); + + let csv_reader = match delimiter { + None => csv_reader, + Some(d) => { + if d.item.len() != 1 { + return Err(ShellError::GenericError { + error: "Incorrect delimiter".into(), + msg: "Delimiter has to be one character".into(), + span: Some(d.span), + help: None, + inner: vec![], + }); + } else { + let delimiter = match d.item.chars().next() { + Some(d) => d as u8, + None => unreachable!(), + }; + csv_reader.with_separator(delimiter) + } + } + }; + + let csv_reader = csv_reader.has_header(!no_header); + + let csv_reader = match maybe_schema { + Some(schema) => csv_reader.with_schema(Some(schema.into())), + None => csv_reader, + }; + + let csv_reader = match infer_schema { + None => csv_reader, + Some(r) => csv_reader.infer_schema(Some(r)), + }; + + let csv_reader = match skip_rows { + None => csv_reader, + Some(r) => csv_reader.with_skip_rows(r), + }; + + let csv_reader = match columns { + None => csv_reader, + Some(columns) => csv_reader.with_columns(Some(columns)), + }; + + let df: NuDataFrame = csv_reader + .finish() + .map_err(|e| ShellError::GenericError { + error: "Parquet reader error".into(), + msg: format!("{e:?}"), + span: Some(call.head), + help: None, + inner: vec![], + })? + .into(); + + df.cache_and_to_value(plugin, engine, call.head) } - - let df: NuLazyFrame = polars_df.into(); - df.cache_and_to_value(plugin, engine, call.head) } diff --git a/crates/nu_plugin_polars/src/dataframe/eager/query_df.rs b/crates/nu_plugin_polars/src/dataframe/eager/query_df.rs index aacfe5e3df..a09da57250 100644 --- a/crates/nu_plugin_polars/src/dataframe/eager/query_df.rs +++ b/crates/nu_plugin_polars/src/dataframe/eager/query_df.rs @@ -91,7 +91,7 @@ fn command( help: None, inner: vec![], })?; - let lazy = NuLazyFrame::new(df_sql); + let lazy = NuLazyFrame::new(!df.from_lazy, df_sql); lazy.to_pipeline_data(plugin, engine, call.head) } diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/rename.rs b/crates/nu_plugin_polars/src/dataframe/eager/rename.rs similarity index 77% rename from crates/nu_plugin_polars/src/dataframe/lazy/rename.rs rename to crates/nu_plugin_polars/src/dataframe/eager/rename.rs index c32b8d9451..724cf1f983 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/rename.rs +++ b/crates/nu_plugin_polars/src/dataframe/eager/rename.rs @@ -6,7 +6,7 @@ use nu_protocol::{ use crate::{ dataframe::{utils::extract_strings, values::NuLazyFrame}, - values::CustomValueSupport, + values::{CustomValueSupport, PolarsPluginObject}, PolarsPlugin, }; @@ -49,7 +49,7 @@ impl PluginCommand for RenameDF { vec![ Example { description: "Renames a series", - example: "[5 6 7 8] | polars into-df | polars rename '0' new_name | polars collect", + example: "[5 6 7 8] | polars into-df | polars rename '0' new_name", result: Some( NuDataFrame::try_from_columns( vec![Column::new( @@ -69,7 +69,7 @@ impl PluginCommand for RenameDF { }, Example { description: "Renames a dataframe column", - example: "[[a b]; [1 2] [3 4]] | polars into-df | polars rename a a_new | polars collect", + example: "[[a b]; [1 2] [3 4]] | polars into-df | polars rename a a_new", result: Some( NuDataFrame::try_from_columns( vec![ @@ -91,7 +91,7 @@ impl PluginCommand for RenameDF { Example { description: "Renames two dataframe columns", example: - "[[a b]; [1 2] [3 4]] | polars into-df | polars rename [a b] [a_new b_new] | polars collect", + "[[a b]; [1 2] [3 4]] | polars into-df | polars rename [a b] [a_new b_new]", result: Some( NuDataFrame::try_from_columns( vec![ @@ -121,11 +121,49 @@ impl PluginCommand for RenameDF { input: PipelineData, ) -> Result { let value = input.into_value(call.head)?; - let lazy = NuLazyFrame::try_from_value_coerce(plugin, &value)?; - command_lazy(plugin, engine, call, lazy).map_err(LabeledError::from) + match PolarsPluginObject::try_from_value(plugin, &value).map_err(LabeledError::from)? { + PolarsPluginObject::NuDataFrame(df) => { + command_eager(plugin, engine, call, df).map_err(LabeledError::from) + } + PolarsPluginObject::NuLazyFrame(lazy) => { + command_lazy(plugin, engine, call, lazy).map_err(LabeledError::from) + } + _ => Err(LabeledError::new(format!("Unsupported type: {value:?}")) + .with_label("Unsupported Type", call.head)), + } } } +fn command_eager( + plugin: &PolarsPlugin, + engine: &EngineInterface, + call: &EvaluatedCall, + df: NuDataFrame, +) -> Result { + let columns: Value = call.req(0)?; + let columns = extract_strings(columns)?; + + let new_names: Value = call.req(1)?; + let new_names = extract_strings(new_names)?; + + let mut polars_df = df.to_polars(); + + for (from, to) in columns.iter().zip(new_names.iter()) { + polars_df + .rename(from, to) + .map_err(|e| ShellError::GenericError { + error: "Error renaming".into(), + msg: e.to_string(), + span: Some(call.head), + help: None, + inner: vec![], + })?; + } + + let df = NuDataFrame::new(false, polars_df); + df.to_pipeline_data(plugin, engine, call.head) +} + fn command_lazy( plugin: &PolarsPlugin, engine: &EngineInterface, diff --git a/crates/nu_plugin_polars/src/dataframe/eager/sample.rs b/crates/nu_plugin_polars/src/dataframe/eager/sample.rs index 64f7608c5c..59f9ad6eee 100644 --- a/crates/nu_plugin_polars/src/dataframe/eager/sample.rs +++ b/crates/nu_plugin_polars/src/dataframe/eager/sample.rs @@ -147,7 +147,7 @@ fn command( inner: vec![], }), }; - let df = NuDataFrame::new(df?); + let df = NuDataFrame::new(false, df?); df.to_pipeline_data(plugin, engine, call.head) } diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/slice.rs b/crates/nu_plugin_polars/src/dataframe/eager/slice.rs similarity index 87% rename from crates/nu_plugin_polars/src/dataframe/lazy/slice.rs rename to crates/nu_plugin_polars/src/dataframe/eager/slice.rs index 664339d242..c7ebaff4d7 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/slice.rs +++ b/crates/nu_plugin_polars/src/dataframe/eager/slice.rs @@ -4,11 +4,7 @@ use nu_protocol::{ Value, }; -use crate::{ - dataframe::values::Column, - values::{CustomValueSupport, NuLazyFrame}, - PolarsPlugin, -}; +use crate::{dataframe::values::Column, values::CustomValueSupport, PolarsPlugin}; use super::super::values::NuDataFrame; @@ -40,7 +36,7 @@ impl PluginCommand for SliceDF { fn examples(&self) -> Vec { vec![Example { description: "Create new dataframe from a slice of the rows", - example: "[[a b]; [1 2] [3 4]] | polars into-df | polars slice 0 1 | polars collect", + example: "[[a b]; [1 2] [3 4]] | polars into-df | polars slice 0 1", result: Some( NuDataFrame::try_from_columns( vec![ @@ -73,12 +69,12 @@ fn command( input: PipelineData, ) -> Result { let offset: i64 = call.req(0)?; - let size: i64 = call.req(1)?; + let size: usize = call.req(1)?; - let df = NuLazyFrame::try_from_pipeline_coerce(plugin, input, call.head)?; + let df = NuDataFrame::try_from_pipeline_coerce(plugin, input, call.head)?; - let res = df.to_polars().slice(offset, size as u32); - let res = NuLazyFrame::new(res); + let res = df.as_ref().slice(offset, size); + let res = NuDataFrame::new(false, res); res.to_pipeline_data(plugin, engine, call.head) } diff --git a/crates/nu_plugin_polars/src/dataframe/eager/summary.rs b/crates/nu_plugin_polars/src/dataframe/eager/summary.rs index 2b22d73bfb..5e377210b9 100644 --- a/crates/nu_plugin_polars/src/dataframe/eager/summary.rs +++ b/crates/nu_plugin_polars/src/dataframe/eager/summary.rs @@ -272,7 +272,7 @@ fn command( inner: vec![], })?; - let df = NuDataFrame::new(polars_df); + let df = NuDataFrame::new(df.from_lazy, polars_df); df.to_pipeline_data(plugin, engine, call.head) } diff --git a/crates/nu_plugin_polars/src/dataframe/eager/take.rs b/crates/nu_plugin_polars/src/dataframe/eager/take.rs index 6cbcd519e0..28b22095a1 100644 --- a/crates/nu_plugin_polars/src/dataframe/eager/take.rs +++ b/crates/nu_plugin_polars/src/dataframe/eager/take.rs @@ -143,7 +143,7 @@ fn command( inner: vec![], })?; - let df = NuDataFrame::new(polars_df); + let df = NuDataFrame::new(df.from_lazy, polars_df); df.to_pipeline_data(plugin, engine, call.head) } diff --git a/crates/nu_plugin_polars/src/dataframe/eager/with_column.rs b/crates/nu_plugin_polars/src/dataframe/eager/with_column.rs new file mode 100644 index 0000000000..5db11766b9 --- /dev/null +++ b/crates/nu_plugin_polars/src/dataframe/eager/with_column.rs @@ -0,0 +1,196 @@ +use super::super::values::{Column, NuDataFrame}; +use crate::{ + dataframe::values::{NuExpression, NuLazyFrame}, + values::{CustomValueSupport, PolarsPluginObject}, + PolarsPlugin, +}; +use nu_plugin::{EngineInterface, EvaluatedCall, PluginCommand}; +use nu_protocol::{ + Category, Example, LabeledError, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, + Value, +}; + +#[derive(Clone)] +pub struct WithColumn; + +impl PluginCommand for WithColumn { + type Plugin = PolarsPlugin; + + fn name(&self) -> &str { + "polars with-column" + } + + fn usage(&self) -> &str { + "Adds a series to the dataframe." + } + + fn signature(&self) -> Signature { + Signature::build(self.name()) + .named("name", SyntaxShape::String, "new column name", Some('n')) + .rest( + "series or expressions", + SyntaxShape::Any, + "series to be added or expressions used to define the new columns", + ) + .input_output_type( + Type::Custom("dataframe".into()), + Type::Custom("dataframe".into()), + ) + .category(Category::Custom("dataframe or lazyframe".into())) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Adds a series to the dataframe", + example: r#"[[a b]; [1 2] [3 4]] + | polars into-df + | polars with-column ([5 6] | polars into-df) --name c"#, + result: Some( + NuDataFrame::try_from_columns( + vec![ + Column::new( + "a".to_string(), + vec![Value::test_int(1), Value::test_int(3)], + ), + Column::new( + "b".to_string(), + vec![Value::test_int(2), Value::test_int(4)], + ), + Column::new( + "c".to_string(), + vec![Value::test_int(5), Value::test_int(6)], + ), + ], + None, + ) + .expect("simple df for test should not fail") + .into_value(Span::test_data()), + ), + }, + Example { + description: "Adds a series to the dataframe", + example: r#"[[a b]; [1 2] [3 4]] + | polars into-lazy + | polars with-column [ + ((polars col a) * 2 | polars as "c") + ((polars col a) * 3 | polars as "d") + ] + | polars collect"#, + result: Some( + NuDataFrame::try_from_columns( + vec![ + Column::new( + "a".to_string(), + vec![Value::test_int(1), Value::test_int(3)], + ), + Column::new( + "b".to_string(), + vec![Value::test_int(2), Value::test_int(4)], + ), + Column::new( + "c".to_string(), + vec![Value::test_int(2), Value::test_int(6)], + ), + Column::new( + "d".to_string(), + vec![Value::test_int(3), Value::test_int(9)], + ), + ], + None, + ) + .expect("simple df for test should not fail") + .into_value(Span::test_data()), + ), + }, + ] + } + + fn run( + &self, + plugin: &Self::Plugin, + engine: &EngineInterface, + call: &EvaluatedCall, + input: PipelineData, + ) -> Result { + let value = input.into_value(call.head)?; + match PolarsPluginObject::try_from_value(plugin, &value)? { + PolarsPluginObject::NuDataFrame(df) => command_eager(plugin, engine, call, df), + PolarsPluginObject::NuLazyFrame(lazy) => command_lazy(plugin, engine, call, lazy), + _ => Err(ShellError::CantConvert { + to_type: "lazy or eager dataframe".into(), + from_type: value.get_type().to_string(), + span: value.span(), + help: None, + }), + } + .map_err(LabeledError::from) + } +} + +fn command_eager( + plugin: &PolarsPlugin, + engine: &EngineInterface, + call: &EvaluatedCall, + df: NuDataFrame, +) -> Result { + let new_column: Value = call.req(0)?; + let column_span = new_column.span(); + + if NuExpression::can_downcast(&new_column) { + let vals: Vec = call.rest(0)?; + let value = Value::list(vals, call.head); + let expressions = NuExpression::extract_exprs(plugin, value)?; + let lazy = NuLazyFrame::new(true, df.lazy().to_polars().with_columns(&expressions)); + let df = lazy.collect(call.head)?; + df.to_pipeline_data(plugin, engine, call.head) + } else { + let mut other = NuDataFrame::try_from_value_coerce(plugin, &new_column, call.head)? + .as_series(column_span)?; + + let name = match call.get_flag::("name")? { + Some(name) => name, + None => other.name().to_string(), + }; + + let series = other.rename(&name).clone(); + + let mut polars_df = df.to_polars(); + polars_df + .with_column(series) + .map_err(|e| ShellError::GenericError { + error: "Error adding column to dataframe".into(), + msg: e.to_string(), + span: Some(column_span), + help: None, + inner: vec![], + })?; + + let df = NuDataFrame::new(df.from_lazy, polars_df); + df.to_pipeline_data(plugin, engine, call.head) + } +} + +fn command_lazy( + plugin: &PolarsPlugin, + engine: &EngineInterface, + call: &EvaluatedCall, + lazy: NuLazyFrame, +) -> Result { + let vals: Vec = call.rest(0)?; + let value = Value::list(vals, call.head); + let expressions = NuExpression::extract_exprs(plugin, value)?; + let lazy: NuLazyFrame = lazy.to_polars().with_columns(&expressions).into(); + lazy.to_pipeline_data(plugin, engine, call.head) +} + +#[cfg(test)] +mod test { + use super::*; + use crate::test::test_polars_plugin_command; + + #[test] + fn test_examples() -> Result<(), ShellError> { + test_polars_plugin_command(&WithColumn) + } +} diff --git a/crates/nu_plugin_polars/src/dataframe/expressions/expressions_macro.rs b/crates/nu_plugin_polars/src/dataframe/expressions/expressions_macro.rs index feb559aba5..5b1f9f1a73 100644 --- a/crates/nu_plugin_polars/src/dataframe/expressions/expressions_macro.rs +++ b/crates/nu_plugin_polars/src/dataframe/expressions/expressions_macro.rs @@ -164,6 +164,7 @@ macro_rules! lazy_expr_command { let lazy = NuLazyFrame::try_from_value_coerce(plugin, &value) .map_err(LabeledError::from)?; let lazy = NuLazyFrame::new( + lazy.from_eager, lazy.to_polars() .$func() .map_err(|e| ShellError::GenericError { @@ -244,6 +245,7 @@ macro_rules! lazy_expr_command { let lazy = NuLazyFrame::try_from_value_coerce(plugin, &value) .map_err(LabeledError::from)?; let lazy = NuLazyFrame::new( + lazy.from_eager, lazy.to_polars() .$func($ddof) .map_err(|e| ShellError::GenericError { diff --git a/crates/nu_plugin_polars/src/dataframe/expressions/is_in.rs b/crates/nu_plugin_polars/src/dataframe/expressions/is_in.rs index 47be15e2f3..136ac5c1e6 100644 --- a/crates/nu_plugin_polars/src/dataframe/expressions/is_in.rs +++ b/crates/nu_plugin_polars/src/dataframe/expressions/is_in.rs @@ -180,7 +180,8 @@ fn command_df( res.rename("is_in"); - let new_df = NuDataFrame::try_from_series_vec(vec![res.into_series()], call.head)?; + let mut new_df = NuDataFrame::try_from_series_vec(vec![res.into_series()], call.head)?; + new_df.from_lazy = df.from_lazy; new_df.to_pipeline_data(plugin, engine, call.head) } diff --git a/crates/nu_plugin_polars/src/dataframe/expressions/otherwise.rs b/crates/nu_plugin_polars/src/dataframe/expressions/otherwise.rs index 0e84d8fe96..73e616f8f8 100644 --- a/crates/nu_plugin_polars/src/dataframe/expressions/otherwise.rs +++ b/crates/nu_plugin_polars/src/dataframe/expressions/otherwise.rs @@ -48,7 +48,7 @@ impl PluginCommand for ExprOtherwise { Example { description: "Create a new column for the dataframe", example: r#"[[a b]; [6 2] [1 4] [4 1]] - | polars into-df + | polars into-lazy | polars with-column ( polars when ((polars col a) > 2) 4 | polars otherwise 5 | polars as c ) diff --git a/crates/nu_plugin_polars/src/dataframe/expressions/when.rs b/crates/nu_plugin_polars/src/dataframe/expressions/when.rs index 3c1b0eb481..9ed9ffddac 100644 --- a/crates/nu_plugin_polars/src/dataframe/expressions/when.rs +++ b/crates/nu_plugin_polars/src/dataframe/expressions/when.rs @@ -57,7 +57,7 @@ impl PluginCommand for ExprWhen { Example { description: "Create a new column for the dataframe", example: r#"[[a b]; [6 2] [1 4] [4 1]] - | polars into-df + | polars into-lazy | polars with-column ( polars when ((polars col a) > 2) 4 | polars otherwise 5 | polars as c ) diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/aggregate.rs b/crates/nu_plugin_polars/src/dataframe/lazy/aggregate.rs index d5b824ed9a..8fa717954f 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/aggregate.rs +++ b/crates/nu_plugin_polars/src/dataframe/lazy/aggregate.rs @@ -80,7 +80,7 @@ impl PluginCommand for LazyAggregate { Example { description: "Group by and perform an aggregation", example: r#"[[a b]; [1 2] [1 4] [2 6] [2 4]] - | polars into-df + | polars into-lazy | polars group-by a | polars agg [ (polars col b | polars min | polars as "b_min") @@ -147,7 +147,7 @@ impl PluginCommand for LazyAggregate { } let polars = group_by.to_polars(); - let lazy = NuLazyFrame::new(polars.agg(&expressions)); + let lazy = NuLazyFrame::new(false, polars.agg(&expressions)); lazy.to_pipeline_data(plugin, engine, call.head) .map_err(LabeledError::from) } diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/collect.rs b/crates/nu_plugin_polars/src/dataframe/lazy/collect.rs index b6d8909e31..91adc4f713 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/collect.rs +++ b/crates/nu_plugin_polars/src/dataframe/lazy/collect.rs @@ -32,8 +32,8 @@ impl PluginCommand for LazyCollect { fn examples(&self) -> Vec { vec![Example { - description: "collect a lazy dataframe", - example: "[[a b]; [1 2] [3 4]] | polars into-df | polars select [(polars col a) (polars col b)] | polars collect", + description: "drop duplicates", + example: "[[a b]; [1 2] [3 4]] | polars into-lazy | polars collect", result: Some( NuDataFrame::try_from_columns( vec![ @@ -64,7 +64,9 @@ impl PluginCommand for LazyCollect { let value = input.into_value(call.head)?; match PolarsPluginObject::try_from_value(plugin, &value)? { PolarsPluginObject::NuLazyFrame(lazy) => { - let eager = lazy.collect(call.head)?; + let mut eager = lazy.collect(call.head)?; + // We don't want this converted back to a lazy frame + eager.from_lazy = true; Ok(PipelineData::Value( eager .cache(plugin, engine, call.head)? diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/fetch.rs b/crates/nu_plugin_polars/src/dataframe/lazy/fetch.rs index 8fee4cd159..eb9663265b 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/fetch.rs +++ b/crates/nu_plugin_polars/src/dataframe/lazy/fetch.rs @@ -70,7 +70,7 @@ impl PluginCommand for LazyFetch { let value = input.into_value(call.head)?; let lazy = NuLazyFrame::try_from_value_coerce(plugin, &value)?; - let eager: NuDataFrame = lazy + let mut eager: NuDataFrame = lazy .to_polars() .fetch(rows as usize) .map_err(|e| ShellError::GenericError { @@ -82,6 +82,8 @@ impl PluginCommand for LazyFetch { })? .into(); + // mark this as not from lazy so it doesn't get converted back to a lazy frame + eager.from_lazy = false; eager .to_pipeline_data(plugin, engine, call.head) .map_err(LabeledError::from) diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/fill_null.rs b/crates/nu_plugin_polars/src/dataframe/lazy/fill_null.rs index c5fb67cd8a..6f4f13b08e 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/fill_null.rs +++ b/crates/nu_plugin_polars/src/dataframe/lazy/fill_null.rs @@ -40,7 +40,7 @@ impl PluginCommand for LazyFillNull { fn examples(&self) -> Vec { vec![Example { description: "Fills the null values by 0", - example: "[1 2 2 3 3] | polars into-df | polars shift 2 | polars fill-null 0 | polars collect", + example: "[1 2 2 3 3] | polars into-df | polars shift 2 | polars fill-null 0", result: Some( NuDataFrame::try_from_columns( vec![Column::new( @@ -96,7 +96,7 @@ fn cmd_lazy( fill: Value, ) -> Result { let expr = NuExpression::try_from_value(plugin, &fill)?.into_polars(); - let lazy = NuLazyFrame::new(lazy.to_polars().fill_null(expr)); + let lazy = NuLazyFrame::new(lazy.from_eager, lazy.to_polars().fill_null(expr)); lazy.to_pipeline_data(plugin, engine, call.head) } diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/filter.rs b/crates/nu_plugin_polars/src/dataframe/lazy/filter.rs index f8d400ddf4..e7e30fd57d 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/filter.rs +++ b/crates/nu_plugin_polars/src/dataframe/lazy/filter.rs @@ -42,7 +42,7 @@ impl PluginCommand for LazyFilter { vec![Example { description: "Filter dataframe using an expression", example: - "[[a b]; [6 2] [4 2] [2 2]] | polars into-df | polars filter ((polars col a) >= 4) | polars collect", + "[[a b]; [6 2] [4 2] [2 2]] | polars into-df | polars filter ((polars col a) >= 4)", result: Some( NuDataFrame::try_from_columns( vec![ @@ -85,7 +85,10 @@ fn command( lazy: NuLazyFrame, filter_expr: NuExpression, ) -> Result { - let lazy = NuLazyFrame::new(lazy.to_polars().filter(filter_expr.into_polars())); + let lazy = NuLazyFrame::new( + lazy.from_eager, + lazy.to_polars().filter(filter_expr.into_polars()), + ); lazy.to_pipeline_data(plugin, engine, call.head) } diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/filter_with.rs b/crates/nu_plugin_polars/src/dataframe/lazy/filter_with.rs deleted file mode 100644 index 12ccfbc376..0000000000 --- a/crates/nu_plugin_polars/src/dataframe/lazy/filter_with.rs +++ /dev/null @@ -1,97 +0,0 @@ -use nu_plugin::{EngineInterface, EvaluatedCall, PluginCommand}; -use nu_protocol::{ - Category, Example, LabeledError, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, - Value, -}; -use polars::prelude::LazyFrame; - -use crate::{ - dataframe::values::{NuExpression, NuLazyFrame}, - values::CustomValueSupport, - PolarsPlugin, -}; - -use super::super::values::{Column, NuDataFrame}; - -#[derive(Clone)] -pub struct FilterWith; - -impl PluginCommand for FilterWith { - type Plugin = PolarsPlugin; - - fn name(&self) -> &str { - "polars filter-with" - } - - fn usage(&self) -> &str { - "Filters dataframe using an expression." - } - - fn signature(&self) -> Signature { - Signature::build(self.name()) - .required( - "filter expression", - SyntaxShape::Any, - "filter expression used to filter dataframe", - ) - .input_output_type( - Type::Custom("dataframe".into()), - Type::Custom("dataframe".into()), - ) - .category(Category::Custom("dataframe or lazyframe".into())) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Filter dataframe using an expression", - example: - "[[a b]; [1 2] [3 4]] | polars into-df | polars filter-with ((polars col a) > 1)", - result: Some( - NuDataFrame::try_from_columns( - vec![ - Column::new("a".to_string(), vec![Value::test_int(3)]), - Column::new("b".to_string(), vec![Value::test_int(4)]), - ], - None, - ) - .expect("simple df for test should not fail") - .into_value(Span::test_data()), - ), - }] - } - - fn run( - &self, - plugin: &Self::Plugin, - engine: &EngineInterface, - call: &EvaluatedCall, - input: PipelineData, - ) -> Result { - let value = input.into_value(call.head)?; - let lazy = NuLazyFrame::try_from_value_coerce(plugin, &value)?; - command_lazy(plugin, engine, call, lazy).map_err(LabeledError::from) - } -} - -fn command_lazy( - plugin: &PolarsPlugin, - engine: &EngineInterface, - call: &EvaluatedCall, - lazy: NuLazyFrame, -) -> Result { - let expr: Value = call.req(0)?; - let expr = NuExpression::try_from_value(plugin, &expr)?; - let lazy = lazy.apply_with_expr(expr, LazyFrame::filter); - lazy.to_pipeline_data(plugin, engine, call.head) -} - -#[cfg(test)] -mod test { - use super::*; - use crate::test::test_polars_plugin_command; - - #[test] - fn test_examples() -> Result<(), ShellError> { - test_polars_plugin_command(&FilterWith) - } -} diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/groupby.rs b/crates/nu_plugin_polars/src/dataframe/lazy/groupby.rs index 7aaccfead9..9edf8f5e60 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/groupby.rs +++ b/crates/nu_plugin_polars/src/dataframe/lazy/groupby.rs @@ -79,7 +79,7 @@ impl PluginCommand for ToLazyGroupBy { Example { description: "Group by and perform an aggregation", example: r#"[[a b]; [1 2] [1 4] [2 6] [2 4]] - | polars into-df + | polars into-lazy | polars group-by a | polars agg [ (polars col b | polars min | polars as "b_min") @@ -152,7 +152,7 @@ fn command( expressions: Vec, ) -> Result { let group_by = lazy.to_polars().group_by(expressions); - let group_by = NuLazyGroupBy::new(group_by, lazy.schema()?); + let group_by = NuLazyGroupBy::new(group_by, lazy.from_eager, lazy.schema()?); group_by.to_pipeline_data(plugin, engine, call.head) } diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/join.rs b/crates/nu_plugin_polars/src/dataframe/lazy/join.rs index 6db0269403..d6d2ef69ba 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/join.rs +++ b/crates/nu_plugin_polars/src/dataframe/lazy/join.rs @@ -54,8 +54,8 @@ impl PluginCommand for LazyJoin { vec![ Example { description: "Join two lazy dataframes", - example: r#"let df_a = ([[a b c];[1 "a" 0] [2 "b" 1] [1 "c" 2] [1 "c" 3]] | polars into-df); - let df_b = ([["foo" "bar" "ham"];[1 "a" "let"] [2 "c" "var"] [3 "c" "const"]] | polars into-df); + example: r#"let df_a = ([[a b c];[1 "a" 0] [2 "b" 1] [1 "c" 2] [1 "c" 3]] | polars into-lazy); + let df_b = ([["foo" "bar" "ham"];[1 "a" "let"] [2 "c" "var"] [3 "c" "const"]] | polars into-lazy); $df_a | polars join $df_b a foo | polars collect"#, result: Some( NuDataFrame::try_from_columns( @@ -115,7 +115,7 @@ impl PluginCommand for LazyJoin { Example { description: "Join one eager dataframe with a lazy dataframe", example: r#"let df_a = ([[a b c];[1 "a" 0] [2 "b" 1] [1 "c" 2] [1 "c" 3]] | polars into-df); - let df_b = ([["foo" "bar" "ham"];[1 "a" "let"] [2 "c" "var"] [3 "c" "const"]] | polars into-df); + let df_b = ([["foo" "bar" "ham"];[1 "a" "let"] [2 "c" "var"] [3 "c" "const"]] | polars into-lazy); $df_a | polars join $df_b a foo"#, result: Some( NuDataFrame::try_from_columns( @@ -230,6 +230,7 @@ impl PluginCommand for LazyJoin { let value = input.into_value(call.head)?; let lazy = NuLazyFrame::try_from_value_coerce(plugin, &value)?; + let from_eager = lazy.from_eager; let lazy = lazy.to_polars(); let lazy = lazy @@ -242,7 +243,7 @@ impl PluginCommand for LazyJoin { .suffix(suffix) .finish(); - let lazy = NuLazyFrame::new(lazy); + let lazy = NuLazyFrame::new(from_eager, lazy); lazy.to_pipeline_data(plugin, engine, call.head) .map_err(LabeledError::from) } diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/macro_commands.rs b/crates/nu_plugin_polars/src/dataframe/lazy/macro_commands.rs index 447c806ea3..1727946f6a 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/macro_commands.rs +++ b/crates/nu_plugin_polars/src/dataframe/lazy/macro_commands.rs @@ -46,7 +46,7 @@ macro_rules! lazy_command { ) -> Result { let lazy = NuLazyFrame::try_from_pipeline_coerce(plugin, input, call.head) .map_err(LabeledError::from)?; - let lazy = NuLazyFrame::new(lazy.to_polars().$func()); + let lazy = NuLazyFrame::new(lazy.from_eager, lazy.to_polars().$func()); lazy.to_pipeline_data(plugin, engine, call.head) .map_err(LabeledError::from) } diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/median.rs b/crates/nu_plugin_polars/src/dataframe/lazy/median.rs index ffd69d14e4..6e42856723 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/median.rs +++ b/crates/nu_plugin_polars/src/dataframe/lazy/median.rs @@ -126,7 +126,7 @@ fn command( span: None, inner: vec![], })?; - let lazy = NuLazyFrame::new(polars_lazy); + let lazy = NuLazyFrame::new(lazy.from_eager, polars_lazy); lazy.to_pipeline_data(plugin, engine, call.head) } diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/mod.rs b/crates/nu_plugin_polars/src/dataframe/lazy/mod.rs index 1048fcc4c0..e70143e6ce 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/mod.rs +++ b/crates/nu_plugin_polars/src/dataframe/lazy/mod.rs @@ -1,30 +1,19 @@ mod aggregate; -mod cast; mod collect; -mod drop; -mod drop_duplicates; -mod drop_nulls; mod explode; mod fetch; mod fill_nan; mod fill_null; mod filter; -mod filter_with; -mod first; mod flatten; -mod get; pub mod groupby; mod join; -mod last; mod macro_commands; mod median; -mod melt; mod quantile; -mod rename; mod select; -mod slice; mod sort_by_expr; -mod with_column; +mod to_lazy; use nu_plugin::PluginCommand; @@ -40,20 +29,13 @@ pub(crate) use crate::dataframe::lazy::macro_commands::*; use crate::dataframe::lazy::quantile::LazyQuantile; pub(crate) use crate::dataframe::lazy::select::LazySelect; use crate::dataframe::lazy::sort_by_expr::LazySortBy; +pub use crate::dataframe::lazy::to_lazy::ToLazyFrame; use crate::PolarsPlugin; pub use explode::LazyExplode; pub use flatten::LazyFlatten; pub(crate) fn lazy_commands() -> Vec>> { vec![ - Box::new(cast::CastDF), - Box::new(drop::DropDF), - Box::new(drop_duplicates::DropDuplicates), - Box::new(drop_nulls::DropNulls), - Box::new(filter_with::FilterWith), - Box::new(first::FirstDF), - Box::new(get::GetDF), - Box::new(last::LastDF), Box::new(LazyAggregate), Box::new(LazyCache), Box::new(LazyCollect), @@ -65,14 +47,11 @@ pub(crate) fn lazy_commands() -> Vec Result { let lazy = NuLazyFrame::new( + lazy.from_eager, lazy.to_polars() .quantile(lit(quantile), QuantileInterpolOptions::default()) .map_err(|e| ShellError::GenericError { diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/select.rs b/crates/nu_plugin_polars/src/dataframe/lazy/select.rs index 75b3f8f804..03c4306c30 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/select.rs +++ b/crates/nu_plugin_polars/src/dataframe/lazy/select.rs @@ -67,7 +67,7 @@ impl PluginCommand for LazySelect { let pipeline_value = input.into_value(call.head)?; let lazy = NuLazyFrame::try_from_value_coerce(plugin, &pipeline_value)?; - let lazy = NuLazyFrame::new(lazy.to_polars().select(&expressions)); + let lazy = NuLazyFrame::new(lazy.from_eager, lazy.to_polars().select(&expressions)); lazy.to_pipeline_data(plugin, engine, call.head) .map_err(LabeledError::from) } diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/sort_by_expr.rs b/crates/nu_plugin_polars/src/dataframe/lazy/sort_by_expr.rs index 2beba4424c..b282bd6d04 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/sort_by_expr.rs +++ b/crates/nu_plugin_polars/src/dataframe/lazy/sort_by_expr.rs @@ -147,7 +147,10 @@ impl PluginCommand for LazySortBy { let pipeline_value = input.into_value(call.head)?; let lazy = NuLazyFrame::try_from_value_coerce(plugin, &pipeline_value)?; - let lazy = NuLazyFrame::new(lazy.to_polars().sort_by_exprs(&expressions, sort_options)); + let lazy = NuLazyFrame::new( + lazy.from_eager, + lazy.to_polars().sort_by_exprs(&expressions, sort_options), + ); lazy.to_pipeline_data(plugin, engine, call.head) .map_err(LabeledError::from) } diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/to_lazy.rs b/crates/nu_plugin_polars/src/dataframe/lazy/to_lazy.rs new file mode 100644 index 0000000000..df6616e178 --- /dev/null +++ b/crates/nu_plugin_polars/src/dataframe/lazy/to_lazy.rs @@ -0,0 +1,90 @@ +use crate::{dataframe::values::NuSchema, values::CustomValueSupport, Cacheable, PolarsPlugin}; + +use super::super::values::{NuDataFrame, NuLazyFrame}; + +use nu_plugin::{EngineInterface, EvaluatedCall, PluginCommand}; +use nu_protocol::{Category, Example, LabeledError, PipelineData, Signature, SyntaxShape, Type}; + +#[derive(Clone)] +pub struct ToLazyFrame; + +impl PluginCommand for ToLazyFrame { + type Plugin = PolarsPlugin; + + fn name(&self) -> &str { + "polars into-lazy" + } + + fn usage(&self) -> &str { + "Converts a dataframe into a lazy dataframe." + } + + fn signature(&self) -> Signature { + Signature::build(self.name()) + .named( + "schema", + SyntaxShape::Record(vec![]), + r#"Polars Schema in format [{name: str}]. CSV, JSON, and JSONL files"#, + Some('s'), + ) + .input_output_type(Type::Any, Type::Custom("dataframe".into())) + .category(Category::Custom("lazyframe".into())) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Takes a table and creates a lazyframe", + example: "[[a b];[1 2] [3 4]] | polars into-lazy", + result: None, + }, + Example { + description: "Takes a table, creates a lazyframe, assigns column 'b' type str, displays the schema", + example: "[[a b];[1 2] [3 4]] | polars into-lazy --schema {b: str} | polars schema", + result: None + }, + ] + } + + fn run( + &self, + plugin: &Self::Plugin, + engine: &EngineInterface, + call: &EvaluatedCall, + input: PipelineData, + ) -> Result { + let maybe_schema = call + .get_flag("schema")? + .map(|schema| NuSchema::try_from(&schema)) + .transpose()?; + + let df = NuDataFrame::try_from_iter(plugin, input.into_iter(), maybe_schema)?; + let mut lazy = NuLazyFrame::from_dataframe(df); + // We don't want this converted back to an eager dataframe at some point + lazy.from_eager = false; + Ok(PipelineData::Value( + lazy.cache(plugin, engine, call.head)?.into_value(call.head), + None, + )) + } +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use nu_plugin_test_support::PluginTest; + use nu_protocol::{ShellError, Span}; + + use super::*; + + #[test] + fn test_to_lazy() -> Result<(), ShellError> { + let plugin: Arc = PolarsPlugin::new_test_mode().into(); + let mut plugin_test = PluginTest::new("polars", Arc::clone(&plugin))?; + let pipeline_data = plugin_test.eval("[[a b]; [6 2] [1 4] [4 1]] | polars into-lazy")?; + let value = pipeline_data.into_value(Span::test_data())?; + let df = NuLazyFrame::try_from_value(&plugin, &value)?; + assert!(!df.from_eager); + Ok(()) + } +} diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/with_column.rs b/crates/nu_plugin_polars/src/dataframe/lazy/with_column.rs deleted file mode 100644 index d2f953b068..0000000000 --- a/crates/nu_plugin_polars/src/dataframe/lazy/with_column.rs +++ /dev/null @@ -1,114 +0,0 @@ -use super::super::values::{Column, NuDataFrame}; -use crate::{ - dataframe::values::{NuExpression, NuLazyFrame}, - values::CustomValueSupport, - PolarsPlugin, -}; -use nu_plugin::{EngineInterface, EvaluatedCall, PluginCommand}; -use nu_protocol::{ - Category, Example, LabeledError, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, - Value, -}; - -#[derive(Clone)] -pub struct WithColumn; - -impl PluginCommand for WithColumn { - type Plugin = PolarsPlugin; - - fn name(&self) -> &str { - "polars with-column" - } - - fn usage(&self) -> &str { - "Adds a series to the dataframe." - } - - fn signature(&self) -> Signature { - Signature::build(self.name()) - .rest( - "series or expressions", - SyntaxShape::Any, - "series to be added or expressions used to define the new columns", - ) - .input_output_type( - Type::Custom("dataframe".into()), - Type::Custom("dataframe".into()), - ) - .category(Category::Custom("dataframe or lazyframe".into())) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Adds a series to the dataframe", - example: r#"[[a b]; [1 2] [3 4]] - | polars into-df - | polars with-column [ - ((polars col a) * 2 | polars as "c") - ((polars col a) * 3 | polars as "d") - ] - | polars collect"#, - result: Some( - NuDataFrame::try_from_columns( - vec![ - Column::new( - "a".to_string(), - vec![Value::test_int(1), Value::test_int(3)], - ), - Column::new( - "b".to_string(), - vec![Value::test_int(2), Value::test_int(4)], - ), - Column::new( - "c".to_string(), - vec![Value::test_int(2), Value::test_int(6)], - ), - Column::new( - "d".to_string(), - vec![Value::test_int(3), Value::test_int(9)], - ), - ], - None, - ) - .expect("simple df for test should not fail") - .into_value(Span::test_data()), - ), - }] - } - - fn run( - &self, - plugin: &Self::Plugin, - engine: &EngineInterface, - call: &EvaluatedCall, - input: PipelineData, - ) -> Result { - let value = input.into_value(call.head)?; - let lazy = NuLazyFrame::try_from_value_coerce(plugin, &value)?; - command_lazy(plugin, engine, call, lazy).map_err(LabeledError::from) - } -} - -fn command_lazy( - plugin: &PolarsPlugin, - engine: &EngineInterface, - call: &EvaluatedCall, - lazy: NuLazyFrame, -) -> Result { - let vals: Vec = call.rest(0)?; - let value = Value::list(vals, call.head); - let expressions = NuExpression::extract_exprs(plugin, value)?; - let lazy: NuLazyFrame = lazy.to_polars().with_columns(&expressions).into(); - lazy.to_pipeline_data(plugin, engine, call.head) -} - -#[cfg(test)] -mod test { - use super::*; - use crate::test::test_polars_plugin_command; - - #[test] - fn test_examples() -> Result<(), ShellError> { - test_polars_plugin_command(&WithColumn) - } -} diff --git a/crates/nu_plugin_polars/src/dataframe/series/shift.rs b/crates/nu_plugin_polars/src/dataframe/series/shift.rs index c37ba2f2e9..58dc64ec47 100644 --- a/crates/nu_plugin_polars/src/dataframe/series/shift.rs +++ b/crates/nu_plugin_polars/src/dataframe/series/shift.rs @@ -1,6 +1,6 @@ use crate::{ dataframe::values::{NuExpression, NuLazyFrame}, - values::CustomValueSupport, + values::{cant_convert_err, CustomValueSupport, PolarsPluginObject, PolarsPluginType}, PolarsPlugin, }; @@ -63,7 +63,8 @@ impl PluginCommand for Shift { }, Example { description: "Shifts the values by a given period, fill absent values with 0", - example: "[1 2 2 3 3] | polars into-df | polars shift 2 --fill 0 | polars collect", + example: + "[1 2 2 3 3] | polars into-lazy | polars shift 2 --fill 0 | polars collect", result: Some( NuDataFrame::try_from_columns( vec![Column::new( @@ -93,11 +94,35 @@ impl PluginCommand for Shift { input: PipelineData, ) -> Result { let value = input.into_value(call.head)?; - let lazy = NuLazyFrame::try_from_value_coerce(plugin, &value)?; - command_lazy(plugin, engine, call, lazy).map_err(LabeledError::from) + + match PolarsPluginObject::try_from_value(plugin, &value)? { + PolarsPluginObject::NuDataFrame(df) => command_eager(plugin, engine, call, df), + PolarsPluginObject::NuLazyFrame(lazy) => command_lazy(plugin, engine, call, lazy), + _ => Err(cant_convert_err( + &value, + &[ + PolarsPluginType::NuDataFrame, + PolarsPluginType::NuLazyGroupBy, + ], + )), + } + .map_err(LabeledError::from) } } +fn command_eager( + plugin: &PolarsPlugin, + engine: &EngineInterface, + call: &EvaluatedCall, + df: NuDataFrame, +) -> Result { + let period: i64 = call.req(0)?; + let series = df.as_series(call.head)?.shift(period); + + let df = NuDataFrame::try_from_series_vec(vec![series], call.head)?; + df.to_pipeline_data(plugin, engine, call.head) +} + fn command_lazy( plugin: &PolarsPlugin, engine: &EngineInterface, diff --git a/crates/nu_plugin_polars/src/dataframe/series/unique.rs b/crates/nu_plugin_polars/src/dataframe/series/unique.rs index 2475ad026a..7626b35404 100644 --- a/crates/nu_plugin_polars/src/dataframe/series/unique.rs +++ b/crates/nu_plugin_polars/src/dataframe/series/unique.rs @@ -1,6 +1,6 @@ use crate::{ dataframe::{utils::extract_strings, values::NuLazyFrame}, - values::CustomValueSupport, + values::{cant_convert_err, CustomValueSupport, PolarsPluginObject, PolarsPluginType}, PolarsPlugin, }; @@ -11,7 +11,7 @@ use nu_protocol::{ Category, Example, LabeledError, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value, }; -use polars::prelude::UniqueKeepStrategy; +use polars::prelude::{IntoSeries, UniqueKeepStrategy}; #[derive(Clone)] pub struct Unique; @@ -68,7 +68,7 @@ impl PluginCommand for Unique { }, Example { description: "Returns unique values in a subset of lazyframe columns", - example: "[[a b c]; [1 2 1] [2 2 2] [3 2 1]] | polars into-df | polars unique --subset [b c] | polars collect", + example: "[[a b c]; [1 2 1] [2 2 2] [3 2 1]] | polars into-lazy | polars unique --subset [b c] | polars collect", result: Some( NuDataFrame::try_from_columns( vec![ @@ -94,7 +94,7 @@ impl PluginCommand for Unique { Example { description: "Returns unique values in a subset of lazyframe columns", example: r#"[[a b c]; [1 2 1] [2 2 2] [3 2 1]] - | polars into-df + | polars into-lazy | polars unique --subset [b c] --last | polars collect"#, result: Some( @@ -135,11 +135,42 @@ impl PluginCommand for Unique { input: PipelineData, ) -> Result { let value = input.into_value(call.head)?; - let df = NuLazyFrame::try_from_value_coerce(plugin, &value)?; - command_lazy(plugin, engine, call, df).map_err(LabeledError::from) + + match PolarsPluginObject::try_from_value(plugin, &value)? { + PolarsPluginObject::NuDataFrame(df) => command_eager(plugin, engine, call, df), + PolarsPluginObject::NuLazyFrame(lazy) => command_lazy(plugin, engine, call, lazy), + _ => Err(cant_convert_err( + &value, + &[ + PolarsPluginType::NuDataFrame, + PolarsPluginType::NuLazyGroupBy, + ], + )), + } + .map_err(LabeledError::from) } } +fn command_eager( + plugin: &PolarsPlugin, + engine: &EngineInterface, + call: &EvaluatedCall, + df: NuDataFrame, +) -> Result { + let series = df.as_series(call.head)?; + + let res = series.unique().map_err(|e| ShellError::GenericError { + error: "Error calculating unique values".into(), + msg: e.to_string(), + span: Some(call.head), + help: Some("The str-slice command can only be used with string columns".into()), + inner: vec![], + })?; + + let df = NuDataFrame::try_from_series_vec(vec![res.into_series()], call.head)?; + df.to_pipeline_data(plugin, engine, call.head) +} + fn command_lazy( plugin: &PolarsPlugin, engine: &EngineInterface, diff --git a/crates/nu_plugin_polars/src/dataframe/values/mod.rs b/crates/nu_plugin_polars/src/dataframe/values/mod.rs index 179c85bf36..d52ee25203 100644 --- a/crates/nu_plugin_polars/src/dataframe/values/mod.rs +++ b/crates/nu_plugin_polars/src/dataframe/values/mod.rs @@ -323,7 +323,19 @@ pub trait CustomValueSupport: Cacheable { engine: &EngineInterface, span: Span, ) -> Result { - Ok(self.cache(plugin, engine, span)?.into_value(span)) + match self.to_cache_value()? { + // if it was from a lazy value, make it lazy again + PolarsPluginObject::NuDataFrame(df) if df.from_lazy => { + let df = df.lazy(); + Ok(df.cache(plugin, engine, span)?.into_value(span)) + } + // if it was from an eager value, make it eager again + PolarsPluginObject::NuLazyFrame(lf) if lf.from_eager => { + let lf = lf.collect(span)?; + Ok(lf.cache(plugin, engine, span)?.into_value(span)) + } + _ => Ok(self.cache(plugin, engine, span)?.into_value(span)), + } } /// Caches the object, converts it to a it's CustomValue counterpart diff --git a/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/conversion.rs b/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/conversion.rs index 7000cf10c4..f7941bf41d 100644 --- a/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/conversion.rs +++ b/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/conversion.rs @@ -472,7 +472,7 @@ pub fn from_parsed_columns(column_values: ColumnMap) -> Result, + pub from_lazy: bool, } impl AsRef for NuDataFrame { @@ -114,16 +115,17 @@ impl AsRef for NuDataFrame { impl From for NuDataFrame { fn from(df: DataFrame) -> Self { - Self::new(df) + Self::new(false, df) } } impl NuDataFrame { - pub fn new(df: DataFrame) -> Self { + pub fn new(from_lazy: bool, df: DataFrame) -> Self { let id = Uuid::new_v4(); Self { id, df: Arc::new(df), + from_lazy, } } @@ -132,12 +134,12 @@ impl NuDataFrame { } pub fn lazy(&self) -> NuLazyFrame { - NuLazyFrame::new(self.to_polars().lazy()) + NuLazyFrame::new(true, self.to_polars().lazy()) } pub fn try_from_series(series: Series, span: Span) -> Result { match DataFrame::new(vec![series]) { - Ok(dataframe) => Ok(NuDataFrame::new(dataframe)), + Ok(dataframe) => Ok(NuDataFrame::new(false, dataframe)), Err(e) => Err(ShellError::GenericError { error: "Error creating dataframe".into(), msg: e.to_string(), @@ -200,7 +202,7 @@ impl NuDataFrame { inner: vec![], })?; - Ok(Self::new(dataframe)) + Ok(Self::new(false, dataframe)) } pub fn try_from_columns( @@ -274,7 +276,7 @@ impl NuDataFrame { inner: vec![], })?; - Ok(Self::new(df)) + Ok(Self::new(false, df)) } pub fn is_series(&self) -> bool { diff --git a/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/operations.rs b/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/operations.rs index db5409aff2..c471fc05b8 100644 --- a/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/operations.rs +++ b/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/operations.rs @@ -147,7 +147,7 @@ impl NuDataFrame { inner: vec![], })?; - Ok(NuDataFrame::new(df_new)) + Ok(NuDataFrame::new(false, df_new)) } Axis::Column => { if self.df.width() != other.df.width() { @@ -205,7 +205,7 @@ impl NuDataFrame { inner: vec![], })?; - Ok(NuDataFrame::new(df_new)) + Ok(NuDataFrame::new(false, df_new)) } } } diff --git a/crates/nu_plugin_polars/src/dataframe/values/nu_expression/custom_value.rs b/crates/nu_plugin_polars/src/dataframe/values/nu_expression/custom_value.rs index a9371f03f2..ea751b0255 100644 --- a/crates/nu_plugin_polars/src/dataframe/values/nu_expression/custom_value.rs +++ b/crates/nu_plugin_polars/src/dataframe/values/nu_expression/custom_value.rs @@ -63,16 +63,45 @@ fn compute_with_value( op: Span, right: &Value, ) -> Result { - let rhs = NuExpression::try_from_value(plugin, right)?; - with_operator( - (plugin, engine), - operator, - left, - &rhs, - lhs_span, - right.span(), - op, - ) + let rhs_span = right.span(); + match right { + Value::Custom { val: rhs, .. } => { + let rhs = rhs.as_any().downcast_ref::().ok_or_else(|| { + ShellError::TypeMismatch { + err_message: "Right hand side not a dataframe expression".into(), + span: rhs_span, + } + })?; + + match rhs.as_ref() { + polars::prelude::Expr::Literal(..) => with_operator( + (plugin, engine), + operator, + left, + rhs, + lhs_span, + right.span(), + op, + ), + _ => Err(ShellError::TypeMismatch { + err_message: "Only literal expressions or number".into(), + span: right.span(), + }), + } + } + _ => { + let rhs = NuExpression::try_from_value(plugin, right)?; + with_operator( + (plugin, engine), + operator, + left, + &rhs, + lhs_span, + right.span(), + op, + ) + } + } } fn with_operator( diff --git a/crates/nu_plugin_polars/src/dataframe/values/nu_lazyframe/mod.rs b/crates/nu_plugin_polars/src/dataframe/values/nu_lazyframe/mod.rs index 48e296e95e..53e2b425b7 100644 --- a/crates/nu_plugin_polars/src/dataframe/values/nu_lazyframe/mod.rs +++ b/crates/nu_plugin_polars/src/dataframe/values/nu_lazyframe/mod.rs @@ -21,6 +21,7 @@ pub use custom_value::NuLazyFrameCustomValue; pub struct NuLazyFrame { pub id: Uuid, pub lazy: Arc, + pub from_eager: bool, } impl fmt::Debug for NuLazyFrame { @@ -31,21 +32,22 @@ impl fmt::Debug for NuLazyFrame { impl From for NuLazyFrame { fn from(lazy_frame: LazyFrame) -> Self { - NuLazyFrame::new(lazy_frame) + NuLazyFrame::new(false, lazy_frame) } } impl NuLazyFrame { - pub fn new(lazy: LazyFrame) -> Self { + pub fn new(from_eager: bool, lazy: LazyFrame) -> Self { Self { id: Uuid::new_v4(), lazy: Arc::new(lazy), + from_eager, } } pub fn from_dataframe(df: NuDataFrame) -> Self { let lazy = df.as_ref().clone().lazy(); - NuLazyFrame::new(lazy) + NuLazyFrame::new(true, lazy) } pub fn to_polars(&self) -> LazyFrame { @@ -62,7 +64,7 @@ impl NuLazyFrame { help: None, inner: vec![], }) - .map(NuDataFrame::new) + .map(|df| NuDataFrame::new(true, df)) } pub fn apply_with_expr(self, expr: NuExpression, f: F) -> Self @@ -72,7 +74,7 @@ impl NuLazyFrame { let df = self.to_polars(); let expr = expr.into_polars(); let new_frame = f(df, expr); - Self::new(new_frame) + Self::new(self.from_eager, new_frame) } pub fn schema(&self) -> Result { diff --git a/crates/nu_plugin_polars/src/dataframe/values/nu_lazygroupby/mod.rs b/crates/nu_plugin_polars/src/dataframe/values/nu_lazygroupby/mod.rs index fe5bc329e7..8540d13c6f 100644 --- a/crates/nu_plugin_polars/src/dataframe/values/nu_lazygroupby/mod.rs +++ b/crates/nu_plugin_polars/src/dataframe/values/nu_lazygroupby/mod.rs @@ -20,6 +20,7 @@ pub struct NuLazyGroupBy { pub id: Uuid, pub group_by: Arc, pub schema: NuSchema, + pub from_eager: bool, } impl fmt::Debug for NuLazyGroupBy { @@ -29,10 +30,11 @@ impl fmt::Debug for NuLazyGroupBy { } impl NuLazyGroupBy { - pub fn new(group_by: LazyGroupBy, schema: NuSchema) -> Self { + pub fn new(group_by: LazyGroupBy, from_eager: bool, schema: NuSchema) -> Self { NuLazyGroupBy { id: Uuid::new_v4(), group_by: Arc::new(group_by), + from_eager, schema, } } diff --git a/crates/nu_plugin_polars/src/dataframe/values/utils.rs b/crates/nu_plugin_polars/src/dataframe/values/utils.rs index 88ce8a4656..6a51821c2f 100644 --- a/crates/nu_plugin_polars/src/dataframe/values/utils.rs +++ b/crates/nu_plugin_polars/src/dataframe/values/utils.rs @@ -48,6 +48,8 @@ pub(crate) fn convert_columns( // Converts a Vec to a Vec with a Span marking the whole // location of the columns for error referencing +// todo - fix +#[allow(dead_code)] pub(crate) fn convert_columns_string( columns: Vec, span: Span, From b06f31d3c634a55cee5031f6a0daefb5f435a925 Mon Sep 17 00:00:00 2001 From: Devyn Cairns Date: Fri, 24 May 2024 16:37:50 -0700 Subject: [PATCH 021/113] Make `from json --objects` streaming (#12949) # Description Makes the `from json --objects` command produce a stream, and read lazily from an input stream to produce its output. Also added a helper, `PipelineData::get_type()`, to make it easier to construct a wrong type error message when matching on `PipelineData`. I expect checking `PipelineData` for either a string value or an `Unknown` or `String` typed `ByteStream` will be very, very common. I would have liked to have a helper that just returns a readable stream from either, but that would either be a bespoke enum or a `Box`, which feels like it wouldn't be so great for performance. So instead, taking the approach I did here is probably better - having a function that accepts the `impl BufRead` and matching to use it. # User-Facing Changes - `from json --objects` no longer collects its input, and can be used for large datasets or streams that produce values over time. # Tests + Formatting All passing. # After Submitting - [ ] release notes --------- Co-authored-by: Ian Manske --- crates/nu-command/src/formats/from/json.rs | 112 ++++++++++++------ .../tests/format_conversions/json.rs | 26 ++++ .../nu-protocol/src/pipeline/pipeline_data.rs | 20 +++- 3 files changed, 124 insertions(+), 34 deletions(-) diff --git a/crates/nu-command/src/formats/from/json.rs b/crates/nu-command/src/formats/from/json.rs index ea449711c1..e8b5d58e9e 100644 --- a/crates/nu-command/src/formats/from/json.rs +++ b/crates/nu-command/src/formats/from/json.rs @@ -1,4 +1,10 @@ +use std::{ + io::{BufRead, Cursor}, + sync::{atomic::AtomicBool, Arc}, +}; + use nu_engine::command_prelude::*; +use nu_protocol::ListStream; #[derive(Clone)] pub struct FromJson; @@ -45,6 +51,15 @@ impl Command for FromJson { "b" => Value::test_int(2), })), }, + Example { + example: r#"'{ "a": 1 } +{ "b": 2 }' | from json --objects"#, + description: "Parse a stream of line-delimited JSON values", + result: Some(Value::test_list(vec![ + Value::test_record(record! {"a" => Value::test_int(1)}), + Value::test_record(record! {"b" => Value::test_int(2)}), + ])), + }, ] } @@ -56,49 +71,80 @@ impl Command for FromJson { input: PipelineData, ) -> Result { let span = call.head; - let (string_input, span, metadata) = input.collect_string_strict(span)?; - - if string_input.is_empty() { - return Ok(Value::nothing(span).into_pipeline_data()); - } let strict = call.has_flag(engine_state, stack, "strict")?; // TODO: turn this into a structured underline of the nu_json error if call.has_flag(engine_state, stack, "objects")? { - let lines = string_input.lines().filter(|line| !line.trim().is_empty()); - - let converted_lines: Vec<_> = if strict { - lines - .map(|line| { - convert_string_to_value_strict(line, span) - .unwrap_or_else(|err| Value::error(err, span)) - }) - .collect() - } else { - lines - .map(|line| { - convert_string_to_value(line, span) - .unwrap_or_else(|err| Value::error(err, span)) - }) - .collect() - }; - - Ok(converted_lines.into_pipeline_data_with_metadata( - span, - engine_state.ctrlc.clone(), - metadata, - )) - } else if strict { - Ok(convert_string_to_value_strict(&string_input, span)? - .into_pipeline_data_with_metadata(metadata)) + // Return a stream of JSON values, one for each non-empty line + match input { + PipelineData::Value(Value::String { val, .. }, metadata) => { + Ok(PipelineData::ListStream( + read_json_lines(Cursor::new(val), span, strict, engine_state.ctrlc.clone()), + metadata, + )) + } + PipelineData::ByteStream(stream, metadata) + if stream.type_() != ByteStreamType::Binary => + { + if let Some(reader) = stream.reader() { + Ok(PipelineData::ListStream( + read_json_lines(reader, span, strict, None), + metadata, + )) + } else { + Ok(PipelineData::Empty) + } + } + _ => Err(ShellError::OnlySupportsThisInputType { + exp_input_type: "string".into(), + wrong_type: input.get_type().to_string(), + dst_span: call.head, + src_span: input.span().unwrap_or(call.head), + }), + } } else { - Ok(convert_string_to_value(&string_input, span)? - .into_pipeline_data_with_metadata(metadata)) + // Return a single JSON value + let (string_input, span, metadata) = input.collect_string_strict(span)?; + + if string_input.is_empty() { + return Ok(Value::nothing(span).into_pipeline_data()); + } + + if strict { + Ok(convert_string_to_value_strict(&string_input, span)? + .into_pipeline_data_with_metadata(metadata)) + } else { + Ok(convert_string_to_value(&string_input, span)? + .into_pipeline_data_with_metadata(metadata)) + } } } } +/// Create a stream of values from a reader that produces line-delimited JSON +fn read_json_lines( + input: impl BufRead + Send + 'static, + span: Span, + strict: bool, + interrupt: Option>, +) -> ListStream { + let iter = input + .lines() + .filter(|line| line.as_ref().is_ok_and(|line| !line.trim().is_empty()) || line.is_err()) + .map(move |line| { + let line = line.err_span(span)?; + if strict { + convert_string_to_value_strict(&line, span) + } else { + convert_string_to_value(&line, span) + } + }) + .map(move |result| result.unwrap_or_else(|err| Value::error(err, span))); + + ListStream::new(iter, span, interrupt) +} + fn convert_nujson_to_value(value: nu_json::Value, span: Span) -> Value { match value { nu_json::Value::Array(array) => Value::list( diff --git a/crates/nu-command/tests/format_conversions/json.rs b/crates/nu-command/tests/format_conversions/json.rs index 1989000df6..643e4c3f22 100644 --- a/crates/nu-command/tests/format_conversions/json.rs +++ b/crates/nu-command/tests/format_conversions/json.rs @@ -96,6 +96,32 @@ fn from_json_text_recognizing_objects_independently_to_table() { }) } +#[test] +fn from_json_text_objects_is_stream() { + Playground::setup("filter_from_json_test_2_is_stream", |dirs, sandbox| { + sandbox.with_files(&[FileWithContentToBeTrimmed( + "katz.txt", + r#" + {"name": "Yehuda", "rusty_luck": 1} + {"name": "JT", "rusty_luck": 1} + {"name": "Andres", "rusty_luck": 1} + {"name":"GorbyPuff", "rusty_luck": 3} + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open katz.txt + | from json -o + | describe -n + "# + )); + + assert_eq!(actual.out, "stream"); + }) +} + #[test] fn from_json_text_recognizing_objects_independently_to_table_strict() { Playground::setup("filter_from_json_test_2_strict", |dirs, sandbox| { diff --git a/crates/nu-protocol/src/pipeline/pipeline_data.rs b/crates/nu-protocol/src/pipeline/pipeline_data.rs index 0a13ffa4b3..03fbc64d21 100644 --- a/crates/nu-protocol/src/pipeline/pipeline_data.rs +++ b/crates/nu-protocol/src/pipeline/pipeline_data.rs @@ -3,7 +3,7 @@ use crate::{ engine::{EngineState, Stack}, process::{ChildPipe, ChildProcess, ExitStatus}, ByteStream, ByteStreamType, Config, ErrSpan, ListStream, OutDest, PipelineMetadata, Range, - ShellError, Span, Value, + ShellError, Span, Type, Value, }; use nu_utils::{stderr_write_all_and_flush, stdout_write_all_and_flush}; use std::{ @@ -99,6 +99,24 @@ impl PipelineData { } } + /// Get a type that is representative of the `PipelineData`. + /// + /// The type returned here makes no effort to collect a stream, so it may be a different type + /// than would be returned by [`Value::get_type()`] on the result of [`.into_value()`]. + /// + /// Specifically, a `ListStream` results in [`list stream`](Type::ListStream) rather than + /// the fully complete [`list`](Type::List) type (which would require knowing the contents), + /// and a `ByteStream` with [unknown](crate::ByteStreamType::Unknown) type results in + /// [`any`](Type::Any) rather than [`string`](Type::String) or [`binary`](Type::Binary). + pub fn get_type(&self) -> Type { + match self { + PipelineData::Empty => Type::Nothing, + PipelineData::Value(value, _) => value.get_type(), + PipelineData::ListStream(_, _) => Type::ListStream, + PipelineData::ByteStream(stream, _) => stream.type_().into(), + } + } + pub fn into_value(self, span: Span) -> Result { match self { PipelineData::Empty => Ok(Value::nothing(span)), From c5d716951fc199b6ef6b6b8ee6a3e7fd773bd824 Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Sat, 25 May 2024 00:54:38 +0000 Subject: [PATCH 022/113] Allow byte streams with unknown type to be compatiable with binary (#12959) # Description Currently, this pipeline doesn't work `open --raw file | take 100`, since the type of the byte stream is `Unknown`, but `take` expects `Binary` streams. This PR changes commands that expect `ByteStreamType::Binary` to also work with `ByteStreamType::Unknown`. This was done by adding two new methods to `ByteStreamType`: `is_binary_coercible` and `is_string_coercible`. These return true if the type is `Unknown` or matches the type in the method name. --- crates/nu-command/src/conversions/into/string.rs | 2 +- crates/nu-command/src/filters/first.rs | 4 ++-- crates/nu-command/src/filters/last.rs | 6 ++---- crates/nu-command/src/filters/skip/skip_.rs | 6 +++--- crates/nu-command/src/filters/take/take_.rs | 4 ++-- crates/nu-protocol/src/pipeline/byte_stream.rs | 12 +++++++++++- 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/crates/nu-command/src/conversions/into/string.rs b/crates/nu-command/src/conversions/into/string.rs index c0731b2e20..7c7d69cf4e 100644 --- a/crates/nu-command/src/conversions/into/string.rs +++ b/crates/nu-command/src/conversions/into/string.rs @@ -160,7 +160,7 @@ fn string_helper( // Just set the type - that should be good enough. There is no guarantee that the data // within a string stream is actually valid UTF-8. But refuse to do it if it was already set // to binary - if stream.type_() != ByteStreamType::Binary { + if stream.type_().is_string_coercible() { Ok(PipelineData::ByteStream( stream.with_type(ByteStreamType::String), metadata, diff --git a/crates/nu-command/src/filters/first.rs b/crates/nu-command/src/filters/first.rs index f625847a3f..97c5159b97 100644 --- a/crates/nu-command/src/filters/first.rs +++ b/crates/nu-command/src/filters/first.rs @@ -1,4 +1,5 @@ use nu_engine::command_prelude::*; +use std::io::Read; #[derive(Clone)] pub struct First; @@ -171,10 +172,9 @@ fn first_helper( } } PipelineData::ByteStream(stream, metadata) => { - if stream.type_() == ByteStreamType::Binary { + if stream.type_().is_binary_coercible() { let span = stream.span(); if let Some(mut reader) = stream.reader() { - use std::io::Read; if return_single_element { // Take a single byte let mut byte = [0u8]; diff --git a/crates/nu-command/src/filters/last.rs b/crates/nu-command/src/filters/last.rs index 510e6457a8..efb300db01 100644 --- a/crates/nu-command/src/filters/last.rs +++ b/crates/nu-command/src/filters/last.rs @@ -1,6 +1,5 @@ use nu_engine::command_prelude::*; - -use std::collections::VecDeque; +use std::{collections::VecDeque, io::Read}; #[derive(Clone)] pub struct Last; @@ -161,10 +160,9 @@ impl Command for Last { } } PipelineData::ByteStream(stream, ..) => { - if stream.type_() == ByteStreamType::Binary { + if stream.type_().is_binary_coercible() { let span = stream.span(); if let Some(mut reader) = stream.reader() { - use std::io::Read; // Have to be a bit tricky here, but just consume into a VecDeque that we // shrink to fit each time const TAKE: u64 = 8192; diff --git a/crates/nu-command/src/filters/skip/skip_.rs b/crates/nu-command/src/filters/skip/skip_.rs index df53cfacba..d293a743da 100644 --- a/crates/nu-command/src/filters/skip/skip_.rs +++ b/crates/nu-command/src/filters/skip/skip_.rs @@ -1,4 +1,5 @@ use nu_engine::command_prelude::*; +use std::io::{self, Read}; #[derive(Clone)] pub struct Skip; @@ -94,12 +95,11 @@ impl Command for Skip { let input_span = input.span().unwrap_or(call.head); match input { PipelineData::ByteStream(stream, metadata) => { - if stream.type_() == ByteStreamType::Binary { + if stream.type_().is_binary_coercible() { let span = stream.span(); if let Some(mut reader) = stream.reader() { - use std::io::Read; // Copy the number of skipped bytes into the sink before proceeding - std::io::copy(&mut (&mut reader).take(n as u64), &mut std::io::sink()) + io::copy(&mut (&mut reader).take(n as u64), &mut io::sink()) .err_span(span)?; Ok(PipelineData::ByteStream( ByteStream::read(reader, call.head, None, ByteStreamType::Binary), diff --git a/crates/nu-command/src/filters/take/take_.rs b/crates/nu-command/src/filters/take/take_.rs index d4bf455c4a..7ebe22f914 100644 --- a/crates/nu-command/src/filters/take/take_.rs +++ b/crates/nu-command/src/filters/take/take_.rs @@ -1,4 +1,5 @@ use nu_engine::command_prelude::*; +use std::io::Read; #[derive(Clone)] pub struct Take; @@ -79,9 +80,8 @@ impl Command for Take { metadata, )), PipelineData::ByteStream(stream, metadata) => { - if stream.type_() == ByteStreamType::Binary { + if stream.type_().is_binary_coercible() { if let Some(reader) = stream.reader() { - use std::io::Read; // Just take 'rows' bytes off the stream, mimicking the binary behavior Ok(PipelineData::ByteStream( ByteStream::read( diff --git a/crates/nu-protocol/src/pipeline/byte_stream.rs b/crates/nu-protocol/src/pipeline/byte_stream.rs index 35ce39ed31..babd195a9e 100644 --- a/crates/nu-protocol/src/pipeline/byte_stream.rs +++ b/crates/nu-protocol/src/pipeline/byte_stream.rs @@ -114,6 +114,16 @@ impl ByteStreamType { ByteStreamType::Unknown => "byte stream", } } + + /// Returns true if the type is `Binary` or `Unknown` + pub fn is_binary_coercible(self) -> bool { + matches!(self, ByteStreamType::Binary | ByteStreamType::Unknown) + } + + /// Returns true if the type is `String` or `Unknown` + pub fn is_string_coercible(self) -> bool { + matches!(self, ByteStreamType::String | ByteStreamType::Unknown) + } } impl From for Type { @@ -483,7 +493,7 @@ impl ByteStream { /// data would have been valid UTF-8. pub fn into_string(self) -> Result { let span = self.span; - if self.type_ != ByteStreamType::Binary { + if self.type_.is_string_coercible() { let trim = self.stream.is_external(); let bytes = self.into_bytes()?; let mut string = String::from_utf8(bytes).map_err(|err| ShellError::NonUtf8Custom { From 95977faf2d0fb048e9c898fef3c4ba542e2a99dd Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Sat, 25 May 2024 00:59:36 +0000 Subject: [PATCH 023/113] Do not propagate glob creation error for external args (#12955) # Description Instead of returning an error, this PR changes `expand_glob` in `run_external.rs` to return the original string arg if glob creation failed. This makes it so that, e.g., ```nushell ^echo `[` ^echo `***` ``` no longer fail with a shell error. (This follows from #12921.) --- crates/nu-command/src/system/run_external.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/crates/nu-command/src/system/run_external.rs b/crates/nu-command/src/system/run_external.rs index 873cee19b1..15bf6ebfd3 100644 --- a/crates/nu-command/src/system/run_external.rs +++ b/crates/nu-command/src/system/run_external.rs @@ -295,19 +295,15 @@ fn expand_tilde(arg: &str) -> String { nu_path::expand_tilde(arg).to_string_lossy().to_string() } -/// Performs glob expansion on `arg`. If the expansion found no matches, returns -/// the original string as the expansion result. +/// Performs glob expansion on `arg`. If the expansion found no matches or the pattern +/// is not a valid glob, then this returns the original string as the expansion result. /// /// Note: This matches the default behavior of Bash, but is known to be /// error-prone. We might want to change this behavior in the future. fn expand_glob(arg: &str, cwd: &Path, span: Span) -> Result, ShellError> { - let paths = - nu_glob::glob_with_parent(arg, nu_glob::MatchOptions::default(), cwd).map_err(|err| { - ShellError::InvalidGlobPattern { - msg: err.msg.to_string(), - span, - } - })?; + let Ok(paths) = nu_glob::glob_with_parent(arg, nu_glob::MatchOptions::default(), cwd) else { + return Ok(vec![arg.into()]); + }; let mut result = vec![]; for path in paths { @@ -647,7 +643,9 @@ mod test { let expected = &["'*.txt'"]; assert_eq!(actual, expected); - expand_glob("[*.txt", cwd, Span::unknown()).unwrap_err(); + let actual = expand_glob("[*.txt", cwd, Span::unknown()).unwrap(); + let expected = &["[*.txt"]; + assert_eq!(actual, expected); } #[test] From 0c5a67f4e5bf17a2fffbe3cbb54792a6464b3237 Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Sat, 25 May 2024 09:10:01 -0500 Subject: [PATCH 024/113] make polars plugin use mimalloc (#12967) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description @maxim-uvarov did a ton of research and work with the dply-rs author and ritchie from polars and found out that the allocator matters on macos and it seems to be what was messing up the performance of polars plugin. ritchie suggested to use jemalloc but i switched it to mimalloc to match nushell and it seems to run better. ## Before (default allocator) note - using 1..10 vs 1..100 since it takes so long. also notice how high the `max` timings are compared to mimalloc below. ```nushell ❯ 1..10 | each {timeit {polars open Data7602DescendingYearOrder.csv | polars group-by year | polars agg (polars col geo_count | polars sum) | polars collect | null}} | | {mean: ($in | math avg), min: ($in | math min), max: ($in | math max), stddev: ($in | into int | into float | math stddev | into int | $'($in)ns' | into duration)} ╭────────┬─────────────────────────╮ │ mean │ 4sec 999ms 605µs 995ns │ │ min │ 983ms 627µs 42ns │ │ max │ 13sec 398ms 135µs 791ns │ │ stddev │ 3sec 476ms 479µs 939ns │ ╰────────┴─────────────────────────╯ ❯ use std bench ❯ bench { polars open Data7602DescendingYearOrder.csv | polars group-by year | polars agg (polars col geo_count | polars sum) | polars collect | null } -n 10 ╭───────┬────────────────────────╮ │ mean │ 6sec 220ms 783µs 983ns │ │ min │ 1sec 184ms 997µs 708ns │ │ max │ 18sec 882ms 81µs 708ns │ │ std │ 5sec 350ms 375µs 697ns │ │ times │ [list 10 items] │ ╰───────┴────────────────────────╯ ``` ## After (using mimalloc) ```nushell ❯ 1..100 | each {timeit {polars open Data7602DescendingYearOrder.csv | polars group-by year | polars agg (polars col geo_count | polars sum) | polars collect | null}} | | {mean: ($in | math avg), min: ($in | math min), max: ($in | math max), stddev: ($in | into int | into float | math stddev | into int | $'($in)ns' | into duration)} ╭────────┬───────────────────╮ │ mean │ 103ms 728µs 902ns │ │ min │ 97ms 107µs 42ns │ │ max │ 149ms 430µs 84ns │ │ stddev │ 5ms 690µs 664ns │ ╰────────┴───────────────────╯ ❯ use std bench ❯ bench { polars open Data7602DescendingYearOrder.csv | polars group-by year | polars agg (polars col geo_count | polars sum) | polars collect | null } -n 100 ╭───────┬───────────────────╮ │ mean │ 103ms 620µs 195ns │ │ min │ 97ms 541µs 166ns │ │ max │ 130ms 262µs 166ns │ │ std │ 4ms 948µs 654ns │ │ times │ [list 100 items] │ ╰───────┴───────────────────╯ ``` ## After (using jemalloc - just for comparison) ```nushell ❯ 1..100 | each {timeit {polars open Data7602DescendingYearOrder.csv | polars group-by year | polars agg (polars col geo_count | polars sum) | polars collect | null}} | | {mean: ($in | math avg), min: ($in | math min), max: ($in | math max), stddev: ($in | into int | into float | math stddev | into int | $'($in)ns' | into duration)} ╭────────┬───────────────────╮ │ mean │ 113ms 939µs 777ns │ │ min │ 108ms 337µs 333ns │ │ max │ 166ms 467µs 458ns │ │ stddev │ 6ms 175µs 618ns │ ╰────────┴───────────────────╯ ❯ use std bench ❯ bench { polars open Data7602DescendingYearOrder.csv | polars group-by year | polars agg (polars col geo_count | polars sum) | polars collect | null } -n 100 ╭───────┬───────────────────╮ │ mean │ 114ms 363µs 530ns │ │ min │ 108ms 804µs 833ns │ │ max │ 143ms 521µs 459ns │ │ std │ 5ms 88µs 56ns │ │ times │ [list 100 items] │ ╰───────┴───────────────────╯ ``` ## After (using parquet + mimalloc) ```nushell ❯ 1..100 | each {timeit {polars open data.parquet | polars group-by year | polars agg (polars col geo_count | polars sum) | polars collect | null}} | | {mean: ($in | math avg), min: ($in | math min), max: ($in | math max), stddev: ($in | into int | into float | math stddev | into int | $'($in)ns' | into duration)} ╭────────┬──────────────────╮ │ mean │ 34ms 255µs 492ns │ │ min │ 31ms 787µs 250ns │ │ max │ 76ms 408µs 416ns │ │ stddev │ 4ms 472µs 916ns │ ╰────────┴──────────────────╯ ❯ use std bench ❯ bench { polars open data.parquet | polars group-by year | polars agg (polars col geo_count | polars sum) | polars collect | null } -n 100 ╭───────┬──────────────────╮ │ mean │ 34ms 897µs 562ns │ │ min │ 31ms 518µs 542ns │ │ max │ 65ms 943µs 625ns │ │ std │ 3ms 450µs 741ns │ │ times │ [list 100 items] │ ╰───────┴──────────────────╯ ``` # User-Facing Changes # Tests + Formatting # After Submitting --- Cargo.lock | 1 + crates/nu_plugin_polars/Cargo.toml | 1 + crates/nu_plugin_polars/src/main.rs | 3 +++ 3 files changed, 5 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 2ee4c6fc25..6e9216d447 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3387,6 +3387,7 @@ dependencies = [ "chrono-tz 0.9.0", "fancy-regex", "indexmap", + "mimalloc", "nu-cmd-lang", "nu-command", "nu-engine", diff --git a/crates/nu_plugin_polars/Cargo.toml b/crates/nu_plugin_polars/Cargo.toml index 6a2a980383..03d050638d 100644 --- a/crates/nu_plugin_polars/Cargo.toml +++ b/crates/nu_plugin_polars/Cargo.toml @@ -26,6 +26,7 @@ chrono = { workspace = true, features = ["std", "unstable-locales"], default-fea chrono-tz = "0.9" fancy-regex = { workspace = true } indexmap = { version = "2.2" } +mimalloc = { version = "0.1.42" } num = {version = "0.4"} serde = { version = "1.0", features = ["derive"] } sqlparser = { version = "0.45"} diff --git a/crates/nu_plugin_polars/src/main.rs b/crates/nu_plugin_polars/src/main.rs index e060d7cd6d..4a757701ad 100644 --- a/crates/nu_plugin_polars/src/main.rs +++ b/crates/nu_plugin_polars/src/main.rs @@ -1,6 +1,9 @@ use nu_plugin::{serve_plugin, MsgPackSerializer}; use nu_plugin_polars::PolarsPlugin; +#[global_allocator] +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; + fn main() { serve_plugin(&PolarsPlugin::default(), MsgPackSerializer {}) } From f38f88d42cdcd42e2dac3616eb5fafcc35fd819b Mon Sep 17 00:00:00 2001 From: YizhePKU Date: Sun, 26 May 2024 07:06:17 +0800 Subject: [PATCH 025/113] Fixes `.` expanded incorrectly as external argument (#12950) This PR fixes a bug where `.` is expanded into an empty string when used as an argument to external commands. Fixes https://github.com/nushell/nushell/issues/12948. --------- Co-authored-by: Ian Manske --- crates/nu-command/src/system/run_external.rs | 15 ++++++++++++++- tests/shell/pipeline/commands/external.rs | 7 +++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/crates/nu-command/src/system/run_external.rs b/crates/nu-command/src/system/run_external.rs index 15bf6ebfd3..8531217d4b 100644 --- a/crates/nu-command/src/system/run_external.rs +++ b/crates/nu-command/src/system/run_external.rs @@ -312,7 +312,16 @@ fn expand_glob(arg: &str, cwd: &Path, span: Span) -> Result, ShellEr span, })?; // Strip PWD from the resulting paths if possible. - let path_stripped = path.strip_prefix(cwd).unwrap_or(&path); + let path_stripped = if let Ok(remainder) = path.strip_prefix(cwd) { + // If stripping PWD results in an empty path, return `.` instead. + if remainder.components().next().is_none() { + Path::new(".") + } else { + remainder + } + } else { + &path + }; let path_string = path_stripped.to_string_lossy().to_string(); result.push(path_string); } @@ -643,6 +652,10 @@ mod test { let expected = &["'*.txt'"]; assert_eq!(actual, expected); + let actual = expand_glob(cwd.to_str().unwrap(), cwd, Span::unknown()).unwrap(); + let expected = &["."]; + assert_eq!(actual, expected); + let actual = expand_glob("[*.txt", cwd, Span::unknown()).unwrap(); let expected = &["[*.txt"]; assert_eq!(actual, expected); diff --git a/tests/shell/pipeline/commands/external.rs b/tests/shell/pipeline/commands/external.rs index 8557e9e327..2b116eb86d 100644 --- a/tests/shell/pipeline/commands/external.rs +++ b/tests/shell/pipeline/commands/external.rs @@ -61,6 +61,13 @@ fn automatically_change_directory_with_trailing_slash_and_same_name_as_command() }) } +#[test] +fn pass_dot_as_external_arguments() { + let actual = nu!("nu --testbin cococo ."); + + assert_eq!(actual.out, "."); +} + #[test] fn correctly_escape_external_arguments() { let actual = nu!("^nu --testbin cococo '$0'"); From a1fc41db22e326309926b606e1a4c747afb673da Mon Sep 17 00:00:00 2001 From: YizhePKU Date: Mon, 27 May 2024 01:23:52 +0800 Subject: [PATCH 026/113] Fix `path type` using PWD from the environment (#12975) This PR fixes the `path type` command so that it resolves relative paths using PWD from the engine state. As a bonus, it also fixes the issue of `path type` returning an empty string instead of an error when it fails. --- crates/nu-command/src/path/type.rs | 42 +++++++++---------- .../nu-command/tests/commands/path/type_.rs | 11 +++++ 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/crates/nu-command/src/path/type.rs b/crates/nu-command/src/path/type.rs index 8fbc270445..e048679220 100644 --- a/crates/nu-command/src/path/type.rs +++ b/crates/nu-command/src/path/type.rs @@ -1,10 +1,11 @@ use super::PathSubcommandArguments; use nu_engine::command_prelude::*; -use nu_path::expand_tilde; use nu_protocol::engine::StateWorkingSet; -use std::path::Path; +use std::path::{Path, PathBuf}; -struct Arguments; +struct Arguments { + pwd: PathBuf, +} impl PathSubcommandArguments for Arguments {} @@ -45,19 +46,21 @@ If nothing is found, an empty string will be returned."# fn run( &self, engine_state: &EngineState, - _stack: &mut Stack, + stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { let head = call.head; - let args = Arguments; + let args = Arguments { + pwd: engine_state.cwd(Some(stack))?, + }; // This doesn't match explicit nulls if matches!(input, PipelineData::Empty) { return Err(ShellError::PipelineEmpty { dst_span: head }); } input.map( - move |value| super::operate(&r#type, &args, value, head), + move |value| super::operate(&path_type, &args, value, head), engine_state.ctrlc.clone(), ) } @@ -69,14 +72,16 @@ If nothing is found, an empty string will be returned."# input: PipelineData, ) -> Result { let head = call.head; - let args = Arguments; + let args = Arguments { + pwd: working_set.permanent().cwd(None)?, + }; // This doesn't match explicit nulls if matches!(input, PipelineData::Empty) { return Err(ShellError::PipelineEmpty { dst_span: head }); } input.map( - move |value| super::operate(&r#type, &args, value, head), + move |value| super::operate(&path_type, &args, value, head), working_set.permanent().ctrlc.clone(), ) } @@ -97,21 +102,12 @@ If nothing is found, an empty string will be returned."# } } -fn r#type(path: &Path, span: Span, _: &Arguments) -> Value { - let meta = if path.starts_with("~") { - let p = expand_tilde(path); - std::fs::symlink_metadata(p) - } else { - std::fs::symlink_metadata(path) - }; - - Value::string( - match &meta { - Ok(data) => get_file_type(data), - Err(_) => "", - }, - span, - ) +fn path_type(path: &Path, span: Span, args: &Arguments) -> Value { + let path = nu_path::expand_path_with(path, &args.pwd, true); + match std::fs::symlink_metadata(path) { + Ok(metadata) => Value::string(get_file_type(&metadata), span), + Err(err) => Value::error(err.into(), span), + } } fn get_file_type(md: &std::fs::Metadata) -> &str { diff --git a/crates/nu-command/tests/commands/path/type_.rs b/crates/nu-command/tests/commands/path/type_.rs index 2317cea060..e67b957e4c 100644 --- a/crates/nu-command/tests/commands/path/type_.rs +++ b/crates/nu-command/tests/commands/path/type_.rs @@ -74,3 +74,14 @@ fn returns_type_of_existing_file_const() { assert_eq!(actual.out, "dir"); }) } + +#[test] +fn respects_cwd() { + Playground::setup("path_type_respects_cwd", |dirs, sandbox| { + sandbox.within("foo").with_files(&[EmptyFile("bar.txt")]); + + let actual = nu!(cwd: dirs.test(), "cd foo; 'bar.txt' | path type"); + + assert_eq!(actual.out, "file"); + }) +} From f74dd33ba9213e85e08ee96ba25558d1a89f1fb2 Mon Sep 17 00:00:00 2001 From: YizhePKU Date: Mon, 27 May 2024 01:24:00 +0800 Subject: [PATCH 027/113] Fix `touch --reference` using PWD from the environment (#12976) This PR fixes `touch --reference path` so that it resolves `path` using PWD from the engine state. --- crates/nu-command/src/filesystem/touch.rs | 12 +++++------- crates/nu-command/tests/commands/touch.rs | 13 +++++++++++++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/crates/nu-command/src/filesystem/touch.rs b/crates/nu-command/src/filesystem/touch.rs index 08843b11f0..0253e7e317 100644 --- a/crates/nu-command/src/filesystem/touch.rs +++ b/crates/nu-command/src/filesystem/touch.rs @@ -1,10 +1,9 @@ use filetime::FileTime; -#[allow(deprecated)] -use nu_engine::{command_prelude::*, current_dir}; +use nu_engine::command_prelude::*; use nu_path::expand_path_with; use nu_protocol::NuGlob; -use std::{fs::OpenOptions, path::Path, time::SystemTime}; +use std::{fs::OpenOptions, time::SystemTime}; use super::util::get_rest_for_glob_pattern; @@ -69,6 +68,8 @@ impl Command for Touch { let no_create: bool = call.has_flag(engine_state, stack, "no-create")?; let files: Vec> = get_rest_for_glob_pattern(engine_state, stack, call, 0)?; + let cwd = engine_state.cwd(Some(stack))?; + if files.is_empty() { return Err(ShellError::MissingParameter { param_name: "requires file paths".to_string(), @@ -86,7 +87,7 @@ impl Command for Touch { } if let Some(reference) = reference { - let reference_path = Path::new(&reference.item); + let reference_path = nu_path::expand_path_with(reference.item, &cwd, true); if !reference_path.exists() { return Err(ShellError::FileNotFoundCustom { msg: "Reference path not found".into(), @@ -114,9 +115,6 @@ impl Command for Touch { })?; } - #[allow(deprecated)] - let cwd = current_dir(engine_state, stack)?; - for glob in files { let path = expand_path_with(glob.item.as_ref(), &cwd, glob.item.is_expand()); diff --git a/crates/nu-command/tests/commands/touch.rs b/crates/nu-command/tests/commands/touch.rs index 26d0325729..5f454cdec4 100644 --- a/crates/nu-command/tests/commands/touch.rs +++ b/crates/nu-command/tests/commands/touch.rs @@ -515,3 +515,16 @@ fn respects_cwd() { assert!(path.exists()); }) } + +#[test] +fn reference_respects_cwd() { + Playground::setup("touch_reference_respects_cwd", |dirs, _sandbox| { + nu!( + cwd: dirs.test(), + "mkdir 'dir'; cd 'dir'; touch 'ref.txt'; touch --reference 'ref.txt' 'foo.txt'" + ); + + let path = dirs.test().join("dir/foo.txt"); + assert!(path.exists()); + }) +} From 6012af24124f5b49c6f1d885a765f1c31e0a8631 Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Mon, 27 May 2024 02:03:06 +0000 Subject: [PATCH 028/113] Fix panic when redirecting nothing (#12970) # Description Fixes #12969 where the parser can panic if a redirection is applied to nothing / an empty command. # Tests + Formatting Added a test. --- crates/nu-parser/src/lite_parser.rs | 148 ++++++++----------- crates/nu-parser/tests/test_parser.rs | 39 +++++ crates/nu-protocol/src/errors/parse_error.rs | 8 + 3 files changed, 111 insertions(+), 84 deletions(-) diff --git a/crates/nu-parser/src/lite_parser.rs b/crates/nu-parser/src/lite_parser.rs index 65bdc4763a..f04b8befdc 100644 --- a/crates/nu-parser/src/lite_parser.rs +++ b/crates/nu-parser/src/lite_parser.rs @@ -51,12 +51,21 @@ impl LiteCommand { self.parts.push(span); } + fn check_accepts_redirection(&self, span: Span) -> Option { + self.parts + .is_empty() + .then_some(ParseError::UnexpectedRedirection { span }) + } + fn try_add_redirection( &mut self, source: RedirectionSource, target: LiteRedirectionTarget, ) -> Result<(), ParseError> { let redirection = match (self.redirection.take(), source) { + (None, _) if self.parts.is_empty() => Err(ParseError::UnexpectedRedirection { + span: target.connector(), + }), (None, source) => Ok(LiteRedirection::Single { source, target }), ( Some(LiteRedirection::Single { @@ -162,94 +171,59 @@ pub fn lite_parse(tokens: &[Token]) -> (LiteBlock, Option) { for (idx, token) in tokens.iter().enumerate() { if let Some((source, append, span)) = file_redirection.take() { - if command.parts.is_empty() { - error = error.or(Some(ParseError::LabeledError( - "Redirection without command or expression".into(), - "there is nothing to redirect".into(), - span, - ))); - - command.push(span); - - match token.contents { - TokenContents::Comment => { - command.comments.push(token.span); - curr_comment = None; - } - TokenContents::Pipe - | TokenContents::ErrGreaterPipe - | TokenContents::OutErrGreaterPipe => { - pipeline.push(&mut command); - command.pipe = Some(token.span); - } - TokenContents::Semicolon => { - pipeline.push(&mut command); - block.push(&mut pipeline); - } - TokenContents::Eol => { - pipeline.push(&mut command); - } - _ => command.push(token.span), + match &token.contents { + TokenContents::PipePipe => { + error = error.or(Some(ParseError::ShellOrOr(token.span))); + command.push(span); + command.push(token.span); } - } else { - match &token.contents { - TokenContents::PipePipe => { - error = error.or(Some(ParseError::ShellOrOr(token.span))); + TokenContents::Item => { + let target = LiteRedirectionTarget::File { + connector: span, + file: token.span, + append, + }; + if let Err(err) = command.try_add_redirection(source, target) { + error = error.or(Some(err)); command.push(span); - command.push(token.span); - } - TokenContents::Item => { - let target = LiteRedirectionTarget::File { - connector: span, - file: token.span, - append, - }; - if let Err(err) = command.try_add_redirection(source, target) { - error = error.or(Some(err)); - command.push(span); - command.push(token.span) - } - } - TokenContents::OutGreaterThan - | TokenContents::OutGreaterGreaterThan - | TokenContents::ErrGreaterThan - | TokenContents::ErrGreaterGreaterThan - | TokenContents::OutErrGreaterThan - | TokenContents::OutErrGreaterGreaterThan => { - error = - error.or(Some(ParseError::Expected("redirection target", token.span))); - command.push(span); - command.push(token.span); - } - TokenContents::Pipe - | TokenContents::ErrGreaterPipe - | TokenContents::OutErrGreaterPipe => { - error = - error.or(Some(ParseError::Expected("redirection target", token.span))); - command.push(span); - pipeline.push(&mut command); - command.pipe = Some(token.span); - } - TokenContents::Eol => { - error = - error.or(Some(ParseError::Expected("redirection target", token.span))); - command.push(span); - pipeline.push(&mut command); - } - TokenContents::Semicolon => { - error = - error.or(Some(ParseError::Expected("redirection target", token.span))); - command.push(span); - pipeline.push(&mut command); - block.push(&mut pipeline); - } - TokenContents::Comment => { - error = error.or(Some(ParseError::Expected("redirection target", span))); - command.push(span); - command.comments.push(token.span); - curr_comment = None; + command.push(token.span) } } + TokenContents::OutGreaterThan + | TokenContents::OutGreaterGreaterThan + | TokenContents::ErrGreaterThan + | TokenContents::ErrGreaterGreaterThan + | TokenContents::OutErrGreaterThan + | TokenContents::OutErrGreaterGreaterThan => { + error = error.or(Some(ParseError::Expected("redirection target", token.span))); + command.push(span); + command.push(token.span); + } + TokenContents::Pipe + | TokenContents::ErrGreaterPipe + | TokenContents::OutErrGreaterPipe => { + error = error.or(Some(ParseError::Expected("redirection target", token.span))); + command.push(span); + pipeline.push(&mut command); + command.pipe = Some(token.span); + } + TokenContents::Eol => { + error = error.or(Some(ParseError::Expected("redirection target", token.span))); + command.push(span); + pipeline.push(&mut command); + } + TokenContents::Semicolon => { + error = error.or(Some(ParseError::Expected("redirection target", token.span))); + command.push(span); + pipeline.push(&mut command); + block.push(&mut pipeline); + } + TokenContents::Comment => { + error = error.or(Some(ParseError::Expected("redirection target", span))); + command.push(span); + command.comments.push(token.span); + curr_comment = None; + } } } else { match &token.contents { @@ -278,22 +252,28 @@ pub fn lite_parse(tokens: &[Token]) -> (LiteBlock, Option) { command.push(token.span); } TokenContents::OutGreaterThan => { + error = error.or(command.check_accepts_redirection(token.span)); file_redirection = Some((RedirectionSource::Stdout, false, token.span)); } TokenContents::OutGreaterGreaterThan => { + error = error.or(command.check_accepts_redirection(token.span)); file_redirection = Some((RedirectionSource::Stdout, true, token.span)); } TokenContents::ErrGreaterThan => { + error = error.or(command.check_accepts_redirection(token.span)); file_redirection = Some((RedirectionSource::Stderr, false, token.span)); } TokenContents::ErrGreaterGreaterThan => { + error = error.or(command.check_accepts_redirection(token.span)); file_redirection = Some((RedirectionSource::Stderr, true, token.span)); } TokenContents::OutErrGreaterThan => { + error = error.or(command.check_accepts_redirection(token.span)); file_redirection = Some((RedirectionSource::StdoutAndStderr, false, token.span)); } TokenContents::OutErrGreaterGreaterThan => { + error = error.or(command.check_accepts_redirection(token.span)); file_redirection = Some((RedirectionSource::StdoutAndStderr, true, token.span)); } TokenContents::ErrGreaterPipe => { diff --git a/crates/nu-parser/tests/test_parser.rs b/crates/nu-parser/tests/test_parser.rs index 9b8ae94317..ef5d968280 100644 --- a/crates/nu-parser/tests/test_parser.rs +++ b/crates/nu-parser/tests/test_parser.rs @@ -727,6 +727,45 @@ fn test_redirection_with_letmut(#[case] phase: &[u8]) { )); } +#[rstest] +#[case(b"o>")] +#[case(b"o>>")] +#[case(b"e>")] +#[case(b"e>>")] +#[case(b"o+e>")] +#[case(b"o+e>>")] +#[case(b"e>|")] +#[case(b"o+e>|")] +#[case(b"|o>")] +#[case(b"|o>>")] +#[case(b"|e>")] +#[case(b"|e>>")] +#[case(b"|o+e>")] +#[case(b"|o+e>>")] +#[case(b"|e>|")] +#[case(b"|o+e>|")] +#[case(b"e> file")] +#[case(b"e>> file")] +#[case(b"o> file")] +#[case(b"o>> file")] +#[case(b"o+e> file")] +#[case(b"o+e>> file")] +#[case(b"|e> file")] +#[case(b"|e>> file")] +#[case(b"|o> file")] +#[case(b"|o>> file")] +#[case(b"|o+e> file")] +#[case(b"|o+e>> file")] +fn test_redirecting_nothing(#[case] text: &[u8]) { + let engine_state = EngineState::new(); + let mut working_set = StateWorkingSet::new(&engine_state); + let _ = parse(&mut working_set, None, text, true); + assert!(matches!( + working_set.parse_errors.first(), + Some(ParseError::UnexpectedRedirection { .. }) + )); +} + #[test] fn test_nothing_comparison_neq() { let engine_state = EngineState::new(); diff --git a/crates/nu-protocol/src/errors/parse_error.rs b/crates/nu-protocol/src/errors/parse_error.rs index 7e39fe1ef6..28c865b841 100644 --- a/crates/nu-protocol/src/errors/parse_error.rs +++ b/crates/nu-protocol/src/errors/parse_error.rs @@ -93,6 +93,13 @@ pub enum ParseError { #[label = "second redirection"] Span, ), + #[error("Unexpected redirection.")] + #[diagnostic(code(nu::parser::unexpected_redirection))] + UnexpectedRedirection { + #[label = "redirecting nothing"] + span: Span, + }, + #[error("{0} is not supported on values of type {3}")] #[diagnostic(code(nu::parser::unsupported_operation))] UnsupportedOperationLHS( @@ -564,6 +571,7 @@ impl ParseError { ParseError::ShellErrRedirect(s) => *s, ParseError::ShellOutErrRedirect(s) => *s, ParseError::MultipleRedirections(_, _, s) => *s, + ParseError::UnexpectedRedirection { span } => *span, ParseError::UnknownOperator(_, _, s) => *s, ParseError::InvalidLiteral(_, _, s) => *s, ParseError::LabeledErrorWithHelp { span: s, .. } => *s, From 4ab2c3238acdc8f4ef1987522b5edb37a78f83e8 Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Tue, 28 May 2024 18:53:51 +0000 Subject: [PATCH 029/113] Disable reedline patch for 0.94.0 (#12986) Disable crates.io git patch for reedline for 0.94.0 release. --- Cargo.lock | 3 ++- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e9216d447..b8777234ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4820,7 +4820,8 @@ dependencies = [ [[package]] name = "reedline" version = "0.32.0" -source = "git+https://github.com/nushell/reedline?branch=main#a580ea56d4e5a889468b2969d2a1534379504ab6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf59e4c97b5049ba96b052cdb652368305a2eddcbce9bf1c16f9d003139eeea" dependencies = [ "arboard", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 665fd21747..6cac862ae1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -298,7 +298,7 @@ bench = false # To use a development version of a dependency please use a global override here # changing versions in each sub-crate of the workspace is tedious [patch.crates-io] -reedline = { git = "https://github.com/nushell/reedline", branch = "main" } +# reedline = { git = "https://github.com/nushell/reedline", branch = "main" } # nu-ansi-term = {git = "https://github.com/nushell/nu-ansi-term.git", branch = "main"} # Run all benchmarks with `cargo bench` From 61182deb96c84fe1171179edcfeef9f1d301e8fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20=C5=BD=C3=A1dn=C3=ADk?= Date: Tue, 28 May 2024 22:04:09 +0300 Subject: [PATCH 030/113] Bump version to 0.94.0 (#12987) --- Cargo.lock | 72 +++++++++---------- Cargo.toml | 42 +++++------ crates/nu-cli/Cargo.toml | 26 +++---- crates/nu-cmd-base/Cargo.toml | 12 ++-- crates/nu-cmd-extra/Cargo.toml | 22 +++--- crates/nu-cmd-lang/Cargo.toml | 12 ++-- crates/nu-cmd-plugin/Cargo.toml | 12 ++-- crates/nu-color-config/Cargo.toml | 10 +-- crates/nu-command/Cargo.toml | 36 +++++----- crates/nu-engine/Cargo.toml | 12 ++-- crates/nu-explore/Cargo.toml | 20 +++--- crates/nu-glob/Cargo.toml | 4 +- crates/nu-json/Cargo.toml | 6 +- crates/nu-lsp/Cargo.toml | 16 ++--- crates/nu-parser/Cargo.toml | 12 ++-- crates/nu-parser/fuzz/Cargo.toml | 2 +- crates/nu-path/Cargo.toml | 4 +- crates/nu-path/fuzz/Cargo.toml | 2 +- crates/nu-plugin-core/Cargo.toml | 8 +-- crates/nu-plugin-engine/Cargo.toml | 14 ++-- crates/nu-plugin-protocol/Cargo.toml | 8 +-- crates/nu-plugin-test-support/Cargo.toml | 20 +++--- crates/nu-plugin/Cargo.toml | 12 ++-- crates/nu-pretty-hex/Cargo.toml | 4 +- crates/nu-protocol/Cargo.toml | 12 ++-- crates/nu-std/Cargo.toml | 10 +-- crates/nu-system/Cargo.toml | 4 +- crates/nu-table/Cargo.toml | 12 ++-- crates/nu-term-grid/Cargo.toml | 6 +- crates/nu-test-support/Cargo.toml | 10 +-- crates/nu-utils/Cargo.toml | 4 +- .../src/sample_config/default_config.nu | 4 +- .../nu-utils/src/sample_config/default_env.nu | 4 +- crates/nu_plugin_custom_values/Cargo.toml | 6 +- crates/nu_plugin_example/Cargo.toml | 10 +-- crates/nu_plugin_formats/Cargo.toml | 8 +-- crates/nu_plugin_gstat/Cargo.toml | 8 +-- crates/nu_plugin_inc/Cargo.toml | 8 +-- .../nu_plugin_nu_example.nu | 4 +- crates/nu_plugin_polars/Cargo.toml | 20 +++--- .../nu_plugin_python_example.py | 4 +- crates/nu_plugin_query/Cargo.toml | 8 +-- crates/nu_plugin_stress_internals/Cargo.toml | 4 +- crates/nuon/Cargo.toml | 10 +-- 44 files changed, 272 insertions(+), 272 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b8777234ad..6bfbddda07 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2770,7 +2770,7 @@ dependencies = [ [[package]] name = "nu" -version = "0.93.1" +version = "0.94.0" dependencies = [ "assert_cmd", "crossterm", @@ -2823,7 +2823,7 @@ dependencies = [ [[package]] name = "nu-cli" -version = "0.93.1" +version = "0.94.0" dependencies = [ "chrono", "crossterm", @@ -2858,7 +2858,7 @@ dependencies = [ [[package]] name = "nu-cmd-base" -version = "0.93.1" +version = "0.94.0" dependencies = [ "indexmap", "miette", @@ -2870,7 +2870,7 @@ dependencies = [ [[package]] name = "nu-cmd-extra" -version = "0.93.1" +version = "0.94.0" dependencies = [ "fancy-regex", "heck 0.5.0", @@ -2895,7 +2895,7 @@ dependencies = [ [[package]] name = "nu-cmd-lang" -version = "0.93.1" +version = "0.94.0" dependencies = [ "itertools 0.12.1", "nu-engine", @@ -2907,7 +2907,7 @@ dependencies = [ [[package]] name = "nu-cmd-plugin" -version = "0.93.1" +version = "0.94.0" dependencies = [ "itertools 0.12.1", "nu-engine", @@ -2918,7 +2918,7 @@ dependencies = [ [[package]] name = "nu-color-config" -version = "0.93.1" +version = "0.94.0" dependencies = [ "nu-ansi-term", "nu-engine", @@ -2930,7 +2930,7 @@ dependencies = [ [[package]] name = "nu-command" -version = "0.93.1" +version = "0.94.0" dependencies = [ "alphanumeric-sort", "base64 0.22.1", @@ -3039,7 +3039,7 @@ dependencies = [ [[package]] name = "nu-engine" -version = "0.93.1" +version = "0.94.0" dependencies = [ "nu-glob", "nu-path", @@ -3049,7 +3049,7 @@ dependencies = [ [[package]] name = "nu-explore" -version = "0.93.1" +version = "0.94.0" dependencies = [ "ansi-str", "anyhow", @@ -3074,14 +3074,14 @@ dependencies = [ [[package]] name = "nu-glob" -version = "0.93.1" +version = "0.94.0" dependencies = [ "doc-comment", ] [[package]] name = "nu-json" -version = "0.93.1" +version = "0.94.0" dependencies = [ "linked-hash-map", "num-traits", @@ -3091,7 +3091,7 @@ dependencies = [ [[package]] name = "nu-lsp" -version = "0.93.1" +version = "0.94.0" dependencies = [ "assert-json-diff", "crossbeam-channel", @@ -3112,7 +3112,7 @@ dependencies = [ [[package]] name = "nu-parser" -version = "0.93.1" +version = "0.94.0" dependencies = [ "bytesize", "chrono", @@ -3128,7 +3128,7 @@ dependencies = [ [[package]] name = "nu-path" -version = "0.93.1" +version = "0.94.0" dependencies = [ "dirs-next", "omnipath", @@ -3137,7 +3137,7 @@ dependencies = [ [[package]] name = "nu-plugin" -version = "0.93.1" +version = "0.94.0" dependencies = [ "log", "nix", @@ -3152,7 +3152,7 @@ dependencies = [ [[package]] name = "nu-plugin-core" -version = "0.93.1" +version = "0.94.0" dependencies = [ "interprocess", "log", @@ -3166,7 +3166,7 @@ dependencies = [ [[package]] name = "nu-plugin-engine" -version = "0.93.1" +version = "0.94.0" dependencies = [ "log", "nu-engine", @@ -3181,7 +3181,7 @@ dependencies = [ [[package]] name = "nu-plugin-protocol" -version = "0.93.1" +version = "0.94.0" dependencies = [ "bincode", "nu-protocol", @@ -3193,7 +3193,7 @@ dependencies = [ [[package]] name = "nu-plugin-test-support" -version = "0.93.1" +version = "0.94.0" dependencies = [ "nu-ansi-term", "nu-cmd-lang", @@ -3211,7 +3211,7 @@ dependencies = [ [[package]] name = "nu-pretty-hex" -version = "0.93.1" +version = "0.94.0" dependencies = [ "heapless", "nu-ansi-term", @@ -3220,7 +3220,7 @@ dependencies = [ [[package]] name = "nu-protocol" -version = "0.93.1" +version = "0.94.0" dependencies = [ "brotli 5.0.0", "byte-unit", @@ -3251,7 +3251,7 @@ dependencies = [ [[package]] name = "nu-std" -version = "0.93.1" +version = "0.94.0" dependencies = [ "log", "miette", @@ -3262,7 +3262,7 @@ dependencies = [ [[package]] name = "nu-system" -version = "0.93.1" +version = "0.94.0" dependencies = [ "chrono", "itertools 0.12.1", @@ -3280,7 +3280,7 @@ dependencies = [ [[package]] name = "nu-table" -version = "0.93.1" +version = "0.94.0" dependencies = [ "fancy-regex", "nu-ansi-term", @@ -3294,7 +3294,7 @@ dependencies = [ [[package]] name = "nu-term-grid" -version = "0.93.1" +version = "0.94.0" dependencies = [ "nu-utils", "unicode-width", @@ -3302,7 +3302,7 @@ dependencies = [ [[package]] name = "nu-test-support" -version = "0.93.1" +version = "0.94.0" dependencies = [ "nu-glob", "nu-path", @@ -3314,7 +3314,7 @@ dependencies = [ [[package]] name = "nu-utils" -version = "0.93.1" +version = "0.94.0" dependencies = [ "crossterm_winapi", "log", @@ -3340,7 +3340,7 @@ dependencies = [ [[package]] name = "nu_plugin_example" -version = "0.93.1" +version = "0.94.0" dependencies = [ "nu-cmd-lang", "nu-plugin", @@ -3350,7 +3350,7 @@ dependencies = [ [[package]] name = "nu_plugin_formats" -version = "0.93.1" +version = "0.94.0" dependencies = [ "eml-parser", "ical", @@ -3363,7 +3363,7 @@ dependencies = [ [[package]] name = "nu_plugin_gstat" -version = "0.93.1" +version = "0.94.0" dependencies = [ "git2", "nu-plugin", @@ -3372,7 +3372,7 @@ dependencies = [ [[package]] name = "nu_plugin_inc" -version = "0.93.1" +version = "0.94.0" dependencies = [ "nu-plugin", "nu-protocol", @@ -3381,7 +3381,7 @@ dependencies = [ [[package]] name = "nu_plugin_polars" -version = "0.93.1" +version = "0.94.0" dependencies = [ "chrono", "chrono-tz 0.9.0", @@ -3412,7 +3412,7 @@ dependencies = [ [[package]] name = "nu_plugin_query" -version = "0.93.1" +version = "0.94.0" dependencies = [ "gjson", "nu-plugin", @@ -3424,7 +3424,7 @@ dependencies = [ [[package]] name = "nu_plugin_stress_internals" -version = "0.93.1" +version = "0.94.0" dependencies = [ "interprocess", "serde", @@ -3550,7 +3550,7 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "nuon" -version = "0.93.1" +version = "0.94.0" dependencies = [ "chrono", "fancy-regex", diff --git a/Cargo.toml b/Cargo.toml index 6cac862ae1..f58a563552 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ license = "MIT" name = "nu" repository = "https://github.com/nushell/nushell" rust-version = "1.77.2" -version = "0.93.1" +version = "0.94.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -174,22 +174,22 @@ windows = "0.54" winreg = "0.52" [dependencies] -nu-cli = { path = "./crates/nu-cli", version = "0.93.1" } -nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.93.1" } -nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.93.1" } -nu-cmd-plugin = { path = "./crates/nu-cmd-plugin", version = "0.93.1", optional = true } -nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.93.1" } -nu-command = { path = "./crates/nu-command", version = "0.93.1" } -nu-engine = { path = "./crates/nu-engine", version = "0.93.1" } -nu-explore = { path = "./crates/nu-explore", version = "0.93.1" } -nu-lsp = { path = "./crates/nu-lsp/", version = "0.93.1" } -nu-parser = { path = "./crates/nu-parser", version = "0.93.1" } -nu-path = { path = "./crates/nu-path", version = "0.93.1" } -nu-plugin-engine = { path = "./crates/nu-plugin-engine", optional = true, version = "0.93.1" } -nu-protocol = { path = "./crates/nu-protocol", version = "0.93.1" } -nu-std = { path = "./crates/nu-std", version = "0.93.1" } -nu-system = { path = "./crates/nu-system", version = "0.93.1" } -nu-utils = { path = "./crates/nu-utils", version = "0.93.1" } +nu-cli = { path = "./crates/nu-cli", version = "0.94.0" } +nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.94.0" } +nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.94.0" } +nu-cmd-plugin = { path = "./crates/nu-cmd-plugin", version = "0.94.0", optional = true } +nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.94.0" } +nu-command = { path = "./crates/nu-command", version = "0.94.0" } +nu-engine = { path = "./crates/nu-engine", version = "0.94.0" } +nu-explore = { path = "./crates/nu-explore", version = "0.94.0" } +nu-lsp = { path = "./crates/nu-lsp/", version = "0.94.0" } +nu-parser = { path = "./crates/nu-parser", version = "0.94.0" } +nu-path = { path = "./crates/nu-path", version = "0.94.0" } +nu-plugin-engine = { path = "./crates/nu-plugin-engine", optional = true, version = "0.94.0" } +nu-protocol = { path = "./crates/nu-protocol", version = "0.94.0" } +nu-std = { path = "./crates/nu-std", version = "0.94.0" } +nu-system = { path = "./crates/nu-system", version = "0.94.0" } +nu-utils = { path = "./crates/nu-utils", version = "0.94.0" } reedline = { workspace = true, features = ["bashisms", "sqlite"] } @@ -218,9 +218,9 @@ nix = { workspace = true, default-features = false, features = [ ] } [dev-dependencies] -nu-test-support = { path = "./crates/nu-test-support", version = "0.93.1" } -nu-plugin-protocol = { path = "./crates/nu-plugin-protocol", version = "0.93.1" } -nu-plugin-core = { path = "./crates/nu-plugin-core", version = "0.93.1" } +nu-test-support = { path = "./crates/nu-test-support", version = "0.94.0" } +nu-plugin-protocol = { path = "./crates/nu-plugin-protocol", version = "0.94.0" } +nu-plugin-core = { path = "./crates/nu-plugin-core", version = "0.94.0" } assert_cmd = "2.0" dirs-next = { workspace = true } tango-bench = "0.5" @@ -305,4 +305,4 @@ bench = false # Run individual benchmarks like `cargo bench -- ` e.g. `cargo bench -- parse` [[bench]] name = "benchmarks" -harness = false +harness = false \ No newline at end of file diff --git a/crates/nu-cli/Cargo.toml b/crates/nu-cli/Cargo.toml index d9cd728f19..2363df58ab 100644 --- a/crates/nu-cli/Cargo.toml +++ b/crates/nu-cli/Cargo.toml @@ -5,27 +5,27 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cli" edition = "2021" license = "MIT" name = "nu-cli" -version = "0.93.1" +version = "0.94.0" [lib] bench = false [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.93.1" } -nu-command = { path = "../nu-command", version = "0.93.1" } -nu-test-support = { path = "../nu-test-support", version = "0.93.1" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.0" } +nu-command = { path = "../nu-command", version = "0.94.0" } +nu-test-support = { path = "../nu-test-support", version = "0.94.0" } rstest = { workspace = true, default-features = false } tempfile = { workspace = true } [dependencies] -nu-cmd-base = { path = "../nu-cmd-base", version = "0.93.1" } -nu-engine = { path = "../nu-engine", version = "0.93.1" } -nu-path = { path = "../nu-path", version = "0.93.1" } -nu-parser = { path = "../nu-parser", version = "0.93.1" } -nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.93.1", optional = true } -nu-protocol = { path = "../nu-protocol", version = "0.93.1" } -nu-utils = { path = "../nu-utils", version = "0.93.1" } -nu-color-config = { path = "../nu-color-config", version = "0.93.1" } +nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.0" } +nu-engine = { path = "../nu-engine", version = "0.94.0" } +nu-path = { path = "../nu-path", version = "0.94.0" } +nu-parser = { path = "../nu-parser", version = "0.94.0" } +nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.0", optional = true } +nu-protocol = { path = "../nu-protocol", version = "0.94.0" } +nu-utils = { path = "../nu-utils", version = "0.94.0" } +nu-color-config = { path = "../nu-color-config", version = "0.94.0" } nu-ansi-term = { workspace = true } reedline = { workspace = true, features = ["bashisms", "sqlite"] } @@ -46,4 +46,4 @@ which = { workspace = true } [features] plugin = ["nu-plugin-engine"] -system-clipboard = ["reedline/system_clipboard"] +system-clipboard = ["reedline/system_clipboard"] \ No newline at end of file diff --git a/crates/nu-cmd-base/Cargo.toml b/crates/nu-cmd-base/Cargo.toml index b163ff447c..10c4613057 100644 --- a/crates/nu-cmd-base/Cargo.toml +++ b/crates/nu-cmd-base/Cargo.toml @@ -5,17 +5,17 @@ edition = "2021" license = "MIT" name = "nu-cmd-base" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-base" -version = "0.93.1" +version = "0.94.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-engine = { path = "../nu-engine", version = "0.93.1" } -nu-parser = { path = "../nu-parser", version = "0.93.1" } -nu-path = { path = "../nu-path", version = "0.93.1" } -nu-protocol = { path = "../nu-protocol", version = "0.93.1" } +nu-engine = { path = "../nu-engine", version = "0.94.0" } +nu-parser = { path = "../nu-parser", version = "0.94.0" } +nu-path = { path = "../nu-path", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0" } indexmap = { workspace = true } miette = { workspace = true } -[dev-dependencies] +[dev-dependencies] \ No newline at end of file diff --git a/crates/nu-cmd-extra/Cargo.toml b/crates/nu-cmd-extra/Cargo.toml index 4c3dce09c7..695adbf120 100644 --- a/crates/nu-cmd-extra/Cargo.toml +++ b/crates/nu-cmd-extra/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "MIT" name = "nu-cmd-extra" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-extra" -version = "0.93.1" +version = "0.94.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -13,13 +13,13 @@ version = "0.93.1" bench = false [dependencies] -nu-cmd-base = { path = "../nu-cmd-base", version = "0.93.1" } -nu-engine = { path = "../nu-engine", version = "0.93.1" } -nu-json = { version = "0.93.1", path = "../nu-json" } -nu-parser = { path = "../nu-parser", version = "0.93.1" } -nu-pretty-hex = { version = "0.93.1", path = "../nu-pretty-hex" } -nu-protocol = { path = "../nu-protocol", version = "0.93.1" } -nu-utils = { path = "../nu-utils", version = "0.93.1" } +nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.0" } +nu-engine = { path = "../nu-engine", version = "0.94.0" } +nu-json = { version = "0.94.0", path = "../nu-json" } +nu-parser = { path = "../nu-parser", version = "0.94.0" } +nu-pretty-hex = { version = "0.94.0", path = "../nu-pretty-hex" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0" } +nu-utils = { path = "../nu-utils", version = "0.94.0" } # Potential dependencies for extras heck = { workspace = true } @@ -37,6 +37,6 @@ extra = ["default"] default = [] [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.93.1" } -nu-command = { path = "../nu-command", version = "0.93.1" } -nu-test-support = { path = "../nu-test-support", version = "0.93.1" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.0" } +nu-command = { path = "../nu-command", version = "0.94.0" } +nu-test-support = { path = "../nu-test-support", version = "0.94.0" } \ No newline at end of file diff --git a/crates/nu-cmd-lang/Cargo.toml b/crates/nu-cmd-lang/Cargo.toml index 45f5b9bc8f..6077b3fa81 100644 --- a/crates/nu-cmd-lang/Cargo.toml +++ b/crates/nu-cmd-lang/Cargo.toml @@ -6,16 +6,16 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-lang" edition = "2021" license = "MIT" name = "nu-cmd-lang" -version = "0.93.1" +version = "0.94.0" [lib] bench = false [dependencies] -nu-engine = { path = "../nu-engine", version = "0.93.1" } -nu-parser = { path = "../nu-parser", version = "0.93.1" } -nu-protocol = { path = "../nu-protocol", version = "0.93.1" } -nu-utils = { path = "../nu-utils", version = "0.93.1" } +nu-engine = { path = "../nu-engine", version = "0.94.0" } +nu-parser = { path = "../nu-parser", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0" } +nu-utils = { path = "../nu-utils", version = "0.94.0" } itertools = { workspace = true } shadow-rs = { version = "0.28", default-features = false } @@ -29,4 +29,4 @@ which-support = [] trash-support = [] sqlite = [] static-link-openssl = [] -system-clipboard = [] +system-clipboard = [] \ No newline at end of file diff --git a/crates/nu-cmd-plugin/Cargo.toml b/crates/nu-cmd-plugin/Cargo.toml index 0d83c3a407..fd6a9921b9 100644 --- a/crates/nu-cmd-plugin/Cargo.toml +++ b/crates/nu-cmd-plugin/Cargo.toml @@ -5,16 +5,16 @@ edition = "2021" license = "MIT" name = "nu-cmd-plugin" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-plugin" -version = "0.93.1" +version = "0.94.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-engine = { path = "../nu-engine", version = "0.93.1" } -nu-path = { path = "../nu-path", version = "0.93.1" } -nu-protocol = { path = "../nu-protocol", version = "0.93.1", features = ["plugin"] } -nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.93.1" } +nu-engine = { path = "../nu-engine", version = "0.94.0" } +nu-path = { path = "../nu-path", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0", features = ["plugin"] } +nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.0" } itertools = { workspace = true } -[dev-dependencies] +[dev-dependencies] \ No newline at end of file diff --git a/crates/nu-color-config/Cargo.toml b/crates/nu-color-config/Cargo.toml index f183f5c054..c1689ccb84 100644 --- a/crates/nu-color-config/Cargo.toml +++ b/crates/nu-color-config/Cargo.toml @@ -5,18 +5,18 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-color-confi edition = "2021" license = "MIT" name = "nu-color-config" -version = "0.93.1" +version = "0.94.0" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.93.1" } -nu-engine = { path = "../nu-engine", version = "0.93.1" } -nu-json = { path = "../nu-json", version = "0.93.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0" } +nu-engine = { path = "../nu-engine", version = "0.94.0" } +nu-json = { path = "../nu-json", version = "0.94.0" } nu-ansi-term = { workspace = true } serde = { workspace = true, features = ["derive"] } [dev-dependencies] -nu-test-support = { path = "../nu-test-support", version = "0.93.1" } +nu-test-support = { path = "../nu-test-support", version = "0.94.0" } \ No newline at end of file diff --git a/crates/nu-command/Cargo.toml b/crates/nu-command/Cargo.toml index d3456764fd..90dac40b0b 100644 --- a/crates/nu-command/Cargo.toml +++ b/crates/nu-command/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "MIT" name = "nu-command" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-command" -version = "0.93.1" +version = "0.94.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -13,21 +13,21 @@ version = "0.93.1" bench = false [dependencies] -nu-cmd-base = { path = "../nu-cmd-base", version = "0.93.1" } -nu-color-config = { path = "../nu-color-config", version = "0.93.1" } -nu-engine = { path = "../nu-engine", version = "0.93.1" } -nu-glob = { path = "../nu-glob", version = "0.93.1" } -nu-json = { path = "../nu-json", version = "0.93.1" } -nu-parser = { path = "../nu-parser", version = "0.93.1" } -nu-path = { path = "../nu-path", version = "0.93.1" } -nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.93.1" } -nu-protocol = { path = "../nu-protocol", version = "0.93.1" } -nu-system = { path = "../nu-system", version = "0.93.1" } -nu-table = { path = "../nu-table", version = "0.93.1" } -nu-term-grid = { path = "../nu-term-grid", version = "0.93.1" } -nu-utils = { path = "../nu-utils", version = "0.93.1" } +nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.0" } +nu-color-config = { path = "../nu-color-config", version = "0.94.0" } +nu-engine = { path = "../nu-engine", version = "0.94.0" } +nu-glob = { path = "../nu-glob", version = "0.94.0" } +nu-json = { path = "../nu-json", version = "0.94.0" } +nu-parser = { path = "../nu-parser", version = "0.94.0" } +nu-path = { path = "../nu-path", version = "0.94.0" } +nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0" } +nu-system = { path = "../nu-system", version = "0.94.0" } +nu-table = { path = "../nu-table", version = "0.94.0" } +nu-term-grid = { path = "../nu-term-grid", version = "0.94.0" } +nu-utils = { path = "../nu-utils", version = "0.94.0" } nu-ansi-term = { workspace = true } -nuon = { path = "../nuon", version = "0.93.1" } +nuon = { path = "../nuon", version = "0.94.0" } alphanumeric-sort = { workspace = true } base64 = { workspace = true } @@ -137,8 +137,8 @@ trash-support = ["trash"] which-support = [] [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.93.1" } -nu-test-support = { path = "../nu-test-support", version = "0.93.1" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.0" } +nu-test-support = { path = "../nu-test-support", version = "0.94.0" } dirs-next = { workspace = true } mockito = { workspace = true, default-features = false } @@ -146,4 +146,4 @@ quickcheck = { workspace = true } quickcheck_macros = { workspace = true } rstest = { workspace = true, default-features = false } pretty_assertions = { workspace = true } -tempfile = { workspace = true } +tempfile = { workspace = true } \ No newline at end of file diff --git a/crates/nu-engine/Cargo.toml b/crates/nu-engine/Cargo.toml index 39fefc525e..671c5c86bf 100644 --- a/crates/nu-engine/Cargo.toml +++ b/crates/nu-engine/Cargo.toml @@ -5,16 +5,16 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-engine" edition = "2021" license = "MIT" name = "nu-engine" -version = "0.93.1" +version = "0.94.0" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", features = ["plugin"], version = "0.93.1" } -nu-path = { path = "../nu-path", version = "0.93.1" } -nu-glob = { path = "../nu-glob", version = "0.93.1" } -nu-utils = { path = "../nu-utils", version = "0.93.1" } +nu-protocol = { path = "../nu-protocol", features = ["plugin"], version = "0.94.0" } +nu-path = { path = "../nu-path", version = "0.94.0" } +nu-glob = { path = "../nu-glob", version = "0.94.0" } +nu-utils = { path = "../nu-utils", version = "0.94.0" } [features] -plugin = [] +plugin = [] \ No newline at end of file diff --git a/crates/nu-explore/Cargo.toml b/crates/nu-explore/Cargo.toml index 46756e4101..274cf369e5 100644 --- a/crates/nu-explore/Cargo.toml +++ b/crates/nu-explore/Cargo.toml @@ -5,21 +5,21 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-explore" edition = "2021" license = "MIT" name = "nu-explore" -version = "0.93.1" +version = "0.94.0" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.93.1" } -nu-parser = { path = "../nu-parser", version = "0.93.1" } -nu-color-config = { path = "../nu-color-config", version = "0.93.1" } -nu-engine = { path = "../nu-engine", version = "0.93.1" } -nu-table = { path = "../nu-table", version = "0.93.1" } -nu-json = { path = "../nu-json", version = "0.93.1" } -nu-utils = { path = "../nu-utils", version = "0.93.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0" } +nu-parser = { path = "../nu-parser", version = "0.94.0" } +nu-color-config = { path = "../nu-color-config", version = "0.94.0" } +nu-engine = { path = "../nu-engine", version = "0.94.0" } +nu-table = { path = "../nu-table", version = "0.94.0" } +nu-json = { path = "../nu-json", version = "0.94.0" } +nu-utils = { path = "../nu-utils", version = "0.94.0" } nu-ansi-term = { workspace = true } -nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.93.1" } +nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.94.0" } anyhow = { workspace = true } log = { workspace = true } @@ -32,4 +32,4 @@ ansi-str = { workspace = true } unicode-width = { workspace = true } lscolors = { workspace = true, default-features = false, features = [ "nu-ansi-term", -] } +] } \ No newline at end of file diff --git a/crates/nu-glob/Cargo.toml b/crates/nu-glob/Cargo.toml index 8a57dbe2a9..164fff93a2 100644 --- a/crates/nu-glob/Cargo.toml +++ b/crates/nu-glob/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nu-glob" -version = "0.93.1" +version = "0.94.0" authors = ["The Nushell Project Developers", "The Rust Project Developers"] license = "MIT/Apache-2.0" description = """ @@ -14,4 +14,4 @@ categories = ["filesystem"] bench = false [dev-dependencies] -doc-comment = "0.3" +doc-comment = "0.3" \ No newline at end of file diff --git a/crates/nu-json/Cargo.toml b/crates/nu-json/Cargo.toml index 303ed75e8a..e5561c1118 100644 --- a/crates/nu-json/Cargo.toml +++ b/crates/nu-json/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-json" edition = "2021" license = "MIT" name = "nu-json" -version = "0.93.1" +version = "0.94.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -23,5 +23,5 @@ serde = { workspace = true } serde_json = { workspace = true } [dev-dependencies] -# nu-path = { path="../nu-path", version = "0.93.1" } -# serde_json = "1.0" +# nu-path = { path="../nu-path", version = "0.94.0" } +# serde_json = "1.0" \ No newline at end of file diff --git a/crates/nu-lsp/Cargo.toml b/crates/nu-lsp/Cargo.toml index c69499cfe3..a47da72e2d 100644 --- a/crates/nu-lsp/Cargo.toml +++ b/crates/nu-lsp/Cargo.toml @@ -3,14 +3,14 @@ authors = ["The Nushell Project Developers"] description = "Nushell's integrated LSP server" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-lsp" name = "nu-lsp" -version = "0.93.1" +version = "0.94.0" edition = "2021" license = "MIT" [dependencies] -nu-cli = { path = "../nu-cli", version = "0.93.1" } -nu-parser = { path = "../nu-parser", version = "0.93.1" } -nu-protocol = { path = "../nu-protocol", version = "0.93.1" } +nu-cli = { path = "../nu-cli", version = "0.94.0" } +nu-parser = { path = "../nu-parser", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0" } reedline = { workspace = true } @@ -23,8 +23,8 @@ serde = { workspace = true } serde_json = { workspace = true } [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.93.1" } -nu-command = { path = "../nu-command", version = "0.93.1" } -nu-test-support = { path = "../nu-test-support", version = "0.93.1" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.0" } +nu-command = { path = "../nu-command", version = "0.94.0" } +nu-test-support = { path = "../nu-test-support", version = "0.94.0" } -assert-json-diff = "2.0" +assert-json-diff = "2.0" \ No newline at end of file diff --git a/crates/nu-parser/Cargo.toml b/crates/nu-parser/Cargo.toml index 9fdf737af3..ea719ebdd4 100644 --- a/crates/nu-parser/Cargo.toml +++ b/crates/nu-parser/Cargo.toml @@ -5,17 +5,17 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-parser" edition = "2021" license = "MIT" name = "nu-parser" -version = "0.93.1" +version = "0.94.0" exclude = ["/fuzz"] [lib] bench = false [dependencies] -nu-engine = { path = "../nu-engine", version = "0.93.1" } -nu-path = { path = "../nu-path", version = "0.93.1" } -nu-plugin-engine = { path = "../nu-plugin-engine", optional = true, version = "0.93.1" } -nu-protocol = { path = "../nu-protocol", version = "0.93.1" } +nu-engine = { path = "../nu-engine", version = "0.94.0" } +nu-path = { path = "../nu-path", version = "0.94.0" } +nu-plugin-engine = { path = "../nu-plugin-engine", optional = true, version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0" } bytesize = { workspace = true } chrono = { default-features = false, features = ['std'], workspace = true } @@ -27,4 +27,4 @@ serde_json = { workspace = true } rstest = { workspace = true, default-features = false } [features] -plugin = ["nu-plugin-engine"] +plugin = ["nu-plugin-engine"] \ No newline at end of file diff --git a/crates/nu-parser/fuzz/Cargo.toml b/crates/nu-parser/fuzz/Cargo.toml index db97e0f654..45216accc9 100644 --- a/crates/nu-parser/fuzz/Cargo.toml +++ b/crates/nu-parser/fuzz/Cargo.toml @@ -26,4 +26,4 @@ debug = 1 name = "parse" path = "fuzz_targets/parse.rs" test = false -doc = false +doc = false \ No newline at end of file diff --git a/crates/nu-path/Cargo.toml b/crates/nu-path/Cargo.toml index dbac11e336..1fc1f78ac4 100644 --- a/crates/nu-path/Cargo.toml +++ b/crates/nu-path/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-path" edition = "2021" license = "MIT" name = "nu-path" -version = "0.93.1" +version = "0.94.0" exclude = ["/fuzz"] [lib] @@ -18,4 +18,4 @@ dirs-next = { workspace = true } omnipath = { workspace = true } [target.'cfg(all(unix, not(target_os = "macos"), not(target_os = "android")))'.dependencies] -pwd = { workspace = true } +pwd = { workspace = true } \ No newline at end of file diff --git a/crates/nu-path/fuzz/Cargo.toml b/crates/nu-path/fuzz/Cargo.toml index 08121602d7..c55453dba9 100644 --- a/crates/nu-path/fuzz/Cargo.toml +++ b/crates/nu-path/fuzz/Cargo.toml @@ -24,4 +24,4 @@ debug = 1 name = "path" path = "fuzz_targets/path_fuzzer.rs" test = false -doc = false +doc = false \ No newline at end of file diff --git a/crates/nu-plugin-core/Cargo.toml b/crates/nu-plugin-core/Cargo.toml index 242cac9bdf..7a2085ee90 100644 --- a/crates/nu-plugin-core/Cargo.toml +++ b/crates/nu-plugin-core/Cargo.toml @@ -5,14 +5,14 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-plugin-core edition = "2021" license = "MIT" name = "nu-plugin-core" -version = "0.93.1" +version = "0.94.0" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.93.1" } -nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.93.1", default-features = false } +nu-protocol = { path = "../nu-protocol", version = "0.94.0" } +nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.0", default-features = false } rmp-serde = { workspace = true } serde = { workspace = true } @@ -25,4 +25,4 @@ default = ["local-socket"] local-socket = ["interprocess", "nu-plugin-protocol/local-socket"] [target.'cfg(target_os = "windows")'.dependencies] -windows = { workspace = true } +windows = { workspace = true } \ No newline at end of file diff --git a/crates/nu-plugin-engine/Cargo.toml b/crates/nu-plugin-engine/Cargo.toml index 9ee6777880..40f482bd78 100644 --- a/crates/nu-plugin-engine/Cargo.toml +++ b/crates/nu-plugin-engine/Cargo.toml @@ -5,17 +5,17 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-plugin-engi edition = "2021" license = "MIT" name = "nu-plugin-engine" -version = "0.93.1" +version = "0.94.0" [lib] bench = false [dependencies] -nu-engine = { path = "../nu-engine", version = "0.93.1" } -nu-protocol = { path = "../nu-protocol", version = "0.93.1" } -nu-system = { path = "../nu-system", version = "0.93.1" } -nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.93.1" } -nu-plugin-core = { path = "../nu-plugin-core", version = "0.93.1", default-features = false } +nu-engine = { path = "../nu-engine", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0" } +nu-system = { path = "../nu-system", version = "0.94.0" } +nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.0" } +nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.0", default-features = false } serde = { workspace = true } log = { workspace = true } @@ -31,4 +31,4 @@ local-socket = ["nu-plugin-core/local-socket"] windows = { workspace = true, features = [ # For setting process creation flags "Win32_System_Threading", -] } +] } \ No newline at end of file diff --git a/crates/nu-plugin-protocol/Cargo.toml b/crates/nu-plugin-protocol/Cargo.toml index 4e364f2dba..996e1ce8f2 100644 --- a/crates/nu-plugin-protocol/Cargo.toml +++ b/crates/nu-plugin-protocol/Cargo.toml @@ -5,14 +5,14 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-plugin-prot edition = "2021" license = "MIT" name = "nu-plugin-protocol" -version = "0.93.1" +version = "0.94.0" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.93.1", features = ["plugin"] } -nu-utils = { path = "../nu-utils", version = "0.93.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0", features = ["plugin"] } +nu-utils = { path = "../nu-utils", version = "0.94.0" } bincode = "1.3" serde = { workspace = true, features = ["derive"] } @@ -21,4 +21,4 @@ typetag = "0.2" [features] default = ["local-socket"] -local-socket = [] +local-socket = [] \ No newline at end of file diff --git a/crates/nu-plugin-test-support/Cargo.toml b/crates/nu-plugin-test-support/Cargo.toml index 5a92ef8d96..04f77ac7fa 100644 --- a/crates/nu-plugin-test-support/Cargo.toml +++ b/crates/nu-plugin-test-support/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nu-plugin-test-support" -version = "0.93.1" +version = "0.94.0" edition = "2021" license = "MIT" description = "Testing support for Nushell plugins" @@ -12,17 +12,17 @@ bench = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-engine = { path = "../nu-engine", version = "0.93.1", features = ["plugin"] } -nu-protocol = { path = "../nu-protocol", version = "0.93.1", features = ["plugin"] } -nu-parser = { path = "../nu-parser", version = "0.93.1", features = ["plugin"] } -nu-plugin = { path = "../nu-plugin", version = "0.93.1" } -nu-plugin-core = { path = "../nu-plugin-core", version = "0.93.1" } -nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.93.1" } -nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.93.1" } -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.93.1" } +nu-engine = { path = "../nu-engine", version = "0.94.0", features = ["plugin"] } +nu-protocol = { path = "../nu-protocol", version = "0.94.0", features = ["plugin"] } +nu-parser = { path = "../nu-parser", version = "0.94.0", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.0" } +nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.0" } +nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.0" } +nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.0" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.0" } nu-ansi-term = { workspace = true } similar = "2.5" [dev-dependencies] typetag = "0.2" -serde = "1.0" +serde = "1.0" \ No newline at end of file diff --git a/crates/nu-plugin/Cargo.toml b/crates/nu-plugin/Cargo.toml index ac0cb612ed..ff19f84273 100644 --- a/crates/nu-plugin/Cargo.toml +++ b/crates/nu-plugin/Cargo.toml @@ -5,16 +5,16 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-plugin" edition = "2021" license = "MIT" name = "nu-plugin" -version = "0.93.1" +version = "0.94.0" [lib] bench = false [dependencies] -nu-engine = { path = "../nu-engine", version = "0.93.1" } -nu-protocol = { path = "../nu-protocol", version = "0.93.1" } -nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.93.1" } -nu-plugin-core = { path = "../nu-plugin-core", version = "0.93.1", default-features = false } +nu-engine = { path = "../nu-engine", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0" } +nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.0" } +nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.0", default-features = false } log = { workspace = true } thiserror = "1.0" @@ -29,4 +29,4 @@ local-socket = ["nu-plugin-core/local-socket"] [target.'cfg(target_family = "unix")'.dependencies] # For setting the process group ID (EnterForeground / LeaveForeground) -nix = { workspace = true, default-features = false, features = ["process"] } +nix = { workspace = true, default-features = false, features = ["process"] } \ No newline at end of file diff --git a/crates/nu-pretty-hex/Cargo.toml b/crates/nu-pretty-hex/Cargo.toml index ffe8f3149b..3849fc9495 100644 --- a/crates/nu-pretty-hex/Cargo.toml +++ b/crates/nu-pretty-hex/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-pretty-hex" edition = "2021" license = "MIT" name = "nu-pretty-hex" -version = "0.93.1" +version = "0.94.0" [lib] doctest = false @@ -18,4 +18,4 @@ nu-ansi-term = { workspace = true } [dev-dependencies] heapless = { version = "0.8", default-features = false } -rand = "0.8" +rand = "0.8" \ No newline at end of file diff --git a/crates/nu-protocol/Cargo.toml b/crates/nu-protocol/Cargo.toml index 84e76b3f5a..5d81535d04 100644 --- a/crates/nu-protocol/Cargo.toml +++ b/crates/nu-protocol/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-protocol" edition = "2021" license = "MIT" name = "nu-protocol" -version = "0.93.1" +version = "0.94.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -13,9 +13,9 @@ version = "0.93.1" bench = false [dependencies] -nu-utils = { path = "../nu-utils", version = "0.93.1" } -nu-path = { path = "../nu-path", version = "0.93.1" } -nu-system = { path = "../nu-system", version = "0.93.1" } +nu-utils = { path = "../nu-utils", version = "0.94.0" } +nu-path = { path = "../nu-path", version = "0.94.0" } +nu-system = { path = "../nu-system", version = "0.94.0" } brotli = { workspace = true, optional = true } byte-unit = { version = "5.1", features = [ "serde" ] } @@ -45,11 +45,11 @@ plugin = [ serde_json = { workspace = true } strum = "0.26" strum_macros = "0.26" -nu-test-support = { path = "../nu-test-support", version = "0.93.1" } +nu-test-support = { path = "../nu-test-support", version = "0.94.0" } pretty_assertions = { workspace = true } rstest = { workspace = true } tempfile = { workspace = true } os_pipe = { workspace = true } [package.metadata.docs.rs] -all-features = true +all-features = true \ No newline at end of file diff --git a/crates/nu-std/Cargo.toml b/crates/nu-std/Cargo.toml index c6f5ae0ffe..3f050b31e1 100644 --- a/crates/nu-std/Cargo.toml +++ b/crates/nu-std/Cargo.toml @@ -5,12 +5,12 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-std" edition = "2021" license = "MIT" name = "nu-std" -version = "0.93.1" +version = "0.94.0" [dependencies] -nu-parser = { version = "0.93.1", path = "../nu-parser" } -nu-protocol = { version = "0.93.1", path = "../nu-protocol" } -nu-engine = { version = "0.93.1", path = "../nu-engine" } +nu-parser = { version = "0.94.0", path = "../nu-parser" } +nu-protocol = { version = "0.94.0", path = "../nu-protocol" } +nu-engine = { version = "0.94.0", path = "../nu-engine" } miette = { workspace = true, features = ["fancy-no-backtrace"] } -log = "0.4" +log = "0.4" \ No newline at end of file diff --git a/crates/nu-system/Cargo.toml b/crates/nu-system/Cargo.toml index 88d6b28b05..e28c72ad53 100644 --- a/crates/nu-system/Cargo.toml +++ b/crates/nu-system/Cargo.toml @@ -3,7 +3,7 @@ authors = ["The Nushell Project Developers", "procs creators"] description = "Nushell system querying" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-system" name = "nu-system" -version = "0.93.1" +version = "0.94.0" edition = "2021" license = "MIT" @@ -45,4 +45,4 @@ windows = { workspace = true, features = [ "Win32_System_SystemInformation", "Win32_System_Threading", "Win32_UI_Shell", -]} +]} \ No newline at end of file diff --git a/crates/nu-table/Cargo.toml b/crates/nu-table/Cargo.toml index 630b72e3e3..b2bed2b555 100644 --- a/crates/nu-table/Cargo.toml +++ b/crates/nu-table/Cargo.toml @@ -5,20 +5,20 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-table" edition = "2021" license = "MIT" name = "nu-table" -version = "0.93.1" +version = "0.94.0" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.93.1" } -nu-utils = { path = "../nu-utils", version = "0.93.1" } -nu-engine = { path = "../nu-engine", version = "0.93.1" } -nu-color-config = { path = "../nu-color-config", version = "0.93.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0" } +nu-utils = { path = "../nu-utils", version = "0.94.0" } +nu-engine = { path = "../nu-engine", version = "0.94.0" } +nu-color-config = { path = "../nu-color-config", version = "0.94.0" } nu-ansi-term = { workspace = true } once_cell = { workspace = true } fancy-regex = { workspace = true } tabled = { workspace = true, features = ["color"], default-features = false } [dev-dependencies] -# nu-test-support = { path="../nu-test-support", version = "0.93.1" } +# nu-test-support = { path="../nu-test-support", version = "0.94.0" } \ No newline at end of file diff --git a/crates/nu-term-grid/Cargo.toml b/crates/nu-term-grid/Cargo.toml index 4a93d15e89..14eefa0ed1 100644 --- a/crates/nu-term-grid/Cargo.toml +++ b/crates/nu-term-grid/Cargo.toml @@ -5,12 +5,12 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-term-grid" edition = "2021" license = "MIT" name = "nu-term-grid" -version = "0.93.1" +version = "0.94.0" [lib] bench = false [dependencies] -nu-utils = { path = "../nu-utils", version = "0.93.1" } +nu-utils = { path = "../nu-utils", version = "0.94.0" } -unicode-width = { workspace = true } +unicode-width = { workspace = true } \ No newline at end of file diff --git a/crates/nu-test-support/Cargo.toml b/crates/nu-test-support/Cargo.toml index 3aa4af9937..8ca77631d1 100644 --- a/crates/nu-test-support/Cargo.toml +++ b/crates/nu-test-support/Cargo.toml @@ -5,17 +5,17 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-test-suppor edition = "2021" license = "MIT" name = "nu-test-support" -version = "0.93.1" +version = "0.94.0" [lib] doctest = false bench = false [dependencies] -nu-path = { path = "../nu-path", version = "0.93.1" } -nu-glob = { path = "../nu-glob", version = "0.93.1" } -nu-utils = { path = "../nu-utils", version = "0.93.1" } +nu-path = { path = "../nu-path", version = "0.94.0" } +nu-glob = { path = "../nu-glob", version = "0.94.0" } +nu-utils = { path = "../nu-utils", version = "0.94.0" } num-format = { workspace = true } which = { workspace = true } -tempfile = { workspace = true } +tempfile = { workspace = true } \ No newline at end of file diff --git a/crates/nu-utils/Cargo.toml b/crates/nu-utils/Cargo.toml index 8cf5f2dab5..681ee7d6f1 100644 --- a/crates/nu-utils/Cargo.toml +++ b/crates/nu-utils/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "MIT" name = "nu-utils" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-utils" -version = "0.93.1" +version = "0.94.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [[bin]] @@ -29,4 +29,4 @@ unicase = "2.7.0" crossterm_winapi = "0.9" [target.'cfg(unix)'.dependencies] -nix = { workspace = true, default-features = false, features = ["user", "fs"] } +nix = { workspace = true, default-features = false, features = ["user", "fs"] } \ No newline at end of file diff --git a/crates/nu-utils/src/sample_config/default_config.nu b/crates/nu-utils/src/sample_config/default_config.nu index 5681fb1a6d..fd9a9642b0 100644 --- a/crates/nu-utils/src/sample_config/default_config.nu +++ b/crates/nu-utils/src/sample_config/default_config.nu @@ -1,6 +1,6 @@ # Nushell Config File # -# version = "0.93.1" +# version = "0.94.0" # For more information on defining custom themes, see # https://www.nushell.sh/book/coloring_and_theming.html @@ -892,4 +892,4 @@ $env.config = { event: { edit: selectall } } ] -} +} \ No newline at end of file diff --git a/crates/nu-utils/src/sample_config/default_env.nu b/crates/nu-utils/src/sample_config/default_env.nu index 65f93eaaba..f68396eec5 100644 --- a/crates/nu-utils/src/sample_config/default_env.nu +++ b/crates/nu-utils/src/sample_config/default_env.nu @@ -1,6 +1,6 @@ # Nushell Environment Config File # -# version = "0.93.1" +# version = "0.94.0" def create_left_prompt [] { let dir = match (do --ignore-shell-errors { $env.PWD | path relative-to $nu.home-path }) { @@ -97,4 +97,4 @@ $env.NU_PLUGIN_DIRS = [ # $env.PATH = ($env.PATH | uniq) # To load from a custom file you can use: -# source ($nu.default-config-dir | path join 'custom.nu') +# source ($nu.default-config-dir | path join 'custom.nu') \ No newline at end of file diff --git a/crates/nu_plugin_custom_values/Cargo.toml b/crates/nu_plugin_custom_values/Cargo.toml index 546436736c..5c9a2bb633 100644 --- a/crates/nu_plugin_custom_values/Cargo.toml +++ b/crates/nu_plugin_custom_values/Cargo.toml @@ -10,10 +10,10 @@ name = "nu_plugin_custom_values" bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.93.1" } -nu-protocol = { path = "../nu-protocol", version = "0.93.1", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0", features = ["plugin"] } serde = { workspace = true, default-features = false } typetag = "0.2" [dev-dependencies] -nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.93.1" } +nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.0" } \ No newline at end of file diff --git a/crates/nu_plugin_example/Cargo.toml b/crates/nu_plugin_example/Cargo.toml index 80d75fd32d..356af74386 100644 --- a/crates/nu_plugin_example/Cargo.toml +++ b/crates/nu_plugin_example/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_exam edition = "2021" license = "MIT" name = "nu_plugin_example" -version = "0.93.1" +version = "0.94.0" [[bin]] name = "nu_plugin_example" @@ -15,9 +15,9 @@ bench = false bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.93.1" } -nu-protocol = { path = "../nu-protocol", version = "0.93.1", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0", features = ["plugin"] } [dev-dependencies] -nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.93.1" } -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.93.1" } +nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.0" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.0" } \ No newline at end of file diff --git a/crates/nu_plugin_formats/Cargo.toml b/crates/nu_plugin_formats/Cargo.toml index e8e1fe3cb9..55c47f33f5 100644 --- a/crates/nu_plugin_formats/Cargo.toml +++ b/crates/nu_plugin_formats/Cargo.toml @@ -5,12 +5,12 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_form edition = "2021" license = "MIT" name = "nu_plugin_formats" -version = "0.93.1" +version = "0.94.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.93.1" } -nu-protocol = { path = "../nu-protocol", version = "0.93.1", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0", features = ["plugin"] } indexmap = { workspace = true } eml-parser = "0.1" @@ -18,4 +18,4 @@ ical = "0.11" rust-ini = "0.21.0" [dev-dependencies] -nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.93.1" } +nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.0" } \ No newline at end of file diff --git a/crates/nu_plugin_gstat/Cargo.toml b/crates/nu_plugin_gstat/Cargo.toml index ff9bd837f8..c779ffd8c4 100644 --- a/crates/nu_plugin_gstat/Cargo.toml +++ b/crates/nu_plugin_gstat/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_gsta edition = "2021" license = "MIT" name = "nu_plugin_gstat" -version = "0.93.1" +version = "0.94.0" [lib] doctest = false @@ -16,7 +16,7 @@ name = "nu_plugin_gstat" bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.93.1" } -nu-protocol = { path = "../nu-protocol", version = "0.93.1" } +nu-plugin = { path = "../nu-plugin", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0" } -git2 = "0.18" +git2 = "0.18" \ No newline at end of file diff --git a/crates/nu_plugin_inc/Cargo.toml b/crates/nu_plugin_inc/Cargo.toml index cd9d27fa92..1c12343598 100644 --- a/crates/nu_plugin_inc/Cargo.toml +++ b/crates/nu_plugin_inc/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_inc" edition = "2021" license = "MIT" name = "nu_plugin_inc" -version = "0.93.1" +version = "0.94.0" [lib] doctest = false @@ -16,7 +16,7 @@ name = "nu_plugin_inc" bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.93.1" } -nu-protocol = { path = "../nu-protocol", version = "0.93.1", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0", features = ["plugin"] } -semver = "1.0" +semver = "1.0" \ No newline at end of file diff --git a/crates/nu_plugin_nu_example/nu_plugin_nu_example.nu b/crates/nu_plugin_nu_example/nu_plugin_nu_example.nu index 6d2b2d772f..74da32809f 100755 --- a/crates/nu_plugin_nu_example/nu_plugin_nu_example.nu +++ b/crates/nu_plugin_nu_example/nu_plugin_nu_example.nu @@ -6,7 +6,7 @@ # it also allows us to test the plugin interface with something manually implemented in a scripting # language without adding any extra dependencies to our tests. -const NUSHELL_VERSION = "0.93.1" +const NUSHELL_VERSION = "0.94.0" def main [--stdio] { if ($stdio) { @@ -257,4 +257,4 @@ def start_plugin [] { }) | each { from json | handle_input } | ignore -} +} \ No newline at end of file diff --git a/crates/nu_plugin_polars/Cargo.toml b/crates/nu_plugin_polars/Cargo.toml index 03d050638d..dced0b4b85 100644 --- a/crates/nu_plugin_polars/Cargo.toml +++ b/crates/nu_plugin_polars/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "MIT" name = "nu_plugin_polars" repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_polars" -version = "0.93.1" +version = "0.94.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -17,9 +17,9 @@ bench = false bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.93.1" } -nu-plugin = { path = "../nu-plugin", version = "0.93.1" } -nu-path = { path = "../nu-path", version = "0.93.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0" } +nu-plugin = { path = "../nu-plugin", version = "0.94.0" } +nu-path = { path = "../nu-path", version = "0.94.0" } # Potential dependencies for extras chrono = { workspace = true, features = ["std", "unstable-locales"], default-features = false } @@ -73,9 +73,9 @@ optional = false version = "0.39" [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.93.1" } -nu-engine = { path = "../nu-engine", version = "0.93.1" } -nu-parser = { path = "../nu-parser", version = "0.93.1" } -nu-command = { path = "../nu-command", version = "0.93.1" } -nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.93.1" } -tempfile.workspace = true +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.0" } +nu-engine = { path = "../nu-engine", version = "0.94.0" } +nu-parser = { path = "../nu-parser", version = "0.94.0" } +nu-command = { path = "../nu-command", version = "0.94.0" } +nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.0" } +tempfile.workspace = true \ No newline at end of file diff --git a/crates/nu_plugin_python/nu_plugin_python_example.py b/crates/nu_plugin_python/nu_plugin_python_example.py index 17913fd28e..ff777b3d64 100755 --- a/crates/nu_plugin_python/nu_plugin_python_example.py +++ b/crates/nu_plugin_python/nu_plugin_python_example.py @@ -27,7 +27,7 @@ import sys import json -NUSHELL_VERSION = "0.93.1" +NUSHELL_VERSION = "0.94.0" def signatures(): @@ -250,4 +250,4 @@ if __name__ == "__main__": if len(sys.argv) == 2 and sys.argv[1] == "--stdio": plugin() else: - print("Run me from inside nushell!") + print("Run me from inside nushell!") \ No newline at end of file diff --git a/crates/nu_plugin_query/Cargo.toml b/crates/nu_plugin_query/Cargo.toml index a640067a4f..52d2c9fd91 100644 --- a/crates/nu_plugin_query/Cargo.toml +++ b/crates/nu_plugin_query/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_quer edition = "2021" license = "MIT" name = "nu_plugin_query" -version = "0.93.1" +version = "0.94.0" [lib] doctest = false @@ -16,10 +16,10 @@ name = "nu_plugin_query" bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.93.1" } -nu-protocol = { path = "../nu-protocol", version = "0.93.1" } +nu-plugin = { path = "../nu-plugin", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0" } gjson = "0.8" scraper = { default-features = false, version = "0.19" } sxd-document = "0.3" -sxd-xpath = "0.4" +sxd-xpath = "0.4" \ No newline at end of file diff --git a/crates/nu_plugin_stress_internals/Cargo.toml b/crates/nu_plugin_stress_internals/Cargo.toml index 2af1858d77..a374263f51 100644 --- a/crates/nu_plugin_stress_internals/Cargo.toml +++ b/crates/nu_plugin_stress_internals/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_stre edition = "2021" license = "MIT" name = "nu_plugin_stress_internals" -version = "0.93.1" +version = "0.94.0" [[bin]] name = "nu_plugin_stress_internals" @@ -16,4 +16,4 @@ bench = false # assumptions about the serialized format serde = { workspace = true } serde_json = { workspace = true } -interprocess = { workspace = true } +interprocess = { workspace = true } \ No newline at end of file diff --git a/crates/nuon/Cargo.toml b/crates/nuon/Cargo.toml index a3d6f4c6fc..ef58fd761e 100644 --- a/crates/nuon/Cargo.toml +++ b/crates/nuon/Cargo.toml @@ -5,16 +5,16 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nuon" edition = "2021" license = "MIT" name = "nuon" -version = "0.93.1" +version = "0.94.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-parser = { path = "../nu-parser", version = "0.93.1" } -nu-protocol = { path = "../nu-protocol", version = "0.93.1" } -nu-engine = { path = "../nu-engine", version = "0.93.1" } +nu-parser = { path = "../nu-parser", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.0" } +nu-engine = { path = "../nu-engine", version = "0.94.0" } once_cell = { workspace = true } fancy-regex = { workspace = true } [dev-dependencies] -chrono = { workspace = true } +chrono = { workspace = true } \ No newline at end of file From f3991f2080284eadaec5a29b92def5bdf8d41248 Mon Sep 17 00:00:00 2001 From: Devyn Cairns Date: Tue, 28 May 2024 15:41:23 -0700 Subject: [PATCH 031/113] Bump version to `0.94.1` (#12988) Merge this PR before merging any other PRs. --- Cargo.lock | 72 +++++++++---------- Cargo.toml | 40 +++++------ crates/nu-cli/Cargo.toml | 24 +++---- crates/nu-cmd-base/Cargo.toml | 10 +-- crates/nu-cmd-extra/Cargo.toml | 22 +++--- crates/nu-cmd-lang/Cargo.toml | 10 +-- crates/nu-cmd-plugin/Cargo.toml | 10 +-- crates/nu-color-config/Cargo.toml | 10 +-- crates/nu-command/Cargo.toml | 34 ++++----- crates/nu-engine/Cargo.toml | 10 +-- crates/nu-explore/Cargo.toml | 18 ++--- crates/nu-glob/Cargo.toml | 2 +- crates/nu-json/Cargo.toml | 4 +- crates/nu-lsp/Cargo.toml | 14 ++-- crates/nu-parser/Cargo.toml | 10 +-- crates/nu-path/Cargo.toml | 2 +- crates/nu-plugin-core/Cargo.toml | 6 +- crates/nu-plugin-engine/Cargo.toml | 12 ++-- crates/nu-plugin-protocol/Cargo.toml | 6 +- crates/nu-plugin-test-support/Cargo.toml | 18 ++--- crates/nu-plugin/Cargo.toml | 10 +-- crates/nu-pretty-hex/Cargo.toml | 2 +- crates/nu-protocol/Cargo.toml | 10 +-- crates/nu-std/Cargo.toml | 8 +-- crates/nu-system/Cargo.toml | 2 +- crates/nu-table/Cargo.toml | 12 ++-- crates/nu-term-grid/Cargo.toml | 4 +- crates/nu-test-support/Cargo.toml | 8 +-- crates/nu-utils/Cargo.toml | 2 +- .../src/sample_config/default_config.nu | 2 +- .../nu-utils/src/sample_config/default_env.nu | 2 +- crates/nu_plugin_custom_values/Cargo.toml | 6 +- crates/nu_plugin_example/Cargo.toml | 10 +-- crates/nu_plugin_formats/Cargo.toml | 8 +-- crates/nu_plugin_gstat/Cargo.toml | 6 +- crates/nu_plugin_inc/Cargo.toml | 6 +- .../nu_plugin_nu_example.nu | 2 +- crates/nu_plugin_polars/Cargo.toml | 18 ++--- .../nu_plugin_python_example.py | 2 +- crates/nu_plugin_query/Cargo.toml | 6 +- crates/nu_plugin_stress_internals/Cargo.toml | 2 +- crates/nuon/Cargo.toml | 8 +-- 42 files changed, 235 insertions(+), 235 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6bfbddda07..2d339ec7da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2770,7 +2770,7 @@ dependencies = [ [[package]] name = "nu" -version = "0.94.0" +version = "0.94.1" dependencies = [ "assert_cmd", "crossterm", @@ -2823,7 +2823,7 @@ dependencies = [ [[package]] name = "nu-cli" -version = "0.94.0" +version = "0.94.1" dependencies = [ "chrono", "crossterm", @@ -2858,7 +2858,7 @@ dependencies = [ [[package]] name = "nu-cmd-base" -version = "0.94.0" +version = "0.94.1" dependencies = [ "indexmap", "miette", @@ -2870,7 +2870,7 @@ dependencies = [ [[package]] name = "nu-cmd-extra" -version = "0.94.0" +version = "0.94.1" dependencies = [ "fancy-regex", "heck 0.5.0", @@ -2895,7 +2895,7 @@ dependencies = [ [[package]] name = "nu-cmd-lang" -version = "0.94.0" +version = "0.94.1" dependencies = [ "itertools 0.12.1", "nu-engine", @@ -2907,7 +2907,7 @@ dependencies = [ [[package]] name = "nu-cmd-plugin" -version = "0.94.0" +version = "0.94.1" dependencies = [ "itertools 0.12.1", "nu-engine", @@ -2918,7 +2918,7 @@ dependencies = [ [[package]] name = "nu-color-config" -version = "0.94.0" +version = "0.94.1" dependencies = [ "nu-ansi-term", "nu-engine", @@ -2930,7 +2930,7 @@ dependencies = [ [[package]] name = "nu-command" -version = "0.94.0" +version = "0.94.1" dependencies = [ "alphanumeric-sort", "base64 0.22.1", @@ -3039,7 +3039,7 @@ dependencies = [ [[package]] name = "nu-engine" -version = "0.94.0" +version = "0.94.1" dependencies = [ "nu-glob", "nu-path", @@ -3049,7 +3049,7 @@ dependencies = [ [[package]] name = "nu-explore" -version = "0.94.0" +version = "0.94.1" dependencies = [ "ansi-str", "anyhow", @@ -3074,14 +3074,14 @@ dependencies = [ [[package]] name = "nu-glob" -version = "0.94.0" +version = "0.94.1" dependencies = [ "doc-comment", ] [[package]] name = "nu-json" -version = "0.94.0" +version = "0.94.1" dependencies = [ "linked-hash-map", "num-traits", @@ -3091,7 +3091,7 @@ dependencies = [ [[package]] name = "nu-lsp" -version = "0.94.0" +version = "0.94.1" dependencies = [ "assert-json-diff", "crossbeam-channel", @@ -3112,7 +3112,7 @@ dependencies = [ [[package]] name = "nu-parser" -version = "0.94.0" +version = "0.94.1" dependencies = [ "bytesize", "chrono", @@ -3128,7 +3128,7 @@ dependencies = [ [[package]] name = "nu-path" -version = "0.94.0" +version = "0.94.1" dependencies = [ "dirs-next", "omnipath", @@ -3137,7 +3137,7 @@ dependencies = [ [[package]] name = "nu-plugin" -version = "0.94.0" +version = "0.94.1" dependencies = [ "log", "nix", @@ -3152,7 +3152,7 @@ dependencies = [ [[package]] name = "nu-plugin-core" -version = "0.94.0" +version = "0.94.1" dependencies = [ "interprocess", "log", @@ -3166,7 +3166,7 @@ dependencies = [ [[package]] name = "nu-plugin-engine" -version = "0.94.0" +version = "0.94.1" dependencies = [ "log", "nu-engine", @@ -3181,7 +3181,7 @@ dependencies = [ [[package]] name = "nu-plugin-protocol" -version = "0.94.0" +version = "0.94.1" dependencies = [ "bincode", "nu-protocol", @@ -3193,7 +3193,7 @@ dependencies = [ [[package]] name = "nu-plugin-test-support" -version = "0.94.0" +version = "0.94.1" dependencies = [ "nu-ansi-term", "nu-cmd-lang", @@ -3211,7 +3211,7 @@ dependencies = [ [[package]] name = "nu-pretty-hex" -version = "0.94.0" +version = "0.94.1" dependencies = [ "heapless", "nu-ansi-term", @@ -3220,7 +3220,7 @@ dependencies = [ [[package]] name = "nu-protocol" -version = "0.94.0" +version = "0.94.1" dependencies = [ "brotli 5.0.0", "byte-unit", @@ -3251,7 +3251,7 @@ dependencies = [ [[package]] name = "nu-std" -version = "0.94.0" +version = "0.94.1" dependencies = [ "log", "miette", @@ -3262,7 +3262,7 @@ dependencies = [ [[package]] name = "nu-system" -version = "0.94.0" +version = "0.94.1" dependencies = [ "chrono", "itertools 0.12.1", @@ -3280,7 +3280,7 @@ dependencies = [ [[package]] name = "nu-table" -version = "0.94.0" +version = "0.94.1" dependencies = [ "fancy-regex", "nu-ansi-term", @@ -3294,7 +3294,7 @@ dependencies = [ [[package]] name = "nu-term-grid" -version = "0.94.0" +version = "0.94.1" dependencies = [ "nu-utils", "unicode-width", @@ -3302,7 +3302,7 @@ dependencies = [ [[package]] name = "nu-test-support" -version = "0.94.0" +version = "0.94.1" dependencies = [ "nu-glob", "nu-path", @@ -3314,7 +3314,7 @@ dependencies = [ [[package]] name = "nu-utils" -version = "0.94.0" +version = "0.94.1" dependencies = [ "crossterm_winapi", "log", @@ -3340,7 +3340,7 @@ dependencies = [ [[package]] name = "nu_plugin_example" -version = "0.94.0" +version = "0.94.1" dependencies = [ "nu-cmd-lang", "nu-plugin", @@ -3350,7 +3350,7 @@ dependencies = [ [[package]] name = "nu_plugin_formats" -version = "0.94.0" +version = "0.94.1" dependencies = [ "eml-parser", "ical", @@ -3363,7 +3363,7 @@ dependencies = [ [[package]] name = "nu_plugin_gstat" -version = "0.94.0" +version = "0.94.1" dependencies = [ "git2", "nu-plugin", @@ -3372,7 +3372,7 @@ dependencies = [ [[package]] name = "nu_plugin_inc" -version = "0.94.0" +version = "0.94.1" dependencies = [ "nu-plugin", "nu-protocol", @@ -3381,7 +3381,7 @@ dependencies = [ [[package]] name = "nu_plugin_polars" -version = "0.94.0" +version = "0.94.1" dependencies = [ "chrono", "chrono-tz 0.9.0", @@ -3412,7 +3412,7 @@ dependencies = [ [[package]] name = "nu_plugin_query" -version = "0.94.0" +version = "0.94.1" dependencies = [ "gjson", "nu-plugin", @@ -3424,7 +3424,7 @@ dependencies = [ [[package]] name = "nu_plugin_stress_internals" -version = "0.94.0" +version = "0.94.1" dependencies = [ "interprocess", "serde", @@ -3550,7 +3550,7 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "nuon" -version = "0.94.0" +version = "0.94.1" dependencies = [ "chrono", "fancy-regex", diff --git a/Cargo.toml b/Cargo.toml index f58a563552..a8576baa95 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ license = "MIT" name = "nu" repository = "https://github.com/nushell/nushell" rust-version = "1.77.2" -version = "0.94.0" +version = "0.94.1" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -174,22 +174,22 @@ windows = "0.54" winreg = "0.52" [dependencies] -nu-cli = { path = "./crates/nu-cli", version = "0.94.0" } -nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.94.0" } -nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.94.0" } -nu-cmd-plugin = { path = "./crates/nu-cmd-plugin", version = "0.94.0", optional = true } -nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.94.0" } -nu-command = { path = "./crates/nu-command", version = "0.94.0" } -nu-engine = { path = "./crates/nu-engine", version = "0.94.0" } -nu-explore = { path = "./crates/nu-explore", version = "0.94.0" } -nu-lsp = { path = "./crates/nu-lsp/", version = "0.94.0" } -nu-parser = { path = "./crates/nu-parser", version = "0.94.0" } -nu-path = { path = "./crates/nu-path", version = "0.94.0" } -nu-plugin-engine = { path = "./crates/nu-plugin-engine", optional = true, version = "0.94.0" } -nu-protocol = { path = "./crates/nu-protocol", version = "0.94.0" } -nu-std = { path = "./crates/nu-std", version = "0.94.0" } -nu-system = { path = "./crates/nu-system", version = "0.94.0" } -nu-utils = { path = "./crates/nu-utils", version = "0.94.0" } +nu-cli = { path = "./crates/nu-cli", version = "0.94.1" } +nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.94.1" } +nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.94.1" } +nu-cmd-plugin = { path = "./crates/nu-cmd-plugin", version = "0.94.1", optional = true } +nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.94.1" } +nu-command = { path = "./crates/nu-command", version = "0.94.1" } +nu-engine = { path = "./crates/nu-engine", version = "0.94.1" } +nu-explore = { path = "./crates/nu-explore", version = "0.94.1" } +nu-lsp = { path = "./crates/nu-lsp/", version = "0.94.1" } +nu-parser = { path = "./crates/nu-parser", version = "0.94.1" } +nu-path = { path = "./crates/nu-path", version = "0.94.1" } +nu-plugin-engine = { path = "./crates/nu-plugin-engine", optional = true, version = "0.94.1" } +nu-protocol = { path = "./crates/nu-protocol", version = "0.94.1" } +nu-std = { path = "./crates/nu-std", version = "0.94.1" } +nu-system = { path = "./crates/nu-system", version = "0.94.1" } +nu-utils = { path = "./crates/nu-utils", version = "0.94.1" } reedline = { workspace = true, features = ["bashisms", "sqlite"] } @@ -218,9 +218,9 @@ nix = { workspace = true, default-features = false, features = [ ] } [dev-dependencies] -nu-test-support = { path = "./crates/nu-test-support", version = "0.94.0" } -nu-plugin-protocol = { path = "./crates/nu-plugin-protocol", version = "0.94.0" } -nu-plugin-core = { path = "./crates/nu-plugin-core", version = "0.94.0" } +nu-test-support = { path = "./crates/nu-test-support", version = "0.94.1" } +nu-plugin-protocol = { path = "./crates/nu-plugin-protocol", version = "0.94.1" } +nu-plugin-core = { path = "./crates/nu-plugin-core", version = "0.94.1" } assert_cmd = "2.0" dirs-next = { workspace = true } tango-bench = "0.5" diff --git a/crates/nu-cli/Cargo.toml b/crates/nu-cli/Cargo.toml index 2363df58ab..516afd9f0b 100644 --- a/crates/nu-cli/Cargo.toml +++ b/crates/nu-cli/Cargo.toml @@ -5,27 +5,27 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cli" edition = "2021" license = "MIT" name = "nu-cli" -version = "0.94.0" +version = "0.94.1" [lib] bench = false [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.0" } -nu-command = { path = "../nu-command", version = "0.94.0" } -nu-test-support = { path = "../nu-test-support", version = "0.94.0" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.1" } +nu-command = { path = "../nu-command", version = "0.94.1" } +nu-test-support = { path = "../nu-test-support", version = "0.94.1" } rstest = { workspace = true, default-features = false } tempfile = { workspace = true } [dependencies] -nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.0" } -nu-engine = { path = "../nu-engine", version = "0.94.0" } -nu-path = { path = "../nu-path", version = "0.94.0" } -nu-parser = { path = "../nu-parser", version = "0.94.0" } -nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.0", optional = true } -nu-protocol = { path = "../nu-protocol", version = "0.94.0" } -nu-utils = { path = "../nu-utils", version = "0.94.0" } -nu-color-config = { path = "../nu-color-config", version = "0.94.0" } +nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.1" } +nu-engine = { path = "../nu-engine", version = "0.94.1" } +nu-path = { path = "../nu-path", version = "0.94.1" } +nu-parser = { path = "../nu-parser", version = "0.94.1" } +nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.1", optional = true } +nu-protocol = { path = "../nu-protocol", version = "0.94.1" } +nu-utils = { path = "../nu-utils", version = "0.94.1" } +nu-color-config = { path = "../nu-color-config", version = "0.94.1" } nu-ansi-term = { workspace = true } reedline = { workspace = true, features = ["bashisms", "sqlite"] } diff --git a/crates/nu-cmd-base/Cargo.toml b/crates/nu-cmd-base/Cargo.toml index 10c4613057..1dcd95ba94 100644 --- a/crates/nu-cmd-base/Cargo.toml +++ b/crates/nu-cmd-base/Cargo.toml @@ -5,15 +5,15 @@ edition = "2021" license = "MIT" name = "nu-cmd-base" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-base" -version = "0.94.0" +version = "0.94.1" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.0" } -nu-parser = { path = "../nu-parser", version = "0.94.0" } -nu-path = { path = "../nu-path", version = "0.94.0" } -nu-protocol = { path = "../nu-protocol", version = "0.94.0" } +nu-engine = { path = "../nu-engine", version = "0.94.1" } +nu-parser = { path = "../nu-parser", version = "0.94.1" } +nu-path = { path = "../nu-path", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1" } indexmap = { workspace = true } miette = { workspace = true } diff --git a/crates/nu-cmd-extra/Cargo.toml b/crates/nu-cmd-extra/Cargo.toml index 695adbf120..9e6270163d 100644 --- a/crates/nu-cmd-extra/Cargo.toml +++ b/crates/nu-cmd-extra/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "MIT" name = "nu-cmd-extra" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-extra" -version = "0.94.0" +version = "0.94.1" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -13,13 +13,13 @@ version = "0.94.0" bench = false [dependencies] -nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.0" } -nu-engine = { path = "../nu-engine", version = "0.94.0" } -nu-json = { version = "0.94.0", path = "../nu-json" } -nu-parser = { path = "../nu-parser", version = "0.94.0" } -nu-pretty-hex = { version = "0.94.0", path = "../nu-pretty-hex" } -nu-protocol = { path = "../nu-protocol", version = "0.94.0" } -nu-utils = { path = "../nu-utils", version = "0.94.0" } +nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.1" } +nu-engine = { path = "../nu-engine", version = "0.94.1" } +nu-json = { version = "0.94.1", path = "../nu-json" } +nu-parser = { path = "../nu-parser", version = "0.94.1" } +nu-pretty-hex = { version = "0.94.1", path = "../nu-pretty-hex" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1" } +nu-utils = { path = "../nu-utils", version = "0.94.1" } # Potential dependencies for extras heck = { workspace = true } @@ -37,6 +37,6 @@ extra = ["default"] default = [] [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.0" } -nu-command = { path = "../nu-command", version = "0.94.0" } -nu-test-support = { path = "../nu-test-support", version = "0.94.0" } \ No newline at end of file +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.1" } +nu-command = { path = "../nu-command", version = "0.94.1" } +nu-test-support = { path = "../nu-test-support", version = "0.94.1" } \ No newline at end of file diff --git a/crates/nu-cmd-lang/Cargo.toml b/crates/nu-cmd-lang/Cargo.toml index 6077b3fa81..f7b43521d1 100644 --- a/crates/nu-cmd-lang/Cargo.toml +++ b/crates/nu-cmd-lang/Cargo.toml @@ -6,16 +6,16 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-lang" edition = "2021" license = "MIT" name = "nu-cmd-lang" -version = "0.94.0" +version = "0.94.1" [lib] bench = false [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.0" } -nu-parser = { path = "../nu-parser", version = "0.94.0" } -nu-protocol = { path = "../nu-protocol", version = "0.94.0" } -nu-utils = { path = "../nu-utils", version = "0.94.0" } +nu-engine = { path = "../nu-engine", version = "0.94.1" } +nu-parser = { path = "../nu-parser", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1" } +nu-utils = { path = "../nu-utils", version = "0.94.1" } itertools = { workspace = true } shadow-rs = { version = "0.28", default-features = false } diff --git a/crates/nu-cmd-plugin/Cargo.toml b/crates/nu-cmd-plugin/Cargo.toml index fd6a9921b9..f461f6bf04 100644 --- a/crates/nu-cmd-plugin/Cargo.toml +++ b/crates/nu-cmd-plugin/Cargo.toml @@ -5,15 +5,15 @@ edition = "2021" license = "MIT" name = "nu-cmd-plugin" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-plugin" -version = "0.94.0" +version = "0.94.1" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.0" } -nu-path = { path = "../nu-path", version = "0.94.0" } -nu-protocol = { path = "../nu-protocol", version = "0.94.0", features = ["plugin"] } -nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.0" } +nu-engine = { path = "../nu-engine", version = "0.94.1" } +nu-path = { path = "../nu-path", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1", features = ["plugin"] } +nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.1" } itertools = { workspace = true } diff --git a/crates/nu-color-config/Cargo.toml b/crates/nu-color-config/Cargo.toml index c1689ccb84..34f0ded963 100644 --- a/crates/nu-color-config/Cargo.toml +++ b/crates/nu-color-config/Cargo.toml @@ -5,18 +5,18 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-color-confi edition = "2021" license = "MIT" name = "nu-color-config" -version = "0.94.0" +version = "0.94.1" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.94.0" } -nu-engine = { path = "../nu-engine", version = "0.94.0" } -nu-json = { path = "../nu-json", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1" } +nu-engine = { path = "../nu-engine", version = "0.94.1" } +nu-json = { path = "../nu-json", version = "0.94.1" } nu-ansi-term = { workspace = true } serde = { workspace = true, features = ["derive"] } [dev-dependencies] -nu-test-support = { path = "../nu-test-support", version = "0.94.0" } \ No newline at end of file +nu-test-support = { path = "../nu-test-support", version = "0.94.1" } \ No newline at end of file diff --git a/crates/nu-command/Cargo.toml b/crates/nu-command/Cargo.toml index 90dac40b0b..25665cfc33 100644 --- a/crates/nu-command/Cargo.toml +++ b/crates/nu-command/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "MIT" name = "nu-command" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-command" -version = "0.94.0" +version = "0.94.1" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -13,21 +13,21 @@ version = "0.94.0" bench = false [dependencies] -nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.0" } -nu-color-config = { path = "../nu-color-config", version = "0.94.0" } -nu-engine = { path = "../nu-engine", version = "0.94.0" } -nu-glob = { path = "../nu-glob", version = "0.94.0" } -nu-json = { path = "../nu-json", version = "0.94.0" } -nu-parser = { path = "../nu-parser", version = "0.94.0" } -nu-path = { path = "../nu-path", version = "0.94.0" } -nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.94.0" } -nu-protocol = { path = "../nu-protocol", version = "0.94.0" } -nu-system = { path = "../nu-system", version = "0.94.0" } -nu-table = { path = "../nu-table", version = "0.94.0" } -nu-term-grid = { path = "../nu-term-grid", version = "0.94.0" } -nu-utils = { path = "../nu-utils", version = "0.94.0" } +nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.1" } +nu-color-config = { path = "../nu-color-config", version = "0.94.1" } +nu-engine = { path = "../nu-engine", version = "0.94.1" } +nu-glob = { path = "../nu-glob", version = "0.94.1" } +nu-json = { path = "../nu-json", version = "0.94.1" } +nu-parser = { path = "../nu-parser", version = "0.94.1" } +nu-path = { path = "../nu-path", version = "0.94.1" } +nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1" } +nu-system = { path = "../nu-system", version = "0.94.1" } +nu-table = { path = "../nu-table", version = "0.94.1" } +nu-term-grid = { path = "../nu-term-grid", version = "0.94.1" } +nu-utils = { path = "../nu-utils", version = "0.94.1" } nu-ansi-term = { workspace = true } -nuon = { path = "../nuon", version = "0.94.0" } +nuon = { path = "../nuon", version = "0.94.1" } alphanumeric-sort = { workspace = true } base64 = { workspace = true } @@ -137,8 +137,8 @@ trash-support = ["trash"] which-support = [] [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.0" } -nu-test-support = { path = "../nu-test-support", version = "0.94.0" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.1" } +nu-test-support = { path = "../nu-test-support", version = "0.94.1" } dirs-next = { workspace = true } mockito = { workspace = true, default-features = false } diff --git a/crates/nu-engine/Cargo.toml b/crates/nu-engine/Cargo.toml index 671c5c86bf..7bf5ffe9d5 100644 --- a/crates/nu-engine/Cargo.toml +++ b/crates/nu-engine/Cargo.toml @@ -5,16 +5,16 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-engine" edition = "2021" license = "MIT" name = "nu-engine" -version = "0.94.0" +version = "0.94.1" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", features = ["plugin"], version = "0.94.0" } -nu-path = { path = "../nu-path", version = "0.94.0" } -nu-glob = { path = "../nu-glob", version = "0.94.0" } -nu-utils = { path = "../nu-utils", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", features = ["plugin"], version = "0.94.1" } +nu-path = { path = "../nu-path", version = "0.94.1" } +nu-glob = { path = "../nu-glob", version = "0.94.1" } +nu-utils = { path = "../nu-utils", version = "0.94.1" } [features] plugin = [] \ No newline at end of file diff --git a/crates/nu-explore/Cargo.toml b/crates/nu-explore/Cargo.toml index 274cf369e5..006e301859 100644 --- a/crates/nu-explore/Cargo.toml +++ b/crates/nu-explore/Cargo.toml @@ -5,21 +5,21 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-explore" edition = "2021" license = "MIT" name = "nu-explore" -version = "0.94.0" +version = "0.94.1" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.94.0" } -nu-parser = { path = "../nu-parser", version = "0.94.0" } -nu-color-config = { path = "../nu-color-config", version = "0.94.0" } -nu-engine = { path = "../nu-engine", version = "0.94.0" } -nu-table = { path = "../nu-table", version = "0.94.0" } -nu-json = { path = "../nu-json", version = "0.94.0" } -nu-utils = { path = "../nu-utils", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1" } +nu-parser = { path = "../nu-parser", version = "0.94.1" } +nu-color-config = { path = "../nu-color-config", version = "0.94.1" } +nu-engine = { path = "../nu-engine", version = "0.94.1" } +nu-table = { path = "../nu-table", version = "0.94.1" } +nu-json = { path = "../nu-json", version = "0.94.1" } +nu-utils = { path = "../nu-utils", version = "0.94.1" } nu-ansi-term = { workspace = true } -nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.94.0" } +nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.94.1" } anyhow = { workspace = true } log = { workspace = true } diff --git a/crates/nu-glob/Cargo.toml b/crates/nu-glob/Cargo.toml index 164fff93a2..c6bfd7e493 100644 --- a/crates/nu-glob/Cargo.toml +++ b/crates/nu-glob/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nu-glob" -version = "0.94.0" +version = "0.94.1" authors = ["The Nushell Project Developers", "The Rust Project Developers"] license = "MIT/Apache-2.0" description = """ diff --git a/crates/nu-json/Cargo.toml b/crates/nu-json/Cargo.toml index e5561c1118..5a0806d7ca 100644 --- a/crates/nu-json/Cargo.toml +++ b/crates/nu-json/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-json" edition = "2021" license = "MIT" name = "nu-json" -version = "0.94.0" +version = "0.94.1" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -23,5 +23,5 @@ serde = { workspace = true } serde_json = { workspace = true } [dev-dependencies] -# nu-path = { path="../nu-path", version = "0.94.0" } +# nu-path = { path="../nu-path", version = "0.94.1" } # serde_json = "1.0" \ No newline at end of file diff --git a/crates/nu-lsp/Cargo.toml b/crates/nu-lsp/Cargo.toml index a47da72e2d..92f468fdbd 100644 --- a/crates/nu-lsp/Cargo.toml +++ b/crates/nu-lsp/Cargo.toml @@ -3,14 +3,14 @@ authors = ["The Nushell Project Developers"] description = "Nushell's integrated LSP server" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-lsp" name = "nu-lsp" -version = "0.94.0" +version = "0.94.1" edition = "2021" license = "MIT" [dependencies] -nu-cli = { path = "../nu-cli", version = "0.94.0" } -nu-parser = { path = "../nu-parser", version = "0.94.0" } -nu-protocol = { path = "../nu-protocol", version = "0.94.0" } +nu-cli = { path = "../nu-cli", version = "0.94.1" } +nu-parser = { path = "../nu-parser", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1" } reedline = { workspace = true } @@ -23,8 +23,8 @@ serde = { workspace = true } serde_json = { workspace = true } [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.0" } -nu-command = { path = "../nu-command", version = "0.94.0" } -nu-test-support = { path = "../nu-test-support", version = "0.94.0" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.1" } +nu-command = { path = "../nu-command", version = "0.94.1" } +nu-test-support = { path = "../nu-test-support", version = "0.94.1" } assert-json-diff = "2.0" \ No newline at end of file diff --git a/crates/nu-parser/Cargo.toml b/crates/nu-parser/Cargo.toml index ea719ebdd4..feb379d091 100644 --- a/crates/nu-parser/Cargo.toml +++ b/crates/nu-parser/Cargo.toml @@ -5,17 +5,17 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-parser" edition = "2021" license = "MIT" name = "nu-parser" -version = "0.94.0" +version = "0.94.1" exclude = ["/fuzz"] [lib] bench = false [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.0" } -nu-path = { path = "../nu-path", version = "0.94.0" } -nu-plugin-engine = { path = "../nu-plugin-engine", optional = true, version = "0.94.0" } -nu-protocol = { path = "../nu-protocol", version = "0.94.0" } +nu-engine = { path = "../nu-engine", version = "0.94.1" } +nu-path = { path = "../nu-path", version = "0.94.1" } +nu-plugin-engine = { path = "../nu-plugin-engine", optional = true, version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1" } bytesize = { workspace = true } chrono = { default-features = false, features = ['std'], workspace = true } diff --git a/crates/nu-path/Cargo.toml b/crates/nu-path/Cargo.toml index 1fc1f78ac4..1f3822089c 100644 --- a/crates/nu-path/Cargo.toml +++ b/crates/nu-path/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-path" edition = "2021" license = "MIT" name = "nu-path" -version = "0.94.0" +version = "0.94.1" exclude = ["/fuzz"] [lib] diff --git a/crates/nu-plugin-core/Cargo.toml b/crates/nu-plugin-core/Cargo.toml index 7a2085ee90..4040095a2a 100644 --- a/crates/nu-plugin-core/Cargo.toml +++ b/crates/nu-plugin-core/Cargo.toml @@ -5,14 +5,14 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-plugin-core edition = "2021" license = "MIT" name = "nu-plugin-core" -version = "0.94.0" +version = "0.94.1" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.94.0" } -nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.0", default-features = false } +nu-protocol = { path = "../nu-protocol", version = "0.94.1" } +nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.1", default-features = false } rmp-serde = { workspace = true } serde = { workspace = true } diff --git a/crates/nu-plugin-engine/Cargo.toml b/crates/nu-plugin-engine/Cargo.toml index 40f482bd78..715c2b7f74 100644 --- a/crates/nu-plugin-engine/Cargo.toml +++ b/crates/nu-plugin-engine/Cargo.toml @@ -5,17 +5,17 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-plugin-engi edition = "2021" license = "MIT" name = "nu-plugin-engine" -version = "0.94.0" +version = "0.94.1" [lib] bench = false [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.0" } -nu-protocol = { path = "../nu-protocol", version = "0.94.0" } -nu-system = { path = "../nu-system", version = "0.94.0" } -nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.0" } -nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.0", default-features = false } +nu-engine = { path = "../nu-engine", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1" } +nu-system = { path = "../nu-system", version = "0.94.1" } +nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.1" } +nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.1", default-features = false } serde = { workspace = true } log = { workspace = true } diff --git a/crates/nu-plugin-protocol/Cargo.toml b/crates/nu-plugin-protocol/Cargo.toml index 996e1ce8f2..8fe1c1102e 100644 --- a/crates/nu-plugin-protocol/Cargo.toml +++ b/crates/nu-plugin-protocol/Cargo.toml @@ -5,14 +5,14 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-plugin-prot edition = "2021" license = "MIT" name = "nu-plugin-protocol" -version = "0.94.0" +version = "0.94.1" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.94.0", features = ["plugin"] } -nu-utils = { path = "../nu-utils", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1", features = ["plugin"] } +nu-utils = { path = "../nu-utils", version = "0.94.1" } bincode = "1.3" serde = { workspace = true, features = ["derive"] } diff --git a/crates/nu-plugin-test-support/Cargo.toml b/crates/nu-plugin-test-support/Cargo.toml index 04f77ac7fa..32df904645 100644 --- a/crates/nu-plugin-test-support/Cargo.toml +++ b/crates/nu-plugin-test-support/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nu-plugin-test-support" -version = "0.94.0" +version = "0.94.1" edition = "2021" license = "MIT" description = "Testing support for Nushell plugins" @@ -12,14 +12,14 @@ bench = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.0", features = ["plugin"] } -nu-protocol = { path = "../nu-protocol", version = "0.94.0", features = ["plugin"] } -nu-parser = { path = "../nu-parser", version = "0.94.0", features = ["plugin"] } -nu-plugin = { path = "../nu-plugin", version = "0.94.0" } -nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.0" } -nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.0" } -nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.0" } -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.0" } +nu-engine = { path = "../nu-engine", version = "0.94.1", features = ["plugin"] } +nu-protocol = { path = "../nu-protocol", version = "0.94.1", features = ["plugin"] } +nu-parser = { path = "../nu-parser", version = "0.94.1", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.1" } +nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.1" } +nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.1" } +nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.1" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.1" } nu-ansi-term = { workspace = true } similar = "2.5" diff --git a/crates/nu-plugin/Cargo.toml b/crates/nu-plugin/Cargo.toml index ff19f84273..150ab6666d 100644 --- a/crates/nu-plugin/Cargo.toml +++ b/crates/nu-plugin/Cargo.toml @@ -5,16 +5,16 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-plugin" edition = "2021" license = "MIT" name = "nu-plugin" -version = "0.94.0" +version = "0.94.1" [lib] bench = false [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.0" } -nu-protocol = { path = "../nu-protocol", version = "0.94.0" } -nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.0" } -nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.0", default-features = false } +nu-engine = { path = "../nu-engine", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1" } +nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.1" } +nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.1", default-features = false } log = { workspace = true } thiserror = "1.0" diff --git a/crates/nu-pretty-hex/Cargo.toml b/crates/nu-pretty-hex/Cargo.toml index 3849fc9495..639ceb0edd 100644 --- a/crates/nu-pretty-hex/Cargo.toml +++ b/crates/nu-pretty-hex/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-pretty-hex" edition = "2021" license = "MIT" name = "nu-pretty-hex" -version = "0.94.0" +version = "0.94.1" [lib] doctest = false diff --git a/crates/nu-protocol/Cargo.toml b/crates/nu-protocol/Cargo.toml index 5d81535d04..8b2870a378 100644 --- a/crates/nu-protocol/Cargo.toml +++ b/crates/nu-protocol/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-protocol" edition = "2021" license = "MIT" name = "nu-protocol" -version = "0.94.0" +version = "0.94.1" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -13,9 +13,9 @@ version = "0.94.0" bench = false [dependencies] -nu-utils = { path = "../nu-utils", version = "0.94.0" } -nu-path = { path = "../nu-path", version = "0.94.0" } -nu-system = { path = "../nu-system", version = "0.94.0" } +nu-utils = { path = "../nu-utils", version = "0.94.1" } +nu-path = { path = "../nu-path", version = "0.94.1" } +nu-system = { path = "../nu-system", version = "0.94.1" } brotli = { workspace = true, optional = true } byte-unit = { version = "5.1", features = [ "serde" ] } @@ -45,7 +45,7 @@ plugin = [ serde_json = { workspace = true } strum = "0.26" strum_macros = "0.26" -nu-test-support = { path = "../nu-test-support", version = "0.94.0" } +nu-test-support = { path = "../nu-test-support", version = "0.94.1" } pretty_assertions = { workspace = true } rstest = { workspace = true } tempfile = { workspace = true } diff --git a/crates/nu-std/Cargo.toml b/crates/nu-std/Cargo.toml index 3f050b31e1..f5c6790c52 100644 --- a/crates/nu-std/Cargo.toml +++ b/crates/nu-std/Cargo.toml @@ -5,12 +5,12 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-std" edition = "2021" license = "MIT" name = "nu-std" -version = "0.94.0" +version = "0.94.1" [dependencies] -nu-parser = { version = "0.94.0", path = "../nu-parser" } -nu-protocol = { version = "0.94.0", path = "../nu-protocol" } -nu-engine = { version = "0.94.0", path = "../nu-engine" } +nu-parser = { version = "0.94.1", path = "../nu-parser" } +nu-protocol = { version = "0.94.1", path = "../nu-protocol" } +nu-engine = { version = "0.94.1", path = "../nu-engine" } miette = { workspace = true, features = ["fancy-no-backtrace"] } log = "0.4" \ No newline at end of file diff --git a/crates/nu-system/Cargo.toml b/crates/nu-system/Cargo.toml index e28c72ad53..33305d07bc 100644 --- a/crates/nu-system/Cargo.toml +++ b/crates/nu-system/Cargo.toml @@ -3,7 +3,7 @@ authors = ["The Nushell Project Developers", "procs creators"] description = "Nushell system querying" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-system" name = "nu-system" -version = "0.94.0" +version = "0.94.1" edition = "2021" license = "MIT" diff --git a/crates/nu-table/Cargo.toml b/crates/nu-table/Cargo.toml index b2bed2b555..6fcb1ffce6 100644 --- a/crates/nu-table/Cargo.toml +++ b/crates/nu-table/Cargo.toml @@ -5,20 +5,20 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-table" edition = "2021" license = "MIT" name = "nu-table" -version = "0.94.0" +version = "0.94.1" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.94.0" } -nu-utils = { path = "../nu-utils", version = "0.94.0" } -nu-engine = { path = "../nu-engine", version = "0.94.0" } -nu-color-config = { path = "../nu-color-config", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1" } +nu-utils = { path = "../nu-utils", version = "0.94.1" } +nu-engine = { path = "../nu-engine", version = "0.94.1" } +nu-color-config = { path = "../nu-color-config", version = "0.94.1" } nu-ansi-term = { workspace = true } once_cell = { workspace = true } fancy-regex = { workspace = true } tabled = { workspace = true, features = ["color"], default-features = false } [dev-dependencies] -# nu-test-support = { path="../nu-test-support", version = "0.94.0" } \ No newline at end of file +# nu-test-support = { path="../nu-test-support", version = "0.94.1" } \ No newline at end of file diff --git a/crates/nu-term-grid/Cargo.toml b/crates/nu-term-grid/Cargo.toml index 14eefa0ed1..2570ce0d68 100644 --- a/crates/nu-term-grid/Cargo.toml +++ b/crates/nu-term-grid/Cargo.toml @@ -5,12 +5,12 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-term-grid" edition = "2021" license = "MIT" name = "nu-term-grid" -version = "0.94.0" +version = "0.94.1" [lib] bench = false [dependencies] -nu-utils = { path = "../nu-utils", version = "0.94.0" } +nu-utils = { path = "../nu-utils", version = "0.94.1" } unicode-width = { workspace = true } \ No newline at end of file diff --git a/crates/nu-test-support/Cargo.toml b/crates/nu-test-support/Cargo.toml index 8ca77631d1..e2525d8c78 100644 --- a/crates/nu-test-support/Cargo.toml +++ b/crates/nu-test-support/Cargo.toml @@ -5,16 +5,16 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-test-suppor edition = "2021" license = "MIT" name = "nu-test-support" -version = "0.94.0" +version = "0.94.1" [lib] doctest = false bench = false [dependencies] -nu-path = { path = "../nu-path", version = "0.94.0" } -nu-glob = { path = "../nu-glob", version = "0.94.0" } -nu-utils = { path = "../nu-utils", version = "0.94.0" } +nu-path = { path = "../nu-path", version = "0.94.1" } +nu-glob = { path = "../nu-glob", version = "0.94.1" } +nu-utils = { path = "../nu-utils", version = "0.94.1" } num-format = { workspace = true } which = { workspace = true } diff --git a/crates/nu-utils/Cargo.toml b/crates/nu-utils/Cargo.toml index 681ee7d6f1..85b80015df 100644 --- a/crates/nu-utils/Cargo.toml +++ b/crates/nu-utils/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "MIT" name = "nu-utils" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-utils" -version = "0.94.0" +version = "0.94.1" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [[bin]] diff --git a/crates/nu-utils/src/sample_config/default_config.nu b/crates/nu-utils/src/sample_config/default_config.nu index fd9a9642b0..357a1cc7d5 100644 --- a/crates/nu-utils/src/sample_config/default_config.nu +++ b/crates/nu-utils/src/sample_config/default_config.nu @@ -1,6 +1,6 @@ # Nushell Config File # -# version = "0.94.0" +# version = "0.94.1" # For more information on defining custom themes, see # https://www.nushell.sh/book/coloring_and_theming.html diff --git a/crates/nu-utils/src/sample_config/default_env.nu b/crates/nu-utils/src/sample_config/default_env.nu index f68396eec5..90705230a9 100644 --- a/crates/nu-utils/src/sample_config/default_env.nu +++ b/crates/nu-utils/src/sample_config/default_env.nu @@ -1,6 +1,6 @@ # Nushell Environment Config File # -# version = "0.94.0" +# version = "0.94.1" def create_left_prompt [] { let dir = match (do --ignore-shell-errors { $env.PWD | path relative-to $nu.home-path }) { diff --git a/crates/nu_plugin_custom_values/Cargo.toml b/crates/nu_plugin_custom_values/Cargo.toml index 5c9a2bb633..7cfbc0b578 100644 --- a/crates/nu_plugin_custom_values/Cargo.toml +++ b/crates/nu_plugin_custom_values/Cargo.toml @@ -10,10 +10,10 @@ name = "nu_plugin_custom_values" bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.94.0" } -nu-protocol = { path = "../nu-protocol", version = "0.94.0", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1", features = ["plugin"] } serde = { workspace = true, default-features = false } typetag = "0.2" [dev-dependencies] -nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.0" } \ No newline at end of file +nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.1" } \ No newline at end of file diff --git a/crates/nu_plugin_example/Cargo.toml b/crates/nu_plugin_example/Cargo.toml index 356af74386..0b4ec44e89 100644 --- a/crates/nu_plugin_example/Cargo.toml +++ b/crates/nu_plugin_example/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_exam edition = "2021" license = "MIT" name = "nu_plugin_example" -version = "0.94.0" +version = "0.94.1" [[bin]] name = "nu_plugin_example" @@ -15,9 +15,9 @@ bench = false bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.94.0" } -nu-protocol = { path = "../nu-protocol", version = "0.94.0", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1", features = ["plugin"] } [dev-dependencies] -nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.0" } -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.0" } \ No newline at end of file +nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.1" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.1" } \ No newline at end of file diff --git a/crates/nu_plugin_formats/Cargo.toml b/crates/nu_plugin_formats/Cargo.toml index 55c47f33f5..213ea74cd5 100644 --- a/crates/nu_plugin_formats/Cargo.toml +++ b/crates/nu_plugin_formats/Cargo.toml @@ -5,12 +5,12 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_form edition = "2021" license = "MIT" name = "nu_plugin_formats" -version = "0.94.0" +version = "0.94.1" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.94.0" } -nu-protocol = { path = "../nu-protocol", version = "0.94.0", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1", features = ["plugin"] } indexmap = { workspace = true } eml-parser = "0.1" @@ -18,4 +18,4 @@ ical = "0.11" rust-ini = "0.21.0" [dev-dependencies] -nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.0" } \ No newline at end of file +nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.1" } \ No newline at end of file diff --git a/crates/nu_plugin_gstat/Cargo.toml b/crates/nu_plugin_gstat/Cargo.toml index c779ffd8c4..7c0ca79ebe 100644 --- a/crates/nu_plugin_gstat/Cargo.toml +++ b/crates/nu_plugin_gstat/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_gsta edition = "2021" license = "MIT" name = "nu_plugin_gstat" -version = "0.94.0" +version = "0.94.1" [lib] doctest = false @@ -16,7 +16,7 @@ name = "nu_plugin_gstat" bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.94.0" } -nu-protocol = { path = "../nu-protocol", version = "0.94.0" } +nu-plugin = { path = "../nu-plugin", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1" } git2 = "0.18" \ No newline at end of file diff --git a/crates/nu_plugin_inc/Cargo.toml b/crates/nu_plugin_inc/Cargo.toml index 1c12343598..543982d599 100644 --- a/crates/nu_plugin_inc/Cargo.toml +++ b/crates/nu_plugin_inc/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_inc" edition = "2021" license = "MIT" name = "nu_plugin_inc" -version = "0.94.0" +version = "0.94.1" [lib] doctest = false @@ -16,7 +16,7 @@ name = "nu_plugin_inc" bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.94.0" } -nu-protocol = { path = "../nu-protocol", version = "0.94.0", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1", features = ["plugin"] } semver = "1.0" \ No newline at end of file diff --git a/crates/nu_plugin_nu_example/nu_plugin_nu_example.nu b/crates/nu_plugin_nu_example/nu_plugin_nu_example.nu index 74da32809f..d900f498da 100755 --- a/crates/nu_plugin_nu_example/nu_plugin_nu_example.nu +++ b/crates/nu_plugin_nu_example/nu_plugin_nu_example.nu @@ -6,7 +6,7 @@ # it also allows us to test the plugin interface with something manually implemented in a scripting # language without adding any extra dependencies to our tests. -const NUSHELL_VERSION = "0.94.0" +const NUSHELL_VERSION = "0.94.1" def main [--stdio] { if ($stdio) { diff --git a/crates/nu_plugin_polars/Cargo.toml b/crates/nu_plugin_polars/Cargo.toml index dced0b4b85..f93e183926 100644 --- a/crates/nu_plugin_polars/Cargo.toml +++ b/crates/nu_plugin_polars/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "MIT" name = "nu_plugin_polars" repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_polars" -version = "0.94.0" +version = "0.94.1" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -17,9 +17,9 @@ bench = false bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.94.0" } -nu-plugin = { path = "../nu-plugin", version = "0.94.0" } -nu-path = { path = "../nu-path", version = "0.94.0" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1" } +nu-plugin = { path = "../nu-plugin", version = "0.94.1" } +nu-path = { path = "../nu-path", version = "0.94.1" } # Potential dependencies for extras chrono = { workspace = true, features = ["std", "unstable-locales"], default-features = false } @@ -73,9 +73,9 @@ optional = false version = "0.39" [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.0" } -nu-engine = { path = "../nu-engine", version = "0.94.0" } -nu-parser = { path = "../nu-parser", version = "0.94.0" } -nu-command = { path = "../nu-command", version = "0.94.0" } -nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.0" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.1" } +nu-engine = { path = "../nu-engine", version = "0.94.1" } +nu-parser = { path = "../nu-parser", version = "0.94.1" } +nu-command = { path = "../nu-command", version = "0.94.1" } +nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.1" } tempfile.workspace = true \ No newline at end of file diff --git a/crates/nu_plugin_python/nu_plugin_python_example.py b/crates/nu_plugin_python/nu_plugin_python_example.py index ff777b3d64..55746d89c1 100755 --- a/crates/nu_plugin_python/nu_plugin_python_example.py +++ b/crates/nu_plugin_python/nu_plugin_python_example.py @@ -27,7 +27,7 @@ import sys import json -NUSHELL_VERSION = "0.94.0" +NUSHELL_VERSION = "0.94.1" def signatures(): diff --git a/crates/nu_plugin_query/Cargo.toml b/crates/nu_plugin_query/Cargo.toml index 52d2c9fd91..b48ca14fa5 100644 --- a/crates/nu_plugin_query/Cargo.toml +++ b/crates/nu_plugin_query/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_quer edition = "2021" license = "MIT" name = "nu_plugin_query" -version = "0.94.0" +version = "0.94.1" [lib] doctest = false @@ -16,8 +16,8 @@ name = "nu_plugin_query" bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.94.0" } -nu-protocol = { path = "../nu-protocol", version = "0.94.0" } +nu-plugin = { path = "../nu-plugin", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1" } gjson = "0.8" scraper = { default-features = false, version = "0.19" } diff --git a/crates/nu_plugin_stress_internals/Cargo.toml b/crates/nu_plugin_stress_internals/Cargo.toml index a374263f51..159e0b616c 100644 --- a/crates/nu_plugin_stress_internals/Cargo.toml +++ b/crates/nu_plugin_stress_internals/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_stre edition = "2021" license = "MIT" name = "nu_plugin_stress_internals" -version = "0.94.0" +version = "0.94.1" [[bin]] name = "nu_plugin_stress_internals" diff --git a/crates/nuon/Cargo.toml b/crates/nuon/Cargo.toml index ef58fd761e..69e7d89713 100644 --- a/crates/nuon/Cargo.toml +++ b/crates/nuon/Cargo.toml @@ -5,14 +5,14 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nuon" edition = "2021" license = "MIT" name = "nuon" -version = "0.94.0" +version = "0.94.1" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-parser = { path = "../nu-parser", version = "0.94.0" } -nu-protocol = { path = "../nu-protocol", version = "0.94.0" } -nu-engine = { path = "../nu-engine", version = "0.94.0" } +nu-parser = { path = "../nu-parser", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.1" } +nu-engine = { path = "../nu-engine", version = "0.94.1" } once_cell = { workspace = true } fancy-regex = { workspace = true } From 6a2996251ceaf97ea30d74f0161ee08d29602ebe Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Wed, 29 May 2024 18:06:47 -0500 Subject: [PATCH 032/113] fixes a bug in OSC9;9 execution (#12994) # Description This fixes a bug in the `OSC 9;9` functionality where the path wasn't being constructed properly and therefore wasn't getting set right for things like "Duplicate Tab" in Windows Terminal. Thanks to @Araxeus for finding it. Related to https://github.com/nushell/nushell/issues/10166 # User-Facing Changes # Tests + Formatting # After Submitting --- crates/nu-cli/src/repl.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/nu-cli/src/repl.rs b/crates/nu-cli/src/repl.rs index 29c2f62734..d9aef32bbb 100644 --- a/crates/nu-cli/src/repl.rs +++ b/crates/nu-cli/src/repl.rs @@ -1110,9 +1110,9 @@ fn run_shell_integration_osc9_9(engine_state: &EngineState, stack: &mut Stack, u let start_time = Instant::now(); // Otherwise, communicate the path as OSC 9;9 from ConEmu (often used for spawning new tabs in the same dir) + // This is helpful in Windows Terminal with Duplicate Tab run_ansi_sequence(&format!( - "\x1b]9;9;{}{}\x1b\\", - if path.starts_with('/') { "" } else { "/" }, + "\x1b]9;9;{}\x1b\\", percent_encoding::utf8_percent_encode(&path, percent_encoding::CONTROLS) )); From 0e1553026e69adec2207d259d8513764deb5f87c Mon Sep 17 00:00:00 2001 From: Devyn Cairns Date: Wed, 29 May 2024 18:48:29 -0700 Subject: [PATCH 033/113] Restore tilde expansion on external command names (#13001) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Fix a regression introduced by #12921, where tilde expansion was no longer done on the external command name, breaking things like ```nushell > ~/.cargo/bin/exa ``` This properly handles quoted strings, so they don't expand: ```nushell > ^"~/.cargo/bin/exa" Error: nu::shell::external_command × External command failed ╭─[entry #1:1:2] 1 │ ^"~/.cargo/bin/exa" · ─────────┬──────── · ╰── Command `~/.cargo/bin/exa` not found ╰──── help: `~/.cargo/bin/exa` is neither a Nushell built-in or a known external command ``` This required a change to the parser, so the command name is also parsed in the same way the arguments are - i.e. the quotes on the outside remain in the expression. Hopefully that doesn't break anything else. 🤞 Fixes #13000. Should include in patch release 0.94.1 cc @YizhePKU # User-Facing Changes - Tilde expansion now works again for external commands - The `command` of `run-external` will now have its quotes removed like the other arguments if it is a literal string - The parser is changed to include quotes in the command expression of `ExternalCall` if they were present # Tests + Formatting I would like to add a regression test for this, but it's complicated because we need a well-known binary within the home directory, which just isn't a thing. We could drop one there, but that's kind of a bad behavior for a test to do. I also considered changing the home directory for the test, but that's so platform-specific - potentially could get it working on specific platforms though. Changing `HOME` env on Linux definitely works as far as tilde expansion works. - :green_circle: `toolkit fmt` - :green_circle: `toolkit clippy` - :green_circle: `toolkit test` - :green_circle: `toolkit test stdlib` --- crates/nu-command/src/system/run_external.rs | 25 ++++++++++++++++++-- crates/nu-parser/src/parser.rs | 5 ++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/crates/nu-command/src/system/run_external.rs b/crates/nu-command/src/system/run_external.rs index 8531217d4b..69c4a319bb 100644 --- a/crates/nu-command/src/system/run_external.rs +++ b/crates/nu-command/src/system/run_external.rs @@ -46,15 +46,36 @@ impl Command for External { ) -> Result { let cwd = engine_state.cwd(Some(stack))?; + // Evaluate the command name in the same way the arguments are evaluated. Since this isn't + // a spread, it should return a one-element vec. + let name_expr = call + .positional_nth(0) + .ok_or_else(|| ShellError::MissingParameter { + param_name: "command".into(), + span: call.head, + })?; + let name = eval_argument(engine_state, stack, name_expr, false)? + .pop() + .expect("eval_argument returned zero-element vec") + .into_spanned(name_expr.span); + // Find the absolute path to the executable. On Windows, set the // executable to "cmd.exe" if it's is a CMD internal command. If the // command is not found, display a helpful error message. - let name: Spanned = call.req(engine_state, stack, 0)?; let executable = if cfg!(windows) && is_cmd_internal_command(&name.item) { PathBuf::from("cmd.exe") } else { + // Expand tilde on the name if it's a bare string (#13000) + let expanded_name = if is_bare_string(name_expr) { + expand_tilde(&name.item) + } else { + name.item.clone() + }; + + // Determine the PATH to be used and then use `which` to find it - though this has no + // effect if it's an absolute path already let paths = nu_engine::env::path_str(engine_state, stack, call.head)?; - let Some(executable) = which(&name.item, &paths, &cwd) else { + let Some(executable) = which(&expanded_name, &paths, &cwd) else { return Err(command_not_found( &name.item, call.head, diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 61a4261d8d..ad5e7d4f42 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -278,13 +278,14 @@ pub fn parse_external_call(working_set: &mut StateWorkingSet, spans: &[Span]) -> let arg = parse_expression(working_set, &[head_span]); Box::new(arg) } else { - let (contents, err) = unescape_unquote_string(&head_contents, head_span); + // Eval stage will unquote the string, so we don't bother with that here + let (contents, err) = unescape_string(&head_contents, head_span); if let Some(err) = err { working_set.error(err) } Box::new(Expression { - expr: Expr::String(contents), + expr: Expr::String(String::from_utf8_lossy(&contents).into_owned()), span: head_span, ty: Type::String, custom_completion: None, From 40772fea15a31dddfa721be871af2185a99a1947 Mon Sep 17 00:00:00 2001 From: Wind Date: Thu, 30 May 2024 21:29:46 +0800 Subject: [PATCH 034/113] fix do closure with both required, options, and rest args (#13002) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Fixes: #12985 `val_iter` has already handle required positional and optional positional arguments, it not skip them again while handling rest arguments. # User-Facing Changes Makes `do {|a, ...b| echo $a ...$b} 1 2 3 4` output the following again: ```nushell ╭───┬───╮ │ 0 │ 1 │ │ 1 │ 2 │ │ 2 │ 3 │ │ 3 │ 4 │ ╰───┴───╯ ``` # Tests + Formatting Added some test cases --- crates/nu-cmd-lang/src/core_commands/do_.rs | 4 +--- tests/shell/pipeline/commands/internal.rs | 9 +++++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/crates/nu-cmd-lang/src/core_commands/do_.rs b/crates/nu-cmd-lang/src/core_commands/do_.rs index 5f14e88c07..8ca3fbac56 100644 --- a/crates/nu-cmd-lang/src/core_commands/do_.rs +++ b/crates/nu-cmd-lang/src/core_commands/do_.rs @@ -298,9 +298,7 @@ fn bind_args_to( if let Some(rest_positional) = &signature.rest_positional { let mut rest_items = vec![]; - for result in - val_iter.skip(signature.required_positional.len() + signature.optional_positional.len()) - { + for result in val_iter { rest_items.push(result); } diff --git a/tests/shell/pipeline/commands/internal.rs b/tests/shell/pipeline/commands/internal.rs index 67d4ee31a9..98f3fb88c9 100644 --- a/tests/shell/pipeline/commands/internal.rs +++ b/tests/shell/pipeline/commands/internal.rs @@ -539,6 +539,15 @@ fn dynamic_closure_optional_arg() { fn dynamic_closure_rest_args() { let actual = nu!(r#"let closure = {|...args| $args | str join ""}; do $closure 1 2 3"#); assert_eq!(actual.out, "123"); + + let actual = nu!( + r#"let closure = {|required, ...args| $"($required), ($args | str join "")"}; do $closure 1 2 3"# + ); + assert_eq!(actual.out, "1, 23"); + let actual = nu!( + r#"let closure = {|required, optional?, ...args| $"($required), ($optional), ($args | str join "")"}; do $closure 1 2 3"# + ); + assert_eq!(actual.out, "1, 2, 3"); } #[cfg(feature = "which-support")] From 31f3d2f6642b585f0d88192724723bf0ce330ecf Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Thu, 30 May 2024 13:42:22 +0000 Subject: [PATCH 035/113] Restore `path type` behavior (#13006) # Description Restores `path type` to return an empty string on error like it did pre 0.94.0. --- crates/nu-command/src/path/type.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/crates/nu-command/src/path/type.rs b/crates/nu-command/src/path/type.rs index e048679220..0897593109 100644 --- a/crates/nu-command/src/path/type.rs +++ b/crates/nu-command/src/path/type.rs @@ -104,10 +104,9 @@ If nothing is found, an empty string will be returned."# fn path_type(path: &Path, span: Span, args: &Arguments) -> Value { let path = nu_path::expand_path_with(path, &args.pwd, true); - match std::fs::symlink_metadata(path) { - Ok(metadata) => Value::string(get_file_type(&metadata), span), - Err(err) => Value::error(err.into(), span), - } + let meta = path.symlink_metadata(); + let ty = meta.as_ref().map(get_file_type).unwrap_or(""); + Value::string(ty, span) } fn get_file_type(md: &std::fs::Metadata) -> &str { From f3cf693ec701ab3086f984a8aeadfc9b50fadd90 Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Thu, 30 May 2024 19:24:48 +0000 Subject: [PATCH 036/113] Disallow more characters in arguments for internal `cmd` commands (#13009) # Description Makes `run-external` error if arguments to `cmd.exe` internal commands contain newlines or a percent sign. This is because the percent sign can expand environment variables, potentially? allowing command injection. Newlines I think will truncate the rest of the arguments and should probably be disallowed to be safe. # After Submitting - If the user calls `cmd.exe` directly, then this bypasses our handling/checking for internal `cmd` commands. Instead, we use the handling from the Rust std lib which, in this case, does not do special handling and is potentially unsafe. Then again, it could be the user's specific intention to run `cmd` with whatever trusted input. The problem is that since we use the std lib handling, it assumes the exe uses the C runtime escaping rules and will perform some unwanted escaping. E.g., it will add backslashes to the quotes in `cmd echo /c '""'`. - If `cmd` is called indirectly via a `.bat` or `.cmd` file, then we use the Rust std lib which has separate handling for bat files that should be safe, but will reject some inputs. - ~~I'm not sure how we handle `PATHEXT`, that can also cause a file without an extension to be run as a bat file. If so, I don't know where the handling, if any, is done for that.~~ It looks like we use the `which` crate to do the lookup using `PATHEXT`. Then, we pass the exe path from that to the Rust std lib `Command`, which should be safe (except for the first `cmd.exe` note). So, in the future we need to unify and/or fix these different implementations, including our own special handling for internal `cmd` commands that this PR tries to fix. --- crates/nu-command/src/system/run_external.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/crates/nu-command/src/system/run_external.rs b/crates/nu-command/src/system/run_external.rs index 69c4a319bb..a200ce75de 100644 --- a/crates/nu-command/src/system/run_external.rs +++ b/crates/nu-command/src/system/run_external.rs @@ -565,12 +565,20 @@ fn has_cmd_special_character(s: &str) -> bool { SPECIAL_CHARS.iter().any(|c| s.contains(*c)) } -/// Escape an argument for CMD internal commands. The result can be safely -/// passed to `raw_arg()`. +/// Escape an argument for CMD internal commands. The result can be safely passed to `raw_arg()`. #[cfg(windows)] fn escape_cmd_argument(arg: &Spanned) -> Result, ShellError> { let Spanned { item: arg, span } = arg; - if arg.contains('"') { + if arg.contains(['\r', '\n', '%']) { + // \r and \n trunacte the rest of the arguments and % can expand environment variables + Err(ShellError::ExternalCommand { + label: + "Arguments to CMD internal commands cannot contain new lines or percent signs '%'" + .into(), + help: "some characters currently cannot be securely escaped".into(), + span: *span, + }) + } else if arg.contains('"') { // If `arg` is already quoted by double quotes, confirm there's no // embedded double quotes, then leave it as is. if arg.chars().filter(|c| *c == '"').count() == 2 @@ -582,7 +590,7 @@ fn escape_cmd_argument(arg: &Spanned) -> Result, ShellError Err(ShellError::ExternalCommand { label: "Arguments to CMD internal commands cannot contain embedded double quotes" .into(), - help: "CMD doesn't support escaping double quotes inside double quotes".into(), + help: "this case currently cannot be securely handled".into(), span: *span, }) } @@ -590,6 +598,7 @@ fn escape_cmd_argument(arg: &Spanned) -> Result, ShellError // If `arg` contains space or special characters, quote the entire argument by double quotes. Ok(Cow::Owned(format!("\"{arg}\""))) } else { + // FIXME?: what if `arg.is_empty()`? Ok(Cow::Borrowed(arg)) } } From 6635b74d9d8d71ae6813a1bfaa3b977f792723a4 Mon Sep 17 00:00:00 2001 From: Devyn Cairns Date: Mon, 3 Jun 2024 00:28:35 -0700 Subject: [PATCH 037/113] Bump version to `0.94.2` (#13014) Version bump after 0.94.1 patch release. --- Cargo.lock | 72 +++++++++---------- Cargo.toml | 40 +++++------ crates/nu-cli/Cargo.toml | 24 +++---- crates/nu-cmd-base/Cargo.toml | 10 +-- crates/nu-cmd-extra/Cargo.toml | 22 +++--- crates/nu-cmd-lang/Cargo.toml | 10 +-- crates/nu-cmd-plugin/Cargo.toml | 10 +-- crates/nu-color-config/Cargo.toml | 10 +-- crates/nu-command/Cargo.toml | 34 ++++----- crates/nu-engine/Cargo.toml | 10 +-- crates/nu-explore/Cargo.toml | 18 ++--- crates/nu-glob/Cargo.toml | 2 +- crates/nu-json/Cargo.toml | 4 +- crates/nu-lsp/Cargo.toml | 14 ++-- crates/nu-parser/Cargo.toml | 10 +-- crates/nu-path/Cargo.toml | 2 +- crates/nu-plugin-core/Cargo.toml | 6 +- crates/nu-plugin-engine/Cargo.toml | 12 ++-- crates/nu-plugin-protocol/Cargo.toml | 6 +- crates/nu-plugin-test-support/Cargo.toml | 18 ++--- crates/nu-plugin/Cargo.toml | 10 +-- crates/nu-pretty-hex/Cargo.toml | 2 +- crates/nu-protocol/Cargo.toml | 10 +-- crates/nu-std/Cargo.toml | 8 +-- crates/nu-system/Cargo.toml | 2 +- crates/nu-table/Cargo.toml | 12 ++-- crates/nu-term-grid/Cargo.toml | 4 +- crates/nu-test-support/Cargo.toml | 8 +-- crates/nu-utils/Cargo.toml | 2 +- .../src/sample_config/default_config.nu | 2 +- .../nu-utils/src/sample_config/default_env.nu | 2 +- crates/nu_plugin_custom_values/Cargo.toml | 6 +- crates/nu_plugin_example/Cargo.toml | 10 +-- crates/nu_plugin_formats/Cargo.toml | 8 +-- crates/nu_plugin_gstat/Cargo.toml | 6 +- crates/nu_plugin_inc/Cargo.toml | 6 +- .../nu_plugin_nu_example.nu | 2 +- crates/nu_plugin_polars/Cargo.toml | 18 ++--- .../nu_plugin_python_example.py | 2 +- crates/nu_plugin_query/Cargo.toml | 6 +- crates/nu_plugin_stress_internals/Cargo.toml | 2 +- crates/nuon/Cargo.toml | 8 +-- 42 files changed, 235 insertions(+), 235 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2d339ec7da..23cafeefda 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2770,7 +2770,7 @@ dependencies = [ [[package]] name = "nu" -version = "0.94.1" +version = "0.94.2" dependencies = [ "assert_cmd", "crossterm", @@ -2823,7 +2823,7 @@ dependencies = [ [[package]] name = "nu-cli" -version = "0.94.1" +version = "0.94.2" dependencies = [ "chrono", "crossterm", @@ -2858,7 +2858,7 @@ dependencies = [ [[package]] name = "nu-cmd-base" -version = "0.94.1" +version = "0.94.2" dependencies = [ "indexmap", "miette", @@ -2870,7 +2870,7 @@ dependencies = [ [[package]] name = "nu-cmd-extra" -version = "0.94.1" +version = "0.94.2" dependencies = [ "fancy-regex", "heck 0.5.0", @@ -2895,7 +2895,7 @@ dependencies = [ [[package]] name = "nu-cmd-lang" -version = "0.94.1" +version = "0.94.2" dependencies = [ "itertools 0.12.1", "nu-engine", @@ -2907,7 +2907,7 @@ dependencies = [ [[package]] name = "nu-cmd-plugin" -version = "0.94.1" +version = "0.94.2" dependencies = [ "itertools 0.12.1", "nu-engine", @@ -2918,7 +2918,7 @@ dependencies = [ [[package]] name = "nu-color-config" -version = "0.94.1" +version = "0.94.2" dependencies = [ "nu-ansi-term", "nu-engine", @@ -2930,7 +2930,7 @@ dependencies = [ [[package]] name = "nu-command" -version = "0.94.1" +version = "0.94.2" dependencies = [ "alphanumeric-sort", "base64 0.22.1", @@ -3039,7 +3039,7 @@ dependencies = [ [[package]] name = "nu-engine" -version = "0.94.1" +version = "0.94.2" dependencies = [ "nu-glob", "nu-path", @@ -3049,7 +3049,7 @@ dependencies = [ [[package]] name = "nu-explore" -version = "0.94.1" +version = "0.94.2" dependencies = [ "ansi-str", "anyhow", @@ -3074,14 +3074,14 @@ dependencies = [ [[package]] name = "nu-glob" -version = "0.94.1" +version = "0.94.2" dependencies = [ "doc-comment", ] [[package]] name = "nu-json" -version = "0.94.1" +version = "0.94.2" dependencies = [ "linked-hash-map", "num-traits", @@ -3091,7 +3091,7 @@ dependencies = [ [[package]] name = "nu-lsp" -version = "0.94.1" +version = "0.94.2" dependencies = [ "assert-json-diff", "crossbeam-channel", @@ -3112,7 +3112,7 @@ dependencies = [ [[package]] name = "nu-parser" -version = "0.94.1" +version = "0.94.2" dependencies = [ "bytesize", "chrono", @@ -3128,7 +3128,7 @@ dependencies = [ [[package]] name = "nu-path" -version = "0.94.1" +version = "0.94.2" dependencies = [ "dirs-next", "omnipath", @@ -3137,7 +3137,7 @@ dependencies = [ [[package]] name = "nu-plugin" -version = "0.94.1" +version = "0.94.2" dependencies = [ "log", "nix", @@ -3152,7 +3152,7 @@ dependencies = [ [[package]] name = "nu-plugin-core" -version = "0.94.1" +version = "0.94.2" dependencies = [ "interprocess", "log", @@ -3166,7 +3166,7 @@ dependencies = [ [[package]] name = "nu-plugin-engine" -version = "0.94.1" +version = "0.94.2" dependencies = [ "log", "nu-engine", @@ -3181,7 +3181,7 @@ dependencies = [ [[package]] name = "nu-plugin-protocol" -version = "0.94.1" +version = "0.94.2" dependencies = [ "bincode", "nu-protocol", @@ -3193,7 +3193,7 @@ dependencies = [ [[package]] name = "nu-plugin-test-support" -version = "0.94.1" +version = "0.94.2" dependencies = [ "nu-ansi-term", "nu-cmd-lang", @@ -3211,7 +3211,7 @@ dependencies = [ [[package]] name = "nu-pretty-hex" -version = "0.94.1" +version = "0.94.2" dependencies = [ "heapless", "nu-ansi-term", @@ -3220,7 +3220,7 @@ dependencies = [ [[package]] name = "nu-protocol" -version = "0.94.1" +version = "0.94.2" dependencies = [ "brotli 5.0.0", "byte-unit", @@ -3251,7 +3251,7 @@ dependencies = [ [[package]] name = "nu-std" -version = "0.94.1" +version = "0.94.2" dependencies = [ "log", "miette", @@ -3262,7 +3262,7 @@ dependencies = [ [[package]] name = "nu-system" -version = "0.94.1" +version = "0.94.2" dependencies = [ "chrono", "itertools 0.12.1", @@ -3280,7 +3280,7 @@ dependencies = [ [[package]] name = "nu-table" -version = "0.94.1" +version = "0.94.2" dependencies = [ "fancy-regex", "nu-ansi-term", @@ -3294,7 +3294,7 @@ dependencies = [ [[package]] name = "nu-term-grid" -version = "0.94.1" +version = "0.94.2" dependencies = [ "nu-utils", "unicode-width", @@ -3302,7 +3302,7 @@ dependencies = [ [[package]] name = "nu-test-support" -version = "0.94.1" +version = "0.94.2" dependencies = [ "nu-glob", "nu-path", @@ -3314,7 +3314,7 @@ dependencies = [ [[package]] name = "nu-utils" -version = "0.94.1" +version = "0.94.2" dependencies = [ "crossterm_winapi", "log", @@ -3340,7 +3340,7 @@ dependencies = [ [[package]] name = "nu_plugin_example" -version = "0.94.1" +version = "0.94.2" dependencies = [ "nu-cmd-lang", "nu-plugin", @@ -3350,7 +3350,7 @@ dependencies = [ [[package]] name = "nu_plugin_formats" -version = "0.94.1" +version = "0.94.2" dependencies = [ "eml-parser", "ical", @@ -3363,7 +3363,7 @@ dependencies = [ [[package]] name = "nu_plugin_gstat" -version = "0.94.1" +version = "0.94.2" dependencies = [ "git2", "nu-plugin", @@ -3372,7 +3372,7 @@ dependencies = [ [[package]] name = "nu_plugin_inc" -version = "0.94.1" +version = "0.94.2" dependencies = [ "nu-plugin", "nu-protocol", @@ -3381,7 +3381,7 @@ dependencies = [ [[package]] name = "nu_plugin_polars" -version = "0.94.1" +version = "0.94.2" dependencies = [ "chrono", "chrono-tz 0.9.0", @@ -3412,7 +3412,7 @@ dependencies = [ [[package]] name = "nu_plugin_query" -version = "0.94.1" +version = "0.94.2" dependencies = [ "gjson", "nu-plugin", @@ -3424,7 +3424,7 @@ dependencies = [ [[package]] name = "nu_plugin_stress_internals" -version = "0.94.1" +version = "0.94.2" dependencies = [ "interprocess", "serde", @@ -3550,7 +3550,7 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "nuon" -version = "0.94.1" +version = "0.94.2" dependencies = [ "chrono", "fancy-regex", diff --git a/Cargo.toml b/Cargo.toml index a8576baa95..ce9157efb4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ license = "MIT" name = "nu" repository = "https://github.com/nushell/nushell" rust-version = "1.77.2" -version = "0.94.1" +version = "0.94.2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -174,22 +174,22 @@ windows = "0.54" winreg = "0.52" [dependencies] -nu-cli = { path = "./crates/nu-cli", version = "0.94.1" } -nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.94.1" } -nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.94.1" } -nu-cmd-plugin = { path = "./crates/nu-cmd-plugin", version = "0.94.1", optional = true } -nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.94.1" } -nu-command = { path = "./crates/nu-command", version = "0.94.1" } -nu-engine = { path = "./crates/nu-engine", version = "0.94.1" } -nu-explore = { path = "./crates/nu-explore", version = "0.94.1" } -nu-lsp = { path = "./crates/nu-lsp/", version = "0.94.1" } -nu-parser = { path = "./crates/nu-parser", version = "0.94.1" } -nu-path = { path = "./crates/nu-path", version = "0.94.1" } -nu-plugin-engine = { path = "./crates/nu-plugin-engine", optional = true, version = "0.94.1" } -nu-protocol = { path = "./crates/nu-protocol", version = "0.94.1" } -nu-std = { path = "./crates/nu-std", version = "0.94.1" } -nu-system = { path = "./crates/nu-system", version = "0.94.1" } -nu-utils = { path = "./crates/nu-utils", version = "0.94.1" } +nu-cli = { path = "./crates/nu-cli", version = "0.94.2" } +nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.94.2" } +nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.94.2" } +nu-cmd-plugin = { path = "./crates/nu-cmd-plugin", version = "0.94.2", optional = true } +nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.94.2" } +nu-command = { path = "./crates/nu-command", version = "0.94.2" } +nu-engine = { path = "./crates/nu-engine", version = "0.94.2" } +nu-explore = { path = "./crates/nu-explore", version = "0.94.2" } +nu-lsp = { path = "./crates/nu-lsp/", version = "0.94.2" } +nu-parser = { path = "./crates/nu-parser", version = "0.94.2" } +nu-path = { path = "./crates/nu-path", version = "0.94.2" } +nu-plugin-engine = { path = "./crates/nu-plugin-engine", optional = true, version = "0.94.2" } +nu-protocol = { path = "./crates/nu-protocol", version = "0.94.2" } +nu-std = { path = "./crates/nu-std", version = "0.94.2" } +nu-system = { path = "./crates/nu-system", version = "0.94.2" } +nu-utils = { path = "./crates/nu-utils", version = "0.94.2" } reedline = { workspace = true, features = ["bashisms", "sqlite"] } @@ -218,9 +218,9 @@ nix = { workspace = true, default-features = false, features = [ ] } [dev-dependencies] -nu-test-support = { path = "./crates/nu-test-support", version = "0.94.1" } -nu-plugin-protocol = { path = "./crates/nu-plugin-protocol", version = "0.94.1" } -nu-plugin-core = { path = "./crates/nu-plugin-core", version = "0.94.1" } +nu-test-support = { path = "./crates/nu-test-support", version = "0.94.2" } +nu-plugin-protocol = { path = "./crates/nu-plugin-protocol", version = "0.94.2" } +nu-plugin-core = { path = "./crates/nu-plugin-core", version = "0.94.2" } assert_cmd = "2.0" dirs-next = { workspace = true } tango-bench = "0.5" diff --git a/crates/nu-cli/Cargo.toml b/crates/nu-cli/Cargo.toml index 516afd9f0b..0d82fa4aae 100644 --- a/crates/nu-cli/Cargo.toml +++ b/crates/nu-cli/Cargo.toml @@ -5,27 +5,27 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cli" edition = "2021" license = "MIT" name = "nu-cli" -version = "0.94.1" +version = "0.94.2" [lib] bench = false [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.1" } -nu-command = { path = "../nu-command", version = "0.94.1" } -nu-test-support = { path = "../nu-test-support", version = "0.94.1" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.2" } +nu-command = { path = "../nu-command", version = "0.94.2" } +nu-test-support = { path = "../nu-test-support", version = "0.94.2" } rstest = { workspace = true, default-features = false } tempfile = { workspace = true } [dependencies] -nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.1" } -nu-engine = { path = "../nu-engine", version = "0.94.1" } -nu-path = { path = "../nu-path", version = "0.94.1" } -nu-parser = { path = "../nu-parser", version = "0.94.1" } -nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.1", optional = true } -nu-protocol = { path = "../nu-protocol", version = "0.94.1" } -nu-utils = { path = "../nu-utils", version = "0.94.1" } -nu-color-config = { path = "../nu-color-config", version = "0.94.1" } +nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.2" } +nu-engine = { path = "../nu-engine", version = "0.94.2" } +nu-path = { path = "../nu-path", version = "0.94.2" } +nu-parser = { path = "../nu-parser", version = "0.94.2" } +nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.2", optional = true } +nu-protocol = { path = "../nu-protocol", version = "0.94.2" } +nu-utils = { path = "../nu-utils", version = "0.94.2" } +nu-color-config = { path = "../nu-color-config", version = "0.94.2" } nu-ansi-term = { workspace = true } reedline = { workspace = true, features = ["bashisms", "sqlite"] } diff --git a/crates/nu-cmd-base/Cargo.toml b/crates/nu-cmd-base/Cargo.toml index 1dcd95ba94..858ff55e2d 100644 --- a/crates/nu-cmd-base/Cargo.toml +++ b/crates/nu-cmd-base/Cargo.toml @@ -5,15 +5,15 @@ edition = "2021" license = "MIT" name = "nu-cmd-base" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-base" -version = "0.94.1" +version = "0.94.2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.1" } -nu-parser = { path = "../nu-parser", version = "0.94.1" } -nu-path = { path = "../nu-path", version = "0.94.1" } -nu-protocol = { path = "../nu-protocol", version = "0.94.1" } +nu-engine = { path = "../nu-engine", version = "0.94.2" } +nu-parser = { path = "../nu-parser", version = "0.94.2" } +nu-path = { path = "../nu-path", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2" } indexmap = { workspace = true } miette = { workspace = true } diff --git a/crates/nu-cmd-extra/Cargo.toml b/crates/nu-cmd-extra/Cargo.toml index 9e6270163d..b03c7911ed 100644 --- a/crates/nu-cmd-extra/Cargo.toml +++ b/crates/nu-cmd-extra/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "MIT" name = "nu-cmd-extra" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-extra" -version = "0.94.1" +version = "0.94.2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -13,13 +13,13 @@ version = "0.94.1" bench = false [dependencies] -nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.1" } -nu-engine = { path = "../nu-engine", version = "0.94.1" } -nu-json = { version = "0.94.1", path = "../nu-json" } -nu-parser = { path = "../nu-parser", version = "0.94.1" } -nu-pretty-hex = { version = "0.94.1", path = "../nu-pretty-hex" } -nu-protocol = { path = "../nu-protocol", version = "0.94.1" } -nu-utils = { path = "../nu-utils", version = "0.94.1" } +nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.2" } +nu-engine = { path = "../nu-engine", version = "0.94.2" } +nu-json = { version = "0.94.2", path = "../nu-json" } +nu-parser = { path = "../nu-parser", version = "0.94.2" } +nu-pretty-hex = { version = "0.94.2", path = "../nu-pretty-hex" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2" } +nu-utils = { path = "../nu-utils", version = "0.94.2" } # Potential dependencies for extras heck = { workspace = true } @@ -37,6 +37,6 @@ extra = ["default"] default = [] [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.1" } -nu-command = { path = "../nu-command", version = "0.94.1" } -nu-test-support = { path = "../nu-test-support", version = "0.94.1" } \ No newline at end of file +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.2" } +nu-command = { path = "../nu-command", version = "0.94.2" } +nu-test-support = { path = "../nu-test-support", version = "0.94.2" } \ No newline at end of file diff --git a/crates/nu-cmd-lang/Cargo.toml b/crates/nu-cmd-lang/Cargo.toml index f7b43521d1..ad94c331d8 100644 --- a/crates/nu-cmd-lang/Cargo.toml +++ b/crates/nu-cmd-lang/Cargo.toml @@ -6,16 +6,16 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-lang" edition = "2021" license = "MIT" name = "nu-cmd-lang" -version = "0.94.1" +version = "0.94.2" [lib] bench = false [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.1" } -nu-parser = { path = "../nu-parser", version = "0.94.1" } -nu-protocol = { path = "../nu-protocol", version = "0.94.1" } -nu-utils = { path = "../nu-utils", version = "0.94.1" } +nu-engine = { path = "../nu-engine", version = "0.94.2" } +nu-parser = { path = "../nu-parser", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2" } +nu-utils = { path = "../nu-utils", version = "0.94.2" } itertools = { workspace = true } shadow-rs = { version = "0.28", default-features = false } diff --git a/crates/nu-cmd-plugin/Cargo.toml b/crates/nu-cmd-plugin/Cargo.toml index f461f6bf04..62ed6851b5 100644 --- a/crates/nu-cmd-plugin/Cargo.toml +++ b/crates/nu-cmd-plugin/Cargo.toml @@ -5,15 +5,15 @@ edition = "2021" license = "MIT" name = "nu-cmd-plugin" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-plugin" -version = "0.94.1" +version = "0.94.2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.1" } -nu-path = { path = "../nu-path", version = "0.94.1" } -nu-protocol = { path = "../nu-protocol", version = "0.94.1", features = ["plugin"] } -nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.1" } +nu-engine = { path = "../nu-engine", version = "0.94.2" } +nu-path = { path = "../nu-path", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2", features = ["plugin"] } +nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.2" } itertools = { workspace = true } diff --git a/crates/nu-color-config/Cargo.toml b/crates/nu-color-config/Cargo.toml index 34f0ded963..6268acf6f6 100644 --- a/crates/nu-color-config/Cargo.toml +++ b/crates/nu-color-config/Cargo.toml @@ -5,18 +5,18 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-color-confi edition = "2021" license = "MIT" name = "nu-color-config" -version = "0.94.1" +version = "0.94.2" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.94.1" } -nu-engine = { path = "../nu-engine", version = "0.94.1" } -nu-json = { path = "../nu-json", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2" } +nu-engine = { path = "../nu-engine", version = "0.94.2" } +nu-json = { path = "../nu-json", version = "0.94.2" } nu-ansi-term = { workspace = true } serde = { workspace = true, features = ["derive"] } [dev-dependencies] -nu-test-support = { path = "../nu-test-support", version = "0.94.1" } \ No newline at end of file +nu-test-support = { path = "../nu-test-support", version = "0.94.2" } \ No newline at end of file diff --git a/crates/nu-command/Cargo.toml b/crates/nu-command/Cargo.toml index 25665cfc33..1a88a24e5e 100644 --- a/crates/nu-command/Cargo.toml +++ b/crates/nu-command/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "MIT" name = "nu-command" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-command" -version = "0.94.1" +version = "0.94.2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -13,21 +13,21 @@ version = "0.94.1" bench = false [dependencies] -nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.1" } -nu-color-config = { path = "../nu-color-config", version = "0.94.1" } -nu-engine = { path = "../nu-engine", version = "0.94.1" } -nu-glob = { path = "../nu-glob", version = "0.94.1" } -nu-json = { path = "../nu-json", version = "0.94.1" } -nu-parser = { path = "../nu-parser", version = "0.94.1" } -nu-path = { path = "../nu-path", version = "0.94.1" } -nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.94.1" } -nu-protocol = { path = "../nu-protocol", version = "0.94.1" } -nu-system = { path = "../nu-system", version = "0.94.1" } -nu-table = { path = "../nu-table", version = "0.94.1" } -nu-term-grid = { path = "../nu-term-grid", version = "0.94.1" } -nu-utils = { path = "../nu-utils", version = "0.94.1" } +nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.2" } +nu-color-config = { path = "../nu-color-config", version = "0.94.2" } +nu-engine = { path = "../nu-engine", version = "0.94.2" } +nu-glob = { path = "../nu-glob", version = "0.94.2" } +nu-json = { path = "../nu-json", version = "0.94.2" } +nu-parser = { path = "../nu-parser", version = "0.94.2" } +nu-path = { path = "../nu-path", version = "0.94.2" } +nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2" } +nu-system = { path = "../nu-system", version = "0.94.2" } +nu-table = { path = "../nu-table", version = "0.94.2" } +nu-term-grid = { path = "../nu-term-grid", version = "0.94.2" } +nu-utils = { path = "../nu-utils", version = "0.94.2" } nu-ansi-term = { workspace = true } -nuon = { path = "../nuon", version = "0.94.1" } +nuon = { path = "../nuon", version = "0.94.2" } alphanumeric-sort = { workspace = true } base64 = { workspace = true } @@ -137,8 +137,8 @@ trash-support = ["trash"] which-support = [] [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.1" } -nu-test-support = { path = "../nu-test-support", version = "0.94.1" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.2" } +nu-test-support = { path = "../nu-test-support", version = "0.94.2" } dirs-next = { workspace = true } mockito = { workspace = true, default-features = false } diff --git a/crates/nu-engine/Cargo.toml b/crates/nu-engine/Cargo.toml index 7bf5ffe9d5..d8a90fb70e 100644 --- a/crates/nu-engine/Cargo.toml +++ b/crates/nu-engine/Cargo.toml @@ -5,16 +5,16 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-engine" edition = "2021" license = "MIT" name = "nu-engine" -version = "0.94.1" +version = "0.94.2" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", features = ["plugin"], version = "0.94.1" } -nu-path = { path = "../nu-path", version = "0.94.1" } -nu-glob = { path = "../nu-glob", version = "0.94.1" } -nu-utils = { path = "../nu-utils", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", features = ["plugin"], version = "0.94.2" } +nu-path = { path = "../nu-path", version = "0.94.2" } +nu-glob = { path = "../nu-glob", version = "0.94.2" } +nu-utils = { path = "../nu-utils", version = "0.94.2" } [features] plugin = [] \ No newline at end of file diff --git a/crates/nu-explore/Cargo.toml b/crates/nu-explore/Cargo.toml index 006e301859..0837d9d683 100644 --- a/crates/nu-explore/Cargo.toml +++ b/crates/nu-explore/Cargo.toml @@ -5,21 +5,21 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-explore" edition = "2021" license = "MIT" name = "nu-explore" -version = "0.94.1" +version = "0.94.2" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.94.1" } -nu-parser = { path = "../nu-parser", version = "0.94.1" } -nu-color-config = { path = "../nu-color-config", version = "0.94.1" } -nu-engine = { path = "../nu-engine", version = "0.94.1" } -nu-table = { path = "../nu-table", version = "0.94.1" } -nu-json = { path = "../nu-json", version = "0.94.1" } -nu-utils = { path = "../nu-utils", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2" } +nu-parser = { path = "../nu-parser", version = "0.94.2" } +nu-color-config = { path = "../nu-color-config", version = "0.94.2" } +nu-engine = { path = "../nu-engine", version = "0.94.2" } +nu-table = { path = "../nu-table", version = "0.94.2" } +nu-json = { path = "../nu-json", version = "0.94.2" } +nu-utils = { path = "../nu-utils", version = "0.94.2" } nu-ansi-term = { workspace = true } -nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.94.1" } +nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.94.2" } anyhow = { workspace = true } log = { workspace = true } diff --git a/crates/nu-glob/Cargo.toml b/crates/nu-glob/Cargo.toml index c6bfd7e493..d7568f7b2d 100644 --- a/crates/nu-glob/Cargo.toml +++ b/crates/nu-glob/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nu-glob" -version = "0.94.1" +version = "0.94.2" authors = ["The Nushell Project Developers", "The Rust Project Developers"] license = "MIT/Apache-2.0" description = """ diff --git a/crates/nu-json/Cargo.toml b/crates/nu-json/Cargo.toml index 5a0806d7ca..63a80f4b91 100644 --- a/crates/nu-json/Cargo.toml +++ b/crates/nu-json/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-json" edition = "2021" license = "MIT" name = "nu-json" -version = "0.94.1" +version = "0.94.2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -23,5 +23,5 @@ serde = { workspace = true } serde_json = { workspace = true } [dev-dependencies] -# nu-path = { path="../nu-path", version = "0.94.1" } +# nu-path = { path="../nu-path", version = "0.94.2" } # serde_json = "1.0" \ No newline at end of file diff --git a/crates/nu-lsp/Cargo.toml b/crates/nu-lsp/Cargo.toml index 92f468fdbd..0732862bff 100644 --- a/crates/nu-lsp/Cargo.toml +++ b/crates/nu-lsp/Cargo.toml @@ -3,14 +3,14 @@ authors = ["The Nushell Project Developers"] description = "Nushell's integrated LSP server" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-lsp" name = "nu-lsp" -version = "0.94.1" +version = "0.94.2" edition = "2021" license = "MIT" [dependencies] -nu-cli = { path = "../nu-cli", version = "0.94.1" } -nu-parser = { path = "../nu-parser", version = "0.94.1" } -nu-protocol = { path = "../nu-protocol", version = "0.94.1" } +nu-cli = { path = "../nu-cli", version = "0.94.2" } +nu-parser = { path = "../nu-parser", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2" } reedline = { workspace = true } @@ -23,8 +23,8 @@ serde = { workspace = true } serde_json = { workspace = true } [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.1" } -nu-command = { path = "../nu-command", version = "0.94.1" } -nu-test-support = { path = "../nu-test-support", version = "0.94.1" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.2" } +nu-command = { path = "../nu-command", version = "0.94.2" } +nu-test-support = { path = "../nu-test-support", version = "0.94.2" } assert-json-diff = "2.0" \ No newline at end of file diff --git a/crates/nu-parser/Cargo.toml b/crates/nu-parser/Cargo.toml index feb379d091..fa840fc483 100644 --- a/crates/nu-parser/Cargo.toml +++ b/crates/nu-parser/Cargo.toml @@ -5,17 +5,17 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-parser" edition = "2021" license = "MIT" name = "nu-parser" -version = "0.94.1" +version = "0.94.2" exclude = ["/fuzz"] [lib] bench = false [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.1" } -nu-path = { path = "../nu-path", version = "0.94.1" } -nu-plugin-engine = { path = "../nu-plugin-engine", optional = true, version = "0.94.1" } -nu-protocol = { path = "../nu-protocol", version = "0.94.1" } +nu-engine = { path = "../nu-engine", version = "0.94.2" } +nu-path = { path = "../nu-path", version = "0.94.2" } +nu-plugin-engine = { path = "../nu-plugin-engine", optional = true, version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2" } bytesize = { workspace = true } chrono = { default-features = false, features = ['std'], workspace = true } diff --git a/crates/nu-path/Cargo.toml b/crates/nu-path/Cargo.toml index 1f3822089c..bdd0157e4f 100644 --- a/crates/nu-path/Cargo.toml +++ b/crates/nu-path/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-path" edition = "2021" license = "MIT" name = "nu-path" -version = "0.94.1" +version = "0.94.2" exclude = ["/fuzz"] [lib] diff --git a/crates/nu-plugin-core/Cargo.toml b/crates/nu-plugin-core/Cargo.toml index 4040095a2a..580e0287e2 100644 --- a/crates/nu-plugin-core/Cargo.toml +++ b/crates/nu-plugin-core/Cargo.toml @@ -5,14 +5,14 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-plugin-core edition = "2021" license = "MIT" name = "nu-plugin-core" -version = "0.94.1" +version = "0.94.2" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.94.1" } -nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.1", default-features = false } +nu-protocol = { path = "../nu-protocol", version = "0.94.2" } +nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.2", default-features = false } rmp-serde = { workspace = true } serde = { workspace = true } diff --git a/crates/nu-plugin-engine/Cargo.toml b/crates/nu-plugin-engine/Cargo.toml index 715c2b7f74..50fe40ab0a 100644 --- a/crates/nu-plugin-engine/Cargo.toml +++ b/crates/nu-plugin-engine/Cargo.toml @@ -5,17 +5,17 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-plugin-engi edition = "2021" license = "MIT" name = "nu-plugin-engine" -version = "0.94.1" +version = "0.94.2" [lib] bench = false [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.1" } -nu-protocol = { path = "../nu-protocol", version = "0.94.1" } -nu-system = { path = "../nu-system", version = "0.94.1" } -nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.1" } -nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.1", default-features = false } +nu-engine = { path = "../nu-engine", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2" } +nu-system = { path = "../nu-system", version = "0.94.2" } +nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.2" } +nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.2", default-features = false } serde = { workspace = true } log = { workspace = true } diff --git a/crates/nu-plugin-protocol/Cargo.toml b/crates/nu-plugin-protocol/Cargo.toml index 8fe1c1102e..b52655a4f1 100644 --- a/crates/nu-plugin-protocol/Cargo.toml +++ b/crates/nu-plugin-protocol/Cargo.toml @@ -5,14 +5,14 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-plugin-prot edition = "2021" license = "MIT" name = "nu-plugin-protocol" -version = "0.94.1" +version = "0.94.2" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.94.1", features = ["plugin"] } -nu-utils = { path = "../nu-utils", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2", features = ["plugin"] } +nu-utils = { path = "../nu-utils", version = "0.94.2" } bincode = "1.3" serde = { workspace = true, features = ["derive"] } diff --git a/crates/nu-plugin-test-support/Cargo.toml b/crates/nu-plugin-test-support/Cargo.toml index 32df904645..b5ef1e4c02 100644 --- a/crates/nu-plugin-test-support/Cargo.toml +++ b/crates/nu-plugin-test-support/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nu-plugin-test-support" -version = "0.94.1" +version = "0.94.2" edition = "2021" license = "MIT" description = "Testing support for Nushell plugins" @@ -12,14 +12,14 @@ bench = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.1", features = ["plugin"] } -nu-protocol = { path = "../nu-protocol", version = "0.94.1", features = ["plugin"] } -nu-parser = { path = "../nu-parser", version = "0.94.1", features = ["plugin"] } -nu-plugin = { path = "../nu-plugin", version = "0.94.1" } -nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.1" } -nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.1" } -nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.1" } -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.1" } +nu-engine = { path = "../nu-engine", version = "0.94.2", features = ["plugin"] } +nu-protocol = { path = "../nu-protocol", version = "0.94.2", features = ["plugin"] } +nu-parser = { path = "../nu-parser", version = "0.94.2", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.2" } +nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.2" } +nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.2" } +nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.2" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.2" } nu-ansi-term = { workspace = true } similar = "2.5" diff --git a/crates/nu-plugin/Cargo.toml b/crates/nu-plugin/Cargo.toml index 150ab6666d..0a9a169474 100644 --- a/crates/nu-plugin/Cargo.toml +++ b/crates/nu-plugin/Cargo.toml @@ -5,16 +5,16 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-plugin" edition = "2021" license = "MIT" name = "nu-plugin" -version = "0.94.1" +version = "0.94.2" [lib] bench = false [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.1" } -nu-protocol = { path = "../nu-protocol", version = "0.94.1" } -nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.1" } -nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.1", default-features = false } +nu-engine = { path = "../nu-engine", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2" } +nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.2" } +nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.2", default-features = false } log = { workspace = true } thiserror = "1.0" diff --git a/crates/nu-pretty-hex/Cargo.toml b/crates/nu-pretty-hex/Cargo.toml index 639ceb0edd..152d03df72 100644 --- a/crates/nu-pretty-hex/Cargo.toml +++ b/crates/nu-pretty-hex/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-pretty-hex" edition = "2021" license = "MIT" name = "nu-pretty-hex" -version = "0.94.1" +version = "0.94.2" [lib] doctest = false diff --git a/crates/nu-protocol/Cargo.toml b/crates/nu-protocol/Cargo.toml index 8b2870a378..2ccd0a07ce 100644 --- a/crates/nu-protocol/Cargo.toml +++ b/crates/nu-protocol/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-protocol" edition = "2021" license = "MIT" name = "nu-protocol" -version = "0.94.1" +version = "0.94.2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -13,9 +13,9 @@ version = "0.94.1" bench = false [dependencies] -nu-utils = { path = "../nu-utils", version = "0.94.1" } -nu-path = { path = "../nu-path", version = "0.94.1" } -nu-system = { path = "../nu-system", version = "0.94.1" } +nu-utils = { path = "../nu-utils", version = "0.94.2" } +nu-path = { path = "../nu-path", version = "0.94.2" } +nu-system = { path = "../nu-system", version = "0.94.2" } brotli = { workspace = true, optional = true } byte-unit = { version = "5.1", features = [ "serde" ] } @@ -45,7 +45,7 @@ plugin = [ serde_json = { workspace = true } strum = "0.26" strum_macros = "0.26" -nu-test-support = { path = "../nu-test-support", version = "0.94.1" } +nu-test-support = { path = "../nu-test-support", version = "0.94.2" } pretty_assertions = { workspace = true } rstest = { workspace = true } tempfile = { workspace = true } diff --git a/crates/nu-std/Cargo.toml b/crates/nu-std/Cargo.toml index f5c6790c52..4e5850c3fb 100644 --- a/crates/nu-std/Cargo.toml +++ b/crates/nu-std/Cargo.toml @@ -5,12 +5,12 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-std" edition = "2021" license = "MIT" name = "nu-std" -version = "0.94.1" +version = "0.94.2" [dependencies] -nu-parser = { version = "0.94.1", path = "../nu-parser" } -nu-protocol = { version = "0.94.1", path = "../nu-protocol" } -nu-engine = { version = "0.94.1", path = "../nu-engine" } +nu-parser = { version = "0.94.2", path = "../nu-parser" } +nu-protocol = { version = "0.94.2", path = "../nu-protocol" } +nu-engine = { version = "0.94.2", path = "../nu-engine" } miette = { workspace = true, features = ["fancy-no-backtrace"] } log = "0.4" \ No newline at end of file diff --git a/crates/nu-system/Cargo.toml b/crates/nu-system/Cargo.toml index 33305d07bc..17e621db90 100644 --- a/crates/nu-system/Cargo.toml +++ b/crates/nu-system/Cargo.toml @@ -3,7 +3,7 @@ authors = ["The Nushell Project Developers", "procs creators"] description = "Nushell system querying" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-system" name = "nu-system" -version = "0.94.1" +version = "0.94.2" edition = "2021" license = "MIT" diff --git a/crates/nu-table/Cargo.toml b/crates/nu-table/Cargo.toml index 6fcb1ffce6..fe1de742d9 100644 --- a/crates/nu-table/Cargo.toml +++ b/crates/nu-table/Cargo.toml @@ -5,20 +5,20 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-table" edition = "2021" license = "MIT" name = "nu-table" -version = "0.94.1" +version = "0.94.2" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.94.1" } -nu-utils = { path = "../nu-utils", version = "0.94.1" } -nu-engine = { path = "../nu-engine", version = "0.94.1" } -nu-color-config = { path = "../nu-color-config", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2" } +nu-utils = { path = "../nu-utils", version = "0.94.2" } +nu-engine = { path = "../nu-engine", version = "0.94.2" } +nu-color-config = { path = "../nu-color-config", version = "0.94.2" } nu-ansi-term = { workspace = true } once_cell = { workspace = true } fancy-regex = { workspace = true } tabled = { workspace = true, features = ["color"], default-features = false } [dev-dependencies] -# nu-test-support = { path="../nu-test-support", version = "0.94.1" } \ No newline at end of file +# nu-test-support = { path="../nu-test-support", version = "0.94.2" } \ No newline at end of file diff --git a/crates/nu-term-grid/Cargo.toml b/crates/nu-term-grid/Cargo.toml index 2570ce0d68..bc560257f8 100644 --- a/crates/nu-term-grid/Cargo.toml +++ b/crates/nu-term-grid/Cargo.toml @@ -5,12 +5,12 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-term-grid" edition = "2021" license = "MIT" name = "nu-term-grid" -version = "0.94.1" +version = "0.94.2" [lib] bench = false [dependencies] -nu-utils = { path = "../nu-utils", version = "0.94.1" } +nu-utils = { path = "../nu-utils", version = "0.94.2" } unicode-width = { workspace = true } \ No newline at end of file diff --git a/crates/nu-test-support/Cargo.toml b/crates/nu-test-support/Cargo.toml index e2525d8c78..07f4142d43 100644 --- a/crates/nu-test-support/Cargo.toml +++ b/crates/nu-test-support/Cargo.toml @@ -5,16 +5,16 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-test-suppor edition = "2021" license = "MIT" name = "nu-test-support" -version = "0.94.1" +version = "0.94.2" [lib] doctest = false bench = false [dependencies] -nu-path = { path = "../nu-path", version = "0.94.1" } -nu-glob = { path = "../nu-glob", version = "0.94.1" } -nu-utils = { path = "../nu-utils", version = "0.94.1" } +nu-path = { path = "../nu-path", version = "0.94.2" } +nu-glob = { path = "../nu-glob", version = "0.94.2" } +nu-utils = { path = "../nu-utils", version = "0.94.2" } num-format = { workspace = true } which = { workspace = true } diff --git a/crates/nu-utils/Cargo.toml b/crates/nu-utils/Cargo.toml index 85b80015df..584602f184 100644 --- a/crates/nu-utils/Cargo.toml +++ b/crates/nu-utils/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "MIT" name = "nu-utils" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-utils" -version = "0.94.1" +version = "0.94.2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [[bin]] diff --git a/crates/nu-utils/src/sample_config/default_config.nu b/crates/nu-utils/src/sample_config/default_config.nu index 357a1cc7d5..6d84d8d1de 100644 --- a/crates/nu-utils/src/sample_config/default_config.nu +++ b/crates/nu-utils/src/sample_config/default_config.nu @@ -1,6 +1,6 @@ # Nushell Config File # -# version = "0.94.1" +# version = "0.94.2" # For more information on defining custom themes, see # https://www.nushell.sh/book/coloring_and_theming.html diff --git a/crates/nu-utils/src/sample_config/default_env.nu b/crates/nu-utils/src/sample_config/default_env.nu index 90705230a9..edf0830f9f 100644 --- a/crates/nu-utils/src/sample_config/default_env.nu +++ b/crates/nu-utils/src/sample_config/default_env.nu @@ -1,6 +1,6 @@ # Nushell Environment Config File # -# version = "0.94.1" +# version = "0.94.2" def create_left_prompt [] { let dir = match (do --ignore-shell-errors { $env.PWD | path relative-to $nu.home-path }) { diff --git a/crates/nu_plugin_custom_values/Cargo.toml b/crates/nu_plugin_custom_values/Cargo.toml index 7cfbc0b578..2f5ae29e3d 100644 --- a/crates/nu_plugin_custom_values/Cargo.toml +++ b/crates/nu_plugin_custom_values/Cargo.toml @@ -10,10 +10,10 @@ name = "nu_plugin_custom_values" bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.94.1" } -nu-protocol = { path = "../nu-protocol", version = "0.94.1", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2", features = ["plugin"] } serde = { workspace = true, default-features = false } typetag = "0.2" [dev-dependencies] -nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.1" } \ No newline at end of file +nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.2" } \ No newline at end of file diff --git a/crates/nu_plugin_example/Cargo.toml b/crates/nu_plugin_example/Cargo.toml index 0b4ec44e89..de370a0a5d 100644 --- a/crates/nu_plugin_example/Cargo.toml +++ b/crates/nu_plugin_example/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_exam edition = "2021" license = "MIT" name = "nu_plugin_example" -version = "0.94.1" +version = "0.94.2" [[bin]] name = "nu_plugin_example" @@ -15,9 +15,9 @@ bench = false bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.94.1" } -nu-protocol = { path = "../nu-protocol", version = "0.94.1", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2", features = ["plugin"] } [dev-dependencies] -nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.1" } -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.1" } \ No newline at end of file +nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.2" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.2" } \ No newline at end of file diff --git a/crates/nu_plugin_formats/Cargo.toml b/crates/nu_plugin_formats/Cargo.toml index 213ea74cd5..797eb69656 100644 --- a/crates/nu_plugin_formats/Cargo.toml +++ b/crates/nu_plugin_formats/Cargo.toml @@ -5,12 +5,12 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_form edition = "2021" license = "MIT" name = "nu_plugin_formats" -version = "0.94.1" +version = "0.94.2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.94.1" } -nu-protocol = { path = "../nu-protocol", version = "0.94.1", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2", features = ["plugin"] } indexmap = { workspace = true } eml-parser = "0.1" @@ -18,4 +18,4 @@ ical = "0.11" rust-ini = "0.21.0" [dev-dependencies] -nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.1" } \ No newline at end of file +nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.2" } \ No newline at end of file diff --git a/crates/nu_plugin_gstat/Cargo.toml b/crates/nu_plugin_gstat/Cargo.toml index 7c0ca79ebe..a16bf019f6 100644 --- a/crates/nu_plugin_gstat/Cargo.toml +++ b/crates/nu_plugin_gstat/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_gsta edition = "2021" license = "MIT" name = "nu_plugin_gstat" -version = "0.94.1" +version = "0.94.2" [lib] doctest = false @@ -16,7 +16,7 @@ name = "nu_plugin_gstat" bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.94.1" } -nu-protocol = { path = "../nu-protocol", version = "0.94.1" } +nu-plugin = { path = "../nu-plugin", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2" } git2 = "0.18" \ No newline at end of file diff --git a/crates/nu_plugin_inc/Cargo.toml b/crates/nu_plugin_inc/Cargo.toml index 543982d599..7b57d1591c 100644 --- a/crates/nu_plugin_inc/Cargo.toml +++ b/crates/nu_plugin_inc/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_inc" edition = "2021" license = "MIT" name = "nu_plugin_inc" -version = "0.94.1" +version = "0.94.2" [lib] doctest = false @@ -16,7 +16,7 @@ name = "nu_plugin_inc" bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.94.1" } -nu-protocol = { path = "../nu-protocol", version = "0.94.1", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2", features = ["plugin"] } semver = "1.0" \ No newline at end of file diff --git a/crates/nu_plugin_nu_example/nu_plugin_nu_example.nu b/crates/nu_plugin_nu_example/nu_plugin_nu_example.nu index d900f498da..15c8340c0e 100755 --- a/crates/nu_plugin_nu_example/nu_plugin_nu_example.nu +++ b/crates/nu_plugin_nu_example/nu_plugin_nu_example.nu @@ -6,7 +6,7 @@ # it also allows us to test the plugin interface with something manually implemented in a scripting # language without adding any extra dependencies to our tests. -const NUSHELL_VERSION = "0.94.1" +const NUSHELL_VERSION = "0.94.2" def main [--stdio] { if ($stdio) { diff --git a/crates/nu_plugin_polars/Cargo.toml b/crates/nu_plugin_polars/Cargo.toml index f93e183926..0855bc9b16 100644 --- a/crates/nu_plugin_polars/Cargo.toml +++ b/crates/nu_plugin_polars/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "MIT" name = "nu_plugin_polars" repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_polars" -version = "0.94.1" +version = "0.94.2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -17,9 +17,9 @@ bench = false bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.94.1" } -nu-plugin = { path = "../nu-plugin", version = "0.94.1" } -nu-path = { path = "../nu-path", version = "0.94.1" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2" } +nu-plugin = { path = "../nu-plugin", version = "0.94.2" } +nu-path = { path = "../nu-path", version = "0.94.2" } # Potential dependencies for extras chrono = { workspace = true, features = ["std", "unstable-locales"], default-features = false } @@ -73,9 +73,9 @@ optional = false version = "0.39" [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.1" } -nu-engine = { path = "../nu-engine", version = "0.94.1" } -nu-parser = { path = "../nu-parser", version = "0.94.1" } -nu-command = { path = "../nu-command", version = "0.94.1" } -nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.1" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.2" } +nu-engine = { path = "../nu-engine", version = "0.94.2" } +nu-parser = { path = "../nu-parser", version = "0.94.2" } +nu-command = { path = "../nu-command", version = "0.94.2" } +nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.2" } tempfile.workspace = true \ No newline at end of file diff --git a/crates/nu_plugin_python/nu_plugin_python_example.py b/crates/nu_plugin_python/nu_plugin_python_example.py index 55746d89c1..b2cb06c7eb 100755 --- a/crates/nu_plugin_python/nu_plugin_python_example.py +++ b/crates/nu_plugin_python/nu_plugin_python_example.py @@ -27,7 +27,7 @@ import sys import json -NUSHELL_VERSION = "0.94.1" +NUSHELL_VERSION = "0.94.2" def signatures(): diff --git a/crates/nu_plugin_query/Cargo.toml b/crates/nu_plugin_query/Cargo.toml index b48ca14fa5..0fd251e646 100644 --- a/crates/nu_plugin_query/Cargo.toml +++ b/crates/nu_plugin_query/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_quer edition = "2021" license = "MIT" name = "nu_plugin_query" -version = "0.94.1" +version = "0.94.2" [lib] doctest = false @@ -16,8 +16,8 @@ name = "nu_plugin_query" bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.94.1" } -nu-protocol = { path = "../nu-protocol", version = "0.94.1" } +nu-plugin = { path = "../nu-plugin", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2" } gjson = "0.8" scraper = { default-features = false, version = "0.19" } diff --git a/crates/nu_plugin_stress_internals/Cargo.toml b/crates/nu_plugin_stress_internals/Cargo.toml index 159e0b616c..884244a5db 100644 --- a/crates/nu_plugin_stress_internals/Cargo.toml +++ b/crates/nu_plugin_stress_internals/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_stre edition = "2021" license = "MIT" name = "nu_plugin_stress_internals" -version = "0.94.1" +version = "0.94.2" [[bin]] name = "nu_plugin_stress_internals" diff --git a/crates/nuon/Cargo.toml b/crates/nuon/Cargo.toml index 69e7d89713..80a4de36ae 100644 --- a/crates/nuon/Cargo.toml +++ b/crates/nuon/Cargo.toml @@ -5,14 +5,14 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nuon" edition = "2021" license = "MIT" name = "nuon" -version = "0.94.1" +version = "0.94.2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-parser = { path = "../nu-parser", version = "0.94.1" } -nu-protocol = { path = "../nu-protocol", version = "0.94.1" } -nu-engine = { path = "../nu-engine", version = "0.94.1" } +nu-parser = { path = "../nu-parser", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.2" } +nu-engine = { path = "../nu-engine", version = "0.94.2" } once_cell = { workspace = true } fancy-regex = { workspace = true } From b50903cf58a067b78815be620372e8a3d5cbdcae Mon Sep 17 00:00:00 2001 From: Devyn Cairns Date: Mon, 3 Jun 2024 00:28:45 -0700 Subject: [PATCH 038/113] Fix external command name parsing with backslashes, and add tests (#13027) # Description Fixes #13016 and adds tests for many variations of external call parsing. I just realized @kubouch took a crack at this too (#13022) so really whichever is better, but I think the tests are a good addition. --- crates/nu-parser/src/parser.rs | 35 +++-- crates/nu-parser/tests/test_parser.rs | 215 ++++++++++++++++++++++++++ 2 files changed, 239 insertions(+), 11 deletions(-) diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index ad5e7d4f42..830d8b81e0 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -16,6 +16,7 @@ use nu_protocol::{ IN_VARIABLE_ID, }; use std::{ + borrow::Cow, collections::{HashMap, HashSet}, num::ParseIntError, str, @@ -241,15 +242,10 @@ fn parse_external_arg(working_set: &mut StateWorkingSet, span: Span) -> External )) } else { // Eval stage trims the quotes, so we don't have to do the same thing when parsing. - let contents = if contents.starts_with(b"\"") { - let (contents, err) = unescape_string(contents, span); - if let Some(err) = err { - working_set.error(err) - } - String::from_utf8_lossy(&contents).to_string() - } else { - String::from_utf8_lossy(contents).to_string() - }; + let (contents, err) = unescape_string_preserving_quotes(contents, span); + if let Some(err) = err { + working_set.error(err); + } ExternalArgument::Regular(Expression { expr: Expr::String(contents), @@ -279,13 +275,13 @@ pub fn parse_external_call(working_set: &mut StateWorkingSet, spans: &[Span]) -> Box::new(arg) } else { // Eval stage will unquote the string, so we don't bother with that here - let (contents, err) = unescape_string(&head_contents, head_span); + let (contents, err) = unescape_string_preserving_quotes(&head_contents, head_span); if let Some(err) = err { working_set.error(err) } Box::new(Expression { - expr: Expr::String(String::from_utf8_lossy(&contents).into_owned()), + expr: Expr::String(contents), span: head_span, ty: Type::String, custom_completion: None, @@ -2699,6 +2695,23 @@ pub fn unescape_unquote_string(bytes: &[u8], span: Span) -> (String, Option (String, Option) { + let (bytes, err) = if bytes.starts_with(b"\"") { + let (bytes, err) = unescape_string(bytes, span); + (Cow::Owned(bytes), err) + } else { + (Cow::Borrowed(bytes), None) + }; + + // The original code for args used lossy conversion here, even though that's not what we + // typically use for strings. Revisit whether that's actually desirable later, but don't + // want to introduce a breaking change for this patch. + let token = String::from_utf8_lossy(&bytes).into_owned(); + (token, err) +} + pub fn parse_string(working_set: &mut StateWorkingSet, span: Span) -> Expression { trace!("parsing: string"); diff --git a/crates/nu-parser/tests/test_parser.rs b/crates/nu-parser/tests/test_parser.rs index ef5d968280..2646b3cc90 100644 --- a/crates/nu-parser/tests/test_parser.rs +++ b/crates/nu-parser/tests/test_parser.rs @@ -694,6 +694,221 @@ pub fn parse_call_missing_req_flag() { )); } +#[rstest] +#[case("foo-external-call", "foo-external-call", "bare word")] +#[case("^foo-external-call", "foo-external-call", "bare word with caret")] +#[case( + "foo/external-call", + "foo/external-call", + "bare word with forward slash" +)] +#[case( + "^foo/external-call", + "foo/external-call", + "bare word with forward slash and caret" +)] +#[case(r"foo\external-call", r"foo\external-call", "bare word with backslash")] +#[case( + r"^foo\external-call", + r"foo\external-call", + "bare word with backslash and caret" +)] +#[case( + "^'foo external call'", + "'foo external call'", + "single quote with caret" +)] +#[case( + "^'foo/external call'", + "'foo/external call'", + "single quote with forward slash and caret" +)] +#[case( + r"^'foo\external call'", + r"'foo\external call'", + "single quote with backslash and caret" +)] +#[case( + r#"^"foo external call""#, + r#""foo external call""#, + "double quote with caret" +)] +#[case( + r#"^"foo/external call""#, + r#""foo/external call""#, + "double quote with forward slash and caret" +)] +#[case( + r#"^"foo\\external call""#, + r#""foo\external call""#, + "double quote with backslash and caret" +)] +#[case("`foo external call`", "`foo external call`", "backtick quote")] +#[case( + "^`foo external call`", + "`foo external call`", + "backtick quote with caret" +)] +#[case( + "`foo/external call`", + "`foo/external call`", + "backtick quote with forward slash" +)] +#[case( + "^`foo/external call`", + "`foo/external call`", + "backtick quote with forward slash and caret" +)] +#[case( + r"^`foo\external call`", + r"`foo\external call`", + "backtick quote with backslash" +)] +#[case( + r"^`foo\external call`", + r"`foo\external call`", + "backtick quote with backslash and caret" +)] +fn test_external_call_name(#[case] input: &str, #[case] expected: &str, #[case] tag: &str) { + let engine_state = EngineState::new(); + let mut working_set = StateWorkingSet::new(&engine_state); + let block = parse(&mut working_set, None, input.as_bytes(), true); + assert!( + working_set.parse_errors.is_empty(), + "{tag}: errors: {:?}", + working_set.parse_errors + ); + + let pipeline = &block.pipelines[0]; + assert_eq!(1, pipeline.len()); + let element = &pipeline.elements[0]; + match &element.expr.expr { + Expr::ExternalCall(name, args) => { + match &name.expr { + Expr::String(string) => { + assert_eq!(expected, string); + } + other => { + panic!("{tag}: Unexpected expression in command name position: {other:?}"); + } + } + assert_eq!(0, args.len()); + } + other => { + panic!("{tag}: Unexpected expression in pipeline: {other:?}"); + } + } +} + +#[rstest] +#[case("^foo bar-baz", "bar-baz", "bare word")] +#[case("^foo bar/baz", "bar/baz", "bare word with forward slash")] +#[case(r"^foo bar\baz", r"bar\baz", "bare word with backslash")] +#[case("^foo 'bar baz'", "'bar baz'", "single quote")] +#[case("foo 'bar/baz'", "'bar/baz'", "single quote with forward slash")] +#[case(r"foo 'bar\baz'", r"'bar\baz'", "single quote with backslash")] +#[case(r#"^foo "bar baz""#, r#""bar baz""#, "double quote")] +#[case(r#"^foo "bar/baz""#, r#""bar/baz""#, "double quote with forward slash")] +#[case(r#"^foo "bar\\baz""#, r#""bar\baz""#, "double quote with backslash")] +#[case("^foo `bar baz`", "`bar baz`", "backtick quote")] +#[case("^foo `bar/baz`", "`bar/baz`", "backtick quote with forward slash")] +#[case(r"^foo `bar\baz`", r"`bar\baz`", "backtick quote with backslash")] +fn test_external_call_argument_regular( + #[case] input: &str, + #[case] expected: &str, + #[case] tag: &str, +) { + let engine_state = EngineState::new(); + let mut working_set = StateWorkingSet::new(&engine_state); + let block = parse(&mut working_set, None, input.as_bytes(), true); + assert!( + working_set.parse_errors.is_empty(), + "{tag}: errors: {:?}", + working_set.parse_errors + ); + + let pipeline = &block.pipelines[0]; + assert_eq!(1, pipeline.len()); + let element = &pipeline.elements[0]; + match &element.expr.expr { + Expr::ExternalCall(name, args) => { + match &name.expr { + Expr::String(string) => { + assert_eq!("foo", string, "{tag}: incorrect name"); + } + other => { + panic!("{tag}: Unexpected expression in command name position: {other:?}"); + } + } + assert_eq!(1, args.len()); + match &args[0] { + ExternalArgument::Regular(expr) => match &expr.expr { + Expr::String(string) => { + assert_eq!(expected, string, "{tag}: incorrect arg"); + } + other => { + panic!("Unexpected expression in command arg position: {other:?}") + } + }, + other @ ExternalArgument::Spread(..) => { + panic!("Unexpected external spread argument in command arg position: {other:?}") + } + } + } + other => { + panic!("{tag}: Unexpected expression in pipeline: {other:?}"); + } + } +} + +#[test] +fn test_external_call_argument_spread() { + let engine_state = EngineState::new(); + let mut working_set = StateWorkingSet::new(&engine_state); + let block = parse(&mut working_set, None, b"^foo ...[a b c]", true); + assert!( + working_set.parse_errors.is_empty(), + "errors: {:?}", + working_set.parse_errors + ); + + let pipeline = &block.pipelines[0]; + assert_eq!(1, pipeline.len()); + let element = &pipeline.elements[0]; + match &element.expr.expr { + Expr::ExternalCall(name, args) => { + match &name.expr { + Expr::String(string) => { + assert_eq!("foo", string, "incorrect name"); + } + other => { + panic!("Unexpected expression in command name position: {other:?}"); + } + } + assert_eq!(1, args.len()); + match &args[0] { + ExternalArgument::Spread(expr) => match &expr.expr { + Expr::List(items) => { + assert_eq!(3, items.len()); + // that's good enough, don't really need to go so deep into it... + } + other => { + panic!("Unexpected expression in command arg position: {other:?}") + } + }, + other @ ExternalArgument::Regular(..) => { + panic!( + "Unexpected external regular argument in command arg position: {other:?}" + ) + } + } + } + other => { + panic!("Unexpected expression in pipeline: {other:?}"); + } + } +} + #[test] fn test_nothing_comparison_eq() { let engine_state = EngineState::new(); From be8c1dc0066cd1034a6b110a622f47b516bfe029 Mon Sep 17 00:00:00 2001 From: Devyn Cairns Date: Mon, 3 Jun 2024 00:38:55 -0700 Subject: [PATCH 039/113] Fix `run_external::expand_glob()` to return paths that are PWD-relative but reflect the original intent (#13028) # Description Fix #13021 This changes the `expand_glob()` function to use `nu_engine::glob_from()` so that absolute paths are actually preserved, rather than being made relative to the provided parent. This preserves the intent of whoever wrote the original path/glob, and also makes it so that tilde always produces absolute paths. I also made `expand_glob()` handle Ctrl-C so that it can be interrupted. cc @YizhePKU # Tests + Formatting No additional tests here... but that might be a good idea. --- crates/nu-command/src/system/run_external.rs | 143 +++++++++++++------ 1 file changed, 99 insertions(+), 44 deletions(-) diff --git a/crates/nu-command/src/system/run_external.rs b/crates/nu-command/src/system/run_external.rs index a200ce75de..d4645e87e8 100644 --- a/crates/nu-command/src/system/run_external.rs +++ b/crates/nu-command/src/system/run_external.rs @@ -4,7 +4,7 @@ use nu_protocol::{ ast::{Expr, Expression}, did_you_mean, process::ChildProcess, - ByteStream, OutDest, + ByteStream, NuGlob, OutDest, }; use nu_system::ForegroundChild; use nu_utils::IgnoreCaseExt; @@ -13,7 +13,7 @@ use std::{ io::Write, path::{Path, PathBuf}, process::Stdio, - sync::Arc, + sync::{atomic::AtomicBool, Arc}, thread, }; @@ -155,6 +155,9 @@ impl Command for External { } }; + // Log the command we're about to run in case it's useful for debugging purposes. + log::trace!("run-external spawning: {command:?}"); + // Spawn the child process. On Unix, also put the child process to // foreground if we're in an interactive session. #[cfg(windows)] @@ -232,6 +235,7 @@ pub fn eval_arguments_from_call( stack: &mut Stack, call: &Call, ) -> Result>, ShellError> { + let ctrlc = &engine_state.ctrlc; let cwd = engine_state.cwd(Some(stack))?; let mut args: Vec> = vec![]; for (expr, spread) in call.rest_iter(1) { @@ -240,7 +244,7 @@ pub fn eval_arguments_from_call( // glob-expansion, and inner-quotes-removal, in that order. for arg in eval_argument(engine_state, stack, expr, spread)? { let tilde_expanded = expand_tilde(&arg); - for glob_expanded in expand_glob(&tilde_expanded, &cwd, expr.span)? { + for glob_expanded in expand_glob(&tilde_expanded, &cwd, expr.span, ctrlc)? { let inner_quotes_removed = remove_inner_quotes(&glob_expanded); args.push(inner_quotes_removed.into_owned().into_spanned(expr.span)); } @@ -321,37 +325,75 @@ fn expand_tilde(arg: &str) -> String { /// /// Note: This matches the default behavior of Bash, but is known to be /// error-prone. We might want to change this behavior in the future. -fn expand_glob(arg: &str, cwd: &Path, span: Span) -> Result, ShellError> { - let Ok(paths) = nu_glob::glob_with_parent(arg, nu_glob::MatchOptions::default(), cwd) else { +fn expand_glob( + arg: &str, + cwd: &Path, + span: Span, + interrupt: &Option>, +) -> Result, ShellError> { + const GLOB_CHARS: &[char] = &['*', '?', '[']; + + // Don't expand something that doesn't include the GLOB_CHARS + if !arg.contains(GLOB_CHARS) { + return Ok(vec![arg.into()]); + } + + // We must use `nu_engine::glob_from` here, in order to ensure we get paths from the correct + // dir + let glob = NuGlob::Expand(arg.to_owned()).into_spanned(span); + let Ok((_prefix, paths)) = nu_engine::glob_from(&glob, cwd, span, None) else { + // If an error occurred, return the original input return Ok(vec![arg.into()]); }; - let mut result = vec![]; - for path in paths { - let path = path.map_err(|err| ShellError::IOErrorSpanned { - msg: format!("{}: {:?}", err.path().display(), err.error()), - span, - })?; - // Strip PWD from the resulting paths if possible. - let path_stripped = if let Ok(remainder) = path.strip_prefix(cwd) { - // If stripping PWD results in an empty path, return `.` instead. - if remainder.components().next().is_none() { - Path::new(".") - } else { - remainder + // If the first component of the original `arg` string path was '.', that should be preserved + let relative_to_dot = Path::new(arg).starts_with("."); + + let paths = paths + // Skip over glob failures. These are usually just inaccessible paths. + .flat_map(|path_result| match path_result { + Ok(path) => Some(path), + Err(err) => { + // But internally log them just in case we need to debug this. + log::warn!("Error in run_external::expand_glob(): {}", err); + None } - } else { - &path - }; - let path_string = path_stripped.to_string_lossy().to_string(); - result.push(path_string); - } + }) + // Make the paths relative to the cwd + .map(|path| { + path.strip_prefix(cwd) + .map(|path| path.to_owned()) + .unwrap_or(path) + }) + // Add './' to relative paths if the original pattern had it + .map(|path| { + if relative_to_dot && path.is_relative() { + Path::new(".").join(path) + } else { + path + } + }) + // Convert the paths returned to UTF-8 strings. + // + // FIXME: this fails to return the correct results for non-UTF-8 paths, but we don't support + // those in Nushell yet. + .map(|path| path.to_string_lossy().into_owned()) + // Abandon if ctrl-c is pressed + .map(|path| { + if !nu_utils::ctrl_c::was_pressed(interrupt) { + Ok(path) + } else { + Err(ShellError::InterruptedByUser { span: Some(span) }) + } + }) + .collect::, ShellError>>()?; - if result.is_empty() { - result.push(arg.to_string()); + if !paths.is_empty() { + Ok(paths) + } else { + // If we failed to match, return the original input + Ok(vec![arg.into()]) } - - Ok(result) } /// Transforms `--option="value"` into `--option=value`. `value` can be quoted @@ -607,6 +649,7 @@ fn escape_cmd_argument(arg: &Spanned) -> Result, ShellError mod test { use super::*; use nu_protocol::ast::ListItem; + use nu_test_support::{fs::Stub, playground::Playground}; #[test] fn test_remove_quotes() { @@ -669,26 +712,38 @@ mod test { #[test] fn test_expand_glob() { - let tempdir = tempfile::tempdir().unwrap(); - let cwd = tempdir.path(); - std::fs::File::create(cwd.join("a.txt")).unwrap(); - std::fs::File::create(cwd.join("b.txt")).unwrap(); + Playground::setup("test_expand_glob", |dirs, play| { + play.with_files(&[Stub::EmptyFile("a.txt"), Stub::EmptyFile("b.txt")]); - let actual = expand_glob("*.txt", cwd, Span::unknown()).unwrap(); - let expected = &["a.txt", "b.txt"]; - assert_eq!(actual, expected); + let cwd = dirs.test(); - let actual = expand_glob("'*.txt'", cwd, Span::unknown()).unwrap(); - let expected = &["'*.txt'"]; - assert_eq!(actual, expected); + let actual = expand_glob("*.txt", cwd, Span::unknown(), &None).unwrap(); + let expected = &["a.txt", "b.txt"]; + assert_eq!(actual, expected); - let actual = expand_glob(cwd.to_str().unwrap(), cwd, Span::unknown()).unwrap(); - let expected = &["."]; - assert_eq!(actual, expected); + let actual = expand_glob("./*.txt", cwd, Span::unknown(), &None).unwrap(); + let expected = vec![ + Path::new(".").join("a.txt").to_string_lossy().into_owned(), + Path::new(".").join("b.txt").to_string_lossy().into_owned(), + ]; + assert_eq!(actual, expected); - let actual = expand_glob("[*.txt", cwd, Span::unknown()).unwrap(); - let expected = &["[*.txt"]; - assert_eq!(actual, expected); + let actual = expand_glob("'*.txt'", cwd, Span::unknown(), &None).unwrap(); + let expected = &["'*.txt'"]; + assert_eq!(actual, expected); + + let actual = expand_glob(".", cwd, Span::unknown(), &None).unwrap(); + let expected = &["."]; + assert_eq!(actual, expected); + + let actual = expand_glob("./a.txt", cwd, Span::unknown(), &None).unwrap(); + let expected = &["./a.txt"]; + assert_eq!(actual, expected); + + let actual = expand_glob("[*.txt", cwd, Span::unknown(), &None).unwrap(); + let expected = &["[*.txt"]; + assert_eq!(actual, expected); + }) } #[test] From ad5a6cdc00a390ce67238f6d7a7f9552f34a1c98 Mon Sep 17 00:00:00 2001 From: Wind Date: Wed, 5 Jun 2024 06:52:40 +0800 Subject: [PATCH 040/113] bump version to 0.94.3 (#13055) --- Cargo.lock | 72 +++++++++---------- Cargo.toml | 42 +++++------ crates/nu-cli/Cargo.toml | 26 +++---- crates/nu-cmd-base/Cargo.toml | 12 ++-- crates/nu-cmd-extra/Cargo.toml | 22 +++--- crates/nu-cmd-lang/Cargo.toml | 12 ++-- crates/nu-cmd-plugin/Cargo.toml | 12 ++-- crates/nu-color-config/Cargo.toml | 10 +-- crates/nu-command/Cargo.toml | 36 +++++----- crates/nu-engine/Cargo.toml | 12 ++-- crates/nu-explore/Cargo.toml | 20 +++--- crates/nu-glob/Cargo.toml | 4 +- crates/nu-json/Cargo.toml | 6 +- crates/nu-lsp/Cargo.toml | 16 ++--- crates/nu-parser/Cargo.toml | 12 ++-- crates/nu-path/Cargo.toml | 4 +- crates/nu-plugin-core/Cargo.toml | 8 +-- crates/nu-plugin-engine/Cargo.toml | 14 ++-- crates/nu-plugin-protocol/Cargo.toml | 8 +-- crates/nu-plugin-test-support/Cargo.toml | 20 +++--- crates/nu-plugin/Cargo.toml | 12 ++-- crates/nu-pretty-hex/Cargo.toml | 4 +- crates/nu-protocol/Cargo.toml | 12 ++-- crates/nu-std/Cargo.toml | 10 +-- crates/nu-system/Cargo.toml | 4 +- crates/nu-table/Cargo.toml | 12 ++-- crates/nu-term-grid/Cargo.toml | 6 +- crates/nu-test-support/Cargo.toml | 10 +-- crates/nu-utils/Cargo.toml | 4 +- .../src/sample_config/default_config.nu | 4 +- .../nu-utils/src/sample_config/default_env.nu | 4 +- crates/nu_plugin_custom_values/Cargo.toml | 6 +- crates/nu_plugin_example/Cargo.toml | 10 +-- crates/nu_plugin_formats/Cargo.toml | 8 +-- crates/nu_plugin_gstat/Cargo.toml | 8 +-- crates/nu_plugin_inc/Cargo.toml | 8 +-- .../nu_plugin_nu_example.nu | 4 +- crates/nu_plugin_polars/Cargo.toml | 20 +++--- .../nu_plugin_python_example.py | 9 +-- crates/nu_plugin_query/Cargo.toml | 8 +-- crates/nu_plugin_stress_internals/Cargo.toml | 4 +- crates/nuon/Cargo.toml | 10 +-- 42 files changed, 273 insertions(+), 272 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 23cafeefda..7c5596adba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2770,7 +2770,7 @@ dependencies = [ [[package]] name = "nu" -version = "0.94.2" +version = "0.94.3" dependencies = [ "assert_cmd", "crossterm", @@ -2823,7 +2823,7 @@ dependencies = [ [[package]] name = "nu-cli" -version = "0.94.2" +version = "0.94.3" dependencies = [ "chrono", "crossterm", @@ -2858,7 +2858,7 @@ dependencies = [ [[package]] name = "nu-cmd-base" -version = "0.94.2" +version = "0.94.3" dependencies = [ "indexmap", "miette", @@ -2870,7 +2870,7 @@ dependencies = [ [[package]] name = "nu-cmd-extra" -version = "0.94.2" +version = "0.94.3" dependencies = [ "fancy-regex", "heck 0.5.0", @@ -2895,7 +2895,7 @@ dependencies = [ [[package]] name = "nu-cmd-lang" -version = "0.94.2" +version = "0.94.3" dependencies = [ "itertools 0.12.1", "nu-engine", @@ -2907,7 +2907,7 @@ dependencies = [ [[package]] name = "nu-cmd-plugin" -version = "0.94.2" +version = "0.94.3" dependencies = [ "itertools 0.12.1", "nu-engine", @@ -2918,7 +2918,7 @@ dependencies = [ [[package]] name = "nu-color-config" -version = "0.94.2" +version = "0.94.3" dependencies = [ "nu-ansi-term", "nu-engine", @@ -2930,7 +2930,7 @@ dependencies = [ [[package]] name = "nu-command" -version = "0.94.2" +version = "0.94.3" dependencies = [ "alphanumeric-sort", "base64 0.22.1", @@ -3039,7 +3039,7 @@ dependencies = [ [[package]] name = "nu-engine" -version = "0.94.2" +version = "0.94.3" dependencies = [ "nu-glob", "nu-path", @@ -3049,7 +3049,7 @@ dependencies = [ [[package]] name = "nu-explore" -version = "0.94.2" +version = "0.94.3" dependencies = [ "ansi-str", "anyhow", @@ -3074,14 +3074,14 @@ dependencies = [ [[package]] name = "nu-glob" -version = "0.94.2" +version = "0.94.3" dependencies = [ "doc-comment", ] [[package]] name = "nu-json" -version = "0.94.2" +version = "0.94.3" dependencies = [ "linked-hash-map", "num-traits", @@ -3091,7 +3091,7 @@ dependencies = [ [[package]] name = "nu-lsp" -version = "0.94.2" +version = "0.94.3" dependencies = [ "assert-json-diff", "crossbeam-channel", @@ -3112,7 +3112,7 @@ dependencies = [ [[package]] name = "nu-parser" -version = "0.94.2" +version = "0.94.3" dependencies = [ "bytesize", "chrono", @@ -3128,7 +3128,7 @@ dependencies = [ [[package]] name = "nu-path" -version = "0.94.2" +version = "0.94.3" dependencies = [ "dirs-next", "omnipath", @@ -3137,7 +3137,7 @@ dependencies = [ [[package]] name = "nu-plugin" -version = "0.94.2" +version = "0.94.3" dependencies = [ "log", "nix", @@ -3152,7 +3152,7 @@ dependencies = [ [[package]] name = "nu-plugin-core" -version = "0.94.2" +version = "0.94.3" dependencies = [ "interprocess", "log", @@ -3166,7 +3166,7 @@ dependencies = [ [[package]] name = "nu-plugin-engine" -version = "0.94.2" +version = "0.94.3" dependencies = [ "log", "nu-engine", @@ -3181,7 +3181,7 @@ dependencies = [ [[package]] name = "nu-plugin-protocol" -version = "0.94.2" +version = "0.94.3" dependencies = [ "bincode", "nu-protocol", @@ -3193,7 +3193,7 @@ dependencies = [ [[package]] name = "nu-plugin-test-support" -version = "0.94.2" +version = "0.94.3" dependencies = [ "nu-ansi-term", "nu-cmd-lang", @@ -3211,7 +3211,7 @@ dependencies = [ [[package]] name = "nu-pretty-hex" -version = "0.94.2" +version = "0.94.3" dependencies = [ "heapless", "nu-ansi-term", @@ -3220,7 +3220,7 @@ dependencies = [ [[package]] name = "nu-protocol" -version = "0.94.2" +version = "0.94.3" dependencies = [ "brotli 5.0.0", "byte-unit", @@ -3251,7 +3251,7 @@ dependencies = [ [[package]] name = "nu-std" -version = "0.94.2" +version = "0.94.3" dependencies = [ "log", "miette", @@ -3262,7 +3262,7 @@ dependencies = [ [[package]] name = "nu-system" -version = "0.94.2" +version = "0.94.3" dependencies = [ "chrono", "itertools 0.12.1", @@ -3280,7 +3280,7 @@ dependencies = [ [[package]] name = "nu-table" -version = "0.94.2" +version = "0.94.3" dependencies = [ "fancy-regex", "nu-ansi-term", @@ -3294,7 +3294,7 @@ dependencies = [ [[package]] name = "nu-term-grid" -version = "0.94.2" +version = "0.94.3" dependencies = [ "nu-utils", "unicode-width", @@ -3302,7 +3302,7 @@ dependencies = [ [[package]] name = "nu-test-support" -version = "0.94.2" +version = "0.94.3" dependencies = [ "nu-glob", "nu-path", @@ -3314,7 +3314,7 @@ dependencies = [ [[package]] name = "nu-utils" -version = "0.94.2" +version = "0.94.3" dependencies = [ "crossterm_winapi", "log", @@ -3340,7 +3340,7 @@ dependencies = [ [[package]] name = "nu_plugin_example" -version = "0.94.2" +version = "0.94.3" dependencies = [ "nu-cmd-lang", "nu-plugin", @@ -3350,7 +3350,7 @@ dependencies = [ [[package]] name = "nu_plugin_formats" -version = "0.94.2" +version = "0.94.3" dependencies = [ "eml-parser", "ical", @@ -3363,7 +3363,7 @@ dependencies = [ [[package]] name = "nu_plugin_gstat" -version = "0.94.2" +version = "0.94.3" dependencies = [ "git2", "nu-plugin", @@ -3372,7 +3372,7 @@ dependencies = [ [[package]] name = "nu_plugin_inc" -version = "0.94.2" +version = "0.94.3" dependencies = [ "nu-plugin", "nu-protocol", @@ -3381,7 +3381,7 @@ dependencies = [ [[package]] name = "nu_plugin_polars" -version = "0.94.2" +version = "0.94.3" dependencies = [ "chrono", "chrono-tz 0.9.0", @@ -3412,7 +3412,7 @@ dependencies = [ [[package]] name = "nu_plugin_query" -version = "0.94.2" +version = "0.94.3" dependencies = [ "gjson", "nu-plugin", @@ -3424,7 +3424,7 @@ dependencies = [ [[package]] name = "nu_plugin_stress_internals" -version = "0.94.2" +version = "0.94.3" dependencies = [ "interprocess", "serde", @@ -3550,7 +3550,7 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "nuon" -version = "0.94.2" +version = "0.94.3" dependencies = [ "chrono", "fancy-regex", diff --git a/Cargo.toml b/Cargo.toml index ce9157efb4..2d99b7b42e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ license = "MIT" name = "nu" repository = "https://github.com/nushell/nushell" rust-version = "1.77.2" -version = "0.94.2" +version = "0.94.3" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -174,22 +174,22 @@ windows = "0.54" winreg = "0.52" [dependencies] -nu-cli = { path = "./crates/nu-cli", version = "0.94.2" } -nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.94.2" } -nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.94.2" } -nu-cmd-plugin = { path = "./crates/nu-cmd-plugin", version = "0.94.2", optional = true } -nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.94.2" } -nu-command = { path = "./crates/nu-command", version = "0.94.2" } -nu-engine = { path = "./crates/nu-engine", version = "0.94.2" } -nu-explore = { path = "./crates/nu-explore", version = "0.94.2" } -nu-lsp = { path = "./crates/nu-lsp/", version = "0.94.2" } -nu-parser = { path = "./crates/nu-parser", version = "0.94.2" } -nu-path = { path = "./crates/nu-path", version = "0.94.2" } -nu-plugin-engine = { path = "./crates/nu-plugin-engine", optional = true, version = "0.94.2" } -nu-protocol = { path = "./crates/nu-protocol", version = "0.94.2" } -nu-std = { path = "./crates/nu-std", version = "0.94.2" } -nu-system = { path = "./crates/nu-system", version = "0.94.2" } -nu-utils = { path = "./crates/nu-utils", version = "0.94.2" } +nu-cli = { path = "./crates/nu-cli", version = "0.94.3" } +nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.94.3" } +nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.94.3" } +nu-cmd-plugin = { path = "./crates/nu-cmd-plugin", version = "0.94.3", optional = true } +nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.94.3" } +nu-command = { path = "./crates/nu-command", version = "0.94.3" } +nu-engine = { path = "./crates/nu-engine", version = "0.94.3" } +nu-explore = { path = "./crates/nu-explore", version = "0.94.3" } +nu-lsp = { path = "./crates/nu-lsp/", version = "0.94.3" } +nu-parser = { path = "./crates/nu-parser", version = "0.94.3" } +nu-path = { path = "./crates/nu-path", version = "0.94.3" } +nu-plugin-engine = { path = "./crates/nu-plugin-engine", optional = true, version = "0.94.3" } +nu-protocol = { path = "./crates/nu-protocol", version = "0.94.3" } +nu-std = { path = "./crates/nu-std", version = "0.94.3" } +nu-system = { path = "./crates/nu-system", version = "0.94.3" } +nu-utils = { path = "./crates/nu-utils", version = "0.94.3" } reedline = { workspace = true, features = ["bashisms", "sqlite"] } @@ -218,9 +218,9 @@ nix = { workspace = true, default-features = false, features = [ ] } [dev-dependencies] -nu-test-support = { path = "./crates/nu-test-support", version = "0.94.2" } -nu-plugin-protocol = { path = "./crates/nu-plugin-protocol", version = "0.94.2" } -nu-plugin-core = { path = "./crates/nu-plugin-core", version = "0.94.2" } +nu-test-support = { path = "./crates/nu-test-support", version = "0.94.3" } +nu-plugin-protocol = { path = "./crates/nu-plugin-protocol", version = "0.94.3" } +nu-plugin-core = { path = "./crates/nu-plugin-core", version = "0.94.3" } assert_cmd = "2.0" dirs-next = { workspace = true } tango-bench = "0.5" @@ -305,4 +305,4 @@ bench = false # Run individual benchmarks like `cargo bench -- ` e.g. `cargo bench -- parse` [[bench]] name = "benchmarks" -harness = false \ No newline at end of file +harness = false diff --git a/crates/nu-cli/Cargo.toml b/crates/nu-cli/Cargo.toml index 0d82fa4aae..c2ca2c9704 100644 --- a/crates/nu-cli/Cargo.toml +++ b/crates/nu-cli/Cargo.toml @@ -5,27 +5,27 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cli" edition = "2021" license = "MIT" name = "nu-cli" -version = "0.94.2" +version = "0.94.3" [lib] bench = false [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.2" } -nu-command = { path = "../nu-command", version = "0.94.2" } -nu-test-support = { path = "../nu-test-support", version = "0.94.2" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.3" } +nu-command = { path = "../nu-command", version = "0.94.3" } +nu-test-support = { path = "../nu-test-support", version = "0.94.3" } rstest = { workspace = true, default-features = false } tempfile = { workspace = true } [dependencies] -nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.2" } -nu-engine = { path = "../nu-engine", version = "0.94.2" } -nu-path = { path = "../nu-path", version = "0.94.2" } -nu-parser = { path = "../nu-parser", version = "0.94.2" } -nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.2", optional = true } -nu-protocol = { path = "../nu-protocol", version = "0.94.2" } -nu-utils = { path = "../nu-utils", version = "0.94.2" } -nu-color-config = { path = "../nu-color-config", version = "0.94.2" } +nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.3" } +nu-engine = { path = "../nu-engine", version = "0.94.3" } +nu-path = { path = "../nu-path", version = "0.94.3" } +nu-parser = { path = "../nu-parser", version = "0.94.3" } +nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.3", optional = true } +nu-protocol = { path = "../nu-protocol", version = "0.94.3" } +nu-utils = { path = "../nu-utils", version = "0.94.3" } +nu-color-config = { path = "../nu-color-config", version = "0.94.3" } nu-ansi-term = { workspace = true } reedline = { workspace = true, features = ["bashisms", "sqlite"] } @@ -46,4 +46,4 @@ which = { workspace = true } [features] plugin = ["nu-plugin-engine"] -system-clipboard = ["reedline/system_clipboard"] \ No newline at end of file +system-clipboard = ["reedline/system_clipboard"] diff --git a/crates/nu-cmd-base/Cargo.toml b/crates/nu-cmd-base/Cargo.toml index 858ff55e2d..fb6a977ab9 100644 --- a/crates/nu-cmd-base/Cargo.toml +++ b/crates/nu-cmd-base/Cargo.toml @@ -5,17 +5,17 @@ edition = "2021" license = "MIT" name = "nu-cmd-base" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-base" -version = "0.94.2" +version = "0.94.3" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.2" } -nu-parser = { path = "../nu-parser", version = "0.94.2" } -nu-path = { path = "../nu-path", version = "0.94.2" } -nu-protocol = { path = "../nu-protocol", version = "0.94.2" } +nu-engine = { path = "../nu-engine", version = "0.94.3" } +nu-parser = { path = "../nu-parser", version = "0.94.3" } +nu-path = { path = "../nu-path", version = "0.94.3" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3" } indexmap = { workspace = true } miette = { workspace = true } -[dev-dependencies] \ No newline at end of file +[dev-dependencies] diff --git a/crates/nu-cmd-extra/Cargo.toml b/crates/nu-cmd-extra/Cargo.toml index b03c7911ed..39a705f47c 100644 --- a/crates/nu-cmd-extra/Cargo.toml +++ b/crates/nu-cmd-extra/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "MIT" name = "nu-cmd-extra" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-extra" -version = "0.94.2" +version = "0.94.3" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -13,13 +13,13 @@ version = "0.94.2" bench = false [dependencies] -nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.2" } -nu-engine = { path = "../nu-engine", version = "0.94.2" } -nu-json = { version = "0.94.2", path = "../nu-json" } -nu-parser = { path = "../nu-parser", version = "0.94.2" } -nu-pretty-hex = { version = "0.94.2", path = "../nu-pretty-hex" } -nu-protocol = { path = "../nu-protocol", version = "0.94.2" } -nu-utils = { path = "../nu-utils", version = "0.94.2" } +nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.3" } +nu-engine = { path = "../nu-engine", version = "0.94.3" } +nu-json = { version = "0.94.3", path = "../nu-json" } +nu-parser = { path = "../nu-parser", version = "0.94.3" } +nu-pretty-hex = { version = "0.94.3", path = "../nu-pretty-hex" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3" } +nu-utils = { path = "../nu-utils", version = "0.94.3" } # Potential dependencies for extras heck = { workspace = true } @@ -37,6 +37,6 @@ extra = ["default"] default = [] [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.2" } -nu-command = { path = "../nu-command", version = "0.94.2" } -nu-test-support = { path = "../nu-test-support", version = "0.94.2" } \ No newline at end of file +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.3" } +nu-command = { path = "../nu-command", version = "0.94.3" } +nu-test-support = { path = "../nu-test-support", version = "0.94.3" } diff --git a/crates/nu-cmd-lang/Cargo.toml b/crates/nu-cmd-lang/Cargo.toml index ad94c331d8..22e1cad374 100644 --- a/crates/nu-cmd-lang/Cargo.toml +++ b/crates/nu-cmd-lang/Cargo.toml @@ -6,16 +6,16 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-lang" edition = "2021" license = "MIT" name = "nu-cmd-lang" -version = "0.94.2" +version = "0.94.3" [lib] bench = false [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.2" } -nu-parser = { path = "../nu-parser", version = "0.94.2" } -nu-protocol = { path = "../nu-protocol", version = "0.94.2" } -nu-utils = { path = "../nu-utils", version = "0.94.2" } +nu-engine = { path = "../nu-engine", version = "0.94.3" } +nu-parser = { path = "../nu-parser", version = "0.94.3" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3" } +nu-utils = { path = "../nu-utils", version = "0.94.3" } itertools = { workspace = true } shadow-rs = { version = "0.28", default-features = false } @@ -29,4 +29,4 @@ which-support = [] trash-support = [] sqlite = [] static-link-openssl = [] -system-clipboard = [] \ No newline at end of file +system-clipboard = [] diff --git a/crates/nu-cmd-plugin/Cargo.toml b/crates/nu-cmd-plugin/Cargo.toml index 62ed6851b5..d274f46a6a 100644 --- a/crates/nu-cmd-plugin/Cargo.toml +++ b/crates/nu-cmd-plugin/Cargo.toml @@ -5,16 +5,16 @@ edition = "2021" license = "MIT" name = "nu-cmd-plugin" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-plugin" -version = "0.94.2" +version = "0.94.3" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.2" } -nu-path = { path = "../nu-path", version = "0.94.2" } -nu-protocol = { path = "../nu-protocol", version = "0.94.2", features = ["plugin"] } -nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.2" } +nu-engine = { path = "../nu-engine", version = "0.94.3" } +nu-path = { path = "../nu-path", version = "0.94.3" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3", features = ["plugin"] } +nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.3" } itertools = { workspace = true } -[dev-dependencies] \ No newline at end of file +[dev-dependencies] diff --git a/crates/nu-color-config/Cargo.toml b/crates/nu-color-config/Cargo.toml index 6268acf6f6..95b06c1f77 100644 --- a/crates/nu-color-config/Cargo.toml +++ b/crates/nu-color-config/Cargo.toml @@ -5,18 +5,18 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-color-confi edition = "2021" license = "MIT" name = "nu-color-config" -version = "0.94.2" +version = "0.94.3" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.94.2" } -nu-engine = { path = "../nu-engine", version = "0.94.2" } -nu-json = { path = "../nu-json", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3" } +nu-engine = { path = "../nu-engine", version = "0.94.3" } +nu-json = { path = "../nu-json", version = "0.94.3" } nu-ansi-term = { workspace = true } serde = { workspace = true, features = ["derive"] } [dev-dependencies] -nu-test-support = { path = "../nu-test-support", version = "0.94.2" } \ No newline at end of file +nu-test-support = { path = "../nu-test-support", version = "0.94.3" } diff --git a/crates/nu-command/Cargo.toml b/crates/nu-command/Cargo.toml index 1a88a24e5e..c6f71c8d25 100644 --- a/crates/nu-command/Cargo.toml +++ b/crates/nu-command/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "MIT" name = "nu-command" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-command" -version = "0.94.2" +version = "0.94.3" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -13,21 +13,21 @@ version = "0.94.2" bench = false [dependencies] -nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.2" } -nu-color-config = { path = "../nu-color-config", version = "0.94.2" } -nu-engine = { path = "../nu-engine", version = "0.94.2" } -nu-glob = { path = "../nu-glob", version = "0.94.2" } -nu-json = { path = "../nu-json", version = "0.94.2" } -nu-parser = { path = "../nu-parser", version = "0.94.2" } -nu-path = { path = "../nu-path", version = "0.94.2" } -nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.94.2" } -nu-protocol = { path = "../nu-protocol", version = "0.94.2" } -nu-system = { path = "../nu-system", version = "0.94.2" } -nu-table = { path = "../nu-table", version = "0.94.2" } -nu-term-grid = { path = "../nu-term-grid", version = "0.94.2" } -nu-utils = { path = "../nu-utils", version = "0.94.2" } +nu-cmd-base = { path = "../nu-cmd-base", version = "0.94.3" } +nu-color-config = { path = "../nu-color-config", version = "0.94.3" } +nu-engine = { path = "../nu-engine", version = "0.94.3" } +nu-glob = { path = "../nu-glob", version = "0.94.3" } +nu-json = { path = "../nu-json", version = "0.94.3" } +nu-parser = { path = "../nu-parser", version = "0.94.3" } +nu-path = { path = "../nu-path", version = "0.94.3" } +nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.94.3" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3" } +nu-system = { path = "../nu-system", version = "0.94.3" } +nu-table = { path = "../nu-table", version = "0.94.3" } +nu-term-grid = { path = "../nu-term-grid", version = "0.94.3" } +nu-utils = { path = "../nu-utils", version = "0.94.3" } nu-ansi-term = { workspace = true } -nuon = { path = "../nuon", version = "0.94.2" } +nuon = { path = "../nuon", version = "0.94.3" } alphanumeric-sort = { workspace = true } base64 = { workspace = true } @@ -137,8 +137,8 @@ trash-support = ["trash"] which-support = [] [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.2" } -nu-test-support = { path = "../nu-test-support", version = "0.94.2" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.3" } +nu-test-support = { path = "../nu-test-support", version = "0.94.3" } dirs-next = { workspace = true } mockito = { workspace = true, default-features = false } @@ -146,4 +146,4 @@ quickcheck = { workspace = true } quickcheck_macros = { workspace = true } rstest = { workspace = true, default-features = false } pretty_assertions = { workspace = true } -tempfile = { workspace = true } \ No newline at end of file +tempfile = { workspace = true } diff --git a/crates/nu-engine/Cargo.toml b/crates/nu-engine/Cargo.toml index d8a90fb70e..fae2b3eff4 100644 --- a/crates/nu-engine/Cargo.toml +++ b/crates/nu-engine/Cargo.toml @@ -5,16 +5,16 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-engine" edition = "2021" license = "MIT" name = "nu-engine" -version = "0.94.2" +version = "0.94.3" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", features = ["plugin"], version = "0.94.2" } -nu-path = { path = "../nu-path", version = "0.94.2" } -nu-glob = { path = "../nu-glob", version = "0.94.2" } -nu-utils = { path = "../nu-utils", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", features = ["plugin"], version = "0.94.3" } +nu-path = { path = "../nu-path", version = "0.94.3" } +nu-glob = { path = "../nu-glob", version = "0.94.3" } +nu-utils = { path = "../nu-utils", version = "0.94.3" } [features] -plugin = [] \ No newline at end of file +plugin = [] diff --git a/crates/nu-explore/Cargo.toml b/crates/nu-explore/Cargo.toml index 0837d9d683..dc17e6087d 100644 --- a/crates/nu-explore/Cargo.toml +++ b/crates/nu-explore/Cargo.toml @@ -5,21 +5,21 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-explore" edition = "2021" license = "MIT" name = "nu-explore" -version = "0.94.2" +version = "0.94.3" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.94.2" } -nu-parser = { path = "../nu-parser", version = "0.94.2" } -nu-color-config = { path = "../nu-color-config", version = "0.94.2" } -nu-engine = { path = "../nu-engine", version = "0.94.2" } -nu-table = { path = "../nu-table", version = "0.94.2" } -nu-json = { path = "../nu-json", version = "0.94.2" } -nu-utils = { path = "../nu-utils", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3" } +nu-parser = { path = "../nu-parser", version = "0.94.3" } +nu-color-config = { path = "../nu-color-config", version = "0.94.3" } +nu-engine = { path = "../nu-engine", version = "0.94.3" } +nu-table = { path = "../nu-table", version = "0.94.3" } +nu-json = { path = "../nu-json", version = "0.94.3" } +nu-utils = { path = "../nu-utils", version = "0.94.3" } nu-ansi-term = { workspace = true } -nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.94.2" } +nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.94.3" } anyhow = { workspace = true } log = { workspace = true } @@ -32,4 +32,4 @@ ansi-str = { workspace = true } unicode-width = { workspace = true } lscolors = { workspace = true, default-features = false, features = [ "nu-ansi-term", -] } \ No newline at end of file +] } diff --git a/crates/nu-glob/Cargo.toml b/crates/nu-glob/Cargo.toml index d7568f7b2d..3e0dbfbd12 100644 --- a/crates/nu-glob/Cargo.toml +++ b/crates/nu-glob/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nu-glob" -version = "0.94.2" +version = "0.94.3" authors = ["The Nushell Project Developers", "The Rust Project Developers"] license = "MIT/Apache-2.0" description = """ @@ -14,4 +14,4 @@ categories = ["filesystem"] bench = false [dev-dependencies] -doc-comment = "0.3" \ No newline at end of file +doc-comment = "0.3" diff --git a/crates/nu-json/Cargo.toml b/crates/nu-json/Cargo.toml index 63a80f4b91..9d348d00d4 100644 --- a/crates/nu-json/Cargo.toml +++ b/crates/nu-json/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-json" edition = "2021" license = "MIT" name = "nu-json" -version = "0.94.2" +version = "0.94.3" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -23,5 +23,5 @@ serde = { workspace = true } serde_json = { workspace = true } [dev-dependencies] -# nu-path = { path="../nu-path", version = "0.94.2" } -# serde_json = "1.0" \ No newline at end of file +# nu-path = { path="../nu-path", version = "0.94.3" } +# serde_json = "1.0" diff --git a/crates/nu-lsp/Cargo.toml b/crates/nu-lsp/Cargo.toml index 0732862bff..c4e495f040 100644 --- a/crates/nu-lsp/Cargo.toml +++ b/crates/nu-lsp/Cargo.toml @@ -3,14 +3,14 @@ authors = ["The Nushell Project Developers"] description = "Nushell's integrated LSP server" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-lsp" name = "nu-lsp" -version = "0.94.2" +version = "0.94.3" edition = "2021" license = "MIT" [dependencies] -nu-cli = { path = "../nu-cli", version = "0.94.2" } -nu-parser = { path = "../nu-parser", version = "0.94.2" } -nu-protocol = { path = "../nu-protocol", version = "0.94.2" } +nu-cli = { path = "../nu-cli", version = "0.94.3" } +nu-parser = { path = "../nu-parser", version = "0.94.3" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3" } reedline = { workspace = true } @@ -23,8 +23,8 @@ serde = { workspace = true } serde_json = { workspace = true } [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.2" } -nu-command = { path = "../nu-command", version = "0.94.2" } -nu-test-support = { path = "../nu-test-support", version = "0.94.2" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.3" } +nu-command = { path = "../nu-command", version = "0.94.3" } +nu-test-support = { path = "../nu-test-support", version = "0.94.3" } -assert-json-diff = "2.0" \ No newline at end of file +assert-json-diff = "2.0" diff --git a/crates/nu-parser/Cargo.toml b/crates/nu-parser/Cargo.toml index fa840fc483..742009424a 100644 --- a/crates/nu-parser/Cargo.toml +++ b/crates/nu-parser/Cargo.toml @@ -5,17 +5,17 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-parser" edition = "2021" license = "MIT" name = "nu-parser" -version = "0.94.2" +version = "0.94.3" exclude = ["/fuzz"] [lib] bench = false [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.2" } -nu-path = { path = "../nu-path", version = "0.94.2" } -nu-plugin-engine = { path = "../nu-plugin-engine", optional = true, version = "0.94.2" } -nu-protocol = { path = "../nu-protocol", version = "0.94.2" } +nu-engine = { path = "../nu-engine", version = "0.94.3" } +nu-path = { path = "../nu-path", version = "0.94.3" } +nu-plugin-engine = { path = "../nu-plugin-engine", optional = true, version = "0.94.3" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3" } bytesize = { workspace = true } chrono = { default-features = false, features = ['std'], workspace = true } @@ -27,4 +27,4 @@ serde_json = { workspace = true } rstest = { workspace = true, default-features = false } [features] -plugin = ["nu-plugin-engine"] \ No newline at end of file +plugin = ["nu-plugin-engine"] diff --git a/crates/nu-path/Cargo.toml b/crates/nu-path/Cargo.toml index bdd0157e4f..e3c84acdb3 100644 --- a/crates/nu-path/Cargo.toml +++ b/crates/nu-path/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-path" edition = "2021" license = "MIT" name = "nu-path" -version = "0.94.2" +version = "0.94.3" exclude = ["/fuzz"] [lib] @@ -18,4 +18,4 @@ dirs-next = { workspace = true } omnipath = { workspace = true } [target.'cfg(all(unix, not(target_os = "macos"), not(target_os = "android")))'.dependencies] -pwd = { workspace = true } \ No newline at end of file +pwd = { workspace = true } diff --git a/crates/nu-plugin-core/Cargo.toml b/crates/nu-plugin-core/Cargo.toml index 580e0287e2..965b09d085 100644 --- a/crates/nu-plugin-core/Cargo.toml +++ b/crates/nu-plugin-core/Cargo.toml @@ -5,14 +5,14 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-plugin-core edition = "2021" license = "MIT" name = "nu-plugin-core" -version = "0.94.2" +version = "0.94.3" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.94.2" } -nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.2", default-features = false } +nu-protocol = { path = "../nu-protocol", version = "0.94.3" } +nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.3", default-features = false } rmp-serde = { workspace = true } serde = { workspace = true } @@ -25,4 +25,4 @@ default = ["local-socket"] local-socket = ["interprocess", "nu-plugin-protocol/local-socket"] [target.'cfg(target_os = "windows")'.dependencies] -windows = { workspace = true } \ No newline at end of file +windows = { workspace = true } diff --git a/crates/nu-plugin-engine/Cargo.toml b/crates/nu-plugin-engine/Cargo.toml index 50fe40ab0a..95c0298c09 100644 --- a/crates/nu-plugin-engine/Cargo.toml +++ b/crates/nu-plugin-engine/Cargo.toml @@ -5,17 +5,17 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-plugin-engi edition = "2021" license = "MIT" name = "nu-plugin-engine" -version = "0.94.2" +version = "0.94.3" [lib] bench = false [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.2" } -nu-protocol = { path = "../nu-protocol", version = "0.94.2" } -nu-system = { path = "../nu-system", version = "0.94.2" } -nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.2" } -nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.2", default-features = false } +nu-engine = { path = "../nu-engine", version = "0.94.3" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3" } +nu-system = { path = "../nu-system", version = "0.94.3" } +nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.3" } +nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.3", default-features = false } serde = { workspace = true } log = { workspace = true } @@ -31,4 +31,4 @@ local-socket = ["nu-plugin-core/local-socket"] windows = { workspace = true, features = [ # For setting process creation flags "Win32_System_Threading", -] } \ No newline at end of file +] } diff --git a/crates/nu-plugin-protocol/Cargo.toml b/crates/nu-plugin-protocol/Cargo.toml index b52655a4f1..41c8a7c535 100644 --- a/crates/nu-plugin-protocol/Cargo.toml +++ b/crates/nu-plugin-protocol/Cargo.toml @@ -5,14 +5,14 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-plugin-prot edition = "2021" license = "MIT" name = "nu-plugin-protocol" -version = "0.94.2" +version = "0.94.3" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.94.2", features = ["plugin"] } -nu-utils = { path = "../nu-utils", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3", features = ["plugin"] } +nu-utils = { path = "../nu-utils", version = "0.94.3" } bincode = "1.3" serde = { workspace = true, features = ["derive"] } @@ -21,4 +21,4 @@ typetag = "0.2" [features] default = ["local-socket"] -local-socket = [] \ No newline at end of file +local-socket = [] diff --git a/crates/nu-plugin-test-support/Cargo.toml b/crates/nu-plugin-test-support/Cargo.toml index b5ef1e4c02..bc390d3994 100644 --- a/crates/nu-plugin-test-support/Cargo.toml +++ b/crates/nu-plugin-test-support/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nu-plugin-test-support" -version = "0.94.2" +version = "0.94.3" edition = "2021" license = "MIT" description = "Testing support for Nushell plugins" @@ -12,17 +12,17 @@ bench = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.2", features = ["plugin"] } -nu-protocol = { path = "../nu-protocol", version = "0.94.2", features = ["plugin"] } -nu-parser = { path = "../nu-parser", version = "0.94.2", features = ["plugin"] } -nu-plugin = { path = "../nu-plugin", version = "0.94.2" } -nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.2" } -nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.2" } -nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.2" } -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.2" } +nu-engine = { path = "../nu-engine", version = "0.94.3", features = ["plugin"] } +nu-protocol = { path = "../nu-protocol", version = "0.94.3", features = ["plugin"] } +nu-parser = { path = "../nu-parser", version = "0.94.3", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.3" } +nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.3" } +nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.94.3" } +nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.3" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.3" } nu-ansi-term = { workspace = true } similar = "2.5" [dev-dependencies] typetag = "0.2" -serde = "1.0" \ No newline at end of file +serde = "1.0" diff --git a/crates/nu-plugin/Cargo.toml b/crates/nu-plugin/Cargo.toml index 0a9a169474..68b3a7cadd 100644 --- a/crates/nu-plugin/Cargo.toml +++ b/crates/nu-plugin/Cargo.toml @@ -5,16 +5,16 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-plugin" edition = "2021" license = "MIT" name = "nu-plugin" -version = "0.94.2" +version = "0.94.3" [lib] bench = false [dependencies] -nu-engine = { path = "../nu-engine", version = "0.94.2" } -nu-protocol = { path = "../nu-protocol", version = "0.94.2" } -nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.2" } -nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.2", default-features = false } +nu-engine = { path = "../nu-engine", version = "0.94.3" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3" } +nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.94.3" } +nu-plugin-core = { path = "../nu-plugin-core", version = "0.94.3", default-features = false } log = { workspace = true } thiserror = "1.0" @@ -29,4 +29,4 @@ local-socket = ["nu-plugin-core/local-socket"] [target.'cfg(target_family = "unix")'.dependencies] # For setting the process group ID (EnterForeground / LeaveForeground) -nix = { workspace = true, default-features = false, features = ["process"] } \ No newline at end of file +nix = { workspace = true, default-features = false, features = ["process"] } diff --git a/crates/nu-pretty-hex/Cargo.toml b/crates/nu-pretty-hex/Cargo.toml index 152d03df72..ae5be298aa 100644 --- a/crates/nu-pretty-hex/Cargo.toml +++ b/crates/nu-pretty-hex/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-pretty-hex" edition = "2021" license = "MIT" name = "nu-pretty-hex" -version = "0.94.2" +version = "0.94.3" [lib] doctest = false @@ -18,4 +18,4 @@ nu-ansi-term = { workspace = true } [dev-dependencies] heapless = { version = "0.8", default-features = false } -rand = "0.8" \ No newline at end of file +rand = "0.8" diff --git a/crates/nu-protocol/Cargo.toml b/crates/nu-protocol/Cargo.toml index 2ccd0a07ce..de73ba1a2c 100644 --- a/crates/nu-protocol/Cargo.toml +++ b/crates/nu-protocol/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-protocol" edition = "2021" license = "MIT" name = "nu-protocol" -version = "0.94.2" +version = "0.94.3" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -13,9 +13,9 @@ version = "0.94.2" bench = false [dependencies] -nu-utils = { path = "../nu-utils", version = "0.94.2" } -nu-path = { path = "../nu-path", version = "0.94.2" } -nu-system = { path = "../nu-system", version = "0.94.2" } +nu-utils = { path = "../nu-utils", version = "0.94.3" } +nu-path = { path = "../nu-path", version = "0.94.3" } +nu-system = { path = "../nu-system", version = "0.94.3" } brotli = { workspace = true, optional = true } byte-unit = { version = "5.1", features = [ "serde" ] } @@ -45,11 +45,11 @@ plugin = [ serde_json = { workspace = true } strum = "0.26" strum_macros = "0.26" -nu-test-support = { path = "../nu-test-support", version = "0.94.2" } +nu-test-support = { path = "../nu-test-support", version = "0.94.3" } pretty_assertions = { workspace = true } rstest = { workspace = true } tempfile = { workspace = true } os_pipe = { workspace = true } [package.metadata.docs.rs] -all-features = true \ No newline at end of file +all-features = true diff --git a/crates/nu-std/Cargo.toml b/crates/nu-std/Cargo.toml index 4e5850c3fb..660d418097 100644 --- a/crates/nu-std/Cargo.toml +++ b/crates/nu-std/Cargo.toml @@ -5,12 +5,12 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-std" edition = "2021" license = "MIT" name = "nu-std" -version = "0.94.2" +version = "0.94.3" [dependencies] -nu-parser = { version = "0.94.2", path = "../nu-parser" } -nu-protocol = { version = "0.94.2", path = "../nu-protocol" } -nu-engine = { version = "0.94.2", path = "../nu-engine" } +nu-parser = { version = "0.94.3", path = "../nu-parser" } +nu-protocol = { version = "0.94.3", path = "../nu-protocol" } +nu-engine = { version = "0.94.3", path = "../nu-engine" } miette = { workspace = true, features = ["fancy-no-backtrace"] } -log = "0.4" \ No newline at end of file +log = "0.4" diff --git a/crates/nu-system/Cargo.toml b/crates/nu-system/Cargo.toml index 17e621db90..3e888dba49 100644 --- a/crates/nu-system/Cargo.toml +++ b/crates/nu-system/Cargo.toml @@ -3,7 +3,7 @@ authors = ["The Nushell Project Developers", "procs creators"] description = "Nushell system querying" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-system" name = "nu-system" -version = "0.94.2" +version = "0.94.3" edition = "2021" license = "MIT" @@ -45,4 +45,4 @@ windows = { workspace = true, features = [ "Win32_System_SystemInformation", "Win32_System_Threading", "Win32_UI_Shell", -]} \ No newline at end of file +]} diff --git a/crates/nu-table/Cargo.toml b/crates/nu-table/Cargo.toml index fe1de742d9..af7cf19f36 100644 --- a/crates/nu-table/Cargo.toml +++ b/crates/nu-table/Cargo.toml @@ -5,20 +5,20 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-table" edition = "2021" license = "MIT" name = "nu-table" -version = "0.94.2" +version = "0.94.3" [lib] bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.94.2" } -nu-utils = { path = "../nu-utils", version = "0.94.2" } -nu-engine = { path = "../nu-engine", version = "0.94.2" } -nu-color-config = { path = "../nu-color-config", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3" } +nu-utils = { path = "../nu-utils", version = "0.94.3" } +nu-engine = { path = "../nu-engine", version = "0.94.3" } +nu-color-config = { path = "../nu-color-config", version = "0.94.3" } nu-ansi-term = { workspace = true } once_cell = { workspace = true } fancy-regex = { workspace = true } tabled = { workspace = true, features = ["color"], default-features = false } [dev-dependencies] -# nu-test-support = { path="../nu-test-support", version = "0.94.2" } \ No newline at end of file +# nu-test-support = { path="../nu-test-support", version = "0.94.3" } diff --git a/crates/nu-term-grid/Cargo.toml b/crates/nu-term-grid/Cargo.toml index bc560257f8..47f6724b53 100644 --- a/crates/nu-term-grid/Cargo.toml +++ b/crates/nu-term-grid/Cargo.toml @@ -5,12 +5,12 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-term-grid" edition = "2021" license = "MIT" name = "nu-term-grid" -version = "0.94.2" +version = "0.94.3" [lib] bench = false [dependencies] -nu-utils = { path = "../nu-utils", version = "0.94.2" } +nu-utils = { path = "../nu-utils", version = "0.94.3" } -unicode-width = { workspace = true } \ No newline at end of file +unicode-width = { workspace = true } diff --git a/crates/nu-test-support/Cargo.toml b/crates/nu-test-support/Cargo.toml index 07f4142d43..86a1bf35e7 100644 --- a/crates/nu-test-support/Cargo.toml +++ b/crates/nu-test-support/Cargo.toml @@ -5,17 +5,17 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu-test-suppor edition = "2021" license = "MIT" name = "nu-test-support" -version = "0.94.2" +version = "0.94.3" [lib] doctest = false bench = false [dependencies] -nu-path = { path = "../nu-path", version = "0.94.2" } -nu-glob = { path = "../nu-glob", version = "0.94.2" } -nu-utils = { path = "../nu-utils", version = "0.94.2" } +nu-path = { path = "../nu-path", version = "0.94.3" } +nu-glob = { path = "../nu-glob", version = "0.94.3" } +nu-utils = { path = "../nu-utils", version = "0.94.3" } num-format = { workspace = true } which = { workspace = true } -tempfile = { workspace = true } \ No newline at end of file +tempfile = { workspace = true } diff --git a/crates/nu-utils/Cargo.toml b/crates/nu-utils/Cargo.toml index 584602f184..0677f655d0 100644 --- a/crates/nu-utils/Cargo.toml +++ b/crates/nu-utils/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "MIT" name = "nu-utils" repository = "https://github.com/nushell/nushell/tree/main/crates/nu-utils" -version = "0.94.2" +version = "0.94.3" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [[bin]] @@ -29,4 +29,4 @@ unicase = "2.7.0" crossterm_winapi = "0.9" [target.'cfg(unix)'.dependencies] -nix = { workspace = true, default-features = false, features = ["user", "fs"] } \ No newline at end of file +nix = { workspace = true, default-features = false, features = ["user", "fs"] } diff --git a/crates/nu-utils/src/sample_config/default_config.nu b/crates/nu-utils/src/sample_config/default_config.nu index 6d84d8d1de..b6b1fbf3f8 100644 --- a/crates/nu-utils/src/sample_config/default_config.nu +++ b/crates/nu-utils/src/sample_config/default_config.nu @@ -1,6 +1,6 @@ # Nushell Config File # -# version = "0.94.2" +# version = "0.94.3" # For more information on defining custom themes, see # https://www.nushell.sh/book/coloring_and_theming.html @@ -892,4 +892,4 @@ $env.config = { event: { edit: selectall } } ] -} \ No newline at end of file +} diff --git a/crates/nu-utils/src/sample_config/default_env.nu b/crates/nu-utils/src/sample_config/default_env.nu index edf0830f9f..57e255ed20 100644 --- a/crates/nu-utils/src/sample_config/default_env.nu +++ b/crates/nu-utils/src/sample_config/default_env.nu @@ -1,6 +1,6 @@ # Nushell Environment Config File # -# version = "0.94.2" +# version = "0.94.3" def create_left_prompt [] { let dir = match (do --ignore-shell-errors { $env.PWD | path relative-to $nu.home-path }) { @@ -97,4 +97,4 @@ $env.NU_PLUGIN_DIRS = [ # $env.PATH = ($env.PATH | uniq) # To load from a custom file you can use: -# source ($nu.default-config-dir | path join 'custom.nu') \ No newline at end of file +# source ($nu.default-config-dir | path join 'custom.nu') diff --git a/crates/nu_plugin_custom_values/Cargo.toml b/crates/nu_plugin_custom_values/Cargo.toml index 2f5ae29e3d..2791cdaa6f 100644 --- a/crates/nu_plugin_custom_values/Cargo.toml +++ b/crates/nu_plugin_custom_values/Cargo.toml @@ -10,10 +10,10 @@ name = "nu_plugin_custom_values" bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.94.2" } -nu-protocol = { path = "../nu-protocol", version = "0.94.2", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.3" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3", features = ["plugin"] } serde = { workspace = true, default-features = false } typetag = "0.2" [dev-dependencies] -nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.2" } \ No newline at end of file +nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.3" } diff --git a/crates/nu_plugin_example/Cargo.toml b/crates/nu_plugin_example/Cargo.toml index de370a0a5d..b2fd13abd9 100644 --- a/crates/nu_plugin_example/Cargo.toml +++ b/crates/nu_plugin_example/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_exam edition = "2021" license = "MIT" name = "nu_plugin_example" -version = "0.94.2" +version = "0.94.3" [[bin]] name = "nu_plugin_example" @@ -15,9 +15,9 @@ bench = false bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.94.2" } -nu-protocol = { path = "../nu-protocol", version = "0.94.2", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.3" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3", features = ["plugin"] } [dev-dependencies] -nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.2" } -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.2" } \ No newline at end of file +nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.3" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.3" } diff --git a/crates/nu_plugin_formats/Cargo.toml b/crates/nu_plugin_formats/Cargo.toml index 797eb69656..a649a5bc5a 100644 --- a/crates/nu_plugin_formats/Cargo.toml +++ b/crates/nu_plugin_formats/Cargo.toml @@ -5,12 +5,12 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_form edition = "2021" license = "MIT" name = "nu_plugin_formats" -version = "0.94.2" +version = "0.94.3" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.94.2" } -nu-protocol = { path = "../nu-protocol", version = "0.94.2", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.3" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3", features = ["plugin"] } indexmap = { workspace = true } eml-parser = "0.1" @@ -18,4 +18,4 @@ ical = "0.11" rust-ini = "0.21.0" [dev-dependencies] -nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.2" } \ No newline at end of file +nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.3" } diff --git a/crates/nu_plugin_gstat/Cargo.toml b/crates/nu_plugin_gstat/Cargo.toml index a16bf019f6..01e17fdb54 100644 --- a/crates/nu_plugin_gstat/Cargo.toml +++ b/crates/nu_plugin_gstat/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_gsta edition = "2021" license = "MIT" name = "nu_plugin_gstat" -version = "0.94.2" +version = "0.94.3" [lib] doctest = false @@ -16,7 +16,7 @@ name = "nu_plugin_gstat" bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.94.2" } -nu-protocol = { path = "../nu-protocol", version = "0.94.2" } +nu-plugin = { path = "../nu-plugin", version = "0.94.3" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3" } -git2 = "0.18" \ No newline at end of file +git2 = "0.18" diff --git a/crates/nu_plugin_inc/Cargo.toml b/crates/nu_plugin_inc/Cargo.toml index 7b57d1591c..3701ad49bd 100644 --- a/crates/nu_plugin_inc/Cargo.toml +++ b/crates/nu_plugin_inc/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_inc" edition = "2021" license = "MIT" name = "nu_plugin_inc" -version = "0.94.2" +version = "0.94.3" [lib] doctest = false @@ -16,7 +16,7 @@ name = "nu_plugin_inc" bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.94.2" } -nu-protocol = { path = "../nu-protocol", version = "0.94.2", features = ["plugin"] } +nu-plugin = { path = "../nu-plugin", version = "0.94.3" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3", features = ["plugin"] } -semver = "1.0" \ No newline at end of file +semver = "1.0" diff --git a/crates/nu_plugin_nu_example/nu_plugin_nu_example.nu b/crates/nu_plugin_nu_example/nu_plugin_nu_example.nu index 15c8340c0e..028e9735fd 100755 --- a/crates/nu_plugin_nu_example/nu_plugin_nu_example.nu +++ b/crates/nu_plugin_nu_example/nu_plugin_nu_example.nu @@ -6,7 +6,7 @@ # it also allows us to test the plugin interface with something manually implemented in a scripting # language without adding any extra dependencies to our tests. -const NUSHELL_VERSION = "0.94.2" +const NUSHELL_VERSION = "0.94.3" def main [--stdio] { if ($stdio) { @@ -257,4 +257,4 @@ def start_plugin [] { }) | each { from json | handle_input } | ignore -} \ No newline at end of file +} diff --git a/crates/nu_plugin_polars/Cargo.toml b/crates/nu_plugin_polars/Cargo.toml index 0855bc9b16..a2c693128d 100644 --- a/crates/nu_plugin_polars/Cargo.toml +++ b/crates/nu_plugin_polars/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "MIT" name = "nu_plugin_polars" repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_polars" -version = "0.94.2" +version = "0.94.3" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -17,9 +17,9 @@ bench = false bench = false [dependencies] -nu-protocol = { path = "../nu-protocol", version = "0.94.2" } -nu-plugin = { path = "../nu-plugin", version = "0.94.2" } -nu-path = { path = "../nu-path", version = "0.94.2" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3" } +nu-plugin = { path = "../nu-plugin", version = "0.94.3" } +nu-path = { path = "../nu-path", version = "0.94.3" } # Potential dependencies for extras chrono = { workspace = true, features = ["std", "unstable-locales"], default-features = false } @@ -73,9 +73,9 @@ optional = false version = "0.39" [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.2" } -nu-engine = { path = "../nu-engine", version = "0.94.2" } -nu-parser = { path = "../nu-parser", version = "0.94.2" } -nu-command = { path = "../nu-command", version = "0.94.2" } -nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.2" } -tempfile.workspace = true \ No newline at end of file +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.94.3" } +nu-engine = { path = "../nu-engine", version = "0.94.3" } +nu-parser = { path = "../nu-parser", version = "0.94.3" } +nu-command = { path = "../nu-command", version = "0.94.3" } +nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.94.3" } +tempfile.workspace = true diff --git a/crates/nu_plugin_python/nu_plugin_python_example.py b/crates/nu_plugin_python/nu_plugin_python_example.py index b2cb06c7eb..3db89a0afc 100755 --- a/crates/nu_plugin_python/nu_plugin_python_example.py +++ b/crates/nu_plugin_python/nu_plugin_python_example.py @@ -27,7 +27,7 @@ import sys import json -NUSHELL_VERSION = "0.94.2" +NUSHELL_VERSION = "0.94.3" def signatures(): @@ -124,7 +124,7 @@ def process_call(id, plugin_call): span = plugin_call["call"]["head"] # Creates a Value of type List that will be encoded and sent to Nushell - f = lambda x, y: { + def f(x, y): return { "Int": { "val": x * y, "span": span @@ -169,7 +169,7 @@ def tell_nushell_hello(): """ hello = { "Hello": { - "protocol": "nu-plugin", # always this value + "protocol": "nu-plugin", # always this value "version": NUSHELL_VERSION, "features": [] } @@ -246,8 +246,9 @@ def plugin(): input = json.loads(line) handle_input(input) + if __name__ == "__main__": if len(sys.argv) == 2 and sys.argv[1] == "--stdio": plugin() else: - print("Run me from inside nushell!") \ No newline at end of file + print("Run me from inside nushell!") diff --git a/crates/nu_plugin_query/Cargo.toml b/crates/nu_plugin_query/Cargo.toml index 0fd251e646..20a2a2729d 100644 --- a/crates/nu_plugin_query/Cargo.toml +++ b/crates/nu_plugin_query/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_quer edition = "2021" license = "MIT" name = "nu_plugin_query" -version = "0.94.2" +version = "0.94.3" [lib] doctest = false @@ -16,10 +16,10 @@ name = "nu_plugin_query" bench = false [dependencies] -nu-plugin = { path = "../nu-plugin", version = "0.94.2" } -nu-protocol = { path = "../nu-protocol", version = "0.94.2" } +nu-plugin = { path = "../nu-plugin", version = "0.94.3" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3" } gjson = "0.8" scraper = { default-features = false, version = "0.19" } sxd-document = "0.3" -sxd-xpath = "0.4" \ No newline at end of file +sxd-xpath = "0.4" diff --git a/crates/nu_plugin_stress_internals/Cargo.toml b/crates/nu_plugin_stress_internals/Cargo.toml index 884244a5db..7103d99cda 100644 --- a/crates/nu_plugin_stress_internals/Cargo.toml +++ b/crates/nu_plugin_stress_internals/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nu_plugin_stre edition = "2021" license = "MIT" name = "nu_plugin_stress_internals" -version = "0.94.2" +version = "0.94.3" [[bin]] name = "nu_plugin_stress_internals" @@ -16,4 +16,4 @@ bench = false # assumptions about the serialized format serde = { workspace = true } serde_json = { workspace = true } -interprocess = { workspace = true } \ No newline at end of file +interprocess = { workspace = true } diff --git a/crates/nuon/Cargo.toml b/crates/nuon/Cargo.toml index 80a4de36ae..31c0cdd363 100644 --- a/crates/nuon/Cargo.toml +++ b/crates/nuon/Cargo.toml @@ -5,16 +5,16 @@ repository = "https://github.com/nushell/nushell/tree/main/crates/nuon" edition = "2021" license = "MIT" name = "nuon" -version = "0.94.2" +version = "0.94.3" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nu-parser = { path = "../nu-parser", version = "0.94.2" } -nu-protocol = { path = "../nu-protocol", version = "0.94.2" } -nu-engine = { path = "../nu-engine", version = "0.94.2" } +nu-parser = { path = "../nu-parser", version = "0.94.3" } +nu-protocol = { path = "../nu-protocol", version = "0.94.3" } +nu-engine = { path = "../nu-engine", version = "0.94.3" } once_cell = { workspace = true } fancy-regex = { workspace = true } [dev-dependencies] -chrono = { workspace = true } \ No newline at end of file +chrono = { workspace = true } From a84fdb1d375aa0478cae0a452a8b1aa002deef07 Mon Sep 17 00:00:00 2001 From: Jack Wright <56345+ayax79@users.noreply.github.com> Date: Tue, 4 Jun 2024 16:40:02 -0700 Subject: [PATCH 041/113] Fixed a couple of incorrect errors messages (#13043) Fixed a couple of error message that incorrectly reported as parquet errors instead of CSV errors. --- crates/nu_plugin_polars/src/dataframe/eager/open.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/nu_plugin_polars/src/dataframe/eager/open.rs b/crates/nu_plugin_polars/src/dataframe/eager/open.rs index da9352b2d3..81ea537574 100644 --- a/crates/nu_plugin_polars/src/dataframe/eager/open.rs +++ b/crates/nu_plugin_polars/src/dataframe/eager/open.rs @@ -465,7 +465,7 @@ fn from_csv( let df: NuLazyFrame = csv_reader .finish() .map_err(|e| ShellError::GenericError { - error: "Parquet reader error".into(), + error: "CSV reader error".into(), msg: format!("{e:?}"), span: Some(call.head), help: None, @@ -531,7 +531,7 @@ fn from_csv( let df: NuDataFrame = csv_reader .finish() .map_err(|e| ShellError::GenericError { - error: "Parquet reader error".into(), + error: "CSV reader error".into(), msg: format!("{e:?}"), span: Some(call.head), help: None, From 7746e84199a51715df64d19d4ee5ef40ec05c78c Mon Sep 17 00:00:00 2001 From: Reilly Wood <26268125+rgwood@users.noreply.github.com> Date: Tue, 4 Jun 2024 16:43:12 -0700 Subject: [PATCH 042/113] Make LS_COLORS functionality faster in `explore`, especially on Windows (#12984) Closes #12980. More context there, but basically `explore` was getting file metadata for every row every time the record view was rendered. The quick fix for now is to do the `LS_COLORS` colouring with a `&str` instead of a path and file metadata. --- crates/nu-explore/src/nu_common/lscolor.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/crates/nu-explore/src/nu_common/lscolor.rs b/crates/nu-explore/src/nu_common/lscolor.rs index 31a5571ef5..491d2c3f3a 100644 --- a/crates/nu-explore/src/nu_common/lscolor.rs +++ b/crates/nu-explore/src/nu_common/lscolor.rs @@ -4,7 +4,6 @@ use nu_ansi_term::{Color, Style}; use nu_engine::env_to_string; use nu_protocol::engine::{EngineState, Stack}; use nu_utils::get_ls_colors; -use std::fs::symlink_metadata; pub fn create_lscolors(engine_state: &EngineState, stack: &Stack) -> LsColors { let colors = stack @@ -14,6 +13,7 @@ pub fn create_lscolors(engine_state: &EngineState, stack: &Stack) -> LsColors { get_ls_colors(colors) } +/// Colorizes any columns named "name" in the table using LS_COLORS pub fn lscolorize(header: &[String], data: &mut [Vec], lscolors: &LsColors) { for (col, col_name) in header.iter().enumerate() { if col_name != "name" { @@ -33,14 +33,7 @@ pub fn lscolorize(header: &[String], data: &mut [Vec], lscolors: &LsColo fn get_path_style(path: &str, ls_colors: &LsColors) -> Option