Compare commits

...

21 Commits

Author SHA1 Message Date
6c07bc10e2 feat: Refactor and optimize the github release workflow: deliver binary package for more targets (#5649) 2022-05-28 10:41:47 +08:00
6365ba0286 Add search terms for all?, any?, length, and keybindings (#5665)
* Add search terms for `all?`

JavaScript has `Array.every` similar to `all?`

* Add search terms for `any?`

JavaScript has `Array.some` similar to `any?`

* Add search terms for `length`

Count, `len()`, and `size`/`sizeof` in widely-known programming languages are equivalent to `length`

* Add search terms for `keybindings`

Shortcut and hotkey are common synonyms (especially in web and GUI land) for keybindings.
2022-05-27 16:38:54 +02:00
545b1dcd94 Add search terms to error make (#5657)
* add search terms to error make

* add throw

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2022-05-27 06:04:33 -05:00
fb89f2f48c Update reedline: Support more bindings in vi mode (#5654)
Now more bindings are shared between vi-mode and emacs mode.
E.g. Ctrl-D, Ctrl-C, Ctrl-L, Ctrl-O will work in all modes.

Also arrow navigation extra functions will behave consistent.
2022-05-26 23:46:18 +02:00
f6ee21f76b nu-cli/completions: add filtering tests for variables completions (#5653) 2022-05-26 23:38:03 +02:00
d69a4db2e7 Unpin reedline for regular development (#5634)
Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
2022-05-26 23:21:16 +02:00
d4bfbb5eaf feat: add search terms to random & typo fix (#5652)
Co-authored-by: chinsaw <chinsaw@example.com>
2022-05-26 13:09:22 -07:00
507f24d029 Improve test coverage of command examples (#5650)
* Ignore `cargo tarpaulin` output files

* Add expected result for `columns` example

Examples without provided expected output will never be tested.
The subset of commands available in `test_examples()` is limited thus
excluding the tests depending on other commands

* Add example test harness to `reject`

* Test and fix `wrap` example

* Test and fix `drop column` example

* Update `from ods` examples

* Update `from xlsx` examples

* Run `to nuon` examples

* Run `hash base64` examples

* Add example output to `path parse`

* Test and fix the `grid` examples
2022-05-26 13:51:31 -05:00
230c36f2fb Don't build OpenSSL on Windows (#5651) 2022-05-26 14:28:59 -04:00
219c719e98 make cp can copy folders contains dangling symbolic link (#5645)
* cp with no dangling link

* add -p to not follow symbolic link

* change comment

* add one more test case to check symblink body after copied

* better help message
2022-05-26 10:42:52 -05:00
50146bdef3 Shorten the links of parser keywords help msgs (#5648) 2022-05-26 18:15:36 +03:00
2042f7f769 Add 'overlay new' command (#5647)
* Add 'overlay new' command

* Add missing file
2022-05-26 17:47:04 +03:00
0594f9e7aa add case_sensitive_completions config option (#5646) 2022-05-26 09:22:20 -05:00
3b8deb9ec7 Add search terms for describe (#5644) 2022-05-26 08:11:45 -05:00
727ff5f2d4 feat[table]: Allow specific table width with -w, like command grid. (#5643) 2022-05-26 06:53:05 -05:00
3d62528d8c Makes a more helpful error for let in pipeline (#5632)
* a more helpful error for let in pipeline

* a more helpful error for let in pipeline fmt

* changed help message

* type-o

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2022-05-25 19:13:14 -05:00
a42d419b66 nu-cli/completions: fix filter for variable completions (#5641) 2022-05-25 19:10:46 -05:00
9602e82029 make sure no duplicate records exists during eval and merge (#5633) 2022-05-25 19:10:31 -05:00
JT
8e98df8b28 bump to dev version (#5635) 2022-05-25 19:09:44 -05:00
2daf8ec72d cargo update (#5639) 2022-05-25 13:13:14 -04:00
afcacda35f Change embed-resource dep to slimmer winres (#5630) 2022-05-24 23:28:10 -04:00
97 changed files with 1605 additions and 1039 deletions

155
.github/workflows/release-pkg.nu vendored Executable file
View File

@ -0,0 +1,155 @@
#!/usr/bin/env nu
# Created: 2022/05/26 19:05:20
# Description:
# A script to do the github release task, need nushell to be installed.
# REF:
# 1. https://github.com/volks73/cargo-wix
# The main binary file to be released
let bin = 'nu'
let os = $env.OS
let target = $env.TARGET
# Repo source dir like `/home/runner/work/nushell/nushell`
let src = $env.GITHUB_WORKSPACE
let flags = $env.TARGET_RUSTFLAGS
let dist = $'($env.GITHUB_WORKSPACE)/output'
let version = (open Cargo.toml | get package.version)
# $env
$'(char nl)Packaging ($bin) v($version) for ($target) in ($src)...'; hr-line -b
if not ('Cargo.lock' | path exists) { cargo generate-lockfile }
$'Start building ($bin)...'; hr-line
# ----------------------------------------------------------------------------
# Build for Ubuntu and macOS
# ----------------------------------------------------------------------------
if $os in ['ubuntu-latest', 'macos-latest'] {
if $os == 'ubuntu-latest' {
sudo apt-get install libxcb-composite0-dev -y
}
if $target == 'aarch64-unknown-linux-gnu' {
sudo apt-get install gcc-aarch64-linux-gnu -y
let-env CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER = 'aarch64-linux-gnu-gcc'
cargo-build-nu $flags
} else if $target == 'armv7-unknown-linux-gnueabihf' {
sudo apt-get install pkg-config gcc-arm-linux-gnueabihf -y
let-env CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER = 'arm-linux-gnueabihf-gcc'
cargo-build-nu $flags
} else {
# musl-tools to fix 'Failed to find tool. Is `musl-gcc` installed?'
# Actually just for x86_64-unknown-linux-musl target
sudo apt install musl-tools -y
cargo-build-nu $flags
}
}
# ----------------------------------------------------------------------------
# Build for Windows without static-link-openssl feature
# ----------------------------------------------------------------------------
if $os in ['windows-latest'] {
if ($flags | str trim | empty?) {
cargo build --release --all --target $target --features=extra
} else {
cargo build --release --all --target $target --features=extra $flags
}
}
# ----------------------------------------------------------------------------
# Prepare for the release archive
# ----------------------------------------------------------------------------
let suffix = if $os == 'windows-latest' { '.exe' }
# nu, nu_plugin_* were all included
let executable = $'target/($target)/release/($bin)*($suffix)'
$'Current executable file: ($executable)'
cd $src; mkdir $dist;
rm -rf $'target/($target)/release/*.d' $'target/($target)/release/nu_pretty_hex*'
$'(char nl)All executable files:'; hr-line
ls -f $executable
$'(char nl)Copying release files...'; hr-line
cp -v README.release.txt $'($dist)/README.txt'
[LICENSE $executable] | each {|it| cp -rv $it $dist } | flatten
$'(char nl)Check binary release version detail:'; hr-line
let ver = if $os == 'windows-latest' {
(do -i { ./output/nu.exe -c 'version' }) | str collect
} else {
(do -i { ./output/nu -c 'version' }) | str collect
}
if ($ver | str trim | empty?) {
$'(ansi r)Incompatible nu binary...(ansi reset)'
} else { $ver }
# ----------------------------------------------------------------------------
# Create a release archive and send it to output for the following steps
# ----------------------------------------------------------------------------
cd $dist; $'(char nl)Creating release archive...'; hr-line
if $os in ['ubuntu-latest', 'macos-latest'] {
$'(char nl)(ansi g)Archive contents:(ansi reset)'; hr-line; ls
let archive = $'($dist)/($bin)-($version)-($target).tar.gz'
tar czf $archive *
print $'archive: ---> ($archive)'; ls $archive
echo $'::set-output name=archive::($archive)'
} else if $os == 'windows-latest' {
let releaseStem = $'($bin)-($version)-($target)'
$'(char nl)Download less related stuffs...'; hr-line
curl https://github.com/jftuga/less-Windows/releases/download/less-v590/less.exe -o $'($dist)\less.exe'
curl https://raw.githubusercontent.com/jftuga/less-Windows/master/LICENSE -o $'($dist)\LICENSE-for-less.txt'
# Create Windows msi release package
if (get-env _EXTRA_) == 'msi' {
let wixRelease = $'($src)/target/wix/($releaseStem).msi'
$'(char nl)Start creating Windows msi package...'
cd $src; hr-line
# Wix need the binaries be stored in target/release/
cp -r $'($dist)/*' target/release/
cargo install cargo-wix --version 0.3.2
cargo wix --no-build --nocapture --package nu --output $wixRelease
echo $'::set-output name=archive::($wixRelease)'
} else {
$'(char nl)(ansi g)Archive contents:(ansi reset)'; hr-line; ls
let archive = $'($dist)/($releaseStem).zip'
7z a $archive *
print $'archive: ---> ($archive)';
let pkg = (ls -f $archive | get name)
if not ($pkg | empty?) {
echo $'::set-output name=archive::($pkg | get 0)'
}
}
}
def 'cargo-build-nu' [ options: string ] {
if ($options | str trim | empty?) {
cargo build --release --all --target $target --features=extra,static-link-openssl
} else {
cargo build --release --all --target $target --features=extra,static-link-openssl $options
}
}
# Print a horizontal line marker
def 'hr-line' [
--blank-line(-b): bool
] {
print $'(ansi g)---------------------------------------------------------------------------->(ansi reset)'
if $blank-line { char nl }
}
# Get the specified env key's value or ''
def 'get-env' [
key: string # The key to get it's env value
default: string = '' # The default value for an empty env
] {
$env | get -i $key | default $default
}

View File

@ -1,3 +1,7 @@
#
# REF:
# 1. https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrixinclude
#
name: Create Release Draft
on:
@ -5,434 +9,89 @@ on:
push:
tags: ["[0-9]+.[0-9]+.[0-9]+*"]
defaults:
run:
shell: bash
jobs:
linux:
name: Build Linux
runs-on: ubuntu-latest
all:
name: All
strategy:
matrix:
target:
- aarch64-apple-darwin
- x86_64-apple-darwin
- x86_64-pc-windows-msvc
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl
- aarch64-unknown-linux-gnu
- armv7-unknown-linux-gnueabihf
extra: ['bin']
include:
- target: aarch64-apple-darwin
os: macos-latest
target_rustflags: ''
- target: x86_64-apple-darwin
os: macos-latest
target_rustflags: ''
- target: x86_64-pc-windows-msvc
extra: 'bin'
os: windows-latest
target_rustflags: ''
- target: x86_64-pc-windows-msvc
extra: msi
os: windows-latest
target_rustflags: ''
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
target_rustflags: ''
- target: x86_64-unknown-linux-musl
os: ubuntu-latest
target_rustflags: ''
- target: aarch64-unknown-linux-gnu
os: ubuntu-latest
target_rustflags: ''
- target: armv7-unknown-linux-gnueabihf
os: ubuntu-latest
target_rustflags: ''
runs-on: ${{matrix.os}}
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Install libxcb
run: sudo apt-get install libxcb-composite0-dev
- name: Set up cargo
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- name: Build
uses: actions-rs/cargo@v1
with:
command: build
args: --release --all --features=extra,static-link-openssl
# - name: Strip binaries (nu)
# run: strip target/release/nu
# - name: Strip binaries (nu_plugin_inc)
# run: strip target/release/nu_plugin_inc
# - name: Strip binaries (nu_plugin_match)
# run: strip target/release/nu_plugin_match
# - name: Strip binaries (nu_plugin_textview)
# run: strip target/release/nu_plugin_textview
# - name: Strip binaries (nu_plugin_binaryview)
# run: strip target/release/nu_plugin_binaryview
# - name: Strip binaries (nu_plugin_chart_bar)
# run: strip target/release/nu_plugin_chart_bar
# - name: Strip binaries (nu_plugin_chart_line)
# run: strip target/release/nu_plugin_chart_line
# - name: Strip binaries (nu_plugin_from_bson)
# run: strip target/release/nu_plugin_from_bson
# - name: Strip binaries (nu_plugin_from_sqlite)
# run: strip target/release/nu_plugin_from_sqlite
# - name: Strip binaries (nu_plugin_from_mp4)
# run: strip target/release/nu_plugin_from_mp4
# - name: Strip binaries (nu_plugin_query_json)
# run: strip target/release/nu_plugin_query_json
# - name: Strip binaries (nu_plugin_s3)
# run: strip target/release/nu_plugin_s3
# - name: Strip binaries (nu_plugin_selector)
# run: strip target/release/nu_plugin_selector
# - name: Strip binaries (nu_plugin_start)
# run: strip target/release/nu_plugin_start
# - name: Strip binaries (nu_plugin_to_bson)
# run: strip target/release/nu_plugin_to_bson
# - name: Strip binaries (nu_plugin_to_sqlite)
# run: strip target/release/nu_plugin_to_sqlite
# - name: Strip binaries (nu_plugin_tree)
# run: strip target/release/nu_plugin_tree
# - name: Strip binaries (nu_plugin_xpath)
# run: strip target/release/nu_plugin_xpath
- name: Create output directory
run: mkdir output
- name: Copy files to output
run: |
cp target/release/nu target/release/nu_plugin_* output/
cp README.release.txt output/README.txt
cp LICENSE output/LICENSE
rm output/*.d
- name: Upload artifact
uses: actions/upload-artifact@v2
with:
name: linux
path: output/*
macos:
name: Build macOS
runs-on: macos-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up cargo
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- name: Build
uses: actions-rs/cargo@v1
with:
command: build
args: --release --all --features=extra,static-link-openssl
# - name: Strip binaries (nu)
# run: strip target/release/nu
# - name: Strip binaries (nu_plugin_inc)
# run: strip target/release/nu_plugin_inc
# - name: Strip binaries (nu_plugin_match)
# run: strip target/release/nu_plugin_match
# - name: Strip binaries (nu_plugin_textview)
# run: strip target/release/nu_plugin_textview
# - name: Strip binaries (nu_plugin_binaryview)
# run: strip target/release/nu_plugin_binaryview
# - name: Strip binaries (nu_plugin_chart_bar)
# run: strip target/release/nu_plugin_chart_bar
# - name: Strip binaries (nu_plugin_chart_line)
# run: strip target/release/nu_plugin_chart_line
# - name: Strip binaries (nu_plugin_from_bson)
# run: strip target/release/nu_plugin_from_bson
# - name: Strip binaries (nu_plugin_from_sqlite)
# run: strip target/release/nu_plugin_from_sqlite
# - name: Strip binaries (nu_plugin_from_mp4)
# run: strip target/release/nu_plugin_from_mp4
# - name: Strip binaries (nu_plugin_query_json)
# run: strip target/release/nu_plugin_query_json
# - name: Strip binaries (nu_plugin_s3)
# run: strip target/release/nu_plugin_s3
# - name: Strip binaries (nu_plugin_selector)
# run: strip target/release/nu_plugin_selector
# - name: Strip binaries (nu_plugin_start)
# run: strip target/release/nu_plugin_start
# - name: Strip binaries (nu_plugin_to_bson)
# run: strip target/release/nu_plugin_to_bson
# - name: Strip binaries (nu_plugin_to_sqlite)
# run: strip target/release/nu_plugin_to_sqlite
# - name: Strip binaries (nu_plugin_tree)
# run: strip target/release/nu_plugin_tree
# - name: Strip binaries (nu_plugin_xpath)
# run: strip target/release/nu_plugin_xpath
- name: Create output directory
run: mkdir output
- name: Copy files to output
run: |
cp target/release/nu target/release/nu_plugin_* output/
cp README.release.txt output/README.txt
cp LICENSE output/LICENSE
rm output/*.d
- name: Upload artifact
uses: actions/upload-artifact@v2
with:
name: macos
path: output/*
windows:
name: Build Windows
runs-on: windows-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up cargo
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- name: Add cargo-wix subcommand
uses: actions-rs/cargo@v1
with:
command: install
args: cargo-wix --version 0.3.1
- name: Build
uses: actions-rs/cargo@v1
with:
command: build
args: --release --all --features=extra,static-link-openssl
# - name: Strip binaries (nu.exe)
# run: strip target/release/nu.exe
# - name: Strip binaries (nu_plugin_inc.exe)
# run: strip target/release/nu_plugin_inc.exe
# - name: Strip binaries (nu_plugin_match.exe)
# run: strip target/release/nu_plugin_match.exe
# - name: Strip binaries (nu_plugin_textview.exe)
# run: strip target/release/nu_plugin_textview.exe
# - name: Strip binaries (nu_plugin_binaryview.exe)
# run: strip target/release/nu_plugin_binaryview.exe
# - name: Strip binaries (nu_plugin_chart_bar.exe)
# run: strip target/release/nu_plugin_chart_bar.exe
# - name: Strip binaries (nu_plugin_chart_line.exe)
# run: strip target/release/nu_plugin_chart_line.exe
# - name: Strip binaries (nu_plugin_from_bson.exe)
# run: strip target/release/nu_plugin_from_bson.exe
# - name: Strip binaries (nu_plugin_from_sqlite.exe)
# run: strip target/release/nu_plugin_from_sqlite.exe
# - name: Strip binaries (nu_plugin_from_mp4.exe)
# run: strip target/release/nu_plugin_from_mp4.exe
# - name: Strip binaries (nu_plugin_query_json.exe)
# run: strip target/release/nu_plugin_query_json.exe
# - name: Strip binaries (nu_plugin_s3.exe)
# run: strip target/release/nu_plugin_s3.exe
# - name: Strip binaries (nu_plugin_selector.exe)
# run: strip target/release/nu_plugin_selector.exe
# - name: Strip binaries (nu_plugin_start.exe)
# run: strip target/release/nu_plugin_start.exe
# - name: Strip binaries (nu_plugin_to_bson.exe)
# run: strip target/release/nu_plugin_to_bson.exe
# - name: Strip binaries (nu_plugin_to_sqlite.exe)
# run: strip target/release/nu_plugin_to_sqlite.exe
# - name: Strip binaries (nu_plugin_tree.exe)
# run: strip target/release/nu_plugin_tree.exe
# - name: Strip binaries (nu_plugin_xpath.exe)
# run: strip target/release/nu_plugin_xpath.exe
- name: Create output directory
run: mkdir output
- name: Download Less Binary
run: Invoke-WebRequest -Uri "https://github.com/jftuga/less-Windows/releases/download/less-v562.0/less.exe" -OutFile "target\release\less.exe"
- name: Download Less License
run: Invoke-WebRequest -Uri "https://raw.githubusercontent.com/jftuga/less-Windows/master/LICENSE" -OutFile "target\release\LICENSE-for-less.txt"
- name: Copy files to output
run: |
cp target\release\nu.exe output\
cp LICENSE output\
cp target\release\LICENSE-for-less.txt output\
cp target\release\nu_plugin_*.exe output\
cp README.release.txt output\README.txt
cp target\release\less.exe output\
# Note: If the version of `less.exe` needs to be changed, update this URL
# Similarly, if `less.exe` is checked into the repo, copy from the local path here
# moved this stuff down to create wix after we download less
- name: Create msi with wix
uses: actions-rs/cargo@v1
with:
command: wix
args: --no-build --nocapture --output target\wix\nushell-windows.msi
- name: Upload installer
uses: actions/upload-artifact@v2
with:
name: windows-installer
path: target\wix\nushell-windows.msi
- name: Upload zip
uses: actions/upload-artifact@v2
with:
name: windows-zip
path: output\*
release:
name: Publish Release
runs-on: ubuntu-latest
needs:
- linux
- macos
- windows
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Determine Release Info
id: info
env:
GITHUB_REF: ${{ github.ref }}
run: |
VERSION=${GITHUB_REF##*/}
MAJOR=${VERSION%%.*}
MINOR=${VERSION%.*}
MINOR=${MINOR#*.}
PATCH=${VERSION##*.}
echo "::set-output name=version::${VERSION}"
echo "::set-output name=linuxdir::nu_${MAJOR}_${MINOR}_${PATCH}_linux"
echo "::set-output name=macosdir::nu_${MAJOR}_${MINOR}_${PATCH}_macOS"
echo "::set-output name=windowsdir::nu_${MAJOR}_${MINOR}_${PATCH}_windows"
echo "::set-output name=innerdir::nushell-${VERSION}"
- name: Create Release Draft
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: ${{ steps.info.outputs.version }} Release
draft: true
- name: Create Linux Directory
run: mkdir -p ${{ steps.info.outputs.linuxdir }}/${{ steps.info.outputs.innerdir }}
- name: Download Linux Artifacts
uses: actions/download-artifact@v2
with:
name: linux
path: ${{ steps.info.outputs.linuxdir }}/${{ steps.info.outputs.innerdir }}
- name: Restore Linux File Modes
run: |
chmod 755 ${{ steps.info.outputs.linuxdir }}/${{ steps.info.outputs.innerdir }}/nu*
- name: Create Linux tarball
run: tar -zcvf ${{ steps.info.outputs.linuxdir }}.tar.gz ${{ steps.info.outputs.linuxdir }}
- name: Upload Linux Artifact
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./${{ steps.info.outputs.linuxdir }}.tar.gz
asset_name: ${{ steps.info.outputs.linuxdir }}.tar.gz
asset_content_type: application/gzip
- name: Create macOS Directory
run: mkdir -p ${{ steps.info.outputs.macosdir }}/${{ steps.info.outputs.innerdir }}
- name: Download macOS Artifacts
uses: actions/download-artifact@v2
with:
name: macos
path: ${{ steps.info.outputs.macosdir }}/${{ steps.info.outputs.innerdir }}
- name: Restore macOS File Modes
run: chmod 755 ${{ steps.info.outputs.macosdir }}/${{ steps.info.outputs.innerdir }}/nu*
- name: Create macOS Archive
run: zip -r ${{ steps.info.outputs.macosdir }}.zip ${{ steps.info.outputs.macosdir }}
- name: Upload macOS Artifact
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./${{ steps.info.outputs.macosdir }}.zip
asset_name: ${{ steps.info.outputs.macosdir }}.zip
asset_content_type: application/zip
- name: Create Windows Directory
run: mkdir -p ${{ steps.info.outputs.windowsdir }}/${{ steps.info.outputs.innerdir }}
- name: Download Windows zip
uses: actions/download-artifact@v2
with:
name: windows-zip
path: ${{ steps.info.outputs.windowsdir }}/${{ steps.info.outputs.innerdir }}
- name: Show Windows Artifacts
run: ls -la ${{ steps.info.outputs.windowsdir }}/${{ steps.info.outputs.innerdir }}
- name: Create macOS Archive
run: zip -r ${{ steps.info.outputs.windowsdir }}.zip ${{ steps.info.outputs.windowsdir }}
- name: Upload Windows zip
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./${{ steps.info.outputs.windowsdir }}.zip
asset_name: ${{ steps.info.outputs.windowsdir }}.zip
asset_content_type: application/zip
- name: Download Windows installer
uses: actions/download-artifact@v2
with:
name: windows-installer
path: ./
- name: Upload Windows installer
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./nushell-windows.msi
asset_name: ${{ steps.info.outputs.windowsdir }}.msi
asset_content_type: application/x-msi
- uses: actions/checkout@v3.0.2
- name: Install Rust Toolchain Components
uses: actions-rs/toolchain@v1.0.6
with:
override: true
profile: minimal
toolchain: stable
target: ${{ matrix.target }}
- name: Setup Nushell
uses: hustcer/setup-nu@v1
with:
version: 0.63.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Release Nu Binary
id: nu
run: nu .github/workflows/release-pkg.nu
env:
OS: ${{ matrix.os }}
REF: ${{ github.ref }}
TARGET: ${{ matrix.target }}
_EXTRA_: ${{ matrix.extra }}
TARGET_RUSTFLAGS: ${{ matrix.target_rustflags }}
# REF: https://github.com/marketplace/actions/gh-release
- name: Publish Archive
uses: softprops/action-gh-release@v1
if: ${{ startsWith(github.ref, 'refs/tags/') }}
with:
draft: true
files: ${{ steps.nu.outputs.archive }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

4
.gitignore vendored
View File

@ -25,3 +25,7 @@ debian/nu/
# Helix configuration folder
.helix/*
.helix
# Coverage tools
lcov.info
tarpaulin-report.html

713
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,7 @@ name = "nu"
readme = "README.md"
repository = "https://github.com/nushell/nushell"
rust-version = "1.60"
version = "0.63.0"
version = "0.63.1"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -38,28 +38,31 @@ ctrlc = "3.2.1"
log = "0.4"
miette = "4.5.0"
nu-ansi-term = "0.45.1"
nu-cli = { path="./crates/nu-cli", version = "0.63.0" }
nu-color-config = { path = "./crates/nu-color-config", version = "0.63.0" }
nu-command = { path="./crates/nu-command", version = "0.63.0" }
nu-engine = { path="./crates/nu-engine", version = "0.63.0" }
nu-json = { path="./crates/nu-json", version = "0.63.0" }
nu-parser = { path="./crates/nu-parser", version = "0.63.0" }
nu-path = { path="./crates/nu-path", version = "0.63.0" }
nu-plugin = { path = "./crates/nu-plugin", optional = true, version = "0.63.0" }
nu-pretty-hex = { path = "./crates/nu-pretty-hex", version = "0.63.0" }
nu-protocol = { path = "./crates/nu-protocol", version = "0.63.0" }
nu-system = { path = "./crates/nu-system", version = "0.63.0" }
nu-table = { path = "./crates/nu-table", version = "0.63.0" }
nu-term-grid = { path = "./crates/nu-term-grid", version = "0.63.0" }
nu-utils = { path = "./crates/nu-utils", version = "0.63.0" }
openssl = { version = "0.10.38", features = ["vendored"], optional = true }
nu-cli = { path="./crates/nu-cli", version = "0.63.1" }
nu-color-config = { path = "./crates/nu-color-config", version = "0.63.1" }
nu-command = { path="./crates/nu-command", version = "0.63.1" }
nu-engine = { path="./crates/nu-engine", version = "0.63.1" }
nu-json = { path="./crates/nu-json", version = "0.63.1" }
nu-parser = { path="./crates/nu-parser", version = "0.63.1" }
nu-path = { path="./crates/nu-path", version = "0.63.1" }
nu-plugin = { path = "./crates/nu-plugin", optional = true, version = "0.63.1" }
nu-pretty-hex = { path = "./crates/nu-pretty-hex", version = "0.63.1" }
nu-protocol = { path = "./crates/nu-protocol", version = "0.63.1" }
nu-system = { path = "./crates/nu-system", version = "0.63.1" }
nu-table = { path = "./crates/nu-table", version = "0.63.1" }
nu-term-grid = { path = "./crates/nu-term-grid", version = "0.63.1" }
nu-utils = { path = "./crates/nu-utils", version = "0.63.1" }
pretty_env_logger = "0.4.0"
rayon = "1.5.1"
reedline = { version = "0.6.0", features = ["bashisms"]}
reedline = { git = "https://github.com/nushell/reedline", branch = "main", features = ["bashisms"]}
is_executable = "1.0.1"
[target.'cfg(not(target_os = "windows"))'.dependencies]
# Our dependencies don't use OpenSSL on Windows
openssl = { version = "0.10.38", features = ["vendored"], optional = true }
[dev-dependencies]
nu-test-support = { path="./crates/nu-test-support", version = "0.63.0" }
nu-test-support = { path="./crates/nu-test-support", version = "0.63.1" }
tempfile = "3.2.0"
assert_cmd = "2.0.2"
pretty_assertions = "1.0.0"
@ -69,7 +72,7 @@ rstest = "0.12.0"
itertools = "0.10.3"
[target.'cfg(windows)'.build-dependencies]
embed-resource = "1"
winres = "0.1"
[features]
plugin = ["nu-plugin", "nu-cli/plugin", "nu-parser/plugin", "nu-command/plugin", "nu-protocol/plugin", "nu-engine/plugin"]

View File

@ -1,49 +0,0 @@
#include <winver.h>
#define VER_FILEVERSION 0,62,1,0
#define VER_FILEVERSION_STR "0.62.1"
#define VER_PRODUCTVERSION 0,62,1,0
#define VER_PRODUCTVERSION_STR "0.62.1"
#ifdef RC_INVOKED
#ifdef DEBUG // TODO: Actually define DEBUG
#define VER_DEBUG VS_FF_DEBUG
#else
#define VER_DEBUG 0
#endif
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION
PRODUCTVERSION VER_PRODUCTVERSION
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS VER_DEBUG
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "nushell"
VALUE "FileDescription", "Nushell"
VALUE "FileVersion", VER_FILEVERSION_STR
VALUE "InternalName", "nu.exe"
VALUE "LegalCopyright", "Copyright (C) 2022"
VALUE "OriginalFilename", "nu.exe"
VALUE "ProductName", "Nushell"
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#define IDI_ICON 0x101
IDI_ICON ICON "assets/nu_logo.ico"
#endif

View File

@ -1,6 +1,12 @@
#[cfg(windows)]
fn main() {
embed_resource::compile_for("assets/nushell.rc", &["nu"])
let mut res = winres::WindowsResource::new();
res.set("ProductName", "Nushell");
res.set("FileDescription", "Nushell");
res.set("LegalCopyright", "Copyright (C) 2022");
res.set_icon("assets/nu_logo.ico");
res.compile()
.expect("Failed to run the Windows resource compiler (rc.exe)");
}
#[cfg(not(windows))]

View File

@ -4,21 +4,21 @@ description = "CLI-related functionality for Nushell"
edition = "2021"
license = "MIT"
name = "nu-cli"
version = "0.63.0"
version = "0.63.1"
[dev-dependencies]
nu-test-support = { path="../nu-test-support", version = "0.63.0" }
nu-command = { path = "../nu-command", version = "0.63.0" }
nu-test-support = { path="../nu-test-support", version = "0.63.1" }
nu-command = { path = "../nu-command", version = "0.63.1" }
[dependencies]
nu-engine = { path = "../nu-engine", version = "0.63.0" }
nu-path = { path = "../nu-path", version = "0.63.0" }
nu-parser = { path = "../nu-parser", version = "0.63.0" }
nu-protocol = { path = "../nu-protocol", version = "0.63.0" }
nu-utils = { path = "../nu-utils", version = "0.63.0" }
nu-engine = { path = "../nu-engine", version = "0.63.1" }
nu-path = { path = "../nu-path", version = "0.63.1" }
nu-parser = { path = "../nu-parser", version = "0.63.1" }
nu-protocol = { path = "../nu-protocol", version = "0.63.1" }
nu-utils = { path = "../nu-utils", version = "0.63.1" }
nu-ansi-term = "0.45.1"
nu-color-config = { path = "../nu-color-config", version = "0.63.0" }
reedline = { version = "0.6.0", features = ["bashisms"]}
reedline = { git = "https://github.com/nushell/reedline", branch = "main", features = ["bashisms"]}
nu-color-config = { path = "../nu-color-config", version = "0.63.1" }
crossterm = "0.23.0"
miette = { version = "4.5.0", features = ["fancy"] }
thiserror = "1.0.29"

View File

@ -37,7 +37,10 @@ impl NuCompleter {
) -> Vec<Suggestion> {
let config = self.engine_state.get_config();
let mut options = CompletionOptions::default();
let mut options = CompletionOptions {
case_sensitive: config.case_sensitive_completions,
..Default::default()
};
if config.completion_algorithm == "fuzzy" {
options.match_algorithm = MatchAlgorithm::Fuzzy;

View File

@ -70,7 +70,18 @@ impl Completer for VariableCompletion {
self.var_context.1.clone().into_iter().skip(1).collect();
if let Some(val) = env_vars.get(&target_var_str) {
return nested_suggestions(val.clone(), nested_levels, current_span);
for suggestion in
nested_suggestions(val.clone(), nested_levels, current_span)
{
if options
.match_algorithm
.matches_u8(suggestion.value.as_bytes(), &prefix)
{
output.push(suggestion);
}
}
return output;
}
} else {
// No nesting provided, return all env vars
@ -105,7 +116,18 @@ impl Completer for VariableCompletion {
end: current_span.end,
},
) {
return nested_suggestions(nuval, self.var_context.1.clone(), current_span);
for suggestion in
nested_suggestions(nuval, self.var_context.1.clone(), current_span)
{
if options
.match_algorithm
.matches_u8(suggestion.value.as_bytes(), &prefix)
{
output.push(suggestion);
}
}
return output;
}
}
@ -122,7 +144,18 @@ impl Completer for VariableCompletion {
// If the value exists and it's of type Record
if let Ok(value) = var {
return nested_suggestions(value, self.var_context.1.clone(), current_span);
for suggestion in
nested_suggestions(value, self.var_context.1.clone(), current_span)
{
if options
.match_algorithm
.matches_u8(suggestion.value.as_bytes(), &prefix)
{
output.push(suggestion);
}
}
return output;
}
}
}

View File

@ -42,6 +42,16 @@ pub fn new_engine() -> (PathBuf, String, EngineState, Stack) {
},
},
);
stack.add_env_var(
"TEST".to_string(),
Value::String {
val: "NUSHELL".to_string(),
span: nu_protocol::Span {
start: 0,
end: dir_str.len(),
},
},
);
// Merge delta
let merge_result = engine_state.merge_delta(delta, Some(&mut stack), &dir);

View File

@ -35,6 +35,16 @@ fn variables_completions() {
// Match results
match_suggestions(expected, suggestions);
// Test completions for $nu.h (filter)
let suggestions = completer.complete("$nu.h".into(), 5);
assert_eq!(2, suggestions.len());
let expected: Vec<String> = vec!["history-path".into(), "home-path".into()];
// Match results
match_suggestions(expected, suggestions);
// Test completions for custom var
let suggestions = completer.complete("$actor.".into(), 7);
@ -45,12 +55,32 @@ fn variables_completions() {
// Match results
match_suggestions(expected, suggestions);
// Test completions for $env
let suggestions = completer.complete("$env.".into(), 5);
// Test completions for custom var (filtering)
let suggestions = completer.complete("$actor.n".into(), 7);
assert_eq!(1, suggestions.len());
let expected: Vec<String> = vec!["PWD".into()];
let expected: Vec<String> = vec!["name".into()];
// Match results
match_suggestions(expected, suggestions);
// Test completions for $env
let suggestions = completer.complete("$env.".into(), 5);
assert_eq!(2, suggestions.len());
let expected: Vec<String> = vec!["PWD".into(), "TEST".into()];
// Match results
match_suggestions(expected, suggestions);
// Test completions for $env
let suggestions = completer.complete("$env.T".into(), 5);
assert_eq!(1, suggestions.len());
let expected: Vec<String> = vec!["TEST".into()];
// Match results
match_suggestions(expected, suggestions);

View File

@ -4,11 +4,11 @@ description = "Color configuration code used by Nushell"
edition = "2021"
license = "MIT"
name = "nu-color-config"
version = "0.63.0"
version = "0.63.1"
[dependencies]
nu-protocol = { path = "../nu-protocol", version = "0.63.0" }
nu-protocol = { path = "../nu-protocol", version = "0.63.1" }
nu-ansi-term = "0.45.1"
nu-json = { path = "../nu-json", version = "0.63.0" }
nu-table = { path = "../nu-table", version = "0.63.0" }
nu-json = { path = "../nu-json", version = "0.63.1" }
nu-table = { path = "../nu-table", version = "0.63.1" }
serde = { version="1.0.123", features=["derive"] }

View File

@ -4,25 +4,25 @@ description = "Nushell's built-in commands"
edition = "2021"
license = "MIT"
name = "nu-command"
version = "0.63.0"
version = "0.63.1"
build = "build.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nu-color-config = { path = "../nu-color-config", version = "0.63.0" }
nu-engine = { path = "../nu-engine", version = "0.63.0" }
nu-glob = { path = "../nu-glob", version = "0.63.0" }
nu-json = { path = "../nu-json", version = "0.63.0" }
nu-parser = { path = "../nu-parser", version = "0.63.0" }
nu-path = { path = "../nu-path", version = "0.63.0" }
nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.63.0" }
nu-protocol = { path = "../nu-protocol", version = "0.63.0" }
nu-system = { path = "../nu-system", version = "0.63.0" }
nu-table = { path = "../nu-table", version = "0.63.0" }
nu-term-grid = { path = "../nu-term-grid", version = "0.63.0" }
nu-test-support = { path = "../nu-test-support", version = "0.63.0" }
nu-utils = { path = "../nu-utils", version = "0.63.0" }
nu-color-config = { path = "../nu-color-config", version = "0.63.1" }
nu-engine = { path = "../nu-engine", version = "0.63.1" }
nu-glob = { path = "../nu-glob", version = "0.63.1" }
nu-json = { path = "../nu-json", version = "0.63.1" }
nu-parser = { path = "../nu-parser", version = "0.63.1" }
nu-path = { path = "../nu-path", version = "0.63.1" }
nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.63.1" }
nu-protocol = { path = "../nu-protocol", version = "0.63.1" }
nu-system = { path = "../nu-system", version = "0.63.1" }
nu-table = { path = "../nu-table", version = "0.63.1" }
nu-term-grid = { path = "../nu-term-grid", version = "0.63.1" }
nu-test-support = { path = "../nu-test-support", version = "0.63.1" }
nu-utils = { path = "../nu-utils", version = "0.63.1" }
nu-ansi-term = "0.45.1"
# Potential dependencies for extras
@ -82,7 +82,7 @@ unicode-segmentation = "1.8.0"
url = "2.2.1"
uuid = { version = "0.8.2", features = ["v4"] }
which = { version = "4.2.2", optional = true }
reedline = { version = "0.6.0", features = ["bashisms"]}
reedline = { git = "https://github.com/nushell/reedline", branch = "main", features = ["bashisms"]}
wax = { version = "0.4.0", features = ["diagnostics"] }
rusqlite = { version = "0.27.0", features = ["bundled"], optional = true }
sqlparser = { version = "0.16.0", features = ["serde"], optional = true }

View File

@ -26,8 +26,8 @@ impl Command for Alias {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -27,8 +27,8 @@ impl Command for Def {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -27,8 +27,8 @@ impl Command for DefEnv {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -13,7 +13,7 @@ impl Command for Describe {
}
fn usage(&self) -> &str {
"Describe the value(s) piped in."
"Describe the type and structure of the value(s) piped in."
}
fn signature(&self) -> Signature {
@ -55,6 +55,10 @@ impl Command for Describe {
result: Some(Value::test_string("string")),
}]
}
fn search_terms(&self) -> Vec<&str> {
vec!["type", "typeof", "info", "structure"]
}
}
#[cfg(test)]

View File

@ -24,6 +24,10 @@ impl Command for ErrorMake {
"Create an error."
}
fn search_terms(&self) -> Vec<&str> {
vec!["err", "panic", "crash", "throw"]
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -22,8 +22,8 @@ impl Command for ExportCommand {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -26,8 +26,8 @@ impl Command for ExportAlias {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -27,8 +27,8 @@ impl Command for ExportDef {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -27,8 +27,8 @@ impl Command for ExportDefEnv {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -30,8 +30,8 @@ impl Command for ExportEnv {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -22,8 +22,8 @@ impl Command for ExportExtern {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -22,8 +22,8 @@ impl Command for Extern {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -45,8 +45,8 @@ impl Command for For {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -25,9 +25,8 @@ impl Command for Hide {
fn extra_usage(&self) -> &str {
r#"Symbols are hidden by priority: First aliases, then custom commands, then environment variables.
This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages
"#
This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -34,8 +34,8 @@ impl Command for If {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -27,8 +27,8 @@ impl Command for Let {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -26,8 +26,8 @@ impl Command for Module {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -34,8 +34,8 @@ impl Command for OverlayAdd {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -22,8 +22,8 @@ impl Command for Overlay {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -1,9 +1,11 @@
mod add;
mod command;
mod list;
mod new;
mod remove;
pub use add::OverlayAdd;
pub use command::Overlay;
pub use list::OverlayList;
pub use new::OverlayNew;
pub use remove::OverlayRemove;

View File

@ -0,0 +1,74 @@
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Spanned, SyntaxShape};
#[derive(Clone)]
pub struct OverlayNew;
impl Command for OverlayNew {
fn name(&self) -> &str {
"overlay new"
}
fn usage(&self) -> &str {
"Create an empty overlay"
}
fn signature(&self) -> nu_protocol::Signature {
Signature::build("overlay new")
.required("name", SyntaxShape::String, "Name of the overlay")
// TODO:
// .switch(
// "prefix",
// "Prepend module name to the imported symbols",
// Some('p'),
// )
.category(Category::Core)
}
fn extra_usage(&self) -> &str {
r#"The command will first create an empty module, then add it as an overlay.
This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {
true
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
_input: PipelineData,
) -> Result<PipelineData, ShellError> {
let name_arg: Spanned<String> = call.req(engine_state, stack, 0)?;
stack.add_overlay(name_arg.item);
Ok(PipelineData::new(call.head))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Create an empty overlay",
example: r#"overlay new spam"#,
result: None,
}]
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_examples() {
use crate::test_examples;
test_examples(OverlayNew {})
}
}

View File

@ -29,8 +29,8 @@ impl Command for OverlayRemove {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -42,8 +42,8 @@ impl Command for Register {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -27,8 +27,8 @@ impl Command for Source {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -24,8 +24,8 @@ impl Command for Use {
}
fn extra_usage(&self) -> &str {
r#"This command is a parser keyword. For details, check
https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-different-stages"#
r#"This command is a parser keyword. For details, check:
https://www.nushell.sh/book/thinking_in_nushell.html"#
}
fn is_parser_keyword(&self) -> bool {

View File

@ -55,6 +55,7 @@ pub fn create_default_context(cwd: impl AsRef<Path>) -> EngineState {
Overlay,
OverlayAdd,
OverlayList,
OverlayNew,
OverlayRemove,
Let,
Metadata,

View File

@ -1,8 +1,9 @@
use std::fs::read_link;
use std::path::PathBuf;
use nu_engine::env::current_dir;
use nu_engine::CallExt;
use nu_path::canonicalize_with;
use nu_path::{canonicalize_with, expand_path_with};
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
@ -54,6 +55,11 @@ impl Command for Cp {
// TODO: add back in additional features
// .switch("force", "suppress error when no file", Some('f'))
.switch("interactive", "ask user to confirm action", Some('i'))
.switch(
"no-dereference",
"If the -r option is specified, no symbolic links are followed.",
Some('p'),
)
.category(Category::FileSystem)
}
@ -70,9 +76,9 @@ impl Command for Cp {
let verbose = call.has_flag("verbose");
let interactive = call.has_flag("interactive");
let path = current_dir(engine_state, stack)?;
let source = path.join(src.item.as_str());
let destination = path.join(dst.item.as_str());
let current_dir_path = current_dir(engine_state, stack)?;
let source = current_dir_path.join(src.item.as_str());
let destination = current_dir_path.join(dst.item.as_str());
// check if destination is a dir and it exists
let path_last_char = destination.as_os_str().to_string_lossy().chars().last();
@ -140,7 +146,7 @@ impl Command for Cp {
if entry.is_file() {
let sources = sources.paths_applying_with(|(source_file, _depth_level)| {
if destination.is_dir() {
let mut dest = canonicalize_with(&dst.item, &path)?;
let mut dest = canonicalize_with(&dst.item, &current_dir_path)?;
if let Some(name) = entry.file_name() {
dest.push(name);
}
@ -153,7 +159,7 @@ impl Command for Cp {
for (src, dst) in sources {
if src.is_file() {
let res = if interactive && dst.exists() {
interactive_copy_file(interactive, src, dst, span)
interactive_copy(interactive, src, dst, span, copy_file)
} else {
copy_file(src, dst, span)
};
@ -188,9 +194,23 @@ impl Command for Cp {
)
})?;
let not_follow_symlink = call.has_flag("no-dereference");
let sources = sources.paths_applying_with(|(source_file, depth_level)| {
let mut dest = destination.clone();
let path = canonicalize_with(&source_file, &path)?;
let path = if not_follow_symlink {
expand_path_with(&source_file, &current_dir_path)
} else {
canonicalize_with(&source_file, &current_dir_path).or_else(|err| {
// check if dangling symbolic link.
let path = expand_path_with(&source_file, &current_dir_path);
if path.is_symlink() && !path.exists() {
Ok(path)
} else {
Err(err)
}
})?
};
#[allow(clippy::needless_collect)]
let comps: Vec<_> = path
@ -220,14 +240,21 @@ impl Command for Cp {
})?;
}
if s.is_file() {
if s.is_symlink() && not_follow_symlink {
let res = if interactive && d.exists() {
interactive_copy_file(interactive, s, d, span)
interactive_copy(interactive, s, d, span, copy_symlink)
} else {
copy_symlink(s, d, span)
};
result.push(res);
} else if s.is_file() {
let res = if interactive && d.exists() {
interactive_copy(interactive, s, d, span, copy_file)
} else {
copy_file(s, d, span)
};
result.push(res);
}
};
}
}
}
@ -265,7 +292,13 @@ impl Command for Cp {
}
}
fn interactive_copy_file(interactive: bool, src: PathBuf, dst: PathBuf, span: Span) -> Value {
fn interactive_copy(
interactive: bool,
src: PathBuf,
dst: PathBuf,
span: Span,
copy_impl: impl Fn(PathBuf, PathBuf, Span) -> Value,
) -> Value {
let (interaction, confirmed) =
try_interaction(interactive, "cp: overwrite", &dst.to_string_lossy());
if let Err(e) = interaction {
@ -282,7 +315,7 @@ fn interactive_copy_file(interactive: bool, src: PathBuf, dst: PathBuf, span: Sp
let msg = format!("{:} not copied to {:}", src.display(), dst.display());
Value::String { val: msg, span }
} else {
copy_file(src, dst, span)
copy_impl(src, dst, span)
}
}
@ -293,13 +326,51 @@ fn copy_file(src: PathBuf, dst: PathBuf, span: Span) -> Value {
Value::String { val: msg, span }
}
Err(e) => Value::Error {
error: ShellError::GenericError(
e.to_string(),
e.to_string(),
Some(span),
None,
Vec::new(),
),
error: ShellError::FileNotFoundCustom(format!("copy file {src:?} failed: {e}"), span),
},
}
}
fn copy_symlink(src: PathBuf, dst: PathBuf, span: Span) -> Value {
let target_path = read_link(src.as_path());
let target_path = match target_path {
Ok(p) => p,
Err(err) => {
return Value::Error {
error: ShellError::GenericError(
err.to_string(),
err.to_string(),
Some(span),
None,
vec![],
),
}
}
};
let create_symlink = {
#[cfg(unix)]
{
std::os::unix::fs::symlink
}
#[cfg(windows)]
{
if !target_path.exists() || target_path.is_file() {
std::os::windows::fs::symlink_file
} else {
std::os::windows::fs::symlink_dir
}
}
};
match create_symlink(target_path.as_path(), dst.as_path()) {
Ok(_) => {
let msg = format!("copied {:} to {:}", src.display(), dst.display());
Value::String { val: msg, span }
}
Err(e) => Value::Error {
error: ShellError::GenericError(e.to_string(), e.to_string(), Some(span), None, vec![]),
},
}
}

View File

@ -27,6 +27,10 @@ impl Command for All {
"Test if every element of the input matches a predicate."
}
fn search_terms(&self) -> Vec<&str> {
vec!["every"]
}
fn examples(&self) -> Vec<Example> {
vec![
Example {

View File

@ -27,6 +27,10 @@ impl Command for Any {
"Tests if any element of the input matches a predicate."
}
fn search_terms(&self) -> Vec<&str> {
vec!["some"]
}
fn examples(&self) -> Vec<Example> {
vec![
Example {

View File

@ -27,7 +27,14 @@ impl Command for Columns {
Example {
example: "[[name,age,grade]; [bill,20,a]] | columns",
description: "Get the columns from the table",
result: None,
result: Some(Value::List {
vals: vec![
Value::test_string("name"),
Value::test_string("age"),
Value::test_string("grade"),
],
span: Span::test_data(),
}),
},
Example {
example: "[[name,age,grade]; [bill,20,a]] | columns | first",

View File

@ -57,11 +57,18 @@ impl Command for DropColumn {
description: "Remove the last column of a table",
example: "echo [[lib, extension]; [nu-lib, rs] [nu-core, rb]] | drop column",
result: Some(Value::List {
vals: vec![Value::Record {
cols: vec!["lib".into()],
vals: vec![Value::test_string("nu-lib"), Value::test_string("nu-core")],
span: Span::test_data(),
}],
vals: vec![
Value::Record {
cols: vec!["lib".into()],
vals: vec![Value::test_string("nu-lib")],
span: Span::test_data(),
},
Value::Record {
cols: vec!["lib".into()],
vals: vec![Value::test_string("nu-core")],
span: Span::test_data(),
},
],
span: Span::test_data(),
}),
}]
@ -180,3 +187,13 @@ fn get_keep_columns(input: Vec<String>, mut num_of_columns_to_drop: i64) -> Vec<
let num_of_columns_to_keep = (vlen - num_of_columns_to_drop) as usize;
input[0..num_of_columns_to_keep].to_vec()
}
#[cfg(test)]
mod test {
#[test]
fn test_examples() {
use super::DropColumn;
use crate::test_examples;
test_examples(DropColumn {})
}
}

View File

@ -24,6 +24,10 @@ impl Command for Length {
.category(Category::Filters)
}
fn search_terms(&self) -> Vec<&str> {
vec!["count", "len", "size"]
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -59,6 +59,14 @@ impl Command for Merge {
vec![Value::test_int(1), Value::test_int(2), Value::test_int(3)],
)),
},
Example {
example: "{a: 1, b: 3} | merge { {b: 2, c: 4} }",
description: "Merge two records with overlap key",
result: Some(Value::test_record(
vec!["a", "b", "c"],
vec![Value::test_int(1), Value::test_int(2), Value::test_int(4)],
)),
},
]
}
@ -106,8 +114,10 @@ impl Command for Merge {
(Ok((inp_cols, inp_vals)), Some(to_merge)) => {
match to_merge.as_record() {
Ok((to_merge_cols, to_merge_vals)) => {
let cols = [inp_cols, to_merge_cols].concat();
let vals = [inp_vals, to_merge_vals].concat();
let (cols, vals) = do_merge(
(inp_cols.to_vec(), inp_vals.to_vec()),
(to_merge_cols.to_vec(), to_merge_vals.to_vec()),
);
Value::Record {
cols,
vals,
@ -146,12 +156,10 @@ impl Command for Merge {
..,
),
) => {
let mut cols = inp_cols.to_vec();
cols.extend(to_merge_cols.to_vec());
let mut vals = inp_vals.to_vec();
vals.extend(to_merge_vals.to_vec());
let (cols, vals) = do_merge(
(inp_cols.to_vec(), inp_vals.to_vec()),
(to_merge_cols.to_vec(), to_merge_vals.to_vec()),
);
Ok(Value::Record {
cols,
vals,
@ -181,6 +189,29 @@ impl Command for Merge {
}
}
fn do_merge(
input_record: (Vec<String>, Vec<Value>),
to_merge_record: (Vec<String>, Vec<Value>),
) -> (Vec<String>, Vec<Value>) {
let (mut result_cols, mut result_vals) = input_record;
let (to_merge_cols, to_merge_vals) = to_merge_record;
for (col, val) in to_merge_cols.into_iter().zip(to_merge_vals) {
let pos = result_cols.iter().position(|c| c == &col);
// if find, replace existing data, else, push new data.
match pos {
Some(index) => {
result_vals[index] = val;
}
None => {
result_cols.push(col);
result_vals.push(val);
}
}
}
(result_cols, result_vals)
}
#[cfg(test)]
mod test {
use super::*;

View File

@ -205,3 +205,13 @@ fn reject_record_columns(cols: &mut Vec<String>, vals: &mut Vec<Value>, rejects:
}
}
}
#[cfg(test)]
mod test {
#[test]
fn test_examples() {
use super::Reject;
use crate::test_examples;
test_examples(Reject {})
}
}

View File

@ -70,13 +70,35 @@ impl Command for Wrap {
description: "Wrap a list into a table with a given column name",
example: "echo [1 2 3] | wrap num",
result: Some(Value::List {
vals: vec![Value::Record {
cols: vec!["num".into()],
vals: vec![Value::test_int(1), Value::test_int(2), Value::test_int(3)],
span: Span::test_data(),
}],
vals: vec![
Value::Record {
cols: vec!["num".into()],
vals: vec![Value::test_int(1)],
span: Span::test_data(),
},
Value::Record {
cols: vec!["num".into()],
vals: vec![Value::test_int(2)],
span: Span::test_data(),
},
Value::Record {
cols: vec!["num".into()],
vals: vec![Value::test_int(3)],
span: Span::test_data(),
},
],
span: Span::test_data(),
}),
}]
}
}
#[cfg(test)]
mod test {
#[test]
fn test_examples() {
use super::Wrap;
use crate::test_examples;
test_examples(Wrap {})
}
}

View File

@ -55,12 +55,12 @@ impl Command for FromOds {
vec![
Example {
description: "Convert binary .ods data to a table",
example: "open test.txt | from ods",
example: "open --raw test.ods | from ods",
result: None,
},
Example {
description: "Convert binary .ods data to a table, specifying the tables",
example: "open test.txt | from ods -s [Spreadsheet1]",
example: "open --raw test.ods | from ods -s [Spreadsheet1]",
result: None,
},
]

View File

@ -55,12 +55,12 @@ impl Command for FromXlsx {
vec![
Example {
description: "Convert binary .xlsx data to a table",
example: "open test.txt | from xlsx",
example: "open --raw test.xlsx | from xlsx",
result: None,
},
Example {
description: "Convert binary .xlsx data to a table, specifying the tables",
example: "open test.txt | from xlsx -s [Spreadsheet1]",
example: "open --raw test.xlsx | from xlsx -s [Spreadsheet1]",
result: None,
},
]

View File

@ -39,7 +39,7 @@ impl Command for ToNuon {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Outputs a nuon string representing the contents of this table",
description: "Outputs a nuon string representing the contents of this list",
example: "[1 2 3] | to nuon",
result: Some(Value::test_string("[1, 2, 3]")),
}]
@ -147,3 +147,13 @@ fn to_nuon(call: &Call, input: PipelineData) -> Result<String, ShellError> {
value_to_string(&v, call.head)
}
#[cfg(test)]
mod test {
#[test]
fn test_examples() {
use super::ToNuon;
use crate::test_examples;
test_examples(ToNuon {})
}
}

View File

@ -232,9 +232,15 @@ fn action(
#[cfg(test)]
mod tests {
use super::{action, ActionType, Base64Config};
use super::{action, ActionType, Base64, Base64Config};
use nu_protocol::{Span, Value};
#[test]
fn test_examples() {
use crate::test_examples;
test_examples(Base64 {})
}
#[test]
fn base64_encode_standard() {
let word = Value::string("username:password", Span::test_data());

View File

@ -77,7 +77,21 @@ On Windows, an extra 'prefix' column is added."#
Example {
description: "Parse a single path",
example: r"'C:\Users\viking\spam.txt' | path parse",
result: None,
result: Some(Value::Record {
cols: vec![
"prefix".into(),
"parent".into(),
"stem".into(),
"extension".into(),
],
vals: vec![
Value::test_string("C:"),
Value::test_string(r"C:\Users\viking"),
Value::test_string("spam"),
Value::test_string("txt"),
],
span: Span::test_data(),
}),
},
Example {
description: "Replace a complex extension",
@ -87,7 +101,21 @@ On Windows, an extra 'prefix' column is added."#
Example {
description: "Ignore the extension",
example: r"'C:\Users\viking.d' | path parse -e ''",
result: None,
result: Some(Value::Record {
cols: vec![
"prefix".into(),
"parent".into(),
"stem".into(),
"extension".into(),
],
vals: vec![
Value::test_string("C:"),
Value::test_string(r"C:\Users"),
Value::test_string("viking.d"),
Value::test_string(""),
],
span: Span::test_data(),
}),
},
Example {
description: "Parse all paths under the 'name' column",
@ -103,7 +131,15 @@ On Windows, an extra 'prefix' column is added."#
Example {
description: "Parse a path",
example: r"'/home/viking/spam.txt' | path parse",
result: None,
result: Some(Value::Record {
cols: vec!["parent".into(), "stem".into(), "extension".into()],
vals: vec![
Value::test_string("/home/viking"),
Value::test_string("spam"),
Value::test_string("txt"),
],
span: Span::test_data(),
}),
},
Example {
description: "Replace a complex extension",
@ -113,7 +149,15 @@ On Windows, an extra 'prefix' column is added."#
Example {
description: "Ignore the extension",
example: r"'/etc/conf.d' | path parse -e ''",
result: None,
result: Some(Value::Record {
cols: vec!["parent".into(), "stem".into(), "extension".into()],
vals: vec![
Value::test_string("/etc"),
Value::test_string("conf.d"),
Value::test_string(""),
],
span: Span::test_data(),
}),
},
Example {
description: "Parse all paths under the 'name' column",

View File

@ -21,6 +21,10 @@ impl Command for Keybindings {
"Keybindings related commands"
}
fn search_terms(&self) -> Vec<&str> {
vec!["shortcut", "hotkey"]
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -18,7 +18,11 @@ impl Command for RandomCommand {
}
fn usage(&self) -> &str {
"Generate a random values."
"Generate a random value."
}
fn search_terms(&self) -> Vec<&str> {
vec!["generate", "generator"]
}
fn run(

View File

@ -139,7 +139,7 @@ prints out the list properly."#
description: "Render a simple list to a grid",
example: "[1 2 3 a b c] | grid",
result: Some(Value::String {
val: "1 │ 2 │ 3 │ a │ b │ c".to_string(),
val: "1 │ 2 │ 3 │ a │ b │ c\n".to_string(),
span: Span::test_data(),
}),
},
@ -147,7 +147,7 @@ prints out the list properly."#
description: "The above example is the same as:",
example: "[1 2 3 a b c] | wrap name | grid",
result: Some(Value::String {
val: "1 │ 2 │ 3 │ a │ b │ c".to_string(),
val: "1 │ 2 │ 3 │ a │ b │ c\n".to_string(),
span: Span::test_data(),
}),
},
@ -155,7 +155,7 @@ prints out the list properly."#
description: "Render a record to a grid",
example: "{name: 'foo', b: 1, c: 2} | grid",
result: Some(Value::String {
val: "foo".to_string(),
val: "foo\n".to_string(),
span: Span::test_data(),
}),
},
@ -163,7 +163,7 @@ prints out the list properly."#
description: "Render a list of records to a grid",
example: "[{name: 'A', v: 1} {name: 'B', v: 2} {name: 'C', v: 3}] | grid",
result: Some(Value::String {
val: "A │ B │ C".to_string(),
val: "A │ B │ C\n".to_string(),
span: Span::test_data(),
}),
},
@ -171,7 +171,7 @@ prints out the list properly."#
description: "Render a table with 'name' column in it to a grid",
example: "[[name patch]; [0.1.0 false] [0.1.1 true] [0.2.0 false]] | grid",
result: Some(Value::String {
val: "0.1.0 │ 0.1.1 │ 0.2.0".to_string(),
val: "0.1.0 │ 0.1.1 │ 0.2.0\n".to_string(),
span: Span::test_data(),
}),
},
@ -358,3 +358,13 @@ fn convert_to_list(
None
}
}
#[cfg(test)]
mod test {
#[test]
fn test_examples() {
use super::Griddle;
use crate::test_examples;
test_examples(Griddle {})
}
}

View File

@ -18,6 +18,16 @@ use terminal_size::{Height, Width};
const STREAM_PAGE_SIZE: usize = 1000;
const STREAM_TIMEOUT_CHECK_INTERVAL: usize = 100;
fn get_width_param(width_param: Option<i64>) -> usize {
if let Some(col) = width_param {
col as usize
} else if let Some((Width(w), Height(_h))) = terminal_size::terminal_size() {
(w - 1) as usize
} else {
80usize
}
}
#[derive(Clone)]
pub struct Table;
@ -44,6 +54,12 @@ impl Command for Table {
Some('n'),
)
.switch("list", "list available table modes/themes", Some('l'))
.named(
"width",
SyntaxShape::Int,
"number of terminal columns wide (not output columns)",
Some('w'),
)
.category(Category::Viewers)
}
@ -62,11 +78,8 @@ impl Command for Table {
let row_offset = start_num.unwrap_or_default() as usize;
let list: bool = call.has_flag("list");
let term_width = if let Some((Width(w), Height(_h))) = terminal_size::terminal_size() {
(w - 1) as usize
} else {
80usize
};
let width_param: Option<i64> = call.get_flag(engine_state, stack, "width")?;
let term_width = get_width_param(width_param);
if list {
let table_modes = vec![
@ -222,7 +235,7 @@ impl Command for Table {
#[allow(clippy::too_many_arguments)]
fn handle_row_stream(
engine_state: &EngineState,
stack: &Stack,
stack: &mut Stack,
stream: ListStream,
call: &Call,
row_offset: usize,
@ -306,6 +319,7 @@ fn handle_row_stream(
};
let head = call.head;
let width_param: Option<i64> = call.get_flag(engine_state, stack, "width")?;
Ok(PipelineData::ExternalStream {
stdout: Some(RawStream::new(
@ -315,6 +329,7 @@ fn handle_row_stream(
ctrlc: ctrlc.clone(),
head,
stream,
width_param,
}),
ctrlc,
head,
@ -469,6 +484,7 @@ struct PagingTableCreator {
ctrlc: Option<Arc<AtomicBool>>,
config: Config,
row_offset: usize,
width_param: Option<i64>,
}
impl Iterator for PagingTableCreator {
@ -507,12 +523,7 @@ impl Iterator for PagingTableCreator {
}
let color_hm = get_color_config(&self.config);
let term_width = if let Some((Width(w), Height(_h))) = terminal_size::terminal_size() {
(w - 1) as usize
} else {
80usize
};
let term_width = get_width_param(self.width_param);
let table = convert_to_table(
self.row_offset,

View File

@ -1,3 +1,4 @@
use nu_test_support::fs::file_contents;
use nu_test_support::fs::{files_exist_at, AbsoluteFile, Stub::EmptyFile};
use nu_test_support::nu;
use nu_test_support::playground::Playground;
@ -249,3 +250,71 @@ fn copy_to_non_existing_dir() {
assert!(actual.err.contains("destination directory does not exist"));
});
}
#[test]
fn copy_dir_contains_symlink_ignored() {
Playground::setup("cp_test_12", |_dirs, sandbox| {
sandbox
.within("tmp_dir")
.with_files(vec![EmptyFile("hello_there"), EmptyFile("good_bye")])
.within("tmp_dir")
.symlink("good_bye", "dangle_symlink");
// make symbolic link and copy.
nu!(
cwd: sandbox.cwd(),
"rm tmp_dir/good_bye; cp -r tmp_dir tmp_dir_2",
);
// check hello_there exists inside `tmp_dir_2`, and `dangle_symlink` don't exists inside `tmp_dir_2`.
let expected = sandbox.cwd().join("tmp_dir_2");
assert!(files_exist_at(vec!["hello_there"], expected.clone()));
let path = expected.join("dangle_symlink");
assert!(!path.exists() && !path.is_symlink());
});
}
#[test]
fn copy_dir_contains_symlink() {
Playground::setup("cp_test_13", |_dirs, sandbox| {
sandbox
.within("tmp_dir")
.with_files(vec![EmptyFile("hello_there"), EmptyFile("good_bye")])
.within("tmp_dir")
.symlink("good_bye", "dangle_symlink");
// make symbolic link and copy.
nu!(
cwd: sandbox.cwd(),
"rm tmp_dir/good_bye; cp -r -p tmp_dir tmp_dir_2",
);
// check hello_there exists inside `tmp_dir_2`, and `dangle_symlink` also exists inside `tmp_dir_2`.
let expected = sandbox.cwd().join("tmp_dir_2");
assert!(files_exist_at(vec!["hello_there"], expected.clone()));
let path = expected.join("dangle_symlink");
assert!(path.is_symlink());
});
}
#[test]
fn copy_dir_symlink_file_body_not_changed() {
Playground::setup("cp_test_14", |_dirs, sandbox| {
sandbox
.within("tmp_dir")
.with_files(vec![EmptyFile("hello_there"), EmptyFile("good_bye")])
.within("tmp_dir")
.symlink("good_bye", "dangle_symlink");
// make symbolic link and copy.
nu!(
cwd: sandbox.cwd(),
"rm tmp_dir/good_bye; cp -r -p tmp_dir tmp_dir_2; rm -r tmp_dir; cp -r -p tmp_dir_2 tmp_dir; echo hello_data | save tmp_dir/good_bye",
);
// check dangle_symlink in tmp_dir is no longer dangling.
let expected_file = sandbox.cwd().join("tmp_dir").join("dangle_symlink");
let actual = file_contents(expected_file);
assert!(actual.contains("hello_data"));
});
}

View File

@ -81,3 +81,29 @@ fn ignores_duplicate_columns_rejected() {
assert_eq!(actual.out, "last name");
}
#[test]
fn reject_record_from_raw_eval() {
let actual = nu!(
cwd: ".", pipeline(
r#"
{"a": 3, "a": 4} | reject a | describe
"#
)
);
assert!(actual.out.contains("record<>"));
}
#[test]
fn reject_table_from_raw_eval() {
let actual = nu!(
cwd: ".", pipeline(
r#"
[{"a": 3, "a": 4}] | reject a
"#
)
);
assert!(actual.out.contains("record 0 fields"));
}

View File

@ -4,13 +4,13 @@ description = "Nushell's evaluation engine"
edition = "2021"
license = "MIT"
name = "nu-engine"
version = "0.63.0"
version = "0.63.1"
[dependencies]
nu-protocol = { path = "../nu-protocol", features = ["plugin"], version = "0.63.0" }
nu-path = { path = "../nu-path", version = "0.63.0" }
nu-glob = { path = "../nu-glob", version = "0.63.0" }
nu-utils = { path = "../nu-utils", version = "0.63.0" }
nu-protocol = { path = "../nu-protocol", features = ["plugin"], version = "0.63.1" }
nu-path = { path = "../nu-path", version = "0.63.1" }
nu-glob = { path = "../nu-glob", version = "0.63.1" }
nu-utils = { path = "../nu-utils", version = "0.63.1" }
chrono = { version="0.4.19", features=["serde"] }
sysinfo = "0.23.10"

View File

@ -472,8 +472,18 @@ pub fn eval_expression(
let mut cols = vec![];
let mut vals = vec![];
for (col, val) in fields {
cols.push(eval_expression(engine_state, stack, col)?.as_string()?);
vals.push(eval_expression(engine_state, stack, val)?);
// avoid duplicate cols.
let col_name = eval_expression(engine_state, stack, col)?.as_string()?;
let pos = cols.iter().position(|c| c == &col_name);
match pos {
Some(index) => {
vals[index] = eval_expression(engine_state, stack, val)?;
}
None => {
cols.push(col_name);
vals.push(eval_expression(engine_state, stack, val)?);
}
}
}
Ok(Value::Record {

View File

@ -1,6 +1,6 @@
[package]
name = "nu-glob"
version = "0.63.0"
version = "0.63.1"
authors = ["The Nushell Project Developers", "The Rust Project Developers"]
license = "MIT/Apache-2.0"
description = """

View File

@ -4,7 +4,7 @@ description = "Fork of serde-hjson"
edition = "2021"
license = "MIT"
name = "nu-json"
version = "0.63.0"
version = "0.63.1"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -20,5 +20,5 @@ lazy_static = "1"
linked-hash-map = { version="0.5", optional=true }
[dev-dependencies]
nu-path = { path="../nu-path", version = "0.63.0" }
nu-path = { path="../nu-path", version = "0.63.1" }
serde_json = "1.0"

View File

@ -4,16 +4,16 @@ description = "Nushell's parser"
edition = "2021"
license = "MIT"
name = "nu-parser"
version = "0.63.0"
version = "0.63.1"
[dependencies]
chrono = "0.4.19"
miette = "4.5.0"
thiserror = "1.0.29"
serde_json = "1.0"
nu-path = {path = "../nu-path", version = "0.63.0" }
nu-protocol = { path = "../nu-protocol", version = "0.63.0" }
nu-plugin = { path = "../nu-plugin", optional = true, version = "0.63.0" }
nu-path = {path = "../nu-path", version = "0.63.1" }
nu-protocol = { path = "../nu-protocol", version = "0.63.1" }
nu-plugin = { path = "../nu-plugin", optional = true, version = "0.63.1" }
log = "0.4"
[features]

View File

@ -78,6 +78,16 @@ pub enum ParseError {
)]
BuiltinCommandInPipeline(String, #[label("not allowed in pipeline")] Span),
#[error("Let statement used in pipeline.")]
#[diagnostic(
code(nu::parser::unexpected_keyword),
url(docsrs),
help(
"Assigning '{0}' to '{1}' does not produce a value to be piped. If the pipeline is meant to apply to '{0}' by itself, use 'let {1} = ({0} | ...)'."
)
)]
LetInPipeline(String, String, #[label("let in pipeline")] Span),
#[error("Incorrect value")]
#[diagnostic(code(nu::parser::incorrect_value), url(docsrs), help("{2}"))]
IncorrectValue(String, #[label("unexpected {0}")] Span, String),
@ -300,6 +310,7 @@ impl ParseError {
ParseError::ExpectedKeyword(_, s) => *s,
ParseError::UnexpectedKeyword(_, s) => *s,
ParseError::BuiltinCommandInPipeline(_, s) => *s,
ParseError::LetInPipeline(_, _, s) => *s,
ParseError::IncorrectValue(_, s, _) => *s,
ParseError::MultipleRestParams(s) => *s,
ParseError::VariableNotFound(s) => *s,

View File

@ -1745,6 +1745,9 @@ pub fn parse_overlay(
None,
);
}
b"new" => {
return parse_overlay_new(working_set, spans, expand_aliases_denylist);
}
b"remove" => {
return parse_overlay_remove(working_set, spans, expand_aliases_denylist);
}
@ -1802,6 +1805,96 @@ pub fn parse_overlay(
)
}
pub fn parse_overlay_new(
working_set: &mut StateWorkingSet,
spans: &[Span],
expand_aliases_denylist: &[usize],
) -> (Pipeline, Option<ParseError>) {
if spans.len() > 1 && working_set.get_span_contents(span(&spans[0..2])) != b"overlay new" {
return (
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: Wrong call name for 'overlay new' command".into(),
span(spans),
)),
);
}
let (call, call_span) = match working_set.find_decl(b"overlay new") {
Some(decl_id) => {
let (call, mut err) = parse_internal_call(
working_set,
span(&spans[0..2]),
&spans[2..],
decl_id,
expand_aliases_denylist,
);
let decl = working_set.get_decl(decl_id);
let call_span = span(spans);
err = check_call(call_span, &decl.signature(), &call).or(err);
if err.is_some() || call.has_flag("help") {
return (
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
custom_completion: None,
}]),
err,
);
}
(call, call_span)
}
None => {
return (
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: 'overlay new' declaration not found".into(),
span(spans),
)),
)
}
};
let (overlay_name, _) = if let Some(expr) = call.positional_nth(0) {
if let Some(s) = expr.as_string() {
(s, expr.span)
} else {
return (
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: Module name not a string".into(),
expr.span,
)),
);
}
} else {
return (
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: Missing required positional after call parsing".into(),
call_span,
)),
);
};
let pipeline = Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: span(spans),
ty: Type::Any,
custom_completion: None,
}]);
let module_id = working_set.add_module(&overlay_name, Module::new());
working_set.add_overlay(overlay_name.as_bytes().to_vec(), module_id, vec![], vec![]);
(pipeline, None)
}
pub fn parse_overlay_add(
working_set: &mut StateWorkingSet,
spans: &[Span],

View File

@ -4371,7 +4371,12 @@ pub fn parse_expression(
expand_aliases_denylist,
)
.0,
Some(ParseError::BuiltinCommandInPipeline("let".into(), spans[0])),
Some(ParseError::LetInPipeline(
String::from_utf8_lossy(working_set.get_span_contents(spans[spans.len() - 1]))
.to_string(),
String::from_utf8_lossy(working_set.get_span_contents(spans[1])).to_string(),
spans[0],
)),
),
b"alias" => (
parse_call(

View File

@ -4,7 +4,7 @@ description = "Path handling library for Nushell"
edition = "2021"
license = "MIT"
name = "nu-path"
version = "0.63.0"
version = "0.63.1"
[dependencies]
dirs-next = "2.0.0"

View File

@ -4,11 +4,11 @@ description = "Functionality for building Nushell plugins"
edition = "2021"
license = "MIT"
name = "nu-plugin"
version = "0.63.0"
version = "0.63.1"
[dependencies]
capnp = "0.14.3"
nu-protocol = { path = "../nu-protocol", version = "0.63.0" }
nu-engine = { path = "../nu-engine", version = "0.63.0" }
nu-protocol = { path = "../nu-protocol", version = "0.63.1" }
nu-engine = { path = "../nu-engine", version = "0.63.1" }
serde = {version = "1.0.130", features = ["derive"]}
serde_json = { version = "1.0"}

View File

@ -4,7 +4,7 @@ description = "Pretty hex dump of bytes slice in the common style."
edition = "2021"
license = "MIT"
name = "nu-pretty-hex"
version = "0.63.0"
version = "0.63.1"
[lib]
doctest = false

View File

@ -4,12 +4,12 @@ description = "Nushell's internal protocols, including its abstract syntax tree"
edition = "2021"
license = "MIT"
name = "nu-protocol"
version = "0.63.0"
version = "0.63.1"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nu-utils = { path = "../nu-utils", version = "0.63.0" }
nu-utils = { path = "../nu-utils", version = "0.63.1" }
thiserror = "1.0.29"
miette = { version = "4.5.0", features = ["fancy"] }
serde = {version = "1.0.130", features = ["derive"]}
@ -18,7 +18,7 @@ indexmap = { version="1.7", features=["serde-1"] }
chrono-humanize = "0.2.1"
byte-unit = "4.0.9"
serde_json = { version = "1.0", optional = true }
nu-json = { path = "../nu-json", version = "0.63.0" }
nu-json = { path = "../nu-json", version = "0.63.1" }
typetag = "0.1.8"
num-format = "0.4.0"
sys-locale = "0.2.0"

View File

@ -75,6 +75,7 @@ pub struct Config {
pub buffer_editor: String,
pub disable_table_indexes: bool,
pub cd_with_abbreviations: bool,
pub case_sensitive_completions: bool,
}
impl Default for Config {
@ -105,6 +106,7 @@ impl Default for Config {
buffer_editor: String::new(),
disable_table_indexes: false,
cd_with_abbreviations: false,
case_sensitive_completions: false,
}
}
}
@ -311,7 +313,14 @@ impl Value {
if let Ok(b) = value.as_bool() {
config.cd_with_abbreviations = b;
} else {
eprintln!("$config.disable_table_indexes is not a bool")
eprintln!("$config.cd_with_abbreviations is not a bool")
}
}
"case_sensitive_completions" => {
if let Ok(b) = value.as_bool() {
config.case_sensitive_completions = b;
} else {
eprintln!("$config.case_sensitive_completions is not a bool")
}
}
x => {

View File

@ -148,7 +148,7 @@ dependencies = [
[[package]]
name = "nu-system"
version = "0.63.0"
version = "0.63.1"
dependencies = [
"errno",
"libproc",

View File

@ -2,7 +2,7 @@
authors = ["The Nushell Project Developers", "procs creators"]
description = "Nushell system querying"
name = "nu-system"
version = "0.63.0"
version = "0.63.1"
edition = "2021"
license = "MIT"

View File

@ -4,7 +4,7 @@ description = "Nushell table printing"
edition = "2021"
license = "MIT"
name = "nu-table"
version = "0.63.0"
version = "0.63.1"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[[bin]]
@ -13,7 +13,7 @@ path = "src/main.rs"
[dependencies]
nu-ansi-term = "0.45.1"
nu-protocol = { path = "../nu-protocol", version = "0.63.0" }
nu-protocol = { path = "../nu-protocol", version = "0.63.1" }
regex = "1.4"
unicode-width = "0.1.8"
strip-ansi-escapes = "0.1.1"

View File

@ -491,14 +491,20 @@ pub fn draw_table(
config: &Config,
) -> String {
// Remove the edges, if used
let termwidth = if table.theme.print_left_border && table.theme.print_right_border {
termwidth - 3
let edges_width = if table.theme.print_left_border && table.theme.print_right_border {
3
} else if table.theme.print_left_border || table.theme.print_right_border {
termwidth - 1
1
} else {
termwidth
0
};
if termwidth < edges_width {
return format!("Couldn't fit table into {} columns!", termwidth);
}
let termwidth = termwidth - edges_width;
let mut processed_table = process_table(table);
let max_per_column = get_max_column_widths(&processed_table);

View File

@ -4,7 +4,7 @@ description = "Nushell grid printing"
edition = "2021"
license = "MIT"
name = "nu-term-grid"
version = "0.63.0"
version = "0.63.1"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[[bin]]

View File

@ -4,14 +4,14 @@ description = "Support for writing Nushell tests"
edition = "2018"
license = "MIT"
name = "nu-test-support"
version = "0.63.0"
version = "0.63.1"
[lib]
doctest = false
[dependencies]
nu-path = { path="../nu-path", version = "0.63.0" }
nu-glob = { path = "../nu-glob", version = "0.63.0" }
nu-path = { path="../nu-path", version = "0.63.1" }
nu-glob = { path = "../nu-glob", version = "0.63.1" }
getset = "0.1.1"
num-bigint = { version="0.4.3", features=["serde"] }

View File

@ -228,7 +228,9 @@ impl<'a> Playground<'a> {
pub fn within(&mut self, directory: &str) -> &mut Self {
self.cwd.push(directory);
std::fs::create_dir(&self.cwd).expect("can not create directory");
if !(self.cwd.exists() && self.cwd.is_dir()) {
std::fs::create_dir(&self.cwd).expect("can not create directory");
}
self
}

View File

@ -4,7 +4,7 @@ description = "Nushell utility functions"
edition = "2021"
license = "MIT"
name = "nu-utils"
version = "0.63.0"
version = "0.63.1"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[[bin]]

View File

@ -4,8 +4,8 @@ description = "A version incrementer plugin for Nushell"
edition = "2021"
license = "MIT"
name = "nu_plugin_example"
version = "0.63.0"
version = "0.63.1"
[dependencies]
nu-plugin = { path="../nu-plugin", version = "0.63.0" }
nu-protocol = { path="../nu-protocol", version = "0.63.0", features = ["plugin"]}
nu-plugin = { path="../nu-plugin", version = "0.63.1" }
nu-protocol = { path="../nu-protocol", version = "0.63.1", features = ["plugin"]}

View File

@ -4,14 +4,14 @@ description = "A git status plugin for Nushell"
edition = "2021"
license = "MIT"
name = "nu_plugin_gstat"
version = "0.63.0"
version = "0.63.1"
[lib]
doctest = false
[dependencies]
nu-plugin = { path="../nu-plugin", version = "0.63.0" }
nu-protocol = { path="../nu-protocol", version = "0.63.0" }
nu-engine = { path="../nu-engine", version = "0.63.0" }
nu-plugin = { path="../nu-plugin", version = "0.63.1" }
nu-protocol = { path="../nu-protocol", version = "0.63.1" }
nu-engine = { path="../nu-engine", version = "0.63.1" }
git2 = "0.14.2"

View File

@ -4,13 +4,13 @@ description = "A version incrementer plugin for Nushell"
edition = "2021"
license = "MIT"
name = "nu_plugin_inc"
version = "0.63.0"
version = "0.63.1"
[lib]
doctest = false
[dependencies]
nu-plugin = { path="../nu-plugin", version = "0.63.0" }
nu-protocol = { path="../nu-protocol", version = "0.63.0", features = ["plugin"]}
nu-plugin = { path="../nu-plugin", version = "0.63.1" }
nu-protocol = { path="../nu-protocol", version = "0.63.1", features = ["plugin"]}
semver = "0.11.0"

View File

@ -4,15 +4,15 @@ description = "A Nushell plugin to query JSON, XML, and various web data"
edition = "2021"
license = "MIT"
name = "nu_plugin_query"
version = "0.63.0"
version = "0.63.1"
[lib]
doctest = false
[dependencies]
nu-plugin = { path="../nu-plugin", version = "0.63.0" }
nu-protocol = { path="../nu-protocol", version = "0.63.0" }
nu-engine = { path="../nu-engine", version = "0.63.0" }
nu-plugin = { path="../nu-plugin", version = "0.63.1" }
nu-protocol = { path="../nu-protocol", version = "0.63.1" }
nu-engine = { path="../nu-engine", version = "0.63.1" }
gjson = "0.8.0"
scraper = "0.12.0"
sxd-document = "0.3.2"

View File

@ -4,18 +4,18 @@ description = "A plugin to display charts"
edition = "2018"
license = "MIT"
name = "nu_plugin_chart"
version = "0.63.0"
version = "0.63.1"
[lib]
doctest = false
[dependencies]
nu-data = { path="../nu-data", version = "0.63.0" }
nu-errors = { path="../nu-errors", version = "0.63.0" }
nu-plugin = { path="../nu-plugin", version = "0.63.0" }
nu-protocol = { path="../nu-protocol", version = "0.63.0" }
nu-source = { path="../nu-source", version = "0.63.0" }
nu-value-ext = { path="../nu-value-ext", version = "0.63.0" }
nu-data = { path="../nu-data", version = "0.63.1" }
nu-errors = { path="../nu-errors", version = "0.63.1" }
nu-plugin = { path="../nu-plugin", version = "0.63.1" }
nu-protocol = { path="../nu-protocol", version = "0.63.1" }
nu-source = { path="../nu-source", version = "0.63.1" }
nu-value-ext = { path="../nu-value-ext", version = "0.63.1" }
crossterm = "0.19.0"
tui = { version="0.15.0", default-features=false, features=["crossterm"] }

View File

@ -4,7 +4,7 @@ description = "A converter plugin to the bson format for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_from_bson"
version = "0.63.0"
version = "0.63.1"
[lib]
doctest = false
@ -12,9 +12,9 @@ doctest = false
[dependencies]
bigdecimal = { package = "bigdecimal", version = "0.3.0", features = ["serde"] }
bson = { version = "2.0.1", features = [ "chrono-0_4" ] }
nu-errors = { path="../nu-errors", version = "0.63.0" }
nu-plugin = { path="../nu-plugin", version = "0.63.0" }
nu-protocol = { path="../nu-protocol", version = "0.63.0" }
nu-source = { path="../nu-source", version = "0.63.0" }
nu-errors = { path="../nu-errors", version = "0.63.1" }
nu-plugin = { path="../nu-plugin", version = "0.63.1" }
nu-protocol = { path="../nu-protocol", version = "0.63.1" }
nu-source = { path="../nu-source", version = "0.63.1" }
[build-dependencies]

View File

@ -4,16 +4,16 @@ description = "A converter plugin to the mp4 format for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_from_mp4"
version = "0.63.0"
version = "0.63.1"
[lib]
doctest = false
[dependencies]
nu-errors = { path="../nu-errors", version = "0.63.0" }
nu-plugin = { path="../nu-plugin", version = "0.63.0" }
nu-protocol = { path="../nu-protocol", version = "0.63.0" }
nu-source = { path="../nu-source", version = "0.63.0" }
nu-errors = { path="../nu-errors", version = "0.63.1" }
nu-plugin = { path="../nu-plugin", version = "0.63.1" }
nu-protocol = { path="../nu-protocol", version = "0.63.1" }
nu-source = { path="../nu-source", version = "0.63.1" }
tempfile = "3.2.0"
mp4 = "0.9.0"

View File

@ -4,17 +4,17 @@ description = "A converter plugin to the bson format for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_from_sqlite"
version = "0.63.0"
version = "0.63.1"
[lib]
doctest = false
[dependencies]
bigdecimal = { package = "bigdecimal", version = "0.3.0", features = ["serde"] }
nu-errors = { path="../nu-errors", version = "0.63.0" }
nu-plugin = { path="../nu-plugin", version = "0.63.0" }
nu-protocol = { path="../nu-protocol", version = "0.63.0" }
nu-source = { path="../nu-source", version = "0.63.0" }
nu-errors = { path="../nu-errors", version = "0.63.1" }
nu-plugin = { path="../nu-plugin", version = "0.63.1" }
nu-protocol = { path="../nu-protocol", version = "0.63.1" }
nu-source = { path="../nu-source", version = "0.63.1" }
tempfile = "3.2.0"
[dependencies.rusqlite]

View File

@ -4,17 +4,17 @@ description = "An S3 plugin for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_s3"
version = "0.63.0"
version = "0.63.1"
[lib]
doctest = false
[dependencies]
futures = { version="0.3.12", features=["compat", "io-compat"] }
nu-errors = { path="../nu-errors", version = "0.63.0" }
nu-plugin = { path="../nu-plugin", version = "0.63.0" }
nu-protocol = { path="../nu-protocol", version = "0.63.0" }
nu-source = { path="../nu-source", version = "0.63.0" }
nu-errors = { path="../nu-errors", version = "0.63.1" }
nu-plugin = { path="../nu-plugin", version = "0.63.1" }
nu-protocol = { path="../nu-protocol", version = "0.63.1" }
nu-source = { path="../nu-source", version = "0.63.1" }
s3handler = "0.7.5"
[build-dependencies]

View File

@ -4,17 +4,17 @@ description = "A plugin to open files/URLs directly from Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_start"
version = "0.63.0"
version = "0.63.1"
[lib]
doctest = false
[dependencies]
glob = "0.3.0"
nu-errors = { path="../nu-errors", version = "0.63.0" }
nu-plugin = { path="../nu-plugin", version = "0.63.0" }
nu-protocol = { path="../nu-protocol", version = "0.63.0" }
nu-source = { path="../nu-source", version = "0.63.0" }
nu-errors = { path="../nu-errors", version = "0.63.1" }
nu-plugin = { path="../nu-plugin", version = "0.63.1" }
nu-protocol = { path="../nu-protocol", version = "0.63.1" }
nu-source = { path="../nu-source", version = "0.63.1" }
url = "2.2.0"
webbrowser = "0.5.5"
@ -22,5 +22,5 @@ webbrowser = "0.5.5"
open = "1.4.0"
[build-dependencies]
nu-errors = { version = "0.63.0", path="../nu-errors" }
nu-source = { version = "0.63.0", path="../nu-source" }
nu-errors = { version = "0.63.1", path="../nu-errors" }
nu-source = { version = "0.63.1", path="../nu-source" }

View File

@ -4,17 +4,17 @@ description = "A converter plugin to the bson format for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_to_bson"
version = "0.63.0"
version = "0.63.1"
[lib]
doctest = false
[dependencies]
bson = { version = "2.0.1", features = [ "chrono-0_4" ] }
nu-errors = { path="../nu-errors", version = "0.63.0" }
nu-plugin = { path="../nu-plugin", version = "0.63.0" }
nu-protocol = { path="../nu-protocol", version = "0.63.0" }
nu-source = { path="../nu-source", version = "0.63.0" }
nu-errors = { path="../nu-errors", version = "0.63.1" }
nu-plugin = { path="../nu-plugin", version = "0.63.1" }
nu-protocol = { path="../nu-protocol", version = "0.63.1" }
nu-source = { path="../nu-source", version = "0.63.1" }
num-traits = "0.2.14"
[features]

View File

@ -4,17 +4,17 @@ description = "A converter plugin to the SQLite format for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_to_sqlite"
version = "0.63.0"
version = "0.63.1"
[lib]
doctest = false
[dependencies]
hex = "0.4.2"
nu-errors = { path="../nu-errors", version = "0.63.0" }
nu-plugin = { path="../nu-plugin", version = "0.63.0" }
nu-protocol = { path="../nu-protocol", version = "0.63.0" }
nu-source = { path="../nu-source", version = "0.63.0" }
nu-errors = { path="../nu-errors", version = "0.63.1" }
nu-plugin = { path="../nu-plugin", version = "0.63.1" }
nu-protocol = { path="../nu-protocol", version = "0.63.1" }
nu-source = { path="../nu-source", version = "0.63.1" }
tempfile = "3.2.0"
[dependencies.rusqlite]

View File

@ -4,16 +4,16 @@ description = "Tree viewer plugin for Nushell"
edition = "2018"
license = "MIT"
name = "nu_plugin_tree"
version = "0.63.0"
version = "0.63.1"
[lib]
doctest = false
[dependencies]
derive-new = "0.5.8"
nu-errors = { path="../nu-errors", version = "0.63.0" }
nu-plugin = { path="../nu-plugin", version = "0.63.0" }
nu-protocol = { path="../nu-protocol", version = "0.63.0" }
nu-errors = { path="../nu-errors", version = "0.63.1" }
nu-plugin = { path="../nu-plugin", version = "0.63.1" }
nu-protocol = { path="../nu-protocol", version = "0.63.1" }
ptree = { version = "0.4.0", default-features = false }

View File

@ -199,6 +199,8 @@ let-env config = {
shell_integration: true # enables terminal markers and a workaround to arrow keys stop working issue
disable_table_indexes: false # set to true to remove the index column from tables
cd_with_abbreviations: false # set to true to allow you to do things like cd s/o/f and nushell expand it to cd some/other/folder
case_sensitive_completions: false # set to true to enable case-sensitive completions
hooks: {
pre_prompt: [{
$nothing # replace with source code to run before the prompt is shown

View File

@ -2,7 +2,7 @@
authors = ["Nu authors"]
edition = "2018"
name = "wasm"
version = "0.63.0"
version = "0.63.1"
[lib]
crate-type = ["cdylib", "rlib"]

View File

@ -496,3 +496,14 @@ fn reset_overrides() {
assert_eq!(actual.out, "foo");
assert_eq!(actual_repl.out, "foo");
}
#[test]
fn overlay_new() {
let inp = &[r#"overlay new spam"#, r#"overlay list | last"#];
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
let actual_repl = nu_repl("tests/overlays", inp);
assert_eq!(actual.out, "spam");
assert_eq!(actual_repl.out, "spam");
}