diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index 9b7f44feba..c581e4a274 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -161,7 +161,7 @@ jobs: # REF: https://github.com/marketplace/actions/gh-release # Create a release only in nushell/nightly repo - name: Publish Archive - uses: softprops/action-gh-release@v2.0.6 + uses: softprops/action-gh-release@v2.0.8 if: ${{ startsWith(github.repository, 'nushell/nightly') }} with: prerelease: true diff --git a/.github/workflows/release-pkg.nu b/.github/workflows/release-pkg.nu index da2779f6d1..562f42b4a4 100755 --- a/.github/workflows/release-pkg.nu +++ b/.github/workflows/release-pkg.nu @@ -161,8 +161,12 @@ if $os in ['macos-latest'] or $USE_UBUNTU { let releaseStem = $'($bin)-($version)-($target)' print $'(char nl)Download less related stuffs...'; hr-line + # todo: less-v661 is out but is released as a zip file. maybe we should switch to that and extract it? aria2c https://github.com/jftuga/less-Windows/releases/download/less-v608/less.exe -o less.exe - aria2c https://raw.githubusercontent.com/jftuga/less-Windows/master/LICENSE -o LICENSE-for-less.txt + # the below was renamed because it was failing to download for darren. it should work but it wasn't + # todo: maybe we should get rid of this aria2c dependency and just use http get? + #aria2c https://raw.githubusercontent.com/jftuga/less-Windows/master/LICENSE -o LICENSE-for-less.txt + aria2c https://github.com/jftuga/less-Windows/blob/master/LICENSE -o LICENSE-for-less.txt # Create Windows msi release package if (get-env _EXTRA_) == 'msi' { diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 34cad24fbf..53f22cec66 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -91,7 +91,7 @@ jobs: # REF: https://github.com/marketplace/actions/gh-release - name: Publish Archive - uses: softprops/action-gh-release@v2.0.6 + uses: softprops/action-gh-release@v2.0.8 if: ${{ startsWith(github.ref, 'refs/tags/') }} with: draft: true diff --git a/.github/workflows/typos.yml b/.github/workflows/typos.yml index c7c153983d..98ace3be57 100644 --- a/.github/workflows/typos.yml +++ b/.github/workflows/typos.yml @@ -10,4 +10,4 @@ jobs: uses: actions/checkout@v4.1.7 - name: Check spelling - uses: crate-ci/typos@v1.23.2 + uses: crate-ci/typos@v1.23.5 diff --git a/Cargo.lock b/Cargo.lock index 093162409c..2ab8dd7949 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2874,7 +2874,7 @@ dependencies = [ [[package]] name = "nu" -version = "0.95.1" +version = "0.96.2" dependencies = [ "assert_cmd", "crossterm", @@ -2919,16 +2919,16 @@ dependencies = [ [[package]] name = "nu-ansi-term" -version = "0.50.0" +version = "0.50.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd2800e1520bdc966782168a627aa5d1ad92e33b984bf7c7615d31280c83ff14" +checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "nu-cli" -version = "0.95.1" +version = "0.96.2" dependencies = [ "chrono", "crossterm", @@ -2963,7 +2963,7 @@ dependencies = [ [[package]] name = "nu-cmd-base" -version = "0.95.1" +version = "0.96.2" dependencies = [ "indexmap", "miette", @@ -2975,7 +2975,7 @@ dependencies = [ [[package]] name = "nu-cmd-extra" -version = "0.95.1" +version = "0.96.2" dependencies = [ "fancy-regex", "heck 0.5.0", @@ -3000,7 +3000,7 @@ dependencies = [ [[package]] name = "nu-cmd-lang" -version = "0.95.1" +version = "0.96.2" dependencies = [ "itertools 0.12.1", "nu-engine", @@ -3012,7 +3012,7 @@ dependencies = [ [[package]] name = "nu-cmd-plugin" -version = "0.95.1" +version = "0.96.2" dependencies = [ "itertools 0.12.1", "nu-engine", @@ -3023,7 +3023,7 @@ dependencies = [ [[package]] name = "nu-color-config" -version = "0.95.1" +version = "0.96.2" dependencies = [ "nu-ansi-term", "nu-engine", @@ -3035,7 +3035,7 @@ dependencies = [ [[package]] name = "nu-command" -version = "0.95.1" +version = "0.96.2" dependencies = [ "alphanumeric-sort", "base64 0.22.1", @@ -3147,7 +3147,7 @@ dependencies = [ [[package]] name = "nu-derive-value" -version = "0.95.1" +version = "0.96.2" dependencies = [ "convert_case", "proc-macro-error", @@ -3158,18 +3158,19 @@ dependencies = [ [[package]] name = "nu-engine" -version = "0.95.1" +version = "0.96.2" dependencies = [ "log", "nu-glob", "nu-path", "nu-protocol", "nu-utils", + "terminal_size", ] [[package]] name = "nu-explore" -version = "0.95.1" +version = "0.96.2" dependencies = [ "ansi-str", "anyhow", @@ -3194,14 +3195,14 @@ dependencies = [ [[package]] name = "nu-glob" -version = "0.95.1" +version = "0.96.2" dependencies = [ "doc-comment", ] [[package]] name = "nu-json" -version = "0.95.1" +version = "0.96.2" dependencies = [ "fancy-regex", "linked-hash-map", @@ -3214,7 +3215,7 @@ dependencies = [ [[package]] name = "nu-lsp" -version = "0.95.1" +version = "0.96.2" dependencies = [ "assert-json-diff", "crossbeam-channel", @@ -3235,7 +3236,7 @@ dependencies = [ [[package]] name = "nu-parser" -version = "0.95.1" +version = "0.96.2" dependencies = [ "bytesize", "chrono", @@ -3251,7 +3252,7 @@ dependencies = [ [[package]] name = "nu-path" -version = "0.95.1" +version = "0.96.2" dependencies = [ "dirs", "omnipath", @@ -3260,7 +3261,7 @@ dependencies = [ [[package]] name = "nu-plugin" -version = "0.95.1" +version = "0.96.2" dependencies = [ "log", "nix", @@ -3276,7 +3277,7 @@ dependencies = [ [[package]] name = "nu-plugin-core" -version = "0.95.1" +version = "0.96.2" dependencies = [ "interprocess", "log", @@ -3290,7 +3291,7 @@ dependencies = [ [[package]] name = "nu-plugin-engine" -version = "0.95.1" +version = "0.96.2" dependencies = [ "log", "nu-engine", @@ -3306,7 +3307,7 @@ dependencies = [ [[package]] name = "nu-plugin-protocol" -version = "0.95.1" +version = "0.96.2" dependencies = [ "bincode", "nu-protocol", @@ -3318,7 +3319,7 @@ dependencies = [ [[package]] name = "nu-plugin-test-support" -version = "0.95.1" +version = "0.96.2" dependencies = [ "nu-ansi-term", "nu-cmd-lang", @@ -3336,7 +3337,7 @@ dependencies = [ [[package]] name = "nu-pretty-hex" -version = "0.95.1" +version = "0.96.2" dependencies = [ "heapless", "nu-ansi-term", @@ -3345,7 +3346,7 @@ dependencies = [ [[package]] name = "nu-protocol" -version = "0.95.1" +version = "0.96.2" dependencies = [ "brotli", "byte-unit", @@ -3382,7 +3383,7 @@ dependencies = [ [[package]] name = "nu-std" -version = "0.95.1" +version = "0.96.2" dependencies = [ "log", "miette", @@ -3393,7 +3394,7 @@ dependencies = [ [[package]] name = "nu-system" -version = "0.95.1" +version = "0.96.2" dependencies = [ "chrono", "itertools 0.12.1", @@ -3411,7 +3412,7 @@ dependencies = [ [[package]] name = "nu-table" -version = "0.95.1" +version = "0.96.2" dependencies = [ "fancy-regex", "nu-ansi-term", @@ -3425,7 +3426,7 @@ dependencies = [ [[package]] name = "nu-term-grid" -version = "0.95.1" +version = "0.96.2" dependencies = [ "nu-utils", "unicode-width", @@ -3433,7 +3434,7 @@ dependencies = [ [[package]] name = "nu-test-support" -version = "0.95.1" +version = "0.96.2" dependencies = [ "nu-glob", "nu-path", @@ -3445,7 +3446,7 @@ dependencies = [ [[package]] name = "nu-utils" -version = "0.95.1" +version = "0.96.2" dependencies = [ "crossterm_winapi", "log", @@ -3471,7 +3472,7 @@ dependencies = [ [[package]] name = "nu_plugin_example" -version = "0.95.1" +version = "0.96.2" dependencies = [ "nu-cmd-lang", "nu-plugin", @@ -3481,7 +3482,7 @@ dependencies = [ [[package]] name = "nu_plugin_formats" -version = "0.95.1" +version = "0.96.2" dependencies = [ "eml-parser", "ical", @@ -3494,7 +3495,7 @@ dependencies = [ [[package]] name = "nu_plugin_gstat" -version = "0.95.1" +version = "0.96.2" dependencies = [ "git2", "nu-plugin", @@ -3503,7 +3504,7 @@ dependencies = [ [[package]] name = "nu_plugin_inc" -version = "0.95.1" +version = "0.96.2" dependencies = [ "nu-plugin", "nu-protocol", @@ -3512,7 +3513,7 @@ dependencies = [ [[package]] name = "nu_plugin_polars" -version = "0.95.1" +version = "0.96.2" dependencies = [ "chrono", "chrono-tz 0.9.0", @@ -3546,7 +3547,7 @@ dependencies = [ [[package]] name = "nu_plugin_query" -version = "0.95.1" +version = "0.96.2" dependencies = [ "gjson", "nu-plugin", @@ -3561,7 +3562,7 @@ dependencies = [ [[package]] name = "nu_plugin_stress_internals" -version = "0.95.1" +version = "0.96.2" dependencies = [ "interprocess", "serde", @@ -3687,7 +3688,7 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "nuon" -version = "0.95.1" +version = "0.96.2" dependencies = [ "chrono", "fancy-regex", @@ -3795,9 +3796,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.64" +version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ "bitflags 2.5.0", "cfg-if", @@ -3836,9 +3837,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.102" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", @@ -5012,8 +5013,8 @@ dependencies = [ [[package]] name = "reedline" -version = "0.32.0" -source = "git+https://github.com/nushell/reedline?branch=main#480059a3f52cf919341cda88e8c544edd846bc73" +version = "0.33.0" +source = "git+https://github.com/nushell/reedline?branch=main#919292e40fd417e3da882692021961b444150c59" dependencies = [ "arboard", "chrono", @@ -5596,9 +5597,9 @@ dependencies = [ [[package]] name = "shadow-rs" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a600f795d0894cda22235b44eea4b85c2a35b405f65523645ac8e35b306817a" +checksum = "d253e54681d4be0161e965db57974ae642a0b6aaeb18a999424c4dab062be8c5" dependencies = [ "const_format", "is_debug", @@ -5673,9 +5674,9 @@ checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" [[package]] name = "similar" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa42c91313f1d05da9b26f267f931cf178d4aba455b4c4622dd7355eb80c6640" +checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" [[package]] name = "simplelog" diff --git a/Cargo.toml b/Cargo.toml index 81602fb4b1..ce62fa745e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,8 +10,8 @@ homepage = "https://www.nushell.sh" license = "MIT" name = "nu" repository = "https://github.com/nushell/nushell" -rust-version = "1.77.2" -version = "0.95.1" +rust-version = "1.78.0" +version = "0.96.2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -116,7 +116,7 @@ mockito = { version = "1.4", default-features = false } native-tls = "0.2" nix = { version = "0.28", default-features = false } notify-debouncer-full = { version = "0.3", default-features = false } -nu-ansi-term = "0.50.0" +nu-ansi-term = "0.50.1" num-format = "0.4" num-traits = "0.2" omnipath = "0.1" @@ -138,7 +138,7 @@ quote = "1.0" rand = "0.8" ratatui = "0.26" rayon = "1.10" -reedline = "0.32.0" +reedline = "0.33.0" regex = "1.9.5" rmp = "0.8" rmp-serde = "1.3" @@ -183,22 +183,22 @@ windows-sys = "0.48" winreg = "0.52" [dependencies] -nu-cli = { path = "./crates/nu-cli", version = "0.95.1" } -nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.95.1" } -nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.95.1" } -nu-cmd-plugin = { path = "./crates/nu-cmd-plugin", version = "0.95.1", optional = true } -nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.95.1" } -nu-command = { path = "./crates/nu-command", version = "0.95.1" } -nu-engine = { path = "./crates/nu-engine", version = "0.95.1" } -nu-explore = { path = "./crates/nu-explore", version = "0.95.1" } -nu-lsp = { path = "./crates/nu-lsp/", version = "0.95.1" } -nu-parser = { path = "./crates/nu-parser", version = "0.95.1" } -nu-path = { path = "./crates/nu-path", version = "0.95.1" } -nu-plugin-engine = { path = "./crates/nu-plugin-engine", optional = true, version = "0.95.1" } -nu-protocol = { path = "./crates/nu-protocol", version = "0.95.1" } -nu-std = { path = "./crates/nu-std", version = "0.95.1" } -nu-system = { path = "./crates/nu-system", version = "0.95.1" } -nu-utils = { path = "./crates/nu-utils", version = "0.95.1" } +nu-cli = { path = "./crates/nu-cli", version = "0.96.2" } +nu-cmd-base = { path = "./crates/nu-cmd-base", version = "0.96.2" } +nu-cmd-lang = { path = "./crates/nu-cmd-lang", version = "0.96.2" } +nu-cmd-plugin = { path = "./crates/nu-cmd-plugin", version = "0.96.2", optional = true } +nu-cmd-extra = { path = "./crates/nu-cmd-extra", version = "0.96.2" } +nu-command = { path = "./crates/nu-command", version = "0.96.2" } +nu-engine = { path = "./crates/nu-engine", version = "0.96.2" } +nu-explore = { path = "./crates/nu-explore", version = "0.96.2" } +nu-lsp = { path = "./crates/nu-lsp/", version = "0.96.2" } +nu-parser = { path = "./crates/nu-parser", version = "0.96.2" } +nu-path = { path = "./crates/nu-path", version = "0.96.2" } +nu-plugin-engine = { path = "./crates/nu-plugin-engine", optional = true, version = "0.96.2" } +nu-protocol = { path = "./crates/nu-protocol", version = "0.96.2" } +nu-std = { path = "./crates/nu-std", version = "0.96.2" } +nu-system = { path = "./crates/nu-system", version = "0.96.2" } +nu-utils = { path = "./crates/nu-utils", version = "0.96.2" } reedline = { workspace = true, features = ["bashisms", "sqlite"] } crossterm = { workspace = true } @@ -227,9 +227,9 @@ nix = { workspace = true, default-features = false, features = [ ] } [dev-dependencies] -nu-test-support = { path = "./crates/nu-test-support", version = "0.95.1" } -nu-plugin-protocol = { path = "./crates/nu-plugin-protocol", version = "0.95.1" } -nu-plugin-core = { path = "./crates/nu-plugin-core", version = "0.95.1" } +nu-test-support = { path = "./crates/nu-test-support", version = "0.96.2" } +nu-plugin-protocol = { path = "./crates/nu-plugin-protocol", version = "0.96.2" } +nu-plugin-core = { path = "./crates/nu-plugin-core", version = "0.96.2" } assert_cmd = "2.0" dirs = { workspace = true } tango-bench = "0.5" diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..3f161a77f9 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,29 @@ +# Security Policy + +As a shell and programming language Nushell provides you with great powers and the potential to do dangerous things to your computer and data. Whenever there is a risk that a malicious actor can abuse a bug or a violation of documented behavior/assumptions in Nushell to harm you this is a *security* risk. +We want to fix those issues without exposing our users to unnecessary risk. Thus we want to explain our security policy. +Additional issues may be part of *safety* where the behavior of Nushell as designed and implemented can cause unintended harm or a bug causes damage without the involvement of a third party. + +## Supported Versions + +As Nushell is still under very active pre-stable development, the only version the core team prioritizes for security and safety fixes is the [most recent version as published on GitHub](https://github.com/nushell/nushell/releases/latest). +Only if you provide a strong reasoning and the necessary resources, will we consider blessing a backported fix with an official patch release for a previous version. + +## Reporting a Vulnerability + +If you suspect that a bug or behavior of Nushell can affect security or may be potentially exploitable, please report the issue to us in private. +Either reach out to the core team on [our Discord server](https://discord.gg/NtAbbGn) to arrange a private channel or use the [GitHub vulnerability reporting form](https://github.com/nushell/nushell/security/advisories/new). +Please try to answer the following questions: +- How can we reach you for further questions? +- What is the bug? Which system of Nushell may be affected? +- Do you have proof-of-concept for a potential exploit or have you observed an exploit in the wild? +- What is your assessment of the severity based on what could be impacted should the bug be exploited? +- Are additional people aware of the issue or deserve credit for identifying the issue? + +We will try to get back to you within a week with: +- acknowledging the receipt of the report +- an initial plan of how we want to address this including the primary points of contact for further communication +- our preliminary assessment of how severe we judge the issue +- a proposal for how we can coordinate responsible disclosure (e.g. how we ship the bugfix, if we need to coordinate with distribution maintainers, when you can release a blog post if you want to etc.) + +For purely *safety* related issues where the impact is severe by direct user action instead of malicious input or third parties, feel free to open a regular issue. If we deem that there may be an additional *security* risk on a *safety* issue we may continue discussions in a restricted forum. diff --git a/crates/nu-cli/Cargo.toml b/crates/nu-cli/Cargo.toml index 2ed504d502..54af510916 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.95.1" +version = "0.96.2" [lib] bench = false [dev-dependencies] -nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.95.1" } -nu-command = { path = "../nu-command", version = "0.95.1" } -nu-test-support = { path = "../nu-test-support", version = "0.95.1" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.96.2" } +nu-command = { path = "../nu-command", version = "0.96.2" } +nu-test-support = { path = "../nu-test-support", version = "0.96.2" } rstest = { workspace = true, default-features = false } tempfile = { workspace = true } [dependencies] -nu-cmd-base = { path = "../nu-cmd-base", version = "0.95.1" } -nu-engine = { path = "../nu-engine", version = "0.95.1" } -nu-path = { path = "../nu-path", version = "0.95.1" } -nu-parser = { path = "../nu-parser", version = "0.95.1" } -nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.95.1", optional = true } -nu-protocol = { path = "../nu-protocol", version = "0.95.1" } -nu-utils = { path = "../nu-utils", version = "0.95.1" } -nu-color-config = { path = "../nu-color-config", version = "0.95.1" } +nu-cmd-base = { path = "../nu-cmd-base", version = "0.96.2" } +nu-engine = { path = "../nu-engine", version = "0.96.2" } +nu-path = { path = "../nu-path", version = "0.96.2" } +nu-parser = { path = "../nu-parser", version = "0.96.2" } +nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.96.2", optional = true } +nu-protocol = { path = "../nu-protocol", version = "0.96.2" } +nu-utils = { path = "../nu-utils", version = "0.96.2" } +nu-color-config = { path = "../nu-color-config", version = "0.96.2" } nu-ansi-term = { workspace = true } reedline = { workspace = true, features = ["bashisms", "sqlite"] } diff --git a/crates/nu-cli/src/commands/history/history_.rs b/crates/nu-cli/src/commands/history/history_.rs index cdf85eea72..c270cef003 100644 --- a/crates/nu-cli/src/commands/history/history_.rs +++ b/crates/nu-cli/src/commands/history/history_.rs @@ -67,7 +67,7 @@ impl Command for History { } else { let history_reader: Option> = match history.file_format { HistoryFileFormat::Sqlite => { - SqliteBackedHistory::with_file(history_path.clone(), None, None) + SqliteBackedHistory::with_file(history_path.clone().into(), None, None) .map(|inner| { let boxed: Box = Box::new(inner); boxed @@ -77,7 +77,7 @@ impl Command for History { HistoryFileFormat::PlainText => FileBackedHistory::with_file( history.max_size as usize, - history_path.clone(), + history_path.clone().into(), ) .map(|inner| { let boxed: Box = Box::new(inner); @@ -156,58 +156,34 @@ fn create_history_record(idx: usize, entry: HistoryItem, long: bool, head: Span) //2. Create a record of either short or long columns and values let item_id_value = Value::int( - match entry.id { - Some(id) => { - let ids = id.to_string(); - match ids.parse::() { - Ok(i) => i, - _ => 0i64, - } - } - None => 0i64, - }, + entry + .id + .and_then(|id| id.to_string().parse::().ok()) + .unwrap_or_default(), head, ); let start_timestamp_value = Value::string( - match entry.start_timestamp { - Some(time) => time.to_string(), - None => "".into(), - }, + entry + .start_timestamp + .map(|time| time.to_string()) + .unwrap_or_default(), head, ); let command_value = Value::string(entry.command_line, head); let session_id_value = Value::int( - match entry.session_id { - Some(sid) => { - let sids = sid.to_string(); - match sids.parse::() { - Ok(i) => i, - _ => 0i64, - } - } - None => 0i64, - }, - head, - ); - let hostname_value = Value::string( - match entry.hostname { - Some(host) => host, - None => "".into(), - }, - head, - ); - let cwd_value = Value::string( - match entry.cwd { - Some(cwd) => cwd, - None => "".into(), - }, + entry + .session_id + .and_then(|id| id.to_string().parse::().ok()) + .unwrap_or_default(), head, ); + let hostname_value = Value::string(entry.hostname.unwrap_or_default(), head); + let cwd_value = Value::string(entry.cwd.unwrap_or_default(), head); let duration_value = Value::duration( - match entry.duration { - Some(d) => d.as_nanos().try_into().unwrap_or(0), - None => 0, - }, + entry + .duration + .and_then(|d| d.as_nanos().try_into().ok()) + .unwrap_or(0), head, ); let exit_status_value = Value::int(entry.exit_status.unwrap_or(0), head); diff --git a/crates/nu-cli/src/commands/keybindings_list.rs b/crates/nu-cli/src/commands/keybindings_list.rs index 350df7b820..abb5909a97 100644 --- a/crates/nu-cli/src/commands/keybindings_list.rs +++ b/crates/nu-cli/src/commands/keybindings_list.rs @@ -61,10 +61,12 @@ impl Command for KeybindingsList { .map(|option| call.has_flag(engine_state, stack, option)) .collect::, ShellError>>()?; + let no_option_specified = presence.iter().all(|present| !*present); + let records = all_options .iter() .zip(presence) - .filter(|(_, present)| *present) + .filter(|(_, present)| no_option_specified || *present) .flat_map(|(option, _)| get_records(option, call.head)) .collect(); diff --git a/crates/nu-cli/src/completions/command_completions.rs b/crates/nu-cli/src/completions/command_completions.rs index e37f8b2576..f594e3d667 100644 --- a/crates/nu-cli/src/completions/command_completions.rs +++ b/crates/nu-cli/src/completions/command_completions.rs @@ -99,10 +99,9 @@ impl CommandCompletion { suggestion: Suggestion { value: String::from_utf8_lossy(&x.0).to_string(), description: x.1, - style: None, - extra: None, span: reedline::Span::new(span.start - offset, span.end - offset), append_whitespace: true, + ..Suggestion::default() }, kind: Some(SuggestionKind::Command(x.2)), }) @@ -118,11 +117,9 @@ impl CommandCompletion { .map(move |x| SemanticSuggestion { suggestion: Suggestion { value: x, - description: None, - style: None, - extra: None, span: reedline::Span::new(span.start - offset, span.end - offset), append_whitespace: true, + ..Suggestion::default() }, // TODO: is there a way to create a test? kind: None, @@ -136,11 +133,9 @@ impl CommandCompletion { results.push(SemanticSuggestion { suggestion: Suggestion { value: format!("^{}", external.suggestion.value), - description: None, - style: None, - extra: None, span: external.suggestion.span, append_whitespace: true, + ..Suggestion::default() }, kind: external.kind, }) diff --git a/crates/nu-cli/src/completions/completer.rs b/crates/nu-cli/src/completions/completer.rs index 78398b4d19..e794354f09 100644 --- a/crates/nu-cli/src/completions/completer.rs +++ b/crates/nu-cli/src/completions/completer.rs @@ -443,14 +443,11 @@ pub fn map_value_completions<'a>( return Some(SemanticSuggestion { suggestion: Suggestion { value: s, - description: None, - style: None, - extra: None, span: reedline::Span { start: span.start - offset, end: span.end - offset, }, - append_whitespace: false, + ..Suggestion::default() }, kind: Some(SuggestionKind::Type(x.get_type())), }); @@ -460,14 +457,11 @@ pub fn map_value_completions<'a>( if let Ok(record) = x.as_record() { let mut suggestion = Suggestion { value: String::from(""), // Initialize with empty string - description: None, - style: None, - extra: None, span: reedline::Span { start: span.start - offset, end: span.end - offset, }, - append_whitespace: false, + ..Suggestion::default() }; // Iterate the cols looking for `value` and `description` diff --git a/crates/nu-cli/src/completions/completion_common.rs b/crates/nu-cli/src/completions/completion_common.rs index b3bca778a9..2b85f6091e 100644 --- a/crates/nu-cli/src/completions/completion_common.rs +++ b/crates/nu-cli/src/completions/completion_common.rs @@ -10,11 +10,9 @@ use nu_protocol::{ levenshtein_distance, Span, }; use nu_utils::get_ls_colors; -use std::path::{ - is_separator, Component, Path, PathBuf, MAIN_SEPARATOR as SEP, MAIN_SEPARATOR_STR, -}; +use std::path::{is_separator, Component, Path, PathBuf, MAIN_SEPARATOR as SEP}; -use super::SortBy; +use super::{MatchAlgorithm, SortBy}; #[derive(Clone, Default)] pub struct PathBuiltFromString { @@ -22,12 +20,21 @@ pub struct PathBuiltFromString { isdir: bool, } -fn complete_rec( +/// Recursively goes through paths that match a given `partial`. +/// built: State struct for a valid matching path built so far. +/// +/// `isdir`: whether the current partial path has a trailing slash. +/// Parsing a path string into a pathbuf loses that bit of information. +/// +/// want_directory: Whether we want only directories as completion matches. +/// Some commands like `cd` can only be run on directories whereas others +/// like `ls` can be run on regular files as well. +pub fn complete_rec( partial: &[&str], built: &PathBuiltFromString, cwd: &Path, options: &CompletionOptions, - dir: bool, + want_directory: bool, isdir: bool, ) -> Vec { let mut completions = vec![]; @@ -37,7 +44,7 @@ fn complete_rec( let mut built = built.clone(); built.parts.push(base.to_string()); built.isdir = true; - return complete_rec(rest, &built, cwd, options, dir, isdir); + return complete_rec(rest, &built, cwd, options, want_directory, isdir); } } @@ -58,7 +65,7 @@ fn complete_rec( built.parts.push(entry_name.clone()); built.isdir = entry_isdir; - if !dir || entry_isdir { + if !want_directory || entry_isdir { entries.push((entry_name, built)); } } @@ -70,12 +77,29 @@ fn complete_rec( match partial.split_first() { Some((base, rest)) => { if matches(base, &entry_name, options) { + // We use `isdir` to confirm that the current component has + // at least one next component or a slash. + // Serves as confirmation to ignore longer completions for + // components in between. if !rest.is_empty() || isdir { - completions.extend(complete_rec(rest, &built, cwd, options, dir, isdir)); + completions.extend(complete_rec( + rest, + &built, + cwd, + options, + want_directory, + isdir, + )); } else { completions.push(built); } } + if entry_name.eq(base) + && matches!(options.match_algorithm, MatchAlgorithm::Prefix) + && isdir + { + break; + } } None => { completions.push(built); @@ -93,16 +117,16 @@ enum OriginalCwd { } impl OriginalCwd { - fn apply(&self, mut p: PathBuiltFromString) -> String { + fn apply(&self, mut p: PathBuiltFromString, path_separator: char) -> String { match self { Self::None => {} Self::Home => p.parts.insert(0, "~".to_string()), Self::Prefix(s) => p.parts.insert(0, s.clone()), }; - let mut ret = p.parts.join(MAIN_SEPARATOR_STR); + let mut ret = p.parts.join(&path_separator.to_string()); if p.isdir { - ret.push(SEP); + ret.push(path_separator); } ret } @@ -133,6 +157,14 @@ pub fn complete_item( ) -> Vec<(nu_protocol::Span, String, Option