Compare commits

...

65 Commits

Author SHA1 Message Date
JT
d1c719a8cc bump to 0.64 (#5777)
Co-authored-by: sholderbach <sholderbach@users.noreply.github.com>
2022-06-15 14:39:17 +12:00
4d854f36af add --values flag to sort record by values, by default, sort record by keys (#5782) 2022-06-14 20:42:22 -05:00
8d5848c955 bool type for binary operations (#5779)
* bool type for binary operations

* fixed type in commands
2022-06-14 20:31:14 -05:00
fe88d58b1e Pin reedline v0.7.0 for the nushell v0.64.0 release (#5781)
Includes the new History API and sqlite history backend

Release notes: https://github.com/nushell/reedline/releases/tag/v0.7.0
2022-06-14 23:21:14 +02:00
42dbfd1fa0 SQLite History MVP with timestamp, duration, working directory, exit status metadata (#5721)
This PR adds support for an SQLite history via nushell/reedline#401

The SQLite history is enabled by setting history_file_format: "sqlite" in config.nu.

* somewhat working sqlite history
* Hook up history command
* Fix error in SQlitebacked with empty lines

When entering an empty line there previously was the "No command run"
error with `SqliteBackedHistory` during addition of the metadata

May be considered a temporary fix

Co-authored-by: sholderbach <sholderbach@users.noreply.github.com>
2022-06-14 22:53:33 +02:00
534e1fc3ce Add NU config to allow user be able to turn off external completion (#5773)
* 06-07-wsl

* 06-07-linux-issue-with-delete-input

* 06-08-2023

* 06-08-Linux

* commit for merge

* Fix unit test

* format

* clean code

* Add flag to turn off external completion

* change env var to config

* Fix comment

Co-authored-by: Frank Zhang <v-frankz@microsoft.com>
2022-06-14 14:28:11 -05:00
ff946a2f21 each while command (#5771)
* each while command

* test value adjustment
2022-06-14 16:16:31 +02:00
3c0cbec993 sort not change shape (#5778) 2022-06-14 06:41:45 -05:00
48e29e9ed6 path join support multi path (#5775) 2022-06-14 06:34:00 -05:00
ff53352afe Add option to sort-by naturally (#5774)
* add `natural` option to sort-by

* clippy

* Add tests
2022-06-14 09:03:13 +03:00
4fd4136d50 Should we keep old semantics of uniq command? (#5761)
* Update uniq tests with less surprising output

* Remove original nushell surprising semantics
2022-06-14 16:04:29 +12:00
dc1248a454 Fix drop nth bug (#5312)
* Fix drop nth bug on ranges. Should fix & close #5260

* Fix drop nth bug on ranges. Should fix & close #5260

* Add support for ranges

* Working version of drop nth, but the issue is that we unwrap the value which is problematic for Streams. Should convert to the way @stormasm was doing it before and implement the range check

* Fix fmt issue

* Drop nth now works for Lists, Records, and Ranges. We need support for ListStreams and for ExternalStreams

* Keep consistent naming

* Fix fmt issue

* Support ListStreams for drop nth

* Use DropNthIterator instead

* Found a more elegant way to deal with the check for no upper bound input

* Add extra checks for negative inputs or to < from for ranges

Co-authored-by: Stefan Stanciulescu <test@test.com>
2022-06-13 20:49:59 -07:00
de554f8e5f filesize conversion (#5770) 2022-06-13 14:44:32 -05:00
44979f3051 expression to literal (#5769) 2022-06-13 13:22:46 -05:00
JT
7ae7394c85 Force floats to output a decimal in nuon (#5768)
* Force floats to output a decimal in nuon

* Add test
2022-06-14 05:45:07 +12:00
9dbf7556b8 more verbose error handling (#5765) 2022-06-13 07:01:00 -05:00
caafd26deb Attempts to add // math operator (#5759)
* attempts to add `div` math operator

* allows `//` to be used too

* fmt:

* clippy issue

* returns appropriate type

* returns appropriate type 2

* fmt

* ensure consistency; rename to `fdiv`

* Update parser.rs
2022-06-13 13:54:47 +03:00
43a218240c Add setup-nu link in README.md (#5763) 2022-06-13 17:40:38 +08:00
11d7d8ea1e Remove dfr from dataframe commands (#5760)
* input and output tests

* input and output types for dfr

* expression converter

* remove deprecated command

* correct expressions

* cargo clippy

* identifier for ls

* cargo clippy

* type for head and tail expression

* modify full cell path if block
2022-06-12 14:18:00 -05:00
2dea9e6f1f fix arg parse (#5754)
* fix arg parse

* add ut, fix clippy

* simplify code

* fmt code
2022-06-11 20:52:31 +12:00
c5cb369d8d While starting nu, force PWD to be current working directory (#5751)
* fix current working directory during start

* fix tests

* always set PWD to current_dir
2022-06-10 13:01:08 -05:00
b6959197bf Support completion for alias and sub-command (#5749)
* 06-07-wsl

* 06-07-linux-issue-with-delete-input

* 06-08-2023

* 06-08-Linux

* commit for merge

* Fix unit test

* format

* clean code

Co-authored-by: Frank Zhang <v-frankz@microsoft.com>
2022-06-10 12:59:15 -05:00
d5b99ae316 input and output types (#5750)
* input and output types

* added description

* type from stored variable

* string in custom value

* more tests with non custom
2022-06-10 10:59:35 -05:00
9d10007085 Temporarily disable rust-cache in tests (#5747) 2022-06-09 12:03:56 -04:00
2e0b964d5b handle SIGQUIT (#5744)
* handle sigquit

* fix clippy
2022-06-09 07:08:15 -05:00
5bae7e56ef Add $nu.scope.engine_state (#5739)
* Add number of items present in engine state

* Rename num_decls column to num_commands
2022-06-08 13:31:36 -05:00
b42ef45c7c add as record tag to transfer result to record (#5736)
* add as record tag to transfer result to record

* tweak text

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2022-06-08 07:00:19 -05:00
3423cd54a1 add search terms to alias (#5737) 2022-06-08 06:22:53 -05:00
837f0463eb updated Dir to dir 2022-06-07 14:58:23 -05:00
56f6f683fc Clean up README (#5718)
* Clean up README

* Update CONTRIBUTING.md

* Another pass over the README. Table of contents, more install info

* add a little extra features definition

* fix Winget instructions

* Change winget instructions to nushell (easier to remember)

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2022-06-07 12:47:08 -07:00
c57f41e5f2 make to text work more intuitively (#5733) 2022-06-07 14:43:24 -05:00
8c74b1e437 print warning message if meet non utf-8 path (#5731) 2022-06-07 08:22:52 -05:00
8318d59ef1 improve str substring (#5730) 2022-06-07 06:09:16 -05:00
64efa30f3e fix: normalize some parameter names (#5725) 2022-06-06 09:42:13 -05:00
820a6bfb08 feat: add search terms to category of strings (#5723) 2022-06-06 08:47:09 -05:00
b8d253cbd7 Attempts to add a command that checks if nushell is running with admin priveleges (#5712)
* attempts to add is-admin command

* fmt and clippy

* fmt

* Update is_admin.rs

* typos

* typo in example
2022-06-06 06:55:23 -05:00
3c421c5726 Added loginshell config file #4620 (#5714)
* Added loginshell config file #4620

* added sample login.nu

* added environment variable loginshell-path
2022-06-06 06:52:37 -05:00
75b2d26187 fix argument type (#5695)
* fix argument type

* while run external, convert list argument to str

* fix argument converting logic

* using parse_list_expression instead of parse_full_cell_path

* make parsing logic more explicit

* revert changes

* add tests
2022-06-06 13:19:06 +03:00
17a5aa3052 Statically link the CRT on Windows (#5717) 2022-06-05 17:01:01 -07:00
e4a22799d5 nu-engine: better display for shape when showing help params (#5715) 2022-06-05 08:13:04 -05:00
fda456e469 make range require the rows (#5710) 2022-06-04 18:48:01 +12:00
e5d38dcff6 Address lints from clippy for beta/nightly (#5709)
* Fix clippy lints in tests

* Replace `format!` in `.push_str()` with `write!`

Stylistically that might be a bit rough but elides an allocation.

Fallibility of allocation is more explicit, but ignored with `let _ =`
like in the clippy example:

https://rust-lang.github.io/rust-clippy/master/index.html#format_push_string

* Remove unused lifetime

* Fix macro crate relative import

* Derive `Eq` for `PartialEq` with `Eq` members

https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

* Remove unnnecessary `.to_string()` for Cow<str>

* Remove `.to_string()` for `tendril::Tendril`

Implements `Deref<Target = str>`
2022-06-04 18:47:36 +12:00
a82fa75c31 Update nu-ansi-term to remove Deref impl (#5706)
Resolves an unexpected issue due to `Deref` and `ToString` interacting

Details: https://github.com/nushell/nu-ansi-term/pull/5 and https://github.com/nushell/reedline/pull/435#issuecomment-1141348209

Also updates reedline: Includes a fix for a panic when the directory containing the history is deleted during a running reedline session. (nushell/reedline#436)
2022-06-03 21:38:54 +02:00
0c16464320 Use search terms in the help menu search (#5708)
Currently only `help --find` was using the search terms.  With this change they will also be used by the `F1` help menu
2022-06-03 20:30:36 +02:00
888758b813 Fix ls for Windows system files (#5703)
* Fix `ls` for Windows system files

* Fix non-Windows builds

* Make Clippy happy on non-Windows platforms

* Fix new test on GitHub runners

* Move ls Windows code into its own module
2022-06-03 12:37:27 -04:00
cb909f810e fix[table]: Panic when passthru small number of table -w. (#5705) 2022-06-03 07:46:36 -05:00
a75318d7e8 Improve internal documentation of save command (#5704)
- Example for `--append` mode.
- Search terms for redirection
2022-06-03 11:35:31 +02:00
7a9bf06005 Minor fixes to shell integation in repl. (#5701)
Added CMD_FINISHED_MARKER to be emitted when command finishes.
Also switched the names PRE_EXECUTE_MARKER and PRE_PROMPT_MARKER
as the old names were confusing/wrong.
2022-06-02 17:57:19 -05:00
a06299c77a Improve <table> output of 'to html', (#5699)
* Fix <table> output of 'to html',

Specifically, add <thead> and <tbody> elements.
That allows for better styling and (future) some neat JavaScript.

* Update tests for previous <table> changes.
2022-06-02 17:34:31 -05:00
e4bcd1934d Add completions for nu (#5700) 2022-06-02 17:12:59 -05:00
4673adecc5 Fix wrong path help message (#5698) 2022-06-02 23:00:29 +03:00
1b8051ece5 Fix doc building for vuepress-next, avoid using angle brackets (#5696)
* Fix doc building for vuepress-next, avoid using angle brackets

* [ci skip]
2022-06-02 17:38:42 +08:00
d44059c36b feat: Add sensitive flag to get, fix #4295 (#5685)
* feat: Add insensitive flag to get, fix #4295

* add get insensitive example

* Fix get flags

* Update get examples
2022-06-01 08:34:42 -05:00
b79abdb2a5 small typo fix (#5693) 2022-05-31 21:24:16 -05:00
ee8a0c9477 Fix cp bug (#5642) 2022-05-31 18:24:33 -05:00
41853b9f18 expand env for path (#5692) 2022-05-31 12:51:42 +03:00
997d56a288 Lazy dataframes (#5687)
* change between lazy and eager

* when expressions

* examples for aggregations

* more examples for agg

* examples for dataframes

* checked examples

* cargo fmt
2022-05-31 07:29:55 +01:00
0769e9b750 make ls works better with glob (#5691)
* fix glob behavior

* fix doc
2022-05-30 19:13:27 -05:00
f5519e2a09 base64 command more friendly (#5680)
* base64 command more friendly

* using match instead of so much else if..
2022-05-30 09:30:16 +02:00
8259d463aa Update reedline (#5678)
More fixes/changes to default keybindings
2022-05-30 09:26:57 +02:00
e2c015f725 Clarify error message for let in pipeline (#5677)
Refer to the suggestion as an assignment
2022-05-30 09:26:33 +02:00
eb12fffbc6 prevent panic with let alone in pipeline (#5676)
* prevent panic with `let` alone in pipeline

* Update parser.rs
2022-05-29 22:16:41 +02:00
c42096c34e Add '-o'/--output flag to fetch to download to file (#5673)
* attemps to add '-o' flag to `fetch`

* fmt

* changed from 'output' to 'file'.

* Revert "changed from 'output' to 'file'."

As @hustcer mentioned, all typical command line tools for downloading
use `-o` or `-O` and a variation on `--output` for the file

This reverts commit 6baf718f91.

Co-authored-by: sholderbach <sholderbach@users.noreply.github.com>
2022-05-29 18:32:30 +02:00
46eb34b35d Differentiate internal signature from external signature w.r.t. help (#5667)
* Differentiate internal signature from external signature w.r.t. help

* Add in the --help flag to default externs in default config

* Remove unusued build_extern

Co-authored-by: mjclements <clements.michael.james@gmail.com>
2022-05-29 15:14:15 +02:00
23a73cd31f feat: Add search terms to find, where, exit, which and fetch, update #5093 (#5671)
* feat: Add search terms to find, where, exit, which and fetch, update #5093

* Update crates/nu-command/src/filters/where_.rs

Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>

* Update crates/nu-command/src/filters/find.rs

Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>

* Update crates/nu-command/src/shells/exit.rs

Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>

Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>
2022-05-28 13:25:11 +02:00
288 changed files with 7554 additions and 2844 deletions

View File

@ -1,6 +1,7 @@
# increase the default windows stack size
[target.x86_64-pc-windows-msvc]
rustflags = ["-C", "link-args=-stack:10000000"]
# increase the default windows stack size
# statically link the CRT so users don't have to install it
rustflags = ["-C", "link-args=-stack:10000000", "-C", "target-feature=+crt-static"]
# keeping this but commentting out in case we need them in the future

View File

@ -80,9 +80,11 @@ jobs:
toolchain: ${{ matrix.rust }}
override: true
- uses: Swatinem/rust-cache@v1
with:
key: ${{ matrix.style }}v3 # increment this to bust the cache if needed
# Temporarily disabled; the cache was getting huge (2.6GB compressed) on Windows and causing issues.
# TODO: investigate why the cache was so big
# - uses: Swatinem/rust-cache@v1
# with:
# key: ${{ matrix.style }}v3 # increment this to bust the cache if needed
- name: Tests
uses: actions-rs/cargo@v1

View File

@ -1,21 +1,14 @@
# Contributing
Welcome to nushell!
*Note: for a more complete guide see [The nu contributor book](https://www.nushell.sh/contributor-book/)*
For speedy contributions open it in Gitpod, nu will be pre-installed with the latest build in a VSCode like editor all from your browser.
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/nushell/nushell)
Welcome to Nushell!
To get live support from the community see our [Discord](https://discordapp.com/invite/NtAbbGn), [Twitter](https://twitter.com/nu_shell) or file an issue or feature request here on [GitHub](https://github.com/nushell/nushell/issues/new/choose)!
<!--WIP-->
## Developing
### Set up
### Setup
This is no different than other Rust projects.
Nushell requires a recent Rust toolchain and some dependencies; [refer to the Nu Book for up-to-date requirements](https://www.nushell.sh/book/installation.html#build-from-source). After installing dependencies, you should be able to clone+build Nu like any other Rust project:
```bash
git clone https://github.com/nushell/nushell
@ -28,24 +21,24 @@ cargo build
- Build and run Nushell:
```shell
cargo build --release && cargo run --release
cargo run
```
- Build and run with extra features:
- Build and run with extra features. Currently extra features include dataframes and sqlite database support.
```shell
cargo build --release --features=extra && cargo run --release --features=extra
cargo run --features=extra
```
- Run Clippy on Nushell:
```shell
cargo clippy --all --features=stable
cargo clippy --workspace --features=extra -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect
```
- Run all tests:
```shell
cargo test --all --features=stable
cargo test --workspace --features=extra
```
- Run all tests for a specific command
@ -71,5 +64,5 @@ cargo build
- To view verbose logs when developing, enable the `trace` log level.
```shell
cargo build --release --features=extra && cargo run --release --features=extra -- --log-level trace
cargo run --release --features=extra -- --log-level trace
```

201
Cargo.lock generated
View File

@ -215,9 +215,9 @@ dependencies = [
[[package]]
name = "async-trait"
version = "0.1.53"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600"
checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716"
dependencies = [
"proc-macro2",
"quote",
@ -375,9 +375,9 @@ dependencies = [
[[package]]
name = "bumpalo"
version = "3.9.1"
version = "3.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3"
[[package]]
name = "byte-unit"
@ -561,9 +561,9 @@ dependencies = [
[[package]]
name = "const_format"
version = "0.2.23"
version = "0.2.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0936ffe6d0c8d6a51b3b0a73b2acbe925d786f346cf45bfddc8341d79fb7dc8a"
checksum = "e6a1316fa6a23fea1ee41cb80321590385e5f3e575e99f77c4d918ce5d44379d"
dependencies = [
"const_format_proc_macros",
]
@ -603,9 +603,9 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
name = "cortex-m"
version = "0.7.4"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37ff967e867ca14eba0c34ac25cd71ea98c678e741e3915d923999bb2fe7c826"
checksum = "cd20d4ac4aa86f4f75f239d59e542ef67de87cce2c282818dc6e84155d3ea126"
dependencies = [
"bare-metal 0.2.5",
"bitfield",
@ -698,7 +698,7 @@ dependencies = [
"crossterm_winapi",
"libc",
"mio 0.8.3",
"parking_lot 0.12.0",
"parking_lot 0.12.1",
"serde",
"signal-hook",
"signal-hook-mio",
@ -1128,13 +1128,11 @@ dependencies = [
[[package]]
name = "flate2"
version = "1.0.23"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af"
checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
dependencies = [
"cfg-if 1.0.0",
"crc32fast",
"libc",
"miniz_oxide",
]
@ -1361,6 +1359,16 @@ dependencies = [
"version_check 0.9.4",
]
[[package]]
name = "gethostname"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e"
dependencies = [
"libc",
"winapi 0.3.9",
]
[[package]]
name = "getopts"
version = "0.2.21"
@ -1649,9 +1657,9 @@ dependencies = [
[[package]]
name = "hyper"
version = "0.14.18"
version = "0.14.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2"
checksum = "42dc3c131584288d375f2d07f822b0cb012d8c6fb899a5b9fdb3cb7eb9b6004f"
dependencies = [
"bytes",
"futures-channel",
@ -1712,9 +1720,9 @@ checksum = "0cfe9645a18782869361d9c8732246be7b410ad4e919d3609ebabdac00ba12c3"
[[package]]
name = "indexmap"
version = "1.8.1"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a"
dependencies = [
"autocfg",
"hashbrown 0.11.2",
@ -1791,6 +1799,16 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b"
[[package]]
name = "is-root"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04a4202a60e86f1c9702706bb42270dadd333f2db7810157563c86f17af3c873"
dependencies = [
"users 0.10.0",
"winapi 0.3.9",
]
[[package]]
name = "is_ci"
version = "1.1.1"
@ -1914,9 +1932,9 @@ dependencies = [
[[package]]
name = "lexical-parse-integer"
version = "0.8.5"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "125e1f93e5003d4bd89758c2ca2771bfae13632df633cde581efe07c87d354e5"
checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9"
dependencies = [
"lexical-util",
"static_assertions",
@ -2015,9 +2033,9 @@ dependencies = [
[[package]]
name = "libz-sys"
version = "1.1.6"
version = "1.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92e7e15d7610cce1d9752e137625f14e61a28cd45929b6e12e47b50fe154ee2e"
checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf"
dependencies = [
"cc",
"libc",
@ -2142,9 +2160,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memmap2"
version = "0.5.3"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "057a3db23999c867821a7a59feb06a578fcb03685e983dff90daf9e7d24ac08f"
checksum = "d5172b50c23043ff43dd53e51392f36519d9b35a8f3a410d30ece5d1aedd58ae"
dependencies = [
"libc",
]
@ -2235,9 +2253,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.5.1"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082"
checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
dependencies = [
"adler",
]
@ -2452,7 +2470,7 @@ dependencies = [
[[package]]
name = "nu"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"assert_cmd",
"chrono",
@ -2486,15 +2504,16 @@ dependencies = [
"reedline",
"rstest",
"serial_test",
"signal-hook",
"tempfile",
"winres",
]
[[package]]
name = "nu-ansi-term"
version = "0.45.1"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7bca0d33a384280d1563b97f49cb95303df9fa22588739a04b7d8015c1ccd50"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
dependencies = [
"overload",
"winapi 0.3.9",
@ -2502,8 +2521,9 @@ dependencies = [
[[package]]
name = "nu-cli"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"chrono",
"crossterm",
"fuzzy-matcher",
"is_executable",
@ -2519,12 +2539,13 @@ dependencies = [
"nu-test-support",
"nu-utils",
"reedline",
"sysinfo 0.24.1",
"thiserror",
]
[[package]]
name = "nu-color-config"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"nu-ansi-term",
"nu-json",
@ -2535,7 +2556,7 @@ dependencies = [
[[package]]
name = "nu-command"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"Inflector",
"alphanumeric-sort",
@ -2560,6 +2581,7 @@ dependencies = [
"htmlescape",
"ical",
"indexmap",
"is-root",
"itertools",
"lazy_static",
"log",
@ -2605,7 +2627,7 @@ dependencies = [
"shadow-rs",
"sqlparser",
"strip-ansi-escapes",
"sysinfo",
"sysinfo 0.23.13",
"terminal_size",
"thiserror",
"titlecase",
@ -2614,27 +2636,28 @@ dependencies = [
"umask",
"unicode-segmentation",
"url",
"users",
"users 0.11.0",
"uuid",
"wax",
"which",
"windows",
]
[[package]]
name = "nu-engine"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"chrono",
"nu-glob",
"nu-path",
"nu-protocol",
"nu-utils",
"sysinfo",
"sysinfo 0.23.13",
]
[[package]]
name = "nu-glob"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"doc-comment",
"tempdir",
@ -2642,7 +2665,7 @@ dependencies = [
[[package]]
name = "nu-json"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"lazy_static",
"linked-hash-map",
@ -2655,7 +2678,7 @@ dependencies = [
[[package]]
name = "nu-parser"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"chrono",
"log",
@ -2669,7 +2692,7 @@ dependencies = [
[[package]]
name = "nu-path"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"dirs-next",
"dunce",
@ -2678,7 +2701,7 @@ dependencies = [
[[package]]
name = "nu-plugin"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"capnp",
"nu-engine",
@ -2689,7 +2712,7 @@ dependencies = [
[[package]]
name = "nu-pretty-hex"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"heapless 0.7.13",
"nu-ansi-term",
@ -2698,7 +2721,7 @@ dependencies = [
[[package]]
name = "nu-protocol"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"byte-unit",
"chrono",
@ -2718,7 +2741,7 @@ dependencies = [
[[package]]
name = "nu-system"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"chrono",
"errno",
@ -2732,7 +2755,7 @@ dependencies = [
[[package]]
name = "nu-table"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"ansi-str",
"atty",
@ -2745,7 +2768,7 @@ dependencies = [
[[package]]
name = "nu-term-grid"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"strip-ansi-escapes",
"unicode-width",
@ -2753,7 +2776,7 @@ dependencies = [
[[package]]
name = "nu-test-support"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"getset",
"hamcrest2",
@ -2765,14 +2788,14 @@ dependencies = [
[[package]]
name = "nu-utils"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"crossterm_winapi",
]
[[package]]
name = "nu_plugin_example"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"nu-plugin",
"nu-protocol",
@ -2780,7 +2803,7 @@ dependencies = [
[[package]]
name = "nu_plugin_gstat"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"git2",
"nu-engine",
@ -2790,7 +2813,7 @@ dependencies = [
[[package]]
name = "nu_plugin_inc"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"nu-plugin",
"nu-protocol",
@ -2799,7 +2822,7 @@ dependencies = [
[[package]]
name = "nu_plugin_query"
version = "0.63.1"
version = "0.64.0"
dependencies = [
"gjson",
"nu-engine",
@ -3028,9 +3051,9 @@ dependencies = [
[[package]]
name = "openssl-sys"
version = "0.9.73"
version = "0.9.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d5fd19fb3e0a8191c1e34935718976a3e70c112ab9a24af6d7cadccd9d90bc0"
checksum = "835363342df5fba8354c5b453325b110ffd54044e588c539cf2f20a8014e4cb1"
dependencies = [
"autocfg",
"cc",
@ -3074,9 +3097,9 @@ dependencies = [
[[package]]
name = "parking_lot"
version = "0.12.0"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core 0.9.3",
@ -3381,7 +3404,7 @@ checksum = "eedc21001f05611e41bb7439b38d0f4ef9406aa49c17f3b289b5f57d8fa40c59"
dependencies = [
"ahash",
"glob",
"parking_lot 0.12.0",
"parking_lot 0.12.1",
"polars-arrow",
"polars-core",
"polars-io",
@ -3419,7 +3442,7 @@ version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7f4cd569d383f5f000abbd6d5146550e6cb4e43fac30d1af98699499a440d56"
dependencies = [
"parking_lot 0.12.0",
"parking_lot 0.12.1",
"rayon",
]
@ -3793,17 +3816,22 @@ dependencies = [
[[package]]
name = "reedline"
version = "0.6.0"
source = "git+https://github.com/nushell/reedline?branch=main#fe795caabc5401d811006b93d5a6d4f220a049ff"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f8163ab90fabf0b8978b824743bb7a384394501b4b40c198a146c0eb9670ca4"
dependencies = [
"chrono",
"crossterm",
"fd-lock",
"gethostname",
"nu-ansi-term",
"rusqlite",
"serde",
"serde_json",
"strip-ansi-escapes",
"strum 0.24.0",
"strum_macros 0.24.0",
"thiserror",
"unicode-segmentation",
"unicode-width",
]
@ -4012,9 +4040,9 @@ dependencies = [
[[package]]
name = "rustix"
version = "0.34.7"
version = "0.34.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f117495127afb702af6706f879fb2b5c008c38ccf3656afc514e26f35bdb8180"
checksum = "2079c267b8394eb529872c3cf92e181c378b41fea36e68130357b52493701d2e"
dependencies = [
"bitflags",
"errno",
@ -4438,7 +4466,7 @@ checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08"
dependencies = [
"new_debug_unreachable",
"once_cell",
"parking_lot 0.12.0",
"parking_lot 0.12.1",
"phf_shared 0.10.0",
"precomputed-hash",
"serde",
@ -4554,9 +4582,9 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.95"
version = "1.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942"
checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf"
dependencies = [
"proc-macro2",
"quote",
@ -4603,6 +4631,21 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "sysinfo"
version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6a8e71535da31837213ac114531d31def75d7aebd133264e420a3451fa7f703"
dependencies = [
"cfg-if 1.0.0",
"core-foundation-sys",
"libc",
"ntapi",
"once_cell",
"rayon",
"winapi 0.3.9",
]
[[package]]
name = "tempdir"
version = "0.3.7"
@ -4747,9 +4790,9 @@ dependencies = [
[[package]]
name = "tokio"
version = "1.18.2"
version = "1.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4903bf0427cf68dddd5aa6a93220756f8be0c34fcfa9f5e6191e103e15a31395"
checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439"
dependencies = [
"bytes",
"libc",
@ -4774,9 +4817,9 @@ dependencies = [
[[package]]
name = "tokio-util"
version = "0.7.2"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f988a1a1adc2fb21f9c12aa96441da33a1728193ae0b95d2be22dbd17fcb4e5c"
checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45"
dependencies = [
"bytes",
"futures-core",
@ -4809,21 +4852,9 @@ checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09"
dependencies = [
"cfg-if 1.0.0",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.26"
@ -4972,6 +5003,16 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "users"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa4227e95324a443c9fcb06e03d4d85e91aabe9a5a02aa818688b6918b6af486"
dependencies = [
"libc",
"log",
]
[[package]]
name = "users"
version = "0.11.0"

View File

@ -11,7 +11,7 @@ name = "nu"
readme = "README.md"
repository = "https://github.com/nushell/nushell"
rust-version = "1.60"
version = "0.63.1"
version = "0.64.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -32,37 +32,38 @@ members = [
]
[dependencies]
chrono = "0.4.19"
chrono = { version = "0.4.19", features = ["serde"] }
crossterm = "0.23.0"
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.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" }
nu-ansi-term = "0.46.0"
nu-cli = { path="./crates/nu-cli", version = "0.64.0" }
nu-color-config = { path = "./crates/nu-color-config", version = "0.64.0" }
nu-command = { path="./crates/nu-command", version = "0.64.0" }
nu-engine = { path="./crates/nu-engine", version = "0.64.0" }
nu-json = { path="./crates/nu-json", version = "0.64.0" }
nu-parser = { path="./crates/nu-parser", version = "0.64.0" }
nu-path = { path="./crates/nu-path", version = "0.64.0" }
nu-plugin = { path = "./crates/nu-plugin", optional = true, version = "0.64.0" }
nu-pretty-hex = { path = "./crates/nu-pretty-hex", version = "0.64.0" }
nu-protocol = { path = "./crates/nu-protocol", version = "0.64.0" }
nu-system = { path = "./crates/nu-system", version = "0.64.0" }
nu-table = { path = "./crates/nu-table", version = "0.64.0" }
nu-term-grid = { path = "./crates/nu-term-grid", version = "0.64.0" }
nu-utils = { path = "./crates/nu-utils", version = "0.64.0" }
reedline = { version = "0.7.0", features = ["bashisms", "sqlite"]}
pretty_env_logger = "0.4.0"
rayon = "1.5.1"
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 }
signal-hook = { version = "0.3.14", default-features = false }
[dev-dependencies]
nu-test-support = { path="./crates/nu-test-support", version = "0.63.1" }
nu-test-support = { path="./crates/nu-test-support", version = "0.64.0" }
tempfile = "3.2.0"
assert_cmd = "2.0.2"
pretty_assertions = "1.0.0"

249
README.md
View File

@ -1,5 +1,4 @@
# README
# Nushell <!-- omit in toc -->
[![Crates.io](https://img.shields.io/crates/v/nu.svg)](https://crates.io/crates/nu)
![Build Status](https://img.shields.io/github/workflow/status/nushell/nushell/continuous-integration)
[![Discord](https://img.shields.io/discord/601130461678272522.svg?logo=discord)](https://discord.gg/NtAbbGn)
@ -8,128 +7,100 @@
![GitHub commit activity](https://img.shields.io/github/commit-activity/m/nushell/nushell)
![GitHub contributors](https://img.shields.io/github/contributors/nushell/nushell)
## Nushell
A new type of shell.
![Example of nushell](images/nushell-autocomplete6.gif "Example of nushell")
## Table of Contents <!-- omit in toc -->
- [Status](#status)
- [Learning About Nu](#learning-about-nu)
- [Installation](#installation)
- [Philosophy](#philosophy)
- [Pipelines](#pipelines)
- [Opening files](#opening-files)
- [Plugins](#plugins)
- [Goals](#goals)
- [Progress](#progress)
- [Officially Supported By](#officially-supported-by)
- [Contributing](#contributing)
- [License](#license)
## Status
This project has reached a minimum-viable product level of quality.
While contributors dogfood it as their daily driver, it may be unstable for some commands.
Future releases will work to fill out missing features and improve stability.
Its design is also subject to change as it matures.
This project has reached a minimum-viable-product level of quality. Many people use it as their daily driver, but it may be unstable for some commands. Nu's design is subject to change as it matures.
Nu comes with a set of built-in commands (listed below).
If a command is unknown, the command will shell-out and execute it (using cmd on Windows or bash on Linux and macOS), correctly passing through stdin, stdout, and stderr, so things like your daily git workflows and even `vim` will work just fine.
## Learning About Nu
## Learning more
The [Nushell book](https://www.nushell.sh/book/) is the primary source of Nushell documentation. You can find [a full list of Nu commands in the book](https://www.nushell.sh/book/command_reference.html), and we have many examples of using Nu in our [cookbook](https://www.nushell.sh/cookbook/).
There are a few good resources to learn about Nu.
There is a [book](https://www.nushell.sh/book/) about Nu that is currently in progress.
The book focuses on using Nu and its core concepts.
If you're a developer who would like to contribute to Nu, we're also working on a [book for developers](https://www.nushell.sh/contributor-book/) to help you get started.
There are also [good first issues](https://github.com/nushell/nushell/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) to help you dive in.
We also have an active [Discord](https://discord.gg/NtAbbGn) and [Twitter](https://twitter.com/nu_shell) if you'd like to come and chat with us.
You can also find information on more specific topics in our [cookbook](https://www.nushell.sh/cookbook/).
We're also active on [Discord](https://discord.gg/NtAbbGn) and [Twitter](https://twitter.com/nu_shell); come and chat with us!
## Installation
### Local
To quickly install Nu:
Up-to-date installation instructions can be found in the [installation chapter of the book](https://www.nushell.sh/book/installation.html). **Windows users**: please note that Nu works on Windows 10 and does not currently have Windows 7/8.1 support.
To build Nu, you will need to use the **latest stable (1.60 or later)** version of the compiler.
Required dependencies:
- pkg-config and libssl (only needed on Linux)
- On Debian/Ubuntu: `apt install pkg-config libssl-dev`
Optional dependencies:
- To use Nu with all possible optional features enabled, you'll also need the following:
- On Linux (on Debian/Ubuntu): `apt install libxcb-composite0-dev libx11-dev`
To install Nu via cargo (make sure you have installed [rustup](https://rustup.rs/) and the latest stable compiler via `rustup install stable`):
For Windows users, you may also need to install the [Microsoft Visual C++ 2015 Redistributables](https://docs.microsoft.com/cpp/windows/latest-supported-vc-redist).
```shell
cargo install nu
```
To install Nu via the [Windows Package Manager](https://aka.ms/winget-cli):
```shell
```bash
# Linux and macOS
brew install nushell
# Windows
winget install nushell
```
To install Nu via the [Chocolatey](https://chocolatey.org) package manager:
To use `Nu` in Github Action, check [setup-nu](https://github.com/marketplace/actions/setup-nu) for more detail.
```shell
choco install nushell
```
You can also build Nu yourself with all the bells and whistles (be sure to have installed the [dependencies](https://www.nushell.sh/book/installation.html#dependencies) for your platform), once you have checked out this repo with git:
```shell
cargo build --workspace --features=extra
```
### Packaging status
Detailed installation instructions can be found in the [installation chapter of the book](https://www.nushell.sh/book/installation.html). Nu is available via many package managers:
[![Packaging status](https://repology.org/badge/vertical-allrepos/nushell.svg)](https://repology.org/project/nushell/versions)
#### Fedora
[COPR repo](https://copr.fedorainfracloud.org/coprs/atim/nushell/): `sudo dnf copr enable atim/nushell -y && sudo dnf install nushell -y`
## Philosophy
Nu draws inspiration from projects like PowerShell, functional programming languages, and modern CLI tools.
Rather than thinking of files and services as raw streams of text, Nu looks at each input as something with structure.
For example, when you list the contents of a directory, what you get back is a table of rows, where each row represents an item in that directory.
Rather than thinking of files and data as raw streams of text, Nu looks at each input as something with structure.
For example, when you list the contents of a directory what you get back is a table of rows, where each row represents an item in that directory.
These values can be piped through a series of steps, in a series of commands called a 'pipeline'.
### Pipelines
In Unix, it's common to pipe between commands to split up a sophisticated command over multiple steps.
Nu takes this a step further and builds heavily on the idea of _pipelines_.
Just as the Unix philosophy, Nu allows commands to output to stdout and read from stdin.
As in the Unix philosophy, Nu allows commands to output to stdout and read from stdin.
Additionally, commands can output structured data (you can think of this as a third kind of stream).
Commands that work in the pipeline fit into one of three categories:
- Commands that produce a stream (e.g., `ls`)
- Commands that filter a stream (eg, `where type == "Dir"`)
- Commands that consume the output of the pipeline (e.g., `autoview`)
- Commands that filter a stream (eg, `where type == "dir"`)
- Commands that consume the output of the pipeline (e.g., `table`)
Commands are separated by the pipe symbol (`|`) to denote a pipeline flowing left to right.
```shell
> ls | where type == "Dir" | autoview
───┬────────┬──────┬───────┬──────────────
# │ name │ type │ size │ modified
───┼────────┼──────┼───────┼──────────────
0assetsDir │ 128 B │ 5 months ago
1cratesDir │ 704 B │ 50 mins ago
2debianDir │ 352 B │ 5 months ago
3 │ docsDir │ 192 B │ 50 mins ago
4imagesDir │ 160 B │ 5 months ago
5src Dir │ 128 B │ 1 day ago
6targetDir │ 160 B │ 5 days ago
7tests │ Dir │ 192 B │ 3 months ago
───┴────────┴──────┴───────┴──────────────
> ls | where type == "dir" | table
╭────┬──────────┬──────┬─────────┬───────────────╮
# name │ type │ size modified
├────┼──────────┼──────┼─────────┼───────────────┤
0.cargo dir │ 0 B │ 9 minutes ago
1assets dir │ 0 B │ 2 weeks ago
2crates dir │ 4.0 KiB │ 2 weeks ago
3 │ dockerdir │ 0 B │ 2 weeks ago
4docs dir │ 0 B │ 2 weeks ago
5imagesdir │ 0 B │ 2 weeks ago │
6pkg_mgrsdir │ 0 B │ 2 weeks ago
7samples │ dir │ 0 B │ 2 weeks ago
8 │ src │ dir │ 4.0 KiB │ 2 weeks ago │
9 │ target │ dir │ 0 B │ a day ago │
10 │ tests │ dir │ 4.0 KiB │ 2 weeks ago │
11 │ wix │ dir │ 0 B │ 2 weeks ago │
╰────┴──────────┴──────┴─────────┴───────────────╯
```
Because most of the time you'll want to see the output of a pipeline, `autoview` is assumed.
Because most of the time you'll want to see the output of a pipeline, `table` is assumed.
We could have also written the above:
```shell
> ls | where type == Dir
> ls | where type == "dir"
```
Being able to use the same commands and compose them differently is an important philosophy in Nu.
@ -137,15 +108,13 @@ For example, we could use the built-in `ps` command to get a list of the running
```shell
> ps | where cpu > 0
───┬───────┬───────────────────┬─────────┬─────────┬──────────┬──────────
# │ pid name │ status │ cpu mem │ virtual
───┼───────┼───────────────────┼─────────┼─────────┼──────────┼──────────
0 435 │ irq/142-SYNA327 │ Sleeping │ 7.5699 │ 0 B │ 0 B
1 1609pulseaudio │ Sleeping 6.5605 │ 10.6 MB │ 2.3 GB
2 1625 │ gnome-shell Sleeping │ 6.5684 │ 639.6 MB │ 7.3 GB
32202 │ Web Content │ Sleeping │ 6.8157 │ 320.8 MB │ 3.0 GB
4328788 │ nu_plugin_core_ps │ Sleeping │ 92.5750 │ 5.9 MB │ 633.2 MB
───┴────────┴───────────────────┴──────────┴─────────┴──────────┴──────────
───┬───────┬──────────────────┬───────────┬───────────╮
# │ pid name │ cpu mem │ virtual
───┼───────┼──────────────────┼───────────┼───────────┤
02240 │ Slack.exe │ 16.40 │ 178.3 MiB │ 232.6 MiB │
116948Slack.exe16.32 │ 205.0 MiB │ 197.9 MiB │
217700 │ nu.exe 3.77 │ 26.1 MiB │ 8.8 MiB │
╰───┴───────┴───────────┴───────┴───────────┴───────────╯
```
### Opening files
@ -155,72 +124,49 @@ For example, you can load a .toml file as structured data and explore it:
```shell
> open Cargo.toml
────────────────────┬───────────────────────────
bin [table 18 rows]
build-dependencies │ [row serde toml]
dependencies [row 29 columns]
dev-dependencies[row nu-test-support]
features [row 19 columns]
package [row 12 columns]
workspace[row members]
────────────────────┴───────────────────────────
──────────────────┬────────────────────
bin │ [table 1 row]
dependencies {record 24 fields}
│ dev-dependencies │ {record 8 fields}
│ features {record 10 fields}
│ package{record 13 fields}
profile{record 3 fields}
│ target {record 2 fields}
│ workspace │ {record 1 field}
╰──────────────────┴────────────────────╯
```
We can pipeline this into a command that gets the contents of one of the columns:
We can pipe this into a command that gets the contents of one of the columns:
```shell
> open Cargo.toml | get package
───────────────┬────────────────────────────────────
authors │ [table 1 rows]
default-run │ nu
description │ A new type of shell
documentation │ https://www.nushell.sh/book/
edition │ 2018
exclude │ [table 1 rows]
homepage │ https://www.nushell.sh
license │ MIT
name │ nu
readme │ README.md
repository │ https://github.com/nushell/nushell
version │ 0.32.0
───────────────┴────────────────────────────────────
───────────────┬────────────────────────────────────
authors │ [list 1 item]
default-run │ nu
description │ A new type of shell
documentation │ https://www.nushell.sh/book/
edition │ 2018
exclude │ [list 1 item]
homepage │ https://www.nushell.sh
license │ MIT
name │ nu
readme │ README.md
repository │ https://github.com/nushell/nushell
│ rust-version │ 1.60 │
│ version │ 0.63.1 │
╰───────────────┴────────────────────────────────────╯
```
Finally, we can use commands outside of Nu once we have the data we want:
And if needed we can drill down further:
```shell
> open Cargo.toml | get package.version
0.32.0
0.63.1
```
### Configuration
Nu has early support for configuring the shell. You can refer to the book for a list of [all supported variables](https://www.nushell.sh/book/configuration.html).
To set one of these variables, you can use `config set`. For example:
```shell
> config set line_editor.edit_mode "vi"
> config set path $nu.path
```
### Shells
Nu will work inside of a single directory and allow you to navigate around your filesystem by default.
Nu also offers a way of adding additional working directories that you can jump between, allowing you to work in multiple directories simultaneously.
To do so, use the `enter` command, which will allow you to create a new "shell" and enter it at the specified path.
You can toggle between this new shell and the original shell with the `p` (for previous) and `n` (for next), allowing you to navigate around a ring buffer of shells.
Once you're done with a shell, you can `exit` it and remove it from the ring buffer.
Finally, to get a list of all the current shells, you can use the `shells` command.
### Plugins
Nu supports plugins that offer additional functionality to the shell and follow the same structured data model that built-in commands use.
This allows you to extend nu for your needs.
There are a few examples in the `plugins` directory.
Nu supports plugins that offer additional functionality to the shell and follow the same structured data model that built-in commands use. There are a few examples in the `crates/nu_plugins_*` directories.
Plugins are binaries that are available in your path and follow a `nu_plugin_*` naming convention.
These binaries interact with nu via a simple JSON-RPC protocol where the command identifies itself and passes along its configuration, making it available for use.
@ -231,23 +177,19 @@ If the plugin is a sink, it is given the full vector of final data and is given
Nu adheres closely to a set of goals that make up its design philosophy. As features are added, they are checked against these goals.
- First and foremost, Nu is cross-platform. Commands and techniques should carry between platforms and offer consistent first-class support for Windows, macOS, and Linux.
- First and foremost, Nu is cross-platform. Commands and techniques should work across platforms and Nu has first-class support for Windows, macOS, and Linux.
- Nu ensures direct compatibility with existing platform-specific executables that make up people's workflows.
- Nu ensures compatibility with existing platform-specific executables.
- Nu's workflow and tools should have the usability in day-to-day experience of using a shell in 2019 (and beyond).
- Nu's workflow and tools should have the usability expected of modern software in 2022 (and beyond).
- Nu views data as both structured and unstructured. It is a structured shell like PowerShell.
- Nu views data as either structured or unstructured. It is a structured shell like PowerShell.
- Finally, Nu views data functionally. Rather than using mutation, pipelines act as a means to load, change, and save data without mutable state.
## Commands
You can find a list of Nu commands, complete with documentation, in [quick command references](https://www.nushell.sh/book/command_reference.html).
## Progress
Nu is in heavy development and will naturally change as it matures and people use it. The chart below isn't meant to be exhaustive, but rather helps give an idea for some of the areas of development and their relative completion:
Nu is under heavy development and will naturally change as it matures. The chart below isn't meant to be exhaustive, but it helps give an idea for some of the areas of development and their relative maturity:
| Features | Not started | Prototype | MVP | Preview | Mature | Notes |
| ------------- | :---------: | :-------: | :-: | :-----: | :----: | -------------------------------------------------------------------- |
@ -270,20 +212,15 @@ Nu is in heavy development and will naturally change as it matures and people us
Please submit an issue or PR to be added to this list.
### Integrations
- [zoxide](https://github.com/ajeetdsouza/zoxide)
- [starship](https://github.com/starship/starship)
- [oh-my-posh](https://ohmyposh.dev)
- [Couchbase Shell](https://couchbase.sh)
- [virtualenv](https://github.com/pypa/virtualenv)
### Mentions
- [The Python Launcher for Unix](https://github.com/brettcannon/python-launcher#how-do-i-get-a-table-of-python-executables-in-nushell)
## Contributing
See [Contributing](CONTRIBUTING.md) for details.
Thanks to all the people who already contributed!
See [Contributing](CONTRIBUTING.md) for details. Thanks to all the people who already contributed!
<a href="https://github.com/nushell/nushell/graphs/contributors">
<img src="https://contributors-img.web.app/image?repo=nushell/nushell&max=500" />

View File

@ -4,21 +4,21 @@ description = "CLI-related functionality for Nushell"
edition = "2021"
license = "MIT"
name = "nu-cli"
version = "0.63.1"
version = "0.64.0"
[dev-dependencies]
nu-test-support = { path="../nu-test-support", version = "0.63.1" }
nu-command = { path = "../nu-command", version = "0.63.1" }
nu-test-support = { path="../nu-test-support", version = "0.64.0" }
nu-command = { path = "../nu-command", version = "0.64.0" }
[dependencies]
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"
reedline = { git = "https://github.com/nushell/reedline", branch = "main", features = ["bashisms"]}
nu-color-config = { path = "../nu-color-config", version = "0.63.1" }
nu-engine = { path = "../nu-engine", version = "0.64.0" }
nu-path = { path = "../nu-path", version = "0.64.0" }
nu-parser = { path = "../nu-parser", version = "0.64.0" }
nu-protocol = { path = "../nu-protocol", version = "0.64.0" }
nu-utils = { path = "../nu-utils", version = "0.64.0" }
nu-ansi-term = "0.46.0"
nu-color-config = { path = "../nu-color-config", version = "0.64.0" }
reedline = { version = "0.7.0", features = ["bashisms", "sqlite"]}
crossterm = "0.23.0"
miette = { version = "4.5.0", features = ["fancy"] }
thiserror = "1.0.29"
@ -26,6 +26,8 @@ fuzzy-matcher = "0.3.7"
log = "0.4"
is_executable = "1.0.1"
chrono = "0.4.19"
sysinfo = "0.24.1"
[features]
plugin = []

View File

@ -199,12 +199,19 @@ impl Completer for CommandCompletion {
return subcommands;
}
let config = working_set.get_config();
let commands = if matches!(self.flat_shape, nu_parser::FlatShape::External)
|| matches!(self.flat_shape, nu_parser::FlatShape::InternalCall)
|| ((span.end - span.start) == 0)
{
// we're in a gap or at a command
self.complete_commands(working_set, span, offset, true, options.match_algorithm)
self.complete_commands(
working_set,
span,
offset,
config.enable_external_completion,
options.match_algorithm,
)
} else {
vec![]
};

View File

@ -59,37 +59,43 @@ impl NuCompleter {
fn completion_helper(&mut self, line: &str, pos: usize) -> Vec<Suggestion> {
let mut working_set = StateWorkingSet::new(&self.engine_state);
let offset = working_set.next_span_start();
let (mut new_line, alias_offset) = try_find_alias(line.as_bytes(), &working_set);
let initial_line = line.to_string();
let mut line = line.to_string();
line.insert(pos, 'a');
new_line.push(b'a');
let pos = offset + pos;
let (output, _err) = parse(
&mut working_set,
Some("completer"),
line.as_bytes(),
false,
&[],
);
let (output, _err) = parse(&mut working_set, Some("completer"), &new_line, false, &[]);
for pipeline in output.pipelines.into_iter() {
for expr in pipeline.expressions {
let flattened: Vec<_> = flatten_expression(&working_set, &expr);
for (flat_idx, flat) in flattened.iter().enumerate() {
if pos >= flat.0.start && pos < flat.0.end {
let alias = if alias_offset.is_empty() {
0
} else {
alias_offset[flat_idx]
};
if pos >= flat.0.start - alias && pos < flat.0.end - alias {
// Context variables
let most_left_var =
most_left_variable(flat_idx, &working_set, flattened.clone());
// Create a new span
let new_span = Span {
start: flat.0.start,
end: flat.0.end - 1,
let new_span = if flat_idx == 0 {
Span {
start: flat.0.start,
end: flat.0.end - 1 - alias,
}
} else {
Span {
start: flat.0.start - alias,
end: flat.0.end - 1 - alias,
}
};
// Parses the prefix
let mut prefix = working_set.get_span_contents(flat.0).to_vec();
prefix.remove(pos - flat.0.start);
prefix.remove(pos - (flat.0.start - alias));
// Completions that depends on the previous expression (e.g: use, source)
if flat_idx > 0 {
@ -229,6 +235,74 @@ impl ReedlineCompleter for NuCompleter {
}
}
type MatchedAlias<'a> = Vec<(&'a [u8], &'a [u8])>;
// Handler the completion when giving lines contains at least one alias. (e.g: `g checkout`)
// that `g` is an alias of `git`
fn try_find_alias(line: &[u8], working_set: &StateWorkingSet) -> (Vec<u8>, Vec<usize>) {
// An vector represents the offsets of alias
// e.g: the offset is 2 for the alias `g` of `git`
let mut alias_offset = vec![];
let mut output = vec![];
if let Some(matched_alias) = search_alias(line, working_set) {
let mut lens = matched_alias.len();
for (input_vec, line_vec) in matched_alias {
alias_offset.push(line_vec.len() - input_vec.len());
output.extend(line_vec);
if lens > 1 {
output.push(b' ');
lens -= 1;
}
}
} else {
output = line.to_vec();
}
(output, alias_offset)
}
fn search_alias<'a>(input: &'a [u8], working_set: &'a StateWorkingSet) -> Option<MatchedAlias<'a>> {
let mut vec_names = vec![];
let mut vec_alias = vec![];
let mut pos = 0;
let mut is_alias = false;
for (index, character) in input.iter().enumerate() {
if *character == b' ' {
let range = &input[pos..index];
vec_names.push(range);
pos = index + 1;
}
}
// Push the rest to names vector.
if pos < input.len() {
vec_names.push(&input[pos..]);
}
for name in &vec_names {
if let Some(alias_id) = working_set.find_alias(name) {
let alias_span = working_set.get_alias(alias_id);
is_alias = true;
for alias in alias_span {
let name = working_set.get_span_contents(*alias);
if !name.is_empty() {
vec_alias.push(name);
}
}
} else {
vec_alias.push(name);
}
}
if is_alias {
// Zip names and alias vectors, the original inputs and its aliases mapping.
// e.g:(['g'], ['g','i','t'])
let output = vec_names.into_iter().zip(vec_alias).collect();
Some(output)
} else {
None
}
}
// reads the most left variable returning it's name (e.g: $myvar)
// and the depth (a.b.c)
fn most_left_variable(

View File

@ -2,12 +2,15 @@ use crate::util::{eval_source, report_error};
#[cfg(feature = "plugin")]
use log::info;
use nu_protocol::engine::{EngineState, Stack, StateDelta, StateWorkingSet};
use nu_protocol::{PipelineData, Span};
use nu_protocol::{HistoryFileFormat, PipelineData, Span};
use std::path::PathBuf;
#[cfg(feature = "plugin")]
const PLUGIN_FILE: &str = "plugin.nu";
const HISTORY_FILE_TXT: &str = "history.txt";
const HISTORY_FILE_SQLITE: &str = "history.sqlite3";
#[cfg(feature = "plugin")]
pub fn read_plugin_file(
engine_state: &mut EngineState,
@ -84,3 +87,14 @@ pub fn eval_config_contents(
}
}
}
pub(crate) fn get_history_path(storage_path: &str, mode: HistoryFileFormat) -> Option<PathBuf> {
nu_path::config_dir().map(|mut history_path| {
history_path.push(storage_path);
history_path.push(match mode {
HistoryFileFormat::PlainText => HISTORY_FILE_TXT,
HistoryFileFormat::Sqlite => HISTORY_FILE_SQLITE,
});
history_path
})
}

View File

@ -4,6 +4,7 @@ use log::trace;
use miette::{IntoDiagnostic, Result};
use nu_engine::convert_env_values;
use nu_parser::parse;
use nu_protocol::Type;
use nu_protocol::{
ast::Call,
engine::{EngineState, Stack, StateWorkingSet},
@ -34,7 +35,7 @@ pub fn evaluate_file(
let _ = parse(&mut working_set, Some(&path), &file, false, &[]);
if working_set.find_decl(b"main").is_some() {
if working_set.find_decl(b"main", &Type::Any).is_some() {
let args = format!("main {}", args.join(" "));
if !eval_source(

View File

@ -1,6 +1,7 @@
use nu_engine::documentation::get_flags_section;
use nu_protocol::{engine::EngineState, levenshtein_distance};
use reedline::{Completer, Suggestion};
use std::fmt::Write;
use std::sync::Arc;
pub struct NuHelpCompleter(Arc<EngineState>);
@ -19,6 +20,10 @@ impl NuHelpCompleter {
.filter(|(sig, _, _, _)| {
sig.name.to_lowercase().contains(&line.to_lowercase())
|| sig.usage.to_lowercase().contains(&line.to_lowercase())
|| sig
.search_terms
.iter()
.any(|term| term.to_lowercase().contains(&line.to_lowercase()))
|| sig
.extra_usage
.to_lowercase()
@ -49,7 +54,7 @@ impl NuHelpCompleter {
long_desc.push_str("\r\n\r\n");
}
long_desc.push_str(&format!("Usage:\r\n > {}\r\n", sig.call_signature()));
let _ = write!(long_desc, "Usage:\r\n > {}\r\n", sig.call_signature());
if !sig.named.is_empty() {
long_desc.push_str(&get_flags_section(sig))
@ -61,27 +66,28 @@ impl NuHelpCompleter {
{
long_desc.push_str("\r\nParameters:\r\n");
for positional in &sig.required_positional {
long_desc
.push_str(&format!(" {}: {}\r\n", positional.name, positional.desc));
let _ = write!(long_desc, " {}: {}\r\n", positional.name, positional.desc);
}
for positional in &sig.optional_positional {
long_desc.push_str(&format!(
let _ = write!(
long_desc,
" (optional) {}: {}\r\n",
positional.name, positional.desc
));
);
}
if let Some(rest_positional) = &sig.rest_positional {
long_desc.push_str(&format!(
let _ = write!(
long_desc,
" ...{}: {}\r\n",
rest_positional.name, rest_positional.desc
));
);
}
}
let extra: Vec<String> = examples
.iter()
.map(|example| example.example.to_string())
.map(|example| example.example.replace('\n', "\r\n"))
.collect();
Suggestion {

View File

@ -19,6 +19,10 @@ impl Command for NuHighlight {
"Syntax highlight the input string."
}
fn search_terms(&self) -> Vec<&str> {
vec!["syntax", "color", "convert"]
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -17,7 +17,7 @@ impl Command for Print {
Signature::build("print")
.rest("rest", SyntaxShape::Any, "the values to print")
.switch(
"no_newline",
"no-newline",
"print without inserting a newline for the line ending",
Some('n'),
)
@ -28,6 +28,10 @@ impl Command for Print {
"Prints the values given"
}
fn search_terms(&self) -> Vec<&str> {
vec!["display"]
}
fn run(
&self,
engine_state: &EngineState,
@ -36,7 +40,7 @@ impl Command for Print {
_input: PipelineData,
) -> Result<PipelineData, ShellError> {
let args: Vec<Value> = call.rest(engine_state, stack, 0)?;
let no_newline = call.has_flag("no_newline");
let no_newline = call.has_flag("no-newline");
let head = call.head;
for arg in args {

View File

@ -12,21 +12,22 @@ use nu_engine::{convert_env_values, eval_block};
use nu_parser::lex;
use nu_protocol::{
engine::{EngineState, Stack, StateWorkingSet},
BlockId, PipelineData, PositionalArg, ShellError, Span, Value,
BlockId, HistoryFileFormat, PipelineData, PositionalArg, ShellError, Span, Value,
};
use reedline::{DefaultHinter, Emacs, Vi};
use reedline::{DefaultHinter, Emacs, SqliteBackedHistory, Vi};
use std::io::{self, Write};
use std::path::PathBuf;
use std::{sync::atomic::Ordering, time::Instant};
use sysinfo::SystemExt;
const PRE_EXECUTE_MARKER: &str = "\x1b]133;A\x1b\\";
const PRE_PROMPT_MARKER: &str = "\x1b]133;C\x1b\\";
const PRE_PROMPT_MARKER: &str = "\x1b]133;A\x1b\\";
const PRE_EXECUTE_MARKER: &str = "\x1b]133;C\x1b\\";
const CMD_FINISHED_MARKER: &str = "\x1b]133;D\x1b\\";
const RESET_APPLICATION_MODE: &str = "\x1b[?1l";
pub fn evaluate_repl(
engine_state: &mut EngineState,
stack: &mut Stack,
history_path: Option<PathBuf>,
nushell_path: &str,
is_perf_true: bool,
) -> Result<()> {
use reedline::{FileBackedHistory, Reedline, Signal};
@ -84,20 +85,32 @@ pub fn evaluate_repl(
info!("setup reedline {}:{}:{}", file!(), line!(), column!());
}
let mut line_editor = Reedline::create();
let history_path = crate::config_files::get_history_path(
nushell_path,
engine_state.config.history_file_format,
);
if let Some(history_path) = history_path.as_deref() {
if is_perf_true {
info!("setup history {}:{}:{}", file!(), line!(), column!());
}
let history = Box::new(
FileBackedHistory::with_file(
config.max_history_size as usize,
history_path.to_path_buf(),
)
.into_diagnostic()?,
);
let history: Box<dyn reedline::History> = match engine_state.config.history_file_format {
HistoryFileFormat::PlainText => Box::new(
FileBackedHistory::with_file(
config.max_history_size as usize,
history_path.to_path_buf(),
)
.into_diagnostic()?,
),
HistoryFileFormat::Sqlite => Box::new(
SqliteBackedHistory::with_file(history_path.to_path_buf()).into_diagnostic()?,
),
};
line_editor = line_editor.with_history(history);
};
let sys = sysinfo::System::new();
loop {
if is_perf_true {
info!(
@ -112,6 +125,10 @@ pub fn evaluate_repl(
if let Some(ctrlc) = &mut engine_state.ctrlc {
ctrlc.store(false, Ordering::SeqCst);
}
// Reset the SIGQUIT handler
if let Some(sig_quit) = engine_state.get_sig_quit() {
sig_quit.store(false, Ordering::SeqCst);
}
config = engine_state.get_config();
@ -272,8 +289,9 @@ pub fn evaluate_repl(
config = engine_state.get_config();
if config.shell_integration {
run_ansi_sequence(PRE_EXECUTE_MARKER)?;
let shell_integration = config.shell_integration;
if shell_integration {
run_ansi_sequence(PRE_PROMPT_MARKER)?;
}
let prompt =
@ -294,6 +312,20 @@ pub fn evaluate_repl(
match input {
Ok(Signal::Success(s)) => {
let history_supports_meta =
matches!(config.history_file_format, HistoryFileFormat::Sqlite);
if history_supports_meta && !s.is_empty() {
line_editor
.update_last_command_context(&|mut c| {
c.start_timestamp = Some(chrono::Utc::now());
c.hostname = sys.host_name();
c.cwd = Some(StateWorkingSet::new(engine_state).get_cwd());
c
})
.into_diagnostic()?; // todo: don't stop repl if error here?
}
// Right before we start running the code the user gave us,
// fire the "pre_execution" hook
if let Some(hook) = &config.hooks.pre_execution {
@ -303,9 +335,9 @@ pub fn evaluate_repl(
}
}
if config.shell_integration {
if shell_integration {
run_ansi_sequence(RESET_APPLICATION_MODE)?;
run_ansi_sequence(PRE_PROMPT_MARKER)?;
run_ansi_sequence(PRE_EXECUTE_MARKER)?;
if let Some(cwd) = stack.get_env_var(engine_state, "PWD") {
let path = cwd.as_string()?;
// Try to abbreviate string for windows title
@ -395,11 +427,12 @@ pub fn evaluate_repl(
PipelineData::new(Span::new(0, 0)),
);
}
let cmd_duration = start_time.elapsed();
stack.add_env_var(
"CMD_DURATION_MS".into(),
Value::String {
val: format!("{}", start_time.elapsed().as_millis()),
val: format!("{}", cmd_duration.as_millis()),
span: Span { start: 0, end: 0 },
},
);
@ -411,12 +444,35 @@ pub fn evaluate_repl(
let _ = std::env::set_current_dir(path);
engine_state.add_env_var("PWD".into(), cwd);
}
if history_supports_meta && !s.is_empty() {
line_editor
.update_last_command_context(&|mut c| {
c.duration = Some(cmd_duration);
c.exit_status = stack
.get_env_var(engine_state, "LAST_EXIT_CODE")
.and_then(|e| e.as_i64().ok());
c
})
.into_diagnostic()?; // todo: don't stop repl if error here?
}
if shell_integration {
// FIXME: use variant with exit code, if apropriate
run_ansi_sequence(CMD_FINISHED_MARKER)?;
}
}
Ok(Signal::CtrlC) => {
// `Reedline` clears the line content. New prompt is shown
if shell_integration {
run_ansi_sequence(CMD_FINISHED_MARKER)?;
}
}
Ok(Signal::CtrlD) => {
// When exiting clear to a new line
if shell_integration {
run_ansi_sequence(CMD_FINISHED_MARKER)?;
}
println!();
break;
}
@ -425,6 +481,9 @@ pub fn evaluate_repl(
if !message.contains("duration") {
println!("Error: {:?}", err);
}
if shell_integration {
run_ansi_sequence(CMD_FINISHED_MARKER)?;
}
}
}
}

View File

@ -9,18 +9,35 @@ use nu_protocol::{
};
#[cfg(windows)]
use nu_utils::enable_vt_processing;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
// This will collect environment variables from std::env and adds them to a stack.
//
// In order to ensure the values have spans, it first creates a dummy file, writes the collected
// env vars into it (in a "NAME"="value" format, quite similar to the output of the Unix 'env'
// tool), then uses the file to get the spans. The file stays in memory, no filesystem IO is done.
pub fn gather_parent_env_vars(engine_state: &mut EngineState) {
gather_env_vars(std::env::vars(), engine_state);
//
// The "PWD" env value will be forced to `init_cwd`.
// The reason to use `init_cwd`:
//
// While gathering parent env vars, the parent `PWD` may not be the same as `current working directory`.
// Consider to the following command as the case (assume we execute command inside `/tmp`):
//
// tmux split-window -v -c "#{pane_current_path}"
//
// Here nu execute external command `tmux`, and tmux starts a new `nushell`, with `init_cwd` value "#{pane_current_path}".
// But at the same time `PWD` still remains to be `/tmp`.
//
// In this scenario, the new `nushell`'s PWD should be "#{pane_current_path}" rather init_cwd.
pub fn gather_parent_env_vars(engine_state: &mut EngineState, init_cwd: &Path) {
gather_env_vars(std::env::vars(), engine_state, init_cwd);
}
fn gather_env_vars(vars: impl Iterator<Item = (String, String)>, engine_state: &mut EngineState) {
fn gather_env_vars(
vars: impl Iterator<Item = (String, String)>,
engine_state: &mut EngineState,
init_cwd: &Path,
) {
fn report_capture_error(engine_state: &EngineState, env_str: &str, msg: &str) {
let working_set = StateWorkingSet::new(engine_state);
report_error(
@ -43,35 +60,31 @@ fn gather_env_vars(vars: impl Iterator<Item = (String, String)>, engine_state: &
}
let mut fake_env_file = String::new();
let mut has_pwd = false;
// Write all the env vars into a fake file
for (name, val) in vars {
if name == "PWD" {
has_pwd = true;
}
put_env_to_fake_file(&name, &val, &mut fake_env_file);
}
if !has_pwd {
match std::env::current_dir() {
Ok(cwd) => {
put_env_to_fake_file("PWD", &cwd.to_string_lossy(), &mut fake_env_file);
}
Err(e) => {
// Could not capture current working directory
let working_set = StateWorkingSet::new(engine_state);
report_error(
&working_set,
&ShellError::GenericError(
"Current directory not found".to_string(),
"".to_string(),
None,
Some(format!("Retrieving current directory failed: {:?}", e)),
Vec::new(),
),
);
}
match init_cwd.to_str() {
Some(cwd) => {
put_env_to_fake_file("PWD", cwd, &mut fake_env_file);
}
None => {
// Could not capture current working directory
let working_set = StateWorkingSet::new(engine_state);
report_error(
&working_set,
&ShellError::GenericError(
"Current directory is not a valid utf-8 path".to_string(),
"".to_string(),
None,
Some(format!(
"Retrieving current directory failed: {:?} not a valid utf-8 path",
init_cwd
)),
Vec::new(),
),
);
}
}
@ -314,6 +327,7 @@ mod test {
]
.into_iter(),
&mut engine_state,
Path::new("t"),
);
let env = engine_state.render_env_vars();

View File

@ -18,7 +18,7 @@ fn variables_completions() {
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
// Test completions for $nu
let suggestions = completer.complete("my-command ".into(), 11);
let suggestions = completer.complete("my-command ", 11);
assert_eq!(3, suggestions.len());

View File

@ -12,7 +12,7 @@ fn flag_completions() {
// Instatiate a new completer
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
// Test completions for the 'ls' flags
let suggestions = completer.complete("ls -".into(), 4);
let suggestions = completer.complete("ls -", 4);
assert_eq!(12, suggestions.len());

View File

@ -89,7 +89,7 @@ pub fn merge_input(
dir: PathBuf,
) -> Result<(), ShellError> {
let (block, delta) = {
let mut working_set = StateWorkingSet::new(&engine_state);
let mut working_set = StateWorkingSet::new(engine_state);
let (block, err) = parse(&mut working_set, None, input, false, &[]);
@ -98,7 +98,7 @@ pub fn merge_input(
(block, working_set.render())
};
assert!(eval_block(
&engine_state,
engine_state,
stack,
&block,
PipelineData::Value(

View File

@ -17,15 +17,16 @@ fn variables_completions() {
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
// Test completions for $nu
let suggestions = completer.complete("$nu.".into(), 4);
let suggestions = completer.complete("$nu.", 4);
assert_eq!(8, suggestions.len());
assert_eq!(9, suggestions.len());
let expected: Vec<String> = vec![
"config-path".into(),
"env-path".into(),
"history-path".into(),
"home-path".into(),
"loginshell-path".into(),
"os-info".into(),
"pid".into(),
"scope".into(),
@ -36,7 +37,7 @@ fn variables_completions() {
match_suggestions(expected, suggestions);
// Test completions for $nu.h (filter)
let suggestions = completer.complete("$nu.h".into(), 5);
let suggestions = completer.complete("$nu.h", 5);
assert_eq!(2, suggestions.len());
@ -46,7 +47,7 @@ fn variables_completions() {
match_suggestions(expected, suggestions);
// Test completions for custom var
let suggestions = completer.complete("$actor.".into(), 7);
let suggestions = completer.complete("$actor.", 7);
assert_eq!(2, suggestions.len());
@ -56,7 +57,7 @@ fn variables_completions() {
match_suggestions(expected, suggestions);
// Test completions for custom var (filtering)
let suggestions = completer.complete("$actor.n".into(), 7);
let suggestions = completer.complete("$actor.n", 8);
assert_eq!(1, suggestions.len());
@ -66,7 +67,7 @@ fn variables_completions() {
match_suggestions(expected, suggestions);
// Test completions for $env
let suggestions = completer.complete("$env.".into(), 5);
let suggestions = completer.complete("$env.", 5);
assert_eq!(2, suggestions.len());
@ -76,7 +77,7 @@ fn variables_completions() {
match_suggestions(expected, suggestions);
// Test completions for $env
let suggestions = completer.complete("$env.T".into(), 5);
let suggestions = completer.complete("$env.T", 6);
assert_eq!(1, suggestions.len());

View File

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

View File

@ -1,7 +1,7 @@
use nu_ansi_term::{Color, Style};
use serde::Deserialize;
#[derive(Deserialize, PartialEq, Debug)]
#[derive(Deserialize, PartialEq, Eq, Debug)]
pub struct NuStyle {
pub fg: Option<String>,
pub bg: Option<String>,

View File

@ -4,26 +4,26 @@ description = "Nushell's built-in commands"
edition = "2021"
license = "MIT"
name = "nu-command"
version = "0.63.1"
version = "0.64.0"
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.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"
nu-color-config = { path = "../nu-color-config", version = "0.64.0" }
nu-engine = { path = "../nu-engine", version = "0.64.0" }
nu-glob = { path = "../nu-glob", version = "0.64.0" }
nu-json = { path = "../nu-json", version = "0.64.0" }
nu-parser = { path = "../nu-parser", version = "0.64.0" }
nu-path = { path = "../nu-path", version = "0.64.0" }
nu-pretty-hex = { path = "../nu-pretty-hex", version = "0.64.0" }
nu-protocol = { path = "../nu-protocol", version = "0.64.0" }
nu-system = { path = "../nu-system", version = "0.64.0" }
nu-table = { path = "../nu-table", version = "0.64.0" }
nu-term-grid = { path = "../nu-term-grid", version = "0.64.0" }
nu-test-support = { path = "../nu-test-support", version = "0.64.0" }
nu-utils = { path = "../nu-utils", version = "0.64.0" }
nu-ansi-term = "0.46.0"
# Potential dependencies for extras
alphanumeric-sort = "1.4.4"
@ -47,6 +47,7 @@ htmlescape = "0.3.1"
ical = "0.7.0"
indexmap = { version="1.7", features=["serde-1"] }
Inflector = "0.11"
is-root = "0.1.2"
itertools = "0.10.0"
lazy_static = "1.4.0"
log = "0.4.14"
@ -82,7 +83,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 = { git = "https://github.com/nushell/reedline", branch = "main", features = ["bashisms"]}
reedline = { version = "0.7.0", features = ["bashisms", "sqlite"]}
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 }
@ -107,6 +108,15 @@ features = [
"dynamic_groupby"
]
[target.'cfg(windows)'.dependencies.windows]
version = "0.37.0"
features = [
"alloc",
"Win32_Foundation",
"Win32_Storage_FileSystem",
"Win32_System_SystemServices",
]
[features]
trash-support = ["trash"]
which-support = ["which"]

View File

@ -191,7 +191,10 @@ pub fn action(input: &Value, span: Span, radix: u32) -> Value {
span,
},
_ => Value::Error {
error: ShellError::UnsupportedInput("'into int' for unsupported type".into(), span),
error: ShellError::UnsupportedInput(
format!("'into int' for unsupported type '{}'", input.get_type()),
span,
),
},
}
}

View File

@ -34,6 +34,10 @@ impl Command for Alias {
true
}
fn search_terms(&self) -> Vec<&str> {
vec!["abbr", "aka", "fn", "func", "function"]
}
fn run(
&self,
_engine_state: &EngineState,

View File

@ -1,14 +1,13 @@
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Value,
Category, Example, HistoryFileFormat, IntoInterruptiblePipelineData, PipelineData, ShellError,
Signature, Value,
};
use reedline::{
FileBackedHistory, History as ReedlineHistory, SearchDirection, SearchQuery,
SqliteBackedHistory,
};
const NEWLINE_ESCAPE_CODE: &str = "<\\n>";
fn decode_newlines(escaped: &str) -> String {
escaped.replace(NEWLINE_ESCAPE_CODE, "\n")
}
#[derive(Clone)]
pub struct History;
@ -36,44 +35,74 @@ impl Command for History {
_input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
let head = call.head;
// todo for sqlite history this command should be an alias to `open ~/.config/nushell/history.sqlite3 | get history`
if let Some(config_path) = nu_path::config_dir() {
let clear = call.has_flag("clear");
let ctrlc = engine_state.ctrlc.clone();
let mut history_path = config_path;
history_path.push("nushell");
history_path.push("history.txt");
match engine_state.config.history_file_format {
HistoryFileFormat::Sqlite => {
history_path.push("history.sqlite3");
}
HistoryFileFormat::PlainText => {
history_path.push("history.txt");
}
}
if clear {
let _ = std::fs::remove_file(history_path);
// TODO: FIXME also clear the auxiliary files when using sqlite
Ok(PipelineData::new(head))
} else {
let contents = std::fs::read_to_string(history_path);
let history_reader: Option<Box<dyn ReedlineHistory>> =
match engine_state.config.history_file_format {
HistoryFileFormat::Sqlite => SqliteBackedHistory::with_file(history_path)
.map(|inner| {
let boxed: Box<dyn ReedlineHistory> = Box::new(inner);
boxed
})
.ok(),
if let Ok(contents) = contents {
Ok(contents
.lines()
.enumerate()
.map(move |(index, command)| Value::Record {
cols: vec!["command".to_string(), "index".to_string()],
vals: vec![
Value::String {
val: decode_newlines(command),
span: head,
},
Value::Int {
val: index as i64,
span: head,
},
],
span: head,
HistoryFileFormat::PlainText => FileBackedHistory::with_file(
engine_state.config.max_history_size as usize,
history_path,
)
.map(|inner| {
let boxed: Box<dyn ReedlineHistory> = Box::new(inner);
boxed
})
.collect::<Vec<_>>()
.into_iter()
.into_pipeline_data(ctrlc))
} else {
Err(ShellError::FileNotFound(head))
}
.ok(),
};
let data = history_reader
.and_then(|h| {
h.search(SearchQuery::everything(SearchDirection::Forward))
.ok()
})
.map(move |entries| {
entries
.into_iter()
.enumerate()
.map(move |(idx, entry)| Value::Record {
cols: vec!["command".to_string(), "index".to_string()],
vals: vec![
Value::String {
val: entry.command_line,
span: head,
},
Value::Int {
val: idx as i64,
span: head,
},
],
span: head,
})
})
.ok_or(ShellError::FileNotFound(head))?
.into_pipeline_data(ctrlc);
Ok(data)
}
} else {
Err(ShellError::FileNotFound(head))

View File

@ -24,7 +24,7 @@ impl Command for OrderByDb {
fn signature(&self) -> Signature {
Signature::build(self.name())
.switch("ascending", "Order by ascending values", Some('a'))
.switch("nulls_first", "Show nulls first in order", Some('n'))
.switch("nulls-first", "Show nulls first in order", Some('n'))
.rest(
"select",
SyntaxShape::Any,
@ -40,10 +40,10 @@ impl Command for OrderByDb {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "orders query by a column",
example: r#"db open db.mysql
| db from table_a
| db select a
| db order-by a
example: r#"db open db.mysql
| db from table_a
| db select a
| db order-by a
| db describe"#,
result: None,
}]
@ -57,7 +57,7 @@ impl Command for OrderByDb {
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let asc = call.has_flag("ascending");
let nulls_first = call.has_flag("nulls_first");
let nulls_first = call.has_flag("nulls-first");
let expressions: Vec<Value> = call.rest(engine_state, stack, 0)?;
let expressions = Value::List {
vals: expressions,

View File

@ -52,7 +52,7 @@ impl CustomValue for ExprDb {
fn follow_path_int(&self, count: usize, span: Span) -> Result<Value, ShellError> {
let path = PathMember::Int { val: count, span };
ExprDb::expr_to_value(self.as_ref(), span).follow_cell_path(&[path])
ExprDb::expr_to_value(self.as_ref(), span).follow_cell_path(&[path], false)
}
fn follow_path_string(&self, column_name: String, span: Span) -> Result<Value, ShellError> {
@ -61,7 +61,7 @@ impl CustomValue for ExprDb {
span,
};
ExprDb::expr_to_value(self.as_ref(), span).follow_cell_path(&[path])
ExprDb::expr_to_value(self.as_ref(), span).follow_cell_path(&[path], false)
}
fn typetag_name(&self) -> &'static str {
@ -91,7 +91,7 @@ impl CustomValue for ExprDb {
Value::Bool { val, .. } => Ok(Expr::Value(sqlparser::ast::Value::Boolean(*val))),
_ => Err(ShellError::OperatorMismatch {
op_span: op,
lhs_ty: Type::Custom,
lhs_ty: Type::Custom(self.typetag_name().into()),
lhs_span,
rhs_ty: right.get_type(),
rhs_span: right.span()?,
@ -112,6 +112,7 @@ impl CustomValue for ExprDb {
Operator::Multiply => Ok(BinaryOperator::Multiply),
Operator::Divide => Ok(BinaryOperator::Divide),
Operator::Modulo => Ok(BinaryOperator::Modulo),
Operator::FloorDivision => Ok(BinaryOperator::Divide),
Operator::And => Ok(BinaryOperator::And),
Operator::Or => Ok(BinaryOperator::Or),
Operator::In

View File

@ -56,7 +56,7 @@ impl CustomValue for SelectDb {
fn follow_path_int(&self, count: usize, span: Span) -> Result<Value, ShellError> {
let path = PathMember::Int { val: count, span };
SelectDb::select_to_value(self.as_ref(), span).follow_cell_path(&[path])
SelectDb::select_to_value(self.as_ref(), span).follow_cell_path(&[path], false)
}
fn follow_path_string(&self, column_name: String, span: Span) -> Result<Value, ShellError> {
@ -64,7 +64,7 @@ impl CustomValue for SelectDb {
val: column_name,
span,
};
SelectDb::select_to_value(self.as_ref(), span).follow_cell_path(&[path])
SelectDb::select_to_value(self.as_ref(), span).follow_cell_path(&[path], false)
}
fn typetag_name(&self) -> &'static str {

View File

@ -2,7 +2,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use super::super::values::{Axis, Column, NuDataFrame};
@ -12,7 +12,7 @@ pub struct AppendDF;
impl Command for AppendDF {
fn name(&self) -> &str {
"dfr append"
"append"
}
fn usage(&self) -> &str {
@ -30,8 +30,8 @@ impl Command for AppendDF {
vec![
Example {
description: "Appends a dataframe as new columns",
example: r#"let a = ([[a b]; [1 2] [3 4]] | dfr to-df);
$a | dfr append $a"#,
example: r#"let a = ([[a b]; [1 2] [3 4]] | to-df);
$a | append $a"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
@ -57,8 +57,8 @@ impl Command for AppendDF {
},
Example {
description: "Appends a dataframe merging at the end of columns",
example: r#"let a = ([[a b]; [1 2] [3 4]] | dfr to-df);
$a | dfr append $a --col"#,
example: r#"let a = ([[a b]; [1 2] [3 4]] | to-df);
$a | append $a --col"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
@ -87,6 +87,14 @@ impl Command for AppendDF {
]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -1,87 +0,0 @@
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
};
use super::super::values::{Column, NuDataFrame};
#[derive(Clone)]
pub struct ColumnDF;
impl Command for ColumnDF {
fn name(&self) -> &str {
"dfr column"
}
fn usage(&self) -> &str {
"Returns the selected column"
}
fn signature(&self) -> Signature {
Signature::build(self.name())
.required("column", SyntaxShape::String, "column name")
.category(Category::Custom("dataframe".into()))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Returns the selected column as series",
example: "[[a b]; [1 2] [3 4]] | dfr to-df | dfr column a",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"a".to_string(),
vec![Value::test_int(1), Value::test_int(3)],
)])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
}]
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
command(engine_state, stack, call, input)
}
}
fn command(
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let column: Spanned<String> = call.req(engine_state, stack, 0)?;
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let res = df.as_ref().column(&column.item).map_err(|e| {
ShellError::GenericError(
"Error selecting column".into(),
e.to_string(),
Some(column.span),
None,
Vec::new(),
)
})?;
NuDataFrame::try_from_series(vec![res.clone()], call.head)
.map(|df| PipelineData::Value(NuDataFrame::into_value(df, call.head), None))
}
#[cfg(test)]
mod test {
use super::super::super::test_dataframe::test_dataframe;
use super::*;
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(ColumnDF {})])
}
}

View File

@ -1,42 +0,0 @@
use nu_engine::get_full_help;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, IntoPipelineData, PipelineData, ShellError, Signature, Value,
};
#[derive(Clone)]
pub struct Dataframe;
impl Command for Dataframe {
fn name(&self) -> &str {
"dfr"
}
fn usage(&self) -> &str {
"Dataframe commands"
}
fn signature(&self) -> Signature {
Signature::build(self.name()).category(Category::Custom("dataframe".into()))
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
_input: PipelineData,
) -> Result<PipelineData, ShellError> {
Ok(Value::String {
val: get_full_help(
&Dataframe.signature(),
&Dataframe.examples(),
engine_state,
stack,
),
span: call.head,
}
.into_pipeline_data())
}
}

View File

@ -4,7 +4,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use polars::{
chunked_array::ChunkedArray,
@ -19,7 +19,7 @@ pub struct DescribeDF;
impl Command for DescribeDF {
fn name(&self) -> &str {
"dfr describe"
"describe"
}
fn usage(&self) -> &str {
@ -40,7 +40,7 @@ impl Command for DescribeDF {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "dataframe description",
example: "[[a b]; [1 1] [1 1]] | dfr to-df | dfr describe",
example: "[[a b]; [1 1] [1 1]] | to-df | describe",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
@ -95,6 +95,14 @@ impl Command for DescribeDF {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -2,7 +2,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use super::super::values::utils::convert_columns;
@ -13,7 +13,7 @@ pub struct DropDF;
impl Command for DropDF {
fn name(&self) -> &str {
"dfr drop"
"drop"
}
fn usage(&self) -> &str {
@ -29,7 +29,7 @@ impl Command for DropDF {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "drop column a",
example: "[[a b]; [1 2] [3 4]] | dfr to-df | dfr drop a",
example: "[[a b]; [1 2] [3 4]] | to-df | drop a",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"b".to_string(),
@ -41,6 +41,14 @@ impl Command for DropDF {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -2,7 +2,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use polars::prelude::UniqueKeepStrategy;
@ -14,7 +14,7 @@ pub struct DropDuplicates;
impl Command for DropDuplicates {
fn name(&self) -> &str {
"dfr drop-duplicates"
"drop-duplicates"
}
fn usage(&self) -> &str {
@ -40,7 +40,7 @@ impl Command for DropDuplicates {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "drop duplicates",
example: "[[a b]; [1 2] [3 4] [1 2]] | dfr to-df | dfr drop-duplicates",
example: "[[a b]; [1 2] [3 4] [1 2]] | to-df | drop-duplicates",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
@ -58,6 +58,14 @@ impl Command for DropDuplicates {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -2,7 +2,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use super::super::values::utils::convert_columns_string;
@ -13,7 +13,7 @@ pub struct DropNulls;
impl Command for DropNulls {
fn name(&self) -> &str {
"dfr drop-nulls"
"drop-nulls"
}
fn usage(&self) -> &str {
@ -34,10 +34,10 @@ impl Command for DropNulls {
vec![
Example {
description: "drop null values in dataframe",
example: r#"let df = ([[a b]; [1 2] [3 0] [1 2]] | dfr to-df);
example: r#"let df = ([[a b]; [1 2] [3 0] [1 2]] | to-df);
let res = ($df.b / $df.b);
let a = ($df | dfr with-column $res --name res);
$a | dfr drop-nulls"#,
let a = ($df | with-column $res --name res);
$a | drop-nulls"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
@ -59,8 +59,8 @@ impl Command for DropNulls {
},
Example {
description: "drop null values in dataframe",
example: r#"let s = ([1 2 0 0 3 4] | dfr to-df);
($s / $s) | dfr drop-nulls"#,
example: r#"let s = ([1 2 0 0 3 4] | to-df);
($s / $s) | drop-nulls"#,
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"div_0_0".to_string(),
@ -78,6 +78,14 @@ impl Command for DropNulls {
]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -2,7 +2,7 @@ use super::super::values::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
#[derive(Clone)]
@ -10,7 +10,7 @@ pub struct DataTypes;
impl Command for DataTypes {
fn name(&self) -> &str {
"dfr dtypes"
"dtypes"
}
fn usage(&self) -> &str {
@ -24,7 +24,7 @@ impl Command for DataTypes {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Dataframe dtypes",
example: "[[a b]; [1 2] [3 4]] | dfr to-df | dfr dtypes",
example: "[[a b]; [1 2] [3 4]] | to-df | dtypes",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
@ -42,6 +42,14 @@ impl Command for DataTypes {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -2,7 +2,7 @@ use super::super::values::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
use polars::prelude::DataFrameOps;
@ -11,7 +11,7 @@ pub struct Dummies;
impl Command for Dummies {
fn name(&self) -> &str {
"dfr to-dummies"
"to-dummies"
}
fn usage(&self) -> &str {
@ -26,7 +26,7 @@ impl Command for Dummies {
vec![
Example {
description: "Create new dataframe with dummy variables from a dataframe",
example: "[[a b]; [1 2] [3 4]] | dfr to-df | dfr to-dummies",
example: "[[a b]; [1 2] [3 4]] | to-df | to-dummies",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
@ -52,7 +52,7 @@ impl Command for Dummies {
},
Example {
description: "Create new dataframe with dummy variables from a series",
example: "[1 2 2 3 3] | dfr to-df | dfr to-dummies",
example: "[1 2 2 3 3] | to-df | to-dummies",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
@ -93,6 +93,14 @@ impl Command for Dummies {
]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -2,7 +2,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use polars::prelude::LazyFrame;
@ -15,7 +15,7 @@ pub struct FilterWith;
impl Command for FilterWith {
fn name(&self) -> &str {
"dfr filter-with"
"filter-with"
}
fn usage(&self) -> &str {
@ -29,23 +29,45 @@ impl Command for FilterWith {
SyntaxShape::Any,
"boolean mask used to filter data",
)
.category(Category::Custom("dataframe".into()))
.category(Category::Custom("dataframe or lazyframe".into()))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Filter dataframe using a bool mask",
example: r#"let mask = ([true false] | dfr to-df);
[[a b]; [1 2] [3 4]] | dfr to-df | dfr filter-with $mask"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_int(1)]),
Column::new("b".to_string(), vec![Value::test_int(2)]),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
}]
vec![
Example {
description: "Filter dataframe using a bool mask",
example: r#"let mask = ([true false] | to-df);
[[a b]; [1 2] [3 4]] | to-df | filter-with $mask"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_int(1)]),
Column::new("b".to_string(), vec![Value::test_int(2)]),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
Example {
description: "Filter dataframe using an expression",
example: "[[a b]; [1 2] [3 4]] | to-df | filter-with ((col a) > 1)",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_int(3)]),
Column::new("b".to_string(), vec![Value::test_int(4)]),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
@ -60,16 +82,9 @@ impl Command for FilterWith {
if NuLazyFrame::can_downcast(&value) {
let df = NuLazyFrame::try_from_value(value)?;
command_lazy(engine_state, stack, call, df)
} else if NuDataFrame::can_downcast(&value) {
} else {
let df = NuDataFrame::try_from_value(value)?;
command_eager(engine_state, stack, call, df)
} else {
Err(ShellError::CantConvert(
"expression or query".into(),
value.get_type().to_string(),
value.span()?,
None,
))
}
}
}
@ -81,31 +96,42 @@ fn command_eager(
df: NuDataFrame,
) -> Result<PipelineData, ShellError> {
let mask_value: Value = call.req(engine_state, stack, 0)?;
let mask_span = mask_value.span()?;
let mask = NuDataFrame::try_from_value(mask_value)?.as_series(mask_span)?;
let mask = mask.bool().map_err(|e| {
ShellError::GenericError(
"Error casting to bool".into(),
e.to_string(),
Some(mask_span),
Some("Perhaps you want to use a series with booleans as mask".into()),
Vec::new(),
)
})?;
df.as_ref()
.filter(mask)
.map_err(|e| {
if NuExpression::can_downcast(&mask_value) {
let expression = NuExpression::try_from_value(mask_value)?;
let lazy = NuLazyFrame::new(true, df.lazy());
let lazy = lazy.apply_with_expr(expression, LazyFrame::filter);
Ok(PipelineData::Value(
NuLazyFrame::into_value(lazy, call.head)?,
None,
))
} else {
let mask = NuDataFrame::try_from_value(mask_value)?.as_series(mask_span)?;
let mask = mask.bool().map_err(|e| {
ShellError::GenericError(
"Error calculating dummies".into(),
"Error casting to bool".into(),
e.to_string(),
Some(call.head),
Some("The only allowed column types for dummies are String or Int".into()),
Some(mask_span),
Some("Perhaps you want to use a series with booleans as mask".into()),
Vec::new(),
)
})
.map(|df| PipelineData::Value(NuDataFrame::dataframe_into_value(df, call.head), None))
})?;
df.as_ref()
.filter(mask)
.map_err(|e| {
ShellError::GenericError(
"Error filtering dataframe".into(),
e.to_string(),
Some(call.head),
Some("The only allowed column types for dummies are String or Int".into()),
Vec::new(),
)
})
.map(|df| PipelineData::Value(NuDataFrame::dataframe_into_value(df, call.head), None))
}
}
fn command_lazy(
@ -120,7 +146,7 @@ fn command_lazy(
let lazy = lazy.apply_with_expr(expr, LazyFrame::filter);
Ok(PipelineData::Value(
NuLazyFrame::into_value(lazy, call.head),
NuLazyFrame::into_value(lazy, call.head)?,
None,
))
}
@ -129,9 +155,10 @@ fn command_lazy(
mod test {
use super::super::super::test_dataframe::test_dataframe;
use super::*;
use crate::dataframe::expressions::ExprCol;
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(FilterWith {})])
test_dataframe(vec![Box::new(FilterWith {}), Box::new(ExprCol {})])
}
}

View File

@ -1,10 +1,9 @@
use super::super::values::{utils::DEFAULT_ROWS, Column, NuDataFrame};
use crate::dataframe::values::NuExpression;
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
#[derive(Clone)]
@ -12,11 +11,11 @@ pub struct FirstDF;
impl Command for FirstDF {
fn name(&self) -> &str {
"dfr first"
"first"
}
fn usage(&self) -> &str {
"Creates new dataframe with first rows or creates a first expression"
"Creates new dataframe with first rows"
}
fn signature(&self) -> Signature {
@ -26,25 +25,26 @@ impl Command for FirstDF {
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Create new dataframe with head rows",
example: "[[a b]; [1 2] [3 4]] | dfr to-df | dfr first 1",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_int(1)]),
Column::new("b".to_string(), vec![Value::test_int(2)]),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
Example {
description: "Creates a first expression from a column",
example: "dfr col a | dfr first",
result: None,
},
]
vec![Example {
description: "Create new dataframe with head rows",
example: "[[a b]; [1 2] [3 4]] | to-df | first 1",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_int(1)]),
Column::new("b".to_string(), vec![Value::test_int(2)]),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
@ -54,27 +54,8 @@ impl Command for FirstDF {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let value = input.into_value(call.head);
if NuExpression::can_downcast(&value) {
let expr = NuExpression::try_from_value(value)?;
let expr: NuExpression = expr.into_polars().is_null().into();
Ok(PipelineData::Value(
NuExpression::into_value(expr, call.head),
None,
))
} else if NuDataFrame::can_downcast(&value) {
let df = NuDataFrame::try_from_value(value)?;
command(engine_state, stack, call, df)
} else {
Err(ShellError::CantConvert(
"expression or query".into(),
value.get_type().to_string(),
value.span()?,
None,
))
}
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
command(engine_state, stack, call, df)
}
}

View File

@ -2,7 +2,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use crate::dataframe::values::utils::convert_columns_string;
@ -14,7 +14,7 @@ pub struct GetDF;
impl Command for GetDF {
fn name(&self) -> &str {
"dfr get"
"get"
}
fn usage(&self) -> &str {
@ -29,8 +29,8 @@ impl Command for GetDF {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Creates dataframe with selected columns",
example: "[[a b]; [1 2] [3 4]] | dfr to-df | dfr get a",
description: "Returns the selected column",
example: "[[a b]; [1 2] [3 4]] | to-df | get a",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"a".to_string(),
@ -42,6 +42,14 @@ impl Command for GetDF {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -1,10 +1,9 @@
use super::super::values::{utils::DEFAULT_ROWS, Column, NuDataFrame};
use crate::dataframe::values::NuExpression;
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
#[derive(Clone)]
@ -12,7 +11,7 @@ pub struct LastDF;
impl Command for LastDF {
fn name(&self) -> &str {
"dfr last"
"last"
}
fn usage(&self) -> &str {
@ -26,25 +25,26 @@ impl Command for LastDF {
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Create new dataframe with last rows",
example: "[[a b]; [1 2] [3 4]] | dfr to-df | dfr last 1",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_int(3)]),
Column::new("b".to_string(), vec![Value::test_int(4)]),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
Example {
description: "Creates a last expression from a column",
example: "dfr col a | dfr last",
result: None,
},
]
vec![Example {
description: "Create new dataframe with last rows",
example: "[[a b]; [1 2] [3 4]] | to-df | last 1",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_int(3)]),
Column::new("b".to_string(), vec![Value::test_int(4)]),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
@ -54,27 +54,8 @@ impl Command for LastDF {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let value = input.into_value(call.head);
if NuExpression::can_downcast(&value) {
let expr = NuExpression::try_from_value(value)?;
let expr: NuExpression = expr.into_polars().is_null().into();
Ok(PipelineData::Value(
NuExpression::into_value(expr, call.head),
None,
))
} else if NuDataFrame::can_downcast(&value) {
let df = NuDataFrame::try_from_value(value)?;
command(engine_state, stack, call, df)
} else {
Err(ShellError::CantConvert(
"expression or query".into(),
value.get_type().to_string(),
value.span()?,
None,
))
}
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
command(engine_state, stack, call, df)
}
}

View File

@ -11,7 +11,7 @@ pub struct ListDF;
impl Command for ListDF {
fn name(&self) -> &str {
"dfr ls"
"ls-df"
}
fn usage(&self) -> &str {
@ -25,8 +25,8 @@ impl Command for ListDF {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Creates a new dataframe and shows it in the dataframe list",
example: r#"let test = ([[a b];[1 2] [3 4]] | dfr to-df);
dfr ls"#,
example: r#"let test = ([[a b];[1 2] [3 4]] | to-df);
ls-df"#,
result: None,
}]
}

View File

@ -2,7 +2,8 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type,
Value,
};
use crate::dataframe::values::utils::convert_columns_string;
@ -14,7 +15,7 @@ pub struct MeltDF;
impl Command for MeltDF {
fn name(&self) -> &str {
"dfr melt"
"melt"
}
fn usage(&self) -> &str {
@ -53,8 +54,7 @@ impl Command for MeltDF {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "melt dataframe",
example:
"[[a b c d]; [x 1 4 a] [y 2 5 b] [z 3 6 c]] | dfr to-df | dfr melt -c [b c] -v [a d]",
example: "[[a b c d]; [x 1 4 a] [y 2 5 b] [z 3 6 c]] | to-df | melt -c [b c] -v [a d]",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
@ -108,6 +108,14 @@ impl Command for MeltDF {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -1,6 +1,4 @@
mod append;
mod column;
mod command;
mod describe;
mod drop;
mod drop_duplicates;
@ -18,7 +16,6 @@ mod rename;
mod sample;
mod shape;
mod slice;
mod sort;
mod take;
mod to_csv;
mod to_df;
@ -29,8 +26,6 @@ mod with_column;
use nu_protocol::engine::StateWorkingSet;
pub use append::AppendDF;
pub use column::ColumnDF;
pub use command::Dataframe;
pub use describe::DescribeDF;
pub use drop::DropDF;
pub use drop_duplicates::DropDuplicates;
@ -48,7 +43,6 @@ pub use rename::RenameDF;
pub use sample::SampleDF;
pub use shape::ShapeDF;
pub use slice::SliceDF;
pub use sort::SortDF;
pub use take::TakeDF;
pub use to_csv::ToCSV;
pub use to_df::ToDataFrame;
@ -69,8 +63,6 @@ pub fn add_eager_decls(working_set: &mut StateWorkingSet) {
// Dataframe commands
bind_command!(
AppendDF,
ColumnDF,
Dataframe,
DataTypes,
DescribeDF,
DropDF,
@ -88,7 +80,6 @@ pub fn add_eager_decls(working_set: &mut StateWorkingSet) {
SampleDF,
ShapeDF,
SliceDF,
SortDF,
TakeDF,
ToCSV,
ToDataFrame,

View File

@ -3,7 +3,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Spanned, SyntaxShape,
Category, Example, PipelineData, ShellError, Signature, Spanned, SyntaxShape, Type,
};
use std::{fs::File, io::BufReader, path::PathBuf};
@ -15,7 +15,7 @@ pub struct OpenDataFrame;
impl Command for OpenDataFrame {
fn name(&self) -> &str {
"dfr open"
"open-df"
}
fn usage(&self) -> &str {
@ -64,11 +64,19 @@ impl Command for OpenDataFrame {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Takes a file name and creates a dataframe",
example: "dfr open test.csv",
example: "open test.csv",
result: None,
}]
}
fn input_type(&self) -> Type {
Type::Any
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -2,7 +2,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use crate::dataframe::{utils::extract_strings, values::NuLazyFrame};
@ -14,7 +14,7 @@ pub struct RenameDF;
impl Command for RenameDF {
fn name(&self) -> &str {
"dfr rename-col"
"rename"
}
fn usage(&self) -> &str {
@ -33,28 +33,73 @@ impl Command for RenameDF {
SyntaxShape::Any,
"New names for the selected column(s). A string or list of strings",
)
.category(Category::Custom("dataframe".into()))
.category(Category::Custom("dataframe or lazyframe".into()))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Renames a dataframe column",
example: "[[a b]; [1 2] [3 4]] | dfr to-df | dfr rename-col a a_new",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a_new".to_string(),
vec![Value::test_int(1), Value::test_int(3)],
),
Column::new(
"b".to_string(),
vec![Value::test_int(2), Value::test_int(4)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
}]
vec![
Example {
description: "Renames a series",
example: "[5 6 7 8] | to-df | rename '0' new_name",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"new_name".to_string(),
vec![
Value::test_int(5),
Value::test_int(6),
Value::test_int(7),
Value::test_int(8),
],
)])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
Example {
description: "Renames a dataframe column",
example: "[[a b]; [1 2] [3 4]] | to-df | rename a a_new",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a_new".to_string(),
vec![Value::test_int(1), Value::test_int(3)],
),
Column::new(
"b".to_string(),
vec![Value::test_int(2), Value::test_int(4)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
Example {
description: "Renames two dataframe columns",
example: "[[a b]; [1 2] [3 4]] | to-df | rename [a b] [a_new b_new]",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a_new".to_string(),
vec![Value::test_int(1), Value::test_int(3)],
),
Column::new(
"b_new".to_string(),
vec![Value::test_int(2), Value::test_int(4)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
@ -69,16 +114,9 @@ impl Command for RenameDF {
if NuLazyFrame::can_downcast(&value) {
let df = NuLazyFrame::try_from_value(value)?;
command_lazy(engine_state, stack, call, df)
} else if NuDataFrame::can_downcast(&value) {
} else {
let df = NuDataFrame::try_from_value(value)?;
command_eager(engine_state, stack, call, df)
} else {
Err(ShellError::CantConvert(
"expression or query".into(),
value.get_type().to_string(),
value.span()?,
None,
))
}
}
}
@ -133,7 +171,7 @@ fn command_lazy(
let lazy = lazy.into_polars();
let lazy: NuLazyFrame = lazy.rename(&columns, &new_names).into();
Ok(PipelineData::Value(lazy.into_value(call.head), None))
Ok(PipelineData::Value(lazy.into_value(call.head)?, None))
}
#[cfg(test)]

View File

@ -2,7 +2,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Spanned, SyntaxShape,
Category, Example, PipelineData, ShellError, Signature, Spanned, SyntaxShape, Type,
};
use super::super::values::NuDataFrame;
@ -12,7 +12,7 @@ pub struct SampleDF;
impl Command for SampleDF {
fn name(&self) -> &str {
"dfr sample"
"sample"
}
fn usage(&self) -> &str {
@ -47,17 +47,25 @@ impl Command for SampleDF {
vec![
Example {
description: "Sample rows from dataframe",
example: "[[a b]; [1 2] [3 4]] | dfr to-df | dfr sample -n 1",
example: "[[a b]; [1 2] [3 4]] | to-df | sample -n 1",
result: None, // No expected value because sampling is random
},
Example {
description: "Shows sample row using fraction and replace",
example: "[[a b]; [1 2] [3 4] [5 6]] | dfr to-df | dfr sample -f 0.5 -e",
example: "[[a b]; [1 2] [3 4] [5 6]] | to-df | sample -f 0.5 -e",
result: None, // No expected value because sampling is random
},
]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -1,7 +1,7 @@
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
use crate::dataframe::values::Column;
@ -13,7 +13,7 @@ pub struct ShapeDF;
impl Command for ShapeDF {
fn name(&self) -> &str {
"dfr shape"
"shape"
}
fn usage(&self) -> &str {
@ -27,7 +27,7 @@ impl Command for ShapeDF {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Shows row and column shape",
example: "[[a b]; [1 2] [3 4]] | dfr to-df | dfr shape",
example: "[[a b]; [1 2] [3 4]] | to-df | shape",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("rows".to_string(), vec![Value::test_int(2)]),
@ -39,6 +39,14 @@ impl Command for ShapeDF {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -2,7 +2,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use crate::dataframe::values::Column;
@ -14,7 +14,7 @@ pub struct SliceDF;
impl Command for SliceDF {
fn name(&self) -> &str {
"dfr slice"
"slice"
}
fn usage(&self) -> &str {
@ -31,7 +31,7 @@ impl Command for SliceDF {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Create new dataframe from a slice of the rows",
example: "[[a b]; [1 2] [3 4]] | dfr to-df | dfr slice 0 1",
example: "[[a b]; [1 2] [3 4]] | to-df | slice 0 1",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_int(1)]),
@ -43,6 +43,14 @@ impl Command for SliceDF {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -1,148 +0,0 @@
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
};
use crate::dataframe::values::{utils::convert_columns_string, Column};
use super::super::values::NuDataFrame;
#[derive(Clone)]
pub struct SortDF;
impl Command for SortDF {
fn name(&self) -> &str {
"dfr sort"
}
fn usage(&self) -> &str {
"Creates new sorted dataframe or series"
}
fn signature(&self) -> Signature {
Signature::build(self.name())
.switch("reverse", "invert sort", Some('r'))
.rest("rest", SyntaxShape::Any, "column names to sort dataframe")
.category(Category::Custom("dataframe".into()))
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Create new sorted dataframe",
example: "[[a b]; [3 4] [1 2]] | dfr to-df | dfr sort a",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_int(1), Value::test_int(3)],
),
Column::new(
"b".to_string(),
vec![Value::test_int(2), Value::test_int(4)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
Example {
description: "Create new sorted series",
example: "[3 4 1 2] | dfr to-df | dfr sort",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(),
vec![
Value::test_int(1),
Value::test_int(2),
Value::test_int(3),
Value::test_int(4),
],
)])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
]
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
command(engine_state, stack, call, input)
}
}
fn command(
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let reverse = call.has_flag("reverse");
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
if df.is_series() {
let columns = df.as_ref().get_column_names();
df.as_ref()
.sort(columns, reverse)
.map_err(|e| {
ShellError::GenericError(
"Error sorting dataframe".into(),
e.to_string(),
Some(call.head),
None,
Vec::new(),
)
})
.map(|df| PipelineData::Value(NuDataFrame::dataframe_into_value(df, call.head), None))
} else {
let columns: Vec<Value> = call.rest(engine_state, stack, 0)?;
if !columns.is_empty() {
let (col_string, col_span) = convert_columns_string(columns, call.head)?;
df.as_ref()
.sort(&col_string, reverse)
.map_err(|e| {
ShellError::GenericError(
"Error sorting dataframe".into(),
e.to_string(),
Some(col_span),
None,
Vec::new(),
)
})
.map(|df| {
PipelineData::Value(NuDataFrame::dataframe_into_value(df, call.head), None)
})
} else {
Err(ShellError::GenericError(
"Missing columns".into(),
"missing column name to perform sort".into(),
Some(call.head),
None,
Vec::new(),
))
}
}
}
#[cfg(test)]
mod test {
use super::super::super::test_dataframe::test_dataframe;
use super::*;
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(SortDF {})])
}
}

View File

@ -2,7 +2,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use polars::prelude::DataType;
@ -15,7 +15,7 @@ pub struct TakeDF;
impl Command for TakeDF {
fn name(&self) -> &str {
"dfr take"
"take"
}
fn usage(&self) -> &str {
@ -36,9 +36,9 @@ impl Command for TakeDF {
vec![
Example {
description: "Takes selected rows from dataframe",
example: r#"let df = ([[a b]; [4 1] [5 2] [4 3]] | dfr to-df);
let indices = ([0 2] | dfr to-df);
$df | dfr take $indices"#,
example: r#"let df = ([[a b]; [4 1] [5 2] [4 3]] | to-df);
let indices = ([0 2] | to-df);
$df | take $indices"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
@ -56,9 +56,9 @@ impl Command for TakeDF {
},
Example {
description: "Takes selected rows from series",
example: r#"let series = ([4 1 5 2 4 3] | dfr to-df);
let indices = ([0 2] | dfr to-df);
$series | dfr take $indices"#,
example: r#"let series = ([4 1 5 2 4 3] | to-df);
let indices = ([0 2] | to-df);
$series | take $indices"#,
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(),
@ -71,6 +71,14 @@ impl Command for TakeDF {
]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -4,7 +4,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Spanned, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Spanned, SyntaxShape, Type, Value,
};
use polars::prelude::{CsvWriter, SerWriter};
@ -15,7 +15,7 @@ pub struct ToCSV;
impl Command for ToCSV {
fn name(&self) -> &str {
"dfr to-csv"
"to-csv"
}
fn usage(&self) -> &str {
@ -39,17 +39,25 @@ impl Command for ToCSV {
vec![
Example {
description: "Saves dataframe to csv file",
example: "[[a b]; [1 2] [3 4]] | dfr to-df | dfr to-csv test.csv",
example: "[[a b]; [1 2] [3 4]] | to-df | to-csv test.csv",
result: None,
},
Example {
description: "Saves dataframe to csv file using other delimiter",
example: "[[a b]; [1 2] [3 4]] | dfr to-df | dfr to-csv test.csv -d '|'",
example: "[[a b]; [1 2] [3 4]] | to-df | to-csv test.csv -d '|'",
result: None,
},
]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Any
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -3,7 +3,7 @@ use super::super::values::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
#[derive(Clone)]
@ -11,7 +11,7 @@ pub struct ToDataFrame;
impl Command for ToDataFrame {
fn name(&self) -> &str {
"dfr to-df"
"to-df"
}
fn usage(&self) -> &str {
@ -26,7 +26,7 @@ impl Command for ToDataFrame {
vec![
Example {
description: "Takes a dictionary and creates a dataframe",
example: "[[a b];[1 2] [3 4]] | dfr to-df",
example: "[[a b];[1 2] [3 4]] | to-df",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
@ -44,7 +44,7 @@ impl Command for ToDataFrame {
},
Example {
description: "Takes a list of tables and creates a dataframe",
example: "[[1 2 a] [3 4 b] [5 6 c]] | dfr to-df",
example: "[[1 2 a] [3 4 b] [5 6 c]] | to-df",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
@ -70,7 +70,7 @@ impl Command for ToDataFrame {
},
Example {
description: "Takes a list and creates a dataframe",
example: "[a b c] | dfr to-df",
example: "[a b c] | to-df",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(),
@ -86,7 +86,7 @@ impl Command for ToDataFrame {
},
Example {
description: "Takes a list of booleans and creates a dataframe",
example: "[true true false] | dfr to-df",
example: "[true true false] | to-df",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(),
@ -103,6 +103,14 @@ impl Command for ToDataFrame {
]
}
fn input_type(&self) -> Type {
Type::Any
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
_engine_state: &EngineState,

View File

@ -2,7 +2,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type, Value,
};
use super::super::values::NuDataFrame;
@ -12,7 +12,7 @@ pub struct ToNu;
impl Command for ToNu {
fn name(&self) -> &str {
"dfr to-nu"
"to-nu"
}
fn usage(&self) -> &str {
@ -22,7 +22,7 @@ impl Command for ToNu {
fn signature(&self) -> Signature {
Signature::build(self.name())
.named(
"n-rows",
"rows",
SyntaxShape::Number,
"number of rows to be shown",
Some('n'),
@ -35,17 +35,25 @@ impl Command for ToNu {
vec![
Example {
description: "Shows head rows from dataframe",
example: "[[a b]; [1 2] [3 4]] | dfr to-df | dfr to-nu",
example: "[[a b]; [1 2] [3 4]] | to-df | to nu",
result: None,
},
Example {
description: "Shows tail rows from dataframe",
example: "[[a b]; [1 2] [3 4] [5 6]] | dfr to-df | dfr to-nu -t -n 1",
example: "[[a b]; [1 2] [3 4] [5 6]] | to-df | to nu -t -n 1",
result: None,
},
]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Any
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -4,7 +4,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Spanned, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Spanned, SyntaxShape, Type, Value,
};
use polars::prelude::ParquetWriter;
@ -15,7 +15,7 @@ pub struct ToParquet;
impl Command for ToParquet {
fn name(&self) -> &str {
"dfr to-parquet"
"to-parquet"
}
fn usage(&self) -> &str {
@ -30,12 +30,20 @@ impl Command for ToParquet {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Saves dataframe to csv file",
example: "[[a b]; [1 2] [3 4]] | dfr to-df | dfr to-parquet test.parquet",
description: "Saves dataframe to parquet file",
example: "[[a b]; [1 2] [3 4]] | to-df | to-parquet test.parquet",
result: None,
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Any
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -4,7 +4,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
#[derive(Clone)]
@ -12,7 +12,7 @@ pub struct WithColumn;
impl Command for WithColumn {
fn name(&self) -> &str {
"dfr with-column"
"with-column"
}
fn usage(&self) -> &str {
@ -27,16 +27,16 @@ impl Command for WithColumn {
SyntaxShape::Any,
"series to be added or expressions used to define the new columns",
)
.category(Category::Custom("dataframe".into()))
.category(Category::Custom("dataframe or lazyframe".into()))
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Adds a series to the dataframe",
example: r#"[[a b]; [1 2] [3 4]]
| dfr to-df
| dfr with-column ([5 6] | dfr to-df) --name c"#,
example: r#"[[a b]; [1 2] [3 4]]
| to-df
| with-column ([5 6] | to-df) --name c"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
@ -58,16 +58,47 @@ impl Command for WithColumn {
},
Example {
description: "Adds a series to the dataframe",
example: r#"[[a b]; [1 2] [3 4]]
| dfr to-df
| dfr to-lazy
| dfr with-column ((dfr col a) * 2 | dfr as "c")
| dfr collect"#,
result: None,
example: r#"[[a b]; [1 2] [3 4]]
| to-lazy
| with-column [
((col a) * 2 | as "c")
((col a) * 3 | as "d")
]
| collect"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_int(1), Value::test_int(3)],
),
Column::new(
"b".to_string(),
vec![Value::test_int(2), Value::test_int(4)],
),
Column::new(
"c".to_string(),
vec![Value::test_int(2), Value::test_int(6)],
),
Column::new(
"d".to_string(),
vec![Value::test_int(3), Value::test_int(9)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,
@ -85,7 +116,7 @@ impl Command for WithColumn {
command_eager(engine_state, stack, call, df)
} else {
Err(ShellError::CantConvert(
"expression or query".into(),
"lazy or eager dataframe".into(),
value.get_type().to_string(),
value.span()?,
None,
@ -100,34 +131,49 @@ fn command_eager(
call: &Call,
mut df: NuDataFrame,
) -> Result<PipelineData, ShellError> {
let other_value: Value = call.req(engine_state, stack, 0)?;
let other_span = other_value.span()?;
let mut other = NuDataFrame::try_from_value(other_value)?.as_series(other_span)?;
let new_column: Value = call.req(engine_state, stack, 0)?;
let column_span = new_column.span()?;
let name = match call.get_flag::<String>(engine_state, stack, "name")? {
Some(name) => name,
None => other.name().to_string(),
};
if NuExpression::can_downcast(&new_column) {
let vals: Vec<Value> = call.rest(engine_state, stack, 0)?;
let value = Value::List {
vals,
span: call.head,
};
let expressions = NuExpression::extract_exprs(value)?;
let lazy = NuLazyFrame::new(true, df.lazy().with_columns(&expressions));
let series = other.rename(&name).clone();
let df = lazy.collect(call.head)?;
df.as_mut()
.with_column(series)
.map_err(|e| {
ShellError::GenericError(
"Error adding column to dataframe".into(),
e.to_string(),
Some(other_span),
None,
Vec::new(),
)
})
.map(|df| {
PipelineData::Value(
NuDataFrame::dataframe_into_value(df.clone(), call.head),
None,
)
})
Ok(PipelineData::Value(df.into_value(call.head), None))
} else {
let mut other = NuDataFrame::try_from_value(new_column)?.as_series(column_span)?;
let name = match call.get_flag::<String>(engine_state, stack, "name")? {
Some(name) => name,
None => other.name().to_string(),
};
let series = other.rename(&name).clone();
df.as_mut()
.with_column(series)
.map_err(|e| {
ShellError::GenericError(
"Error adding column to dataframe".into(),
e.to_string(),
Some(column_span),
None,
Vec::new(),
)
})
.map(|df| {
PipelineData::Value(
NuDataFrame::dataframe_into_value(df.clone(), call.head),
None,
)
})
}
}
fn command_lazy(
@ -146,7 +192,7 @@ fn command_lazy(
let lazy: NuLazyFrame = lazy.into_polars().with_columns(&expressions).into();
Ok(PipelineData::Value(
NuLazyFrame::into_value(lazy, call.head),
NuLazyFrame::into_value(lazy, call.head)?,
None,
))
}
@ -155,9 +201,15 @@ fn command_lazy(
mod test {
use super::super::super::test_dataframe::test_dataframe;
use super::*;
use crate::dataframe::expressions::ExprAlias;
use crate::dataframe::expressions::ExprCol;
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(WithColumn {})])
test_dataframe(vec![
Box::new(WithColumn {}),
Box::new(ExprAlias {}),
Box::new(ExprCol {}),
])
}
}

View File

@ -4,7 +4,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, SyntaxShape,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
#[derive(Clone)]
@ -12,7 +12,7 @@ pub struct ExprAlias;
impl Command for ExprAlias {
fn name(&self) -> &str {
"dfr as"
"as"
}
fn usage(&self) -> &str {
@ -26,17 +26,45 @@ impl Command for ExprAlias {
SyntaxShape::String,
"Alias name for the expression",
)
.category(Category::Custom("expressions".into()))
.category(Category::Custom("expression".into()))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Creates and alias expression",
example: "(dfr col a | df as new_a)",
result: None,
example: "col a | as new_a | to-nu",
result: {
let cols = vec!["expr".into(), "value".into()];
let expr = Value::test_string("column");
let value = Value::test_string("a");
let expr = Value::Record {
cols,
vals: vec![expr, value],
span: Span::test_data(),
};
let cols = vec!["expr".into(), "alias".into()];
let value = Value::test_string("new_a");
let record = Value::Record {
cols,
vals: vec![expr, value],
span: Span::test_data(),
};
Some(record)
},
}]
}
fn input_type(&self) -> Type {
Type::Custom("expression".into())
}
fn output_type(&self) -> Type {
Type::Custom("expression".into())
}
fn run(
&self,
engine_state: &EngineState,
@ -55,3 +83,20 @@ impl Command for ExprAlias {
))
}
}
#[cfg(test)]
mod test {
use super::super::super::test_dataframe::test_dataframe;
use super::*;
use crate::dataframe::expressions::ExprAsNu;
use crate::dataframe::expressions::ExprCol;
#[test]
fn test_examples() {
test_dataframe(vec![
Box::new(ExprAlias {}),
Box::new(ExprCol {}),
Box::new(ExprAsNu {}),
])
}
}

View File

@ -3,15 +3,15 @@ use super::super::values::NuExpression;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
#[derive(Clone)]
pub struct ExprToNu;
pub struct ExprAsNu;
impl Command for ExprToNu {
impl Command for ExprAsNu {
fn name(&self) -> &str {
"dfr to-nu"
"to-nu"
}
fn usage(&self) -> &str {
@ -19,13 +19,13 @@ impl Command for ExprToNu {
}
fn signature(&self) -> Signature {
Signature::build(self.name()).category(Category::Custom("expressions".into()))
Signature::build(self.name()).category(Category::Custom("expression".into()))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Convert a col expression into a nushell value",
example: "dfr col col_a | dfr to-nu",
example: "col a | to-nu",
result: Some(Value::Record {
cols: vec!["expr".into(), "value".into()],
vals: vec![
@ -34,7 +34,7 @@ impl Command for ExprToNu {
span: Span::test_data(),
},
Value::String {
val: "col_a".into(),
val: "a".into(),
span: Span::test_data(),
},
],
@ -43,6 +43,14 @@ impl Command for ExprToNu {
}]
}
fn input_type(&self) -> Type {
Type::Custom("expression".into())
}
fn output_type(&self) -> Type {
Type::Any
}
fn run(
&self,
_engine_state: &EngineState,
@ -65,6 +73,6 @@ mod test {
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(ExprToNu {}), Box::new(ExprCol {})])
test_dataframe(vec![Box::new(ExprAsNu {}), Box::new(ExprCol {})])
}
}

View File

@ -3,7 +3,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use polars::prelude::col;
@ -12,7 +12,7 @@ pub struct ExprCol;
impl Command for ExprCol {
fn name(&self) -> &str {
"dfr col"
"col"
}
fn usage(&self) -> &str {
@ -26,13 +26,13 @@ impl Command for ExprCol {
SyntaxShape::String,
"Name of column to be used",
)
.category(Category::Custom("expressions".into()))
.category(Category::Custom("expression".into()))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Creates a named column expression and converts it to a nu object",
example: "dfr col col_a | dfr to-nu",
example: "col a | to-nu",
result: Some(Value::Record {
cols: vec!["expr".into(), "value".into()],
vals: vec![
@ -41,7 +41,7 @@ impl Command for ExprCol {
span: Span::test_data(),
},
Value::String {
val: "col_a".into(),
val: "a".into(),
span: Span::test_data(),
},
],
@ -50,6 +50,14 @@ impl Command for ExprCol {
}]
}
fn input_type(&self) -> Type {
Type::Any
}
fn output_type(&self) -> Type {
Type::Custom("expression".into())
}
fn run(
&self,
engine_state: &EngineState,
@ -66,12 +74,12 @@ impl Command for ExprCol {
#[cfg(test)]
mod test {
use super::super::super::super::test_dataframe::test_dataframe;
use super::super::super::ExprToNu;
use super::super::super::test_dataframe::test_dataframe;
use super::*;
use crate::dataframe::expressions::as_nu::ExprAsNu;
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(ExprCol {}), Box::new(ExprToNu {})])
test_dataframe(vec![Box::new(ExprCol {}), Box::new(ExprAsNu {})])
}
}

View File

@ -1,7 +0,0 @@
mod col;
mod lit;
mod when;
pub(super) use crate::dataframe::expressions::dsl::col::ExprCol;
pub(super) use crate::dataframe::expressions::dsl::lit::ExprLit;
pub(super) use crate::dataframe::expressions::dsl::when::ExprWhen;

View File

@ -1,96 +0,0 @@
use crate::dataframe::values::NuExpression;
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Value,
};
use polars::prelude::when;
#[derive(Clone)]
pub struct ExprWhen;
impl Command for ExprWhen {
fn name(&self) -> &str {
"dfr when"
}
fn usage(&self) -> &str {
"Creates a when expression"
}
fn signature(&self) -> Signature {
Signature::build(self.name())
.required(
"when predicate",
SyntaxShape::Any,
"Name of column to be used",
)
.required_named(
"then",
SyntaxShape::Any,
"Expression that will be applied when predicate is true",
Some('t'),
)
.required_named(
"otherwise",
SyntaxShape::Any,
"Expression that will be applied when predicate is false",
Some('o'),
)
.category(Category::Custom("expressions".into()))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Create a new column for the dataframe",
example: r#"[[a b]; [1 2] [3 4]]
| dfr to-df
| dfr to-lazy
| dfr with-column (
dfr when ((dfr col a) > 2) --then 4 --otherwise 5 | dfr as "c"
)
| dfr collect"#,
result: None,
}]
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
_input: PipelineData,
) -> Result<PipelineData, ShellError> {
let predicate: Value = call.req(engine_state, stack, 0)?;
let predicate = NuExpression::try_from_value(predicate)?;
let then: Value = call
.get_flag(engine_state, stack, "then")?
.expect("it is a required named value");
let then = NuExpression::try_from_value(then)?;
let otherwise: Value = call
.get_flag(engine_state, stack, "otherwise")?
.expect("it is a required named value");
let otherwise = NuExpression::try_from_value(otherwise)?;
let expr: NuExpression = when(predicate.into_polars())
.then(then.into_polars())
.otherwise(otherwise.into_polars())
.into();
Ok(PipelineData::Value(expr.into_value(call.head), None))
}
}
#[cfg(test)]
mod test {
use super::super::super::super::test_dataframe::test_dataframe;
use super::super::super::ExprToNu;
use super::*;
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(ExprWhen {}), Box::new(ExprToNu {})])
}
}

View File

@ -1,18 +1,17 @@
/// Definition of multiple Expression commands using a macro rule
/// All of these expressions have an identical body and only require
/// to have a change in the name, description and expression function
use super::super::values::NuExpression;
use crate::dataframe::values::{Column, NuDataFrame, NuExpression};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
// The structs defined in this file are structs that form part of other commands
// since they share a similar name
macro_rules! expr_command {
($command: ident, $name: expr, $desc: expr, $examples: expr, $func: ident) => {
($command: ident, $name: expr, $desc: expr, $examples: expr, $func: ident, $test: ident) => {
#[derive(Clone)]
pub struct $command;
@ -26,13 +25,21 @@ macro_rules! expr_command {
}
fn signature(&self) -> Signature {
Signature::build(self.name()).category(Category::Custom("dataframe".into()))
Signature::build(self.name()).category(Category::Custom("expression".into()))
}
fn examples(&self) -> Vec<Example> {
$examples
}
fn input_type(&self) -> Type {
Type::Custom("expression".into())
}
fn output_type(&self) -> Type {
Type::Custom("expression".into())
}
fn run(
&self,
_engine_state: &EngineState,
@ -49,6 +56,23 @@ macro_rules! expr_command {
))
}
}
#[cfg(test)]
mod $test {
use super::super::super::test_dataframe::test_dataframe;
use super::*;
use crate::dataframe::lazy::aggregate::LazyAggregate;
use crate::dataframe::lazy::groupby::ToLazyGroupBy;
#[test]
fn test_examples() {
test_dataframe(vec![
Box::new($command {}),
Box::new(LazyAggregate {}),
Box::new(ToLazyGroupBy {}),
])
}
}
};
}
@ -56,54 +80,380 @@ macro_rules! expr_command {
// Expands to a command definition for a list expression
expr_command!(
ExprList,
"dfr list",
"list",
"Aggregates a group to a Series",
vec![Example {
description: "",
example: "",
result: None,
}],
list
list,
test_list
);
// ExprAggGroups command
// Expands to a command definition for a agg groups expression
expr_command!(
ExprAggGroups,
"dfr agg-groups",
"agg-groups",
"creates an agg_groups expression",
vec![Example {
description: "",
example: "",
result: None,
}],
agg_groups
agg_groups,
test_groups
);
// ExprFlatten command
// Expands to a command definition for a flatten expression
expr_command!(
ExprFlatten,
"dfr flatten",
"flatten",
"creates a flatten expression",
vec![Example {
description: "",
example: "",
result: None,
}],
flatten
flatten,
test_flatten
);
// ExprExplode command
// Expands to a command definition for a explode expression
expr_command!(
ExprExplode,
"dfr explode",
"explode",
"creates an explode expression",
vec![Example {
description: "",
example: "",
result: None,
}],
explode
explode,
test_explode
);
// ExprCount command
// Expands to a command definition for a count expression
expr_command!(
ExprCount,
"count",
"creates a count expression",
vec![Example {
description: "",
example: "",
result: None,
}],
count,
test_count
);
// ExprFirst command
// Expands to a command definition for a count expression
expr_command!(
ExprFirst,
"first",
"creates a first expression",
vec![Example {
description: "Creates a first expression from a column",
example: "col a | first",
result: None,
},],
first,
test_first
);
// ExprLast command
// Expands to a command definition for a count expression
expr_command!(
ExprLast,
"last",
"creates a last expression",
vec![Example {
description: "Creates a last expression from a column",
example: "col a | last",
result: None,
},],
last,
test_last
);
// ExprNUnique command
// Expands to a command definition for a n-unique expression
expr_command!(
ExprNUnique,
"n-unique",
"creates a n-unique expression",
vec![Example {
description: "Creates a is n-unique expression from a column",
example: "col a | n-unique",
result: None,
},],
n_unique,
test_nunique
);
// ExprIsNotNull command
// Expands to a command definition for a n-unique expression
expr_command!(
ExprIsNotNull,
"is-not-null",
"creates a is not null expression",
vec![Example {
description: "Creates a is not null expression from a column",
example: "col a | is-not-null",
result: None,
},],
is_not_null,
test_is_not_null
);
// ExprIsNull command
// Expands to a command definition for a n-unique expression
expr_command!(
ExprIsNull,
"is-null",
"creates a is null expression",
vec![Example {
description: "Creates a is null expression from a column",
example: "col a | is-null",
result: None,
},],
is_null,
test_is_null
);
// ExprNot command
// Expands to a command definition for a not expression
expr_command!(
ExprNot,
"expr-not",
"creates a not expression",
vec![Example {
description: "Creates a not expression",
example: "(col a) > 2) | expr-not",
result: None,
},],
not,
test_not
);
// ExprMax command
// Expands to a command definition for max aggregation
expr_command!(
ExprMax,
"max",
"Creates a max expression",
vec![Example {
description: "Max aggregation for a group by",
example: r#"[[a b]; [one 2] [one 4] [two 1]]
| to-df
| group-by a
| agg (col b | max)"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_string("one"), Value::test_string("two")],
),
Column::new(
"b".to_string(),
vec![Value::test_int(4), Value::test_int(1)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
max,
test_max
);
// ExprMin command
// Expands to a command definition for min aggregation
expr_command!(
ExprMin,
"min",
"Creates a min expression",
vec![Example {
description: "Min aggregation for a group by",
example: r#"[[a b]; [one 2] [one 4] [two 1]]
| to-df
| group-by a
| agg (col b | min)"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_string("one"), Value::test_string("two")],
),
Column::new(
"b".to_string(),
vec![Value::test_int(2), Value::test_int(1)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
min,
test_min
);
// ExprSum command
// Expands to a command definition for sum aggregation
expr_command!(
ExprSum,
"sum",
"Creates a sum expression for an aggregation",
vec![Example {
description: "Sum aggregation for a group by",
example: r#"[[a b]; [one 2] [one 4] [two 1]]
| to-df
| group-by a
| agg (col b | sum)"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_string("one"), Value::test_string("two")],
),
Column::new(
"b".to_string(),
vec![Value::test_int(6), Value::test_int(1)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
sum,
test_sum
);
// ExprMean command
// Expands to a command definition for mean aggregation
expr_command!(
ExprMean,
"mean",
"Creates a mean expression for an aggregation",
vec![Example {
description: "Mean aggregation for a group by",
example: r#"[[a b]; [one 2] [one 4] [two 1]]
| to-df
| group-by a
| agg (col b | mean)"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_string("one"), Value::test_string("two")],
),
Column::new(
"b".to_string(),
vec![Value::test_float(3.0), Value::test_float(1.0)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
mean,
test_mean
);
// ExprMedian command
// Expands to a command definition for median aggregation
expr_command!(
ExprMedian,
"median",
"Creates a median expression for an aggregation",
vec![Example {
description: "Median aggregation for a group by",
example: r#"[[a b]; [one 2] [one 4] [two 1]]
| to-df
| group-by a
| agg (col b | median)"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_string("one"), Value::test_string("two")],
),
Column::new(
"b".to_string(),
vec![Value::test_float(3.0), Value::test_float(1.0)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
median,
test_median
);
// ExprStd command
// Expands to a command definition for std aggregation
expr_command!(
ExprStd,
"std",
"Creates a std expression for an aggregation",
vec![Example {
description: "Std aggregation for a group by",
example: r#"[[a b]; [one 2] [one 2] [two 1] [two 1]]
| to-df
| group-by a
| agg (col b | std)"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_string("one"), Value::test_string("two")],
),
Column::new(
"b".to_string(),
vec![Value::test_float(0.0), Value::test_float(0.0)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
std,
test_std
);
// ExprVar command
// Expands to a command definition for var aggregation
expr_command!(
ExprVar,
"var",
"Create a var expression for an aggregation",
vec![Example {
description: "Var aggregation for a group by",
example: r#"[[a b]; [one 2] [one 2] [two 1] [two 1]]
| to-df
| group-by a
| agg (col b | var)"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_string("one"), Value::test_string("two")],
),
Column::new(
"b".to_string(),
vec![Value::test_float(0.0), Value::test_float(0.0)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
var,
test_var
);

View File

@ -3,7 +3,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
#[derive(Clone)]
@ -11,7 +11,7 @@ pub struct ExprLit;
impl Command for ExprLit {
fn name(&self) -> &str {
"dfr lit"
"lit"
}
fn usage(&self) -> &str {
@ -25,13 +25,13 @@ impl Command for ExprLit {
SyntaxShape::Any,
"literal to construct the expression",
)
.category(Category::Custom("expressions".into()))
.category(Category::Custom("expression".into()))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Created a literal expression and converts it to a nu object",
example: "dfr lit 2 | dfr to-nu",
example: "lit 2 | to-nu",
result: Some(Value::Record {
cols: vec!["expr".into(), "value".into()],
vals: vec![
@ -49,6 +49,14 @@ impl Command for ExprLit {
}]
}
fn input_type(&self) -> Type {
Type::Any
}
fn output_type(&self) -> Type {
Type::Custom("expression".into())
}
fn run(
&self,
engine_state: &EngineState,
@ -68,12 +76,12 @@ impl Command for ExprLit {
#[cfg(test)]
mod test {
use super::super::super::super::test_dataframe::test_dataframe;
use super::super::super::ExprToNu;
use super::super::super::test_dataframe::test_dataframe;
use super::*;
use crate::dataframe::expressions::as_nu::ExprAsNu;
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(ExprLit {}), Box::new(ExprToNu {})])
test_dataframe(vec![Box::new(ExprLit {}), Box::new(ExprAsNu {})])
}
}

View File

@ -1,15 +1,22 @@
mod alias;
mod dsl;
mod as_nu;
mod col;
mod expressions_macro;
mod to_nu;
mod lit;
mod otherwise;
mod quantile;
mod when;
use nu_protocol::engine::StateWorkingSet;
use crate::dataframe::expressions::dsl::*;
use crate::dataframe::expressions::alias::ExprAlias;
use crate::dataframe::expressions::expressions_macro::*;
use crate::dataframe::expressions::to_nu::ExprToNu;
pub(crate) use crate::dataframe::expressions::alias::ExprAlias;
use crate::dataframe::expressions::as_nu::ExprAsNu;
pub(super) use crate::dataframe::expressions::col::ExprCol;
pub(crate) use crate::dataframe::expressions::expressions_macro::*;
pub(super) use crate::dataframe::expressions::lit::ExprLit;
pub(super) use crate::dataframe::expressions::otherwise::ExprOtherwise;
pub(super) use crate::dataframe::expressions::quantile::ExprQuantile;
pub(super) use crate::dataframe::expressions::when::ExprWhen;
pub fn add_expressions(working_set: &mut StateWorkingSet) {
macro_rules! bind_command {
@ -25,12 +32,29 @@ pub fn add_expressions(working_set: &mut StateWorkingSet) {
bind_command!(
ExprAlias,
ExprCol,
ExprCount,
ExprLit,
ExprToNu,
ExprAsNu,
ExprWhen,
ExprOtherwise,
ExprQuantile,
ExprList,
ExprAggGroups,
ExprFlatten,
ExprExplode
ExprExplode,
ExprCount,
ExprFirst,
ExprLast,
ExprNUnique,
ExprIsNotNull,
ExprIsNull,
ExprNot,
ExprMax,
ExprMin,
ExprSum,
ExprMean,
ExprMedian,
ExprStd,
ExprVar
);
}

View File

@ -0,0 +1,132 @@
use crate::dataframe::values::{Column, NuDataFrame, NuExpression, NuWhen};
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
#[derive(Clone)]
pub struct ExprOtherwise;
impl Command for ExprOtherwise {
fn name(&self) -> &str {
"otherwise"
}
fn usage(&self) -> &str {
"completes a when expression"
}
fn signature(&self) -> Signature {
Signature::build(self.name())
.required(
"otherwise expression",
SyntaxShape::Any,
"expressioini to apply when no when predicate matches",
)
.category(Category::Custom("expression".into()))
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Create a when conditions",
example: "when ((col a) > 2) 4 | otherwise 5",
result: None,
},
Example {
description: "Create a when conditions",
example: "when ((col a) > 2) 4 | when ((col a) < 0) 6 | otherwise 0",
result: None,
},
Example {
description: "Create a new column for the dataframe",
example: r#"[[a b]; [6 2] [1 4] [4 1]]
| to-lazy
| with-column (
when ((col a) > 2) 4 | otherwise 5 | as c
)
| with-column (
when ((col a) > 5) 10 | when ((col a) < 2) 6 | otherwise 0 | as d
)
| collect"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_int(6), Value::test_int(1), Value::test_int(4)],
),
Column::new(
"b".to_string(),
vec![Value::test_int(2), Value::test_int(4), Value::test_int(1)],
),
Column::new(
"c".to_string(),
vec![Value::test_int(4), Value::test_int(5), Value::test_int(4)],
),
Column::new(
"d".to_string(),
vec![Value::test_int(10), Value::test_int(6), Value::test_int(0)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
]
}
fn input_type(&self) -> Type {
Type::Any
}
fn output_type(&self) -> Type {
Type::Custom("expression".into())
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let otherwise_predicate: Value = call.req(engine_state, stack, 0)?;
let otherwise_predicate = NuExpression::try_from_value(otherwise_predicate)?;
let value = input.into_value(call.head);
let complete: NuExpression = match NuWhen::try_from_value(value)? {
NuWhen::WhenThen(when_then) => when_then
.otherwise(otherwise_predicate.into_polars())
.into(),
NuWhen::WhenThenThen(when_then_then) => when_then_then
.otherwise(otherwise_predicate.into_polars())
.into(),
};
Ok(PipelineData::Value(complete.into_value(call.head), None))
}
}
#[cfg(test)]
mod test {
use super::super::super::test_dataframe::test_dataframe;
use crate::dataframe::eager::WithColumn;
use crate::dataframe::expressions::when::ExprWhen;
use crate::dataframe::expressions::{ExprAlias, ExprAsNu, ExprCol};
use super::*;
#[test]
fn test_examples() {
test_dataframe(vec![
Box::new(WithColumn {}),
Box::new(ExprCol {}),
Box::new(ExprAlias {}),
Box::new(ExprWhen {}),
Box::new(ExprOtherwise {}),
Box::new(ExprAsNu {}),
])
}
}

View File

@ -0,0 +1,102 @@
use crate::dataframe::values::{Column, NuDataFrame, NuExpression};
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use polars::prelude::QuantileInterpolOptions;
#[derive(Clone)]
pub struct ExprQuantile;
impl Command for ExprQuantile {
fn name(&self) -> &str {
"quantile"
}
fn usage(&self) -> &str {
"Aggregates the columns to the selected quantile"
}
fn signature(&self) -> Signature {
Signature::build(self.name())
.required(
"quantile",
SyntaxShape::Number,
"quantile value for quantile operation",
)
.category(Category::Custom("expression".into()))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Quantile aggregation for a group by",
example: r#"[[a b]; [one 2] [one 4] [two 1]]
| to-df
| group-by a
| agg (col b | quantile 0.5)"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_string("one"), Value::test_string("two")],
),
Column::new(
"b".to_string(),
vec![Value::test_float(4.0), Value::test_float(1.0)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
}]
}
fn input_type(&self) -> Type {
Type::Custom("expression".into())
}
fn output_type(&self) -> Type {
Type::Custom("expression".into())
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let value = input.into_value(call.head);
let quantile: f64 = call.req(engine_state, stack, 0)?;
let expr = NuExpression::try_from_value(value)?;
let expr: NuExpression = expr
.into_polars()
.quantile(quantile, QuantileInterpolOptions::default())
.into();
Ok(PipelineData::Value(
NuExpression::into_value(expr, call.head),
None,
))
}
}
#[cfg(test)]
mod test {
use super::super::super::test_dataframe::test_dataframe;
use super::*;
use crate::dataframe::lazy::aggregate::LazyAggregate;
use crate::dataframe::lazy::groupby::ToLazyGroupBy;
#[test]
fn test_examples() {
test_dataframe(vec![
Box::new(ExprQuantile {}),
Box::new(LazyAggregate {}),
Box::new(ToLazyGroupBy {}),
])
}
}

View File

@ -0,0 +1,148 @@
use crate::dataframe::values::{Column, NuDataFrame, NuExpression, NuWhen};
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use polars::prelude::when;
#[derive(Clone)]
pub struct ExprWhen;
impl Command for ExprWhen {
fn name(&self) -> &str {
"when"
}
fn usage(&self) -> &str {
"Creates and modifies a when expression"
}
fn signature(&self) -> Signature {
Signature::build(self.name())
.required(
"when expression",
SyntaxShape::Any,
"when expression used for matching",
)
.required(
"then expression",
SyntaxShape::Any,
"expression that will be applied when predicate is true",
)
.category(Category::Custom("expression".into()))
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Create a when conditions",
example: "when ((col a) > 2) 4",
result: None,
},
Example {
description: "Create a when conditions",
example: "when ((col a) > 2) 4 | when ((col a) < 0) 6",
result: None,
},
Example {
description: "Create a new column for the dataframe",
example: r#"[[a b]; [6 2] [1 4] [4 1]]
| to-lazy
| with-column (
when ((col a) > 2) 4 | otherwise 5 | as c
)
| with-column (
when ((col a) > 5) 10 | when ((col a) < 2) 6 | otherwise 0 | as d
)
| collect"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_int(6), Value::test_int(1), Value::test_int(4)],
),
Column::new(
"b".to_string(),
vec![Value::test_int(2), Value::test_int(4), Value::test_int(1)],
),
Column::new(
"c".to_string(),
vec![Value::test_int(4), Value::test_int(5), Value::test_int(4)],
),
Column::new(
"d".to_string(),
vec![Value::test_int(10), Value::test_int(6), Value::test_int(0)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
]
}
fn input_type(&self) -> Type {
Type::Custom("expression".into())
}
fn output_type(&self) -> Type {
Type::Custom("expression".into())
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let when_predicate: Value = call.req(engine_state, stack, 0)?;
let when_predicate = NuExpression::try_from_value(when_predicate)?;
let then_predicate: Value = call.req(engine_state, stack, 1)?;
let then_predicate = NuExpression::try_from_value(then_predicate)?;
let value = input.into_value(call.head);
let when_then: NuWhen = match value {
Value::Nothing { .. } => when(when_predicate.into_polars())
.then(then_predicate.into_polars())
.into(),
v => match NuWhen::try_from_value(v)? {
NuWhen::WhenThen(when_then) => when_then
.when(when_predicate.into_polars())
.then(then_predicate.into_polars())
.into(),
NuWhen::WhenThenThen(when_then_then) => when_then_then
.when(when_predicate.into_polars())
.then(then_predicate.into_polars())
.into(),
},
};
Ok(PipelineData::Value(when_then.into_value(call.head), None))
}
}
#[cfg(test)]
mod test {
use super::super::super::test_dataframe::test_dataframe;
use crate::dataframe::eager::WithColumn;
use crate::dataframe::expressions::otherwise::ExprOtherwise;
use crate::dataframe::expressions::{ExprAlias, ExprAsNu, ExprCol};
use super::*;
#[test]
fn test_examples() {
test_dataframe(vec![
Box::new(WithColumn {}),
Box::new(ExprCol {}),
Box::new(ExprAlias {}),
Box::new(ExprWhen {}),
Box::new(ExprOtherwise {}),
Box::new(ExprAsNu {}),
])
}
}

View File

@ -1,10 +1,10 @@
use crate::dataframe::values::{NuExpression, NuLazyFrame, NuLazyGroupBy};
use crate::dataframe::values::{Column, NuDataFrame, NuExpression, NuLazyFrame, NuLazyGroupBy};
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
#[derive(Clone)]
@ -12,7 +12,7 @@ pub struct LazyAggregate;
impl Command for LazyAggregate {
fn name(&self) -> &str {
"dfr aggregate"
"agg"
}
fn usage(&self) -> &str {
@ -34,32 +34,81 @@ impl Command for LazyAggregate {
Example {
description: "Group by and perform an aggregation",
example: r#"[[a b]; [1 2] [1 4] [2 6] [2 4]]
| dfr to-df
| dfr group-by a
| dfr aggregate [
("b" | dfr min | dfr as "b_min")
("b" | dfr max | dfr as "b_max")
("b" | dfr sum | dfr as "b_sum")
| to-df
| group-by a
| agg [
(col b | min | as "b_min")
(col b | max | as "b_max")
(col b | sum | as "b_sum")
]"#,
result: None,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_int(1), Value::test_int(2)],
),
Column::new(
"b_min".to_string(),
vec![Value::test_int(2), Value::test_int(4)],
),
Column::new(
"b_max".to_string(),
vec![Value::test_int(4), Value::test_int(6)],
),
Column::new(
"b_sum".to_string(),
vec![Value::test_int(6), Value::test_int(10)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
Example {
description: "Group by and perform an aggregation",
example: r#"[[a b]; [1 2] [1 4] [2 6] [2 4]]
| dfr to-df
| dfr to-lazy
| dfr group-by a
| dfr aggregate [
("b" | dfr min | dfr as "b_min")
("b" | dfr max | dfr as "b_max")
("b" | dfr sum | dfr as "b_sum")
| to-lazy
| group-by a
| agg [
(col b | min | as "b_min")
(col b | max | as "b_max")
(col b | sum | as "b_sum")
]
| dfr collect"#,
result: None,
| collect"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_int(1), Value::test_int(2)],
),
Column::new(
"b_min".to_string(),
vec![Value::test_int(2), Value::test_int(4)],
),
Column::new(
"b_max".to_string(),
vec![Value::test_int(4), Value::test_int(6)],
),
Column::new(
"b_sum".to_string(),
vec![Value::test_int(6), Value::test_int(10)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,
@ -78,14 +127,32 @@ impl Command for LazyAggregate {
let from_eager = group_by.from_eager;
let group_by = group_by.into_polars();
let lazy: NuLazyFrame = group_by.agg(&expressions).into();
let res = if from_eager {
lazy.collect(call.head)?.into_value(call.head)
} else {
lazy.into_value(call.head)
let lazy = NuLazyFrame {
lazy: group_by.agg(&expressions).into(),
from_eager,
};
let res = lazy.into_value(call.head)?;
Ok(PipelineData::Value(res, None))
}
}
#[cfg(test)]
mod test {
use super::super::super::test_dataframe::test_dataframe;
use super::*;
use crate::dataframe::expressions::{ExprAlias, ExprMax, ExprMin, ExprSum};
use crate::dataframe::lazy::groupby::ToLazyGroupBy;
#[test]
fn test_examples() {
test_dataframe(vec![
Box::new(LazyAggregate {}),
Box::new(ToLazyGroupBy {}),
Box::new(ExprAlias {}),
Box::new(ExprMin {}),
Box::new(ExprMax {}),
Box::new(ExprSum {}),
])
}
}

View File

@ -1,9 +1,10 @@
use super::super::values::{NuDataFrame, NuLazyFrame};
use crate::dataframe::values::{Column, NuDataFrame};
use super::super::values::NuLazyFrame;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
#[derive(Clone)]
@ -11,11 +12,11 @@ pub struct LazyCollect;
impl Command for LazyCollect {
fn name(&self) -> &str {
"dfr collect"
"collect"
}
fn usage(&self) -> &str {
"Collect lazy dataframe into dataframe"
"Collect lazy dataframe into eager dataframe"
}
fn signature(&self) -> Signature {
@ -24,12 +25,33 @@ impl Command for LazyCollect {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "",
example: "",
result: None,
description: "drop duplicates",
example: "[[a b]; [1 2] [3 4]] | to-lazy | collect",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_int(1), Value::test_int(3)],
),
Column::new(
"b".to_string(),
vec![Value::test_int(2), Value::test_int(4)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
_engine_state: &EngineState,
@ -39,10 +61,22 @@ impl Command for LazyCollect {
) -> Result<PipelineData, ShellError> {
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?;
let eager = lazy.collect(call.head)?;
let value = Value::CustomValue {
val: Box::new(eager),
span: call.head,
};
Ok(PipelineData::Value(
NuDataFrame::into_value(eager, call.head),
None,
))
Ok(PipelineData::Value(value, None))
}
}
#[cfg(test)]
mod test {
use super::super::super::test_dataframe::test_dataframe;
use super::*;
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(LazyCollect {})])
}
}

View File

@ -1,10 +1,10 @@
use super::super::values::NuLazyFrame;
use crate::dataframe::values::NuDataFrame;
use crate::dataframe::values::{Column, NuDataFrame};
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, SyntaxShape,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
#[derive(Clone)]
@ -12,7 +12,7 @@ pub struct LazyFetch;
impl Command for LazyFetch {
fn name(&self) -> &str {
"dfr fetch"
"fetch"
}
fn usage(&self) -> &str {
@ -31,12 +31,33 @@ impl Command for LazyFetch {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "",
example: "",
result: None,
description: "Fetch a rows from the dataframe",
example: "[[a b]; [6 2] [4 2] [2 2]] | to-df | fetch 2",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_int(6), Value::test_int(4)],
),
Column::new(
"b".to_string(),
vec![Value::test_int(2), Value::test_int(2)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,
@ -68,13 +89,13 @@ impl Command for LazyFetch {
}
}
//#[cfg(test)]
//mod test {
// use super::super::super::test_dataframe::test_dataframe;
// use super::*;
//
// #[test]
// fn test_examples() {
// test_dataframe(vec![Box::new(LazyFetch {})])
// }
//}
#[cfg(test)]
mod test {
use super::super::super::test_dataframe::test_dataframe;
use super::*;
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(LazyFetch {})])
}
}

View File

@ -3,7 +3,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type, Value,
};
#[derive(Clone)]
@ -11,7 +11,7 @@ pub struct LazyFillNA;
impl Command for LazyFillNA {
fn name(&self) -> &str {
"dfr fill-na"
"fill-na"
}
fn usage(&self) -> &str {
@ -36,6 +36,14 @@ impl Command for LazyFillNA {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,
@ -44,22 +52,23 @@ impl Command for LazyFillNA {
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let fill: Value = call.req(engine_state, stack, 0)?;
let value = input.into_value(call.head);
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?.into_polars();
let expr = NuExpression::try_from_value(fill)?.into_polars();
let lazy: NuLazyFrame = lazy.fill_nan(expr).into();
if NuExpression::can_downcast(&value) {
let expr = NuExpression::try_from_value(value)?;
let fill = NuExpression::try_from_value(fill)?.into_polars();
let expr: NuExpression = expr.into_polars().fill_nan(fill).into();
Ok(PipelineData::Value(lazy.into_value(call.head), None))
Ok(PipelineData::Value(
NuExpression::into_value(expr, call.head),
None,
))
} else {
let lazy = NuLazyFrame::try_from_value(value)?;
let expr = NuExpression::try_from_value(fill)?.into_polars();
let lazy = NuLazyFrame::new(lazy.from_eager, lazy.into_polars().fill_nan(expr));
Ok(PipelineData::Value(lazy.into_value(call.head)?, None))
}
}
}
//#[cfg(test)]
//mod test {
// use super::super::super::test_dataframe::test_dataframe;
// use super::*;
//
// #[test]
// fn test_examples() {
// test_dataframe(vec![Box::new(LazyFillNA {})])
// }
//}

View File

@ -1,9 +1,9 @@
use crate::dataframe::values::{NuExpression, NuLazyFrame};
use crate::dataframe::values::{Column, NuDataFrame, NuExpression, NuLazyFrame};
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
#[derive(Clone)]
@ -11,7 +11,7 @@ pub struct LazyFillNull;
impl Command for LazyFillNull {
fn name(&self) -> &str {
"dfr fill-null"
"fill-null"
}
fn usage(&self) -> &str {
@ -30,12 +30,33 @@ impl Command for LazyFillNull {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "",
example: "",
result: None,
description: "Fills the null values by 0",
example: "[1 2 2 3 3] | to-df | shift 2 | fill-null 0",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(),
vec![
Value::test_int(0),
Value::test_int(0),
Value::test_int(1),
Value::test_int(2),
Value::test_int(2),
],
)])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,
@ -44,22 +65,35 @@ impl Command for LazyFillNull {
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let fill: Value = call.req(engine_state, stack, 0)?;
let value = input.into_value(call.head);
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?.into_polars();
let expr = NuExpression::try_from_value(fill)?.into_polars();
let lazy: NuLazyFrame = lazy.fill_null(expr).into();
if NuExpression::can_downcast(&value) {
let expr = NuExpression::try_from_value(value)?;
let fill = NuExpression::try_from_value(fill)?.into_polars();
let expr: NuExpression = expr.into_polars().fill_null(fill).into();
Ok(PipelineData::Value(lazy.into_value(call.head), None))
Ok(PipelineData::Value(
NuExpression::into_value(expr, call.head),
None,
))
} else {
let lazy = NuLazyFrame::try_from_value(value)?;
let expr = NuExpression::try_from_value(fill)?.into_polars();
let lazy = NuLazyFrame::new(lazy.from_eager, lazy.into_polars().fill_null(expr));
Ok(PipelineData::Value(lazy.into_value(call.head)?, None))
}
}
}
//#[cfg(test)]
//mod test {
// use super::super::super::test_dataframe::test_dataframe;
// use super::*;
//
// #[test]
// fn test_examples() {
// test_dataframe(vec![Box::new(LazyFillNull {})])
// }
//}
#[cfg(test)]
mod test {
use super::super::super::series::Shift;
use super::super::super::test_dataframe::test_dataframe;
use super::*;
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(LazyFillNull {}), Box::new(Shift {})])
}
}

View File

@ -1,9 +1,9 @@
use crate::dataframe::values::{NuExpression, NuLazyFrame, NuLazyGroupBy};
use crate::dataframe::values::{Column, NuDataFrame, NuExpression, NuLazyFrame, NuLazyGroupBy};
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use polars::prelude::Expr;
@ -12,7 +12,7 @@ pub struct ToLazyGroupBy;
impl Command for ToLazyGroupBy {
fn name(&self) -> &str {
"dfr group-by"
"group-by"
}
fn usage(&self) -> &str {
@ -34,32 +34,81 @@ impl Command for ToLazyGroupBy {
Example {
description: "Group by and perform an aggregation",
example: r#"[[a b]; [1 2] [1 4] [2 6] [2 4]]
| dfr to-df
| dfr group-by a
| dfr aggregate [
("b" | dfr min | dfr as "b_min")
("b" | dfr max | dfr as "b_max")
("b" | dfr sum | dfr as "b_sum")
| to-df
| group-by a
| agg [
(col b | min | as "b_min")
(col b | max | as "b_max")
(col b | sum | as "b_sum")
]"#,
result: None,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_int(1), Value::test_int(2)],
),
Column::new(
"b_min".to_string(),
vec![Value::test_int(2), Value::test_int(4)],
),
Column::new(
"b_max".to_string(),
vec![Value::test_int(4), Value::test_int(6)],
),
Column::new(
"b_sum".to_string(),
vec![Value::test_int(6), Value::test_int(10)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
Example {
description: "Group by and perform an aggregation",
example: r#"[[a b]; [1 2] [1 4] [2 6] [2 4]]
| dfr to-df
| dfr to-lazy
| dfr group-by a
| dfr aggregate [
("b" | dfr min | dfr as "b_min")
("b" | dfr max | dfr as "b_max")
("b" | dfr sum | dfr as "b_sum")
| to-lazy
| group-by a
| agg [
(col b | min | as "b_min")
(col b | max | as "b_max")
(col b | sum | as "b_sum")
]
| dfr collect"#,
result: None,
| collect"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_int(1), Value::test_int(2)],
),
Column::new(
"b_min".to_string(),
vec![Value::test_int(2), Value::test_int(4)],
),
Column::new(
"b_max".to_string(),
vec![Value::test_int(4), Value::test_int(6)],
),
Column::new(
"b_sum".to_string(),
vec![Value::test_int(6), Value::test_int(10)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,
@ -86,7 +135,8 @@ impl Command for ToLazyGroupBy {
}
let value = input.into_value(call.head);
let (lazy, from_eager) = NuLazyFrame::maybe_is_eager(value)?;
let lazy = NuLazyFrame::try_from_value(value)?;
let from_eager = lazy.from_eager;
let group_by = NuLazyGroupBy {
group_by: Some(lazy.into_polars().groupby(&expressions)),
@ -96,3 +146,23 @@ impl Command for ToLazyGroupBy {
Ok(PipelineData::Value(group_by.into_value(call.head), None))
}
}
#[cfg(test)]
mod test {
use super::super::super::test_dataframe::test_dataframe;
use super::*;
use crate::dataframe::expressions::{ExprAlias, ExprMax, ExprMin, ExprSum};
use crate::dataframe::lazy::aggregate::LazyAggregate;
#[test]
fn test_examples() {
test_dataframe(vec![
Box::new(LazyAggregate {}),
Box::new(ToLazyGroupBy {}),
Box::new(ExprAlias {}),
Box::new(ExprMin {}),
Box::new(ExprMax {}),
Box::new(ExprSum {}),
])
}
}

View File

@ -1,9 +1,9 @@
use crate::dataframe::values::{NuExpression, NuLazyFrame};
use crate::dataframe::values::{Column, NuDataFrame, NuExpression, NuLazyFrame};
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use polars::prelude::{Expr, JoinType};
@ -12,7 +12,7 @@ pub struct LazyJoin;
impl Command for LazyJoin {
fn name(&self) -> &str {
"dfr join"
"join"
}
fn usage(&self) -> &str {
@ -45,21 +45,129 @@ impl Command for LazyJoin {
vec![
Example {
description: "Join two lazy dataframes",
example: r#"let df_a = ([[a b c];[1 "a" 0] [2 "b" 1] [1 "c" 2] [1 "c" 3]] | dfr to-lazy);
let df_b = ([["foo" "bar" "ham"];[1 "a" "let"] [1 "c" "var"] [1 "c" "const"]] | dfr to-lazy);
$df_a | dfr join $df_b a foo | dfr collect"#,
result: None,
example: r#"let df_a = ([[a b c];[1 "a" 0] [2 "b" 1] [1 "c" 2] [1 "c" 3]] | to-lazy);
let df_b = ([["foo" "bar" "ham"];[1 "a" "let"] [2 "c" "var"] [3 "c" "const"]] | to-lazy);
$df_a | join $df_b a foo | collect"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![
Value::test_int(1),
Value::test_int(2),
Value::test_int(1),
Value::test_int(1),
],
),
Column::new(
"b".to_string(),
vec![
Value::test_string("a"),
Value::test_string("b"),
Value::test_string("c"),
Value::test_string("c"),
],
),
Column::new(
"c".to_string(),
vec![
Value::test_int(0),
Value::test_int(1),
Value::test_int(2),
Value::test_int(3),
],
),
Column::new(
"bar".to_string(),
vec![
Value::test_string("a"),
Value::test_string("c"),
Value::test_string("a"),
Value::test_string("a"),
],
),
Column::new(
"ham".to_string(),
vec![
Value::test_string("let"),
Value::test_string("var"),
Value::test_string("let"),
Value::test_string("let"),
],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
Example {
description: "Join one eager dataframe with a lazy dataframe",
example: r#"let df_a = ([[a b c];[1 "a" 0] [2 "b" 1] [1 "c" 2] [1 "c" 3]] | dfr to-df);
let df_b = ([["foo" "bar" "ham"];[1 "a" "let"] [1 "c" "var"] [1 "c" "const"]] | dfr to-lazy);
$df_a | dfr join $df_b a foo"#,
result: None,
example: r#"let df_a = ([[a b c];[1 "a" 0] [2 "b" 1] [1 "c" 2] [1 "c" 3]] | to-df);
let df_b = ([["foo" "bar" "ham"];[1 "a" "let"] [2 "c" "var"] [3 "c" "const"]] | to-lazy);
$df_a | join $df_b a foo"#,
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![
Value::test_int(1),
Value::test_int(2),
Value::test_int(1),
Value::test_int(1),
],
),
Column::new(
"b".to_string(),
vec![
Value::test_string("a"),
Value::test_string("b"),
Value::test_string("c"),
Value::test_string("c"),
],
),
Column::new(
"c".to_string(),
vec![
Value::test_int(0),
Value::test_int(1),
Value::test_int(2),
Value::test_int(3),
],
),
Column::new(
"bar".to_string(),
vec![
Value::test_string("a"),
Value::test_string("c"),
Value::test_string("a"),
Value::test_string("a"),
],
),
Column::new(
"ham".to_string(),
vec![
Value::test_string("let"),
Value::test_string("var"),
Value::test_string("let"),
Value::test_string("let"),
],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,
@ -82,7 +190,7 @@ impl Command for LazyJoin {
};
let other: Value = call.req(engine_state, stack, 0)?;
let (other, _) = NuLazyFrame::maybe_is_eager(other)?;
let other = NuLazyFrame::try_from_value(other)?;
let other = other.into_polars();
let left_on: Value = call.req(engine_state, stack, 1)?;
@ -114,10 +222,11 @@ impl Command for LazyJoin {
let suffix = suffix.unwrap_or_else(|| "_x".into());
let value = input.into_value(call.head);
let (lazy, from_eager) = NuLazyFrame::maybe_is_eager(value)?;
let lazy = NuLazyFrame::try_from_value(value)?;
let from_eager = lazy.from_eager;
let lazy = lazy.into_polars();
let lazy: NuLazyFrame = lazy
let lazy = lazy
.join_builder()
.with(other)
.left_on(left_on)
@ -125,15 +234,21 @@ impl Command for LazyJoin {
.how(how)
.force_parallel(true)
.suffix(suffix)
.finish()
.into();
.finish();
let res = if from_eager {
lazy.collect(call.head)?.into_value(call.head)
} else {
lazy.into_value(call.head)
};
let lazy = NuLazyFrame::new(from_eager, lazy);
Ok(PipelineData::Value(res, None))
Ok(PipelineData::Value(lazy.into_value(call.head)?, None))
}
}
#[cfg(test)]
mod test {
use super::super::super::test_dataframe::test_dataframe;
use super::*;
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(LazyJoin {})])
}
}

View File

@ -1,15 +1,15 @@
/// Definition of multiple lazyframe commands using a macro rule
/// All of these commands have an identical body and only require
/// to have a change in the name, description and function
use crate::dataframe::values::{NuExpression, NuLazyFrame};
use crate::dataframe::values::{Column, NuDataFrame, NuLazyFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
macro_rules! lazy_command {
($command: ident, $name: expr, $desc: expr, $examples: expr, $func: ident) => {
($command: ident, $name: expr, $desc: expr, $examples: expr, $func: ident, $test: ident) => {
#[derive(Clone)]
pub struct $command;
@ -30,6 +30,14 @@ macro_rules! lazy_command {
$examples
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
_engine_state: &EngineState,
@ -37,10 +45,21 @@ macro_rules! lazy_command {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?.into_polars();
let lazy: NuLazyFrame = lazy.$func().into();
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?;
let lazy = NuLazyFrame::new(lazy.from_eager, lazy.into_polars().$func());
Ok(PipelineData::Value(lazy.into_value(call.head), None))
Ok(PipelineData::Value(lazy.into_value(call.head)?, None))
}
}
#[cfg(test)]
mod $test {
use super::super::super::test_dataframe::test_dataframe;
use super::*;
#[test]
fn test_examples() {
test_dataframe(vec![Box::new($command {})])
}
}
};
@ -50,183 +69,195 @@ macro_rules! lazy_command {
// Expands to a command definition for reverse
lazy_command!(
LazyReverse,
"dfr reverse",
"reverse",
"Reverses the LazyFrame",
vec![Example {
description: "",
example: "",
result: None,
}],
reverse
description: "Reverses the dataframe",
example: "[[a b]; [6 2] [4 2] [2 2]] | to-df | reverse",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_int(2), Value::test_int(4), Value::test_int(6),],
),
Column::new(
"b".to_string(),
vec![Value::test_int(2), Value::test_int(2), Value::test_int(2),],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
reverse,
test_reverse
);
// LazyCache command
// Expands to a command definition for cache
lazy_command!(
LazyCache,
"dfr cache",
"cache",
"Caches operations in a new LazyFrame",
vec![Example {
description: "",
example: "",
description: "Caches the result into a new LazyFrame",
example: "[[a b]; [6 2] [4 2] [2 2]] | to-df | reverse | cache",
result: None,
}],
cache
cache,
test_cache
);
// Creates a command that may result in a lazy frame operation or
// lazy frame expression
macro_rules! lazy_expr_command {
($command: ident, $name: expr, $desc: expr, $examples: expr, $func: ident) => {
#[derive(Clone)]
pub struct $command;
impl Command for $command {
fn name(&self) -> &str {
$name
}
fn usage(&self) -> &str {
$desc
}
fn signature(&self) -> Signature {
Signature::build(self.name()).category(Category::Custom("lazyframe".into()))
}
fn examples(&self) -> Vec<Example> {
$examples
}
fn run(
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let value = input.into_value(call.head);
if NuExpression::can_downcast(&value) {
let expr = NuExpression::try_from_value(value)?;
let expr: NuExpression = expr.into_polars().$func().into();
Ok(PipelineData::Value(
NuExpression::into_value(expr, call.head),
None,
))
} else if NuLazyFrame::can_downcast(&value) {
let lazy = NuLazyFrame::try_from_value(value)?.into_polars();
let lazy: NuLazyFrame = lazy.$func().into();
Ok(PipelineData::Value(lazy.into_value(call.head), None))
} else {
Err(ShellError::CantConvert(
"expression or lazyframe".into(),
value.get_type().to_string(),
value.span()?,
None,
))
}
}
}
};
}
// LazyMax command
// Expands to a command definition for max aggregation
lazy_expr_command!(
lazy_command!(
LazyMax,
"dfr max",
"Aggregates columns to their max value or creates a max expression",
"max",
"Aggregates columns to their max value",
vec![Example {
description: "",
example: "",
result: None,
}],
max
description: "Max value from columns in a dataframe",
example: "[[a b]; [6 2] [1 4] [4 1]] | to-df | max",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_int(6)],),
Column::new("b".to_string(), vec![Value::test_int(4)],),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
max,
test_max
);
// LazyMin command
// Expands to a command definition for min aggregation
lazy_expr_command!(
lazy_command!(
LazyMin,
"dfr min",
"Aggregates columns to their min value or creates a min expression",
"min",
"Aggregates columns to their min value",
vec![Example {
description: "",
example: "",
result: None,
}],
min
description: "Min value from columns in a dataframe",
example: "[[a b]; [6 2] [1 4] [4 1]] | to-df | min",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_int(1)],),
Column::new("b".to_string(), vec![Value::test_int(1)],),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
min,
test_min
);
// LazySum command
// Expands to a command definition for sum aggregation
lazy_expr_command!(
lazy_command!(
LazySum,
"dfr sum",
"Aggregates columns to their sum value or creates a sum expression",
"sum",
"Aggregates columns to their sum value",
vec![Example {
description: "",
example: "",
result: None,
}],
sum
description: "Sums all columns in a dataframe",
example: "[[a b]; [6 2] [1 4] [4 1]] | to-df | sum",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_int(11)],),
Column::new("b".to_string(), vec![Value::test_int(7)],),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
sum,
test_sum
);
// LazyMean command
// Expands to a command definition for mean aggregation
lazy_expr_command!(
lazy_command!(
LazyMean,
"dfr mean",
"Aggregates columns to their mean value or creates a mean expression",
"mean",
"Aggregates columns to their mean value",
vec![Example {
description: "",
example: "",
result: None,
}],
mean
description: "Mean value from columns in a dataframe",
example: "[[a b]; [6 2] [4 2] [2 2]] | to-df | mean",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_float(4.0)],),
Column::new("b".to_string(), vec![Value::test_float(2.0)],),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
mean,
test_mean
);
// LazyMedian command
// Expands to a command definition for median aggregation
lazy_expr_command!(
lazy_command!(
LazyMedian,
"dfr median",
"Aggregates columns to their median value or creates a median expression",
"median",
"Aggregates columns to their median value",
vec![Example {
description: "",
example: "",
result: None,
}],
median
description: "Median value from columns in a dataframe",
example: "[[a b]; [6 2] [4 2] [2 2]] | to-df | median",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_float(4.0)],),
Column::new("b".to_string(), vec![Value::test_float(2.0)],),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
median,
test_median
);
// LazyStd command
// Expands to a command definition for std aggregation
lazy_expr_command!(
lazy_command!(
LazyStd,
"dfr std",
"std",
"Aggregates columns to their std value",
vec![Example {
description: "",
example: "",
result: None,
}],
std
description: "Std value from columns in a dataframe",
example: "[[a b]; [6 2] [4 2] [2 2]] | to-df | std",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_float(2.0)],),
Column::new("b".to_string(), vec![Value::test_float(0.0)],),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
std,
test_std
);
// LazyVar command
// Expands to a command definition for var aggregation
lazy_expr_command!(
lazy_command!(
LazyVar,
"dfr var",
"var",
"Aggregates columns to their var value",
vec![Example {
description: "",
example: "",
result: None,
}],
var
description: "Var value from columns in a dataframe",
example: "[[a b]; [6 2] [4 2] [2 2]] | to-df | var",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_float(4.0)],),
Column::new("b".to_string(), vec![Value::test_float(0.0)],),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
var,
test_var
);

View File

@ -1,9 +1,9 @@
mod aggregate;
pub mod aggregate;
mod collect;
mod fetch;
mod fill_na;
mod fill_null;
mod groupby;
pub mod groupby;
mod join;
mod macro_commands;
mod quantile;
@ -13,10 +13,10 @@ mod to_lazy;
use nu_protocol::engine::StateWorkingSet;
use crate::dataframe::lazy::macro_commands::*;
pub(crate) use crate::dataframe::lazy::macro_commands::*;
use crate::dataframe::lazy::aggregate::LazyAggregate;
use crate::dataframe::lazy::collect::LazyCollect;
pub use crate::dataframe::lazy::collect::LazyCollect;
use crate::dataframe::lazy::fetch::LazyFetch;
use crate::dataframe::lazy::fill_na::LazyFillNA;
use crate::dataframe::lazy::fill_null::LazyFillNull;
@ -25,7 +25,7 @@ use crate::dataframe::lazy::join::LazyJoin;
use crate::dataframe::lazy::quantile::LazyQuantile;
use crate::dataframe::lazy::select::LazySelect;
use crate::dataframe::lazy::sort_by_expr::LazySortBy;
use crate::dataframe::lazy::to_lazy::ToLazyFrame;
pub use crate::dataframe::lazy::to_lazy::ToLazyFrame;
pub fn add_lazy_decls(working_set: &mut StateWorkingSet) {
macro_rules! bind_command {

View File

@ -1,9 +1,9 @@
use crate::dataframe::values::NuLazyFrame;
use crate::dataframe::values::{Column, NuDataFrame, NuLazyFrame};
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, SyntaxShape,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use polars::prelude::QuantileInterpolOptions;
@ -12,7 +12,7 @@ pub struct LazyQuantile;
impl Command for LazyQuantile {
fn name(&self) -> &str {
"dfr quantile"
"quantile"
}
fn usage(&self) -> &str {
@ -31,12 +31,27 @@ impl Command for LazyQuantile {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "",
example: "",
result: None,
description: "quantile value from columns in a dataframe",
example: "[[a b]; [6 2] [1 4] [4 1]] | to-df | quantile 0.5",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_float(4.0)]),
Column::new("b".to_string(), vec![Value::test_float(2.0)]),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,
@ -44,24 +59,27 @@ impl Command for LazyQuantile {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let value = input.into_value(call.head);
let quantile: f64 = call.req(engine_state, stack, 0)?;
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?.into_polars();
let lazy: NuLazyFrame = lazy
.quantile(quantile, QuantileInterpolOptions::default())
.into();
let lazy = NuLazyFrame::try_from_value(value)?;
let lazy = NuLazyFrame::new(
lazy.from_eager,
lazy.into_polars()
.quantile(quantile, QuantileInterpolOptions::default()),
);
Ok(PipelineData::Value(lazy.into_value(call.head), None))
Ok(PipelineData::Value(lazy.into_value(call.head)?, None))
}
}
//#[cfg(test)]
//mod test {
// use super::super::super::test_dataframe::test_dataframe;
// use super::*;
//
// #[test]
// fn test_examples() {
// test_dataframe(vec![Box::new(LazyQuantile {})])
// }
//}
#[cfg(test)]
mod test {
use super::super::super::test_dataframe::test_dataframe;
use super::*;
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(LazyQuantile {})])
}
}

View File

@ -1,10 +1,10 @@
use crate::dataframe::values::{NuExpression, NuLazyFrame};
use crate::dataframe::values::{Column, NuDataFrame, NuExpression, NuLazyFrame};
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use polars::prelude::Expr;
@ -13,7 +13,7 @@ pub struct LazySelect;
impl Command for LazySelect {
fn name(&self) -> &str {
"dfr select"
"select"
}
fn usage(&self) -> &str {
@ -22,7 +22,7 @@ impl Command for LazySelect {
fn signature(&self) -> Signature {
Signature::build(self.name())
.required(
.rest(
"select expressions",
SyntaxShape::Any,
"Expression(s) that define the column selection",
@ -32,12 +32,27 @@ impl Command for LazySelect {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "",
example: "",
result: None,
description: "Select a column from the dataframe",
example: "[[a b]; [6 2] [4 2] [2 2]] | to-df | select a",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"a".to_string(),
vec![Value::test_int(6), Value::test_int(4), Value::test_int(2)],
)])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,
@ -45,7 +60,11 @@ impl Command for LazySelect {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let value: Value = call.req(engine_state, stack, 0)?;
let vals: Vec<Value> = call.rest(engine_state, stack, 0)?;
let value = Value::List {
vals,
span: call.head,
};
let expressions = NuExpression::extract_exprs(value)?;
if expressions
@ -59,20 +78,20 @@ impl Command for LazySelect {
));
}
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?.into_polars();
let lazy: NuLazyFrame = lazy.select(&expressions).into();
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?;
let lazy = NuLazyFrame::new(lazy.from_eager, lazy.into_polars().select(&expressions));
Ok(PipelineData::Value(lazy.into_value(call.head), None))
Ok(PipelineData::Value(lazy.into_value(call.head)?, None))
}
}
//#[cfg(test)]
//mod test {
// use super::super::super::test_dataframe::test_dataframe;
// use super::*;
//
// #[test]
// fn test_examples() {
// test_dataframe(vec![Box::new(LazySelect {})])
// }
//}
#[cfg(test)]
mod test {
use super::super::super::test_dataframe::test_dataframe;
use super::*;
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(LazySelect {})])
}
}

View File

@ -1,10 +1,10 @@
use super::super::values::NuLazyFrame;
use crate::dataframe::values::NuExpression;
use crate::dataframe::values::{Column, NuDataFrame, NuExpression};
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
#[derive(Clone)]
@ -12,7 +12,7 @@ pub struct LazySortBy;
impl Command for LazySortBy {
fn name(&self) -> &str {
"dfr sort-by"
"sort-by"
}
fn usage(&self) -> &str {
@ -21,26 +21,77 @@ impl Command for LazySortBy {
fn signature(&self) -> Signature {
Signature::build(self.name())
.required(
"filter expression",
.rest(
"sort expression",
SyntaxShape::Any,
"filtering expression",
"sort expression for the dataframe",
)
.named(
"reverse",
SyntaxShape::List(Box::new(SyntaxShape::Boolean)),
"list indicating if reverse search should be done in the column. Default is false",
"Reverse sorting. Default is false",
Some('r'),
)
.category(Category::Custom("lazyframe".into()))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "",
example: "",
result: None,
}]
vec![
Example {
description: "Sort dataframe by one column",
example: "[[a b]; [6 2] [1 4] [4 1]] | to-df | sort-by a",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![Value::test_int(1), Value::test_int(4), Value::test_int(6)],
),
Column::new(
"b".to_string(),
vec![Value::test_int(4), Value::test_int(1), Value::test_int(2)],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
Example {
description: "Sort column using two columns",
example: "[[a b]; [6 2] [1 1] [1 4] [2 4]] | to-df | sort-by [a b] -r [false true]",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new(
"a".to_string(),
vec![
Value::test_int(1),
Value::test_int(1),
Value::test_int(2),
Value::test_int(6),
],
),
Column::new(
"b".to_string(),
vec![
Value::test_int(4),
Value::test_int(1),
Value::test_int(4),
Value::test_int(2),
],
),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
@ -50,7 +101,11 @@ impl Command for LazySortBy {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let value: Value = call.req(engine_state, stack, 0)?;
let vals: Vec<Value> = call.rest(engine_state, stack, 0)?;
let value = Value::List {
vals,
span: call.head,
};
let expressions = NuExpression::extract_exprs(value)?;
let reverse: Option<Vec<bool>> = call.get_flag(engine_state, stack, "reverse")?;
@ -76,25 +131,25 @@ impl Command for LazySortBy {
};
let lazy = NuLazyFrame::try_from_pipeline(input, call.head)?;
let lazy: NuLazyFrame = lazy
.into_polars()
.sort_by_exprs(&expressions, reverse)
.into();
let lazy = NuLazyFrame::new(
lazy.from_eager,
lazy.into_polars().sort_by_exprs(&expressions, reverse),
);
Ok(PipelineData::Value(
NuLazyFrame::into_value(lazy, call.head),
NuLazyFrame::into_value(lazy, call.head)?,
None,
))
}
}
//#[cfg(test)]
//mod test {
// use super::super::super::test_dataframe::test_dataframe;
// use super::*;
//
// #[test]
// fn test_examples() {
// test_dataframe(vec![Box::new(LazySortBy {})])
// }
//}
#[cfg(test)]
mod test {
use super::super::super::test_dataframe::test_dataframe;
use super::*;
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(LazySortBy {})])
}
}

View File

@ -3,7 +3,7 @@ use super::super::values::{NuDataFrame, NuLazyFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature,
Category, Example, PipelineData, ShellError, Signature, Type, Value,
};
#[derive(Clone)]
@ -11,7 +11,7 @@ pub struct ToLazyFrame;
impl Command for ToLazyFrame {
fn name(&self) -> &str {
"dfr to-lazy"
"to-lazy"
}
fn usage(&self) -> &str {
@ -25,11 +25,19 @@ impl Command for ToLazyFrame {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Takes a dictionary and creates a lazy dataframe",
example: "[[a b];[1 2] [3 4]] | dfr to-df | dfl to-lazy",
example: "[[a b];[1 2] [3 4]] | to-lazy",
result: None,
}]
}
fn input_type(&self) -> Type {
Type::Any
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
_engine_state: &EngineState,
@ -39,7 +47,11 @@ impl Command for ToLazyFrame {
) -> Result<PipelineData, ShellError> {
let df = NuDataFrame::try_from_iter(input.into_iter())?;
let lazy = NuLazyFrame::from_dataframe(df);
let value = Value::CustomValue {
val: Box::new(lazy),
span: call.head,
};
Ok(PipelineData::Value(lazy.into_value(call.head), None))
Ok(PipelineData::Value(value, None))
}
}

View File

@ -3,7 +3,7 @@ use super::super::values::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
#[derive(Clone)]
@ -11,7 +11,7 @@ pub struct AllFalse;
impl Command for AllFalse {
fn name(&self) -> &str {
"dfr all-false"
"all-false"
}
fn usage(&self) -> &str {
@ -26,7 +26,7 @@ impl Command for AllFalse {
vec![
Example {
description: "Returns true if all values are false",
example: "[false false false] | dfr to-df | dfr all-false",
example: "[false false false] | to-df | all-false",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"all_false".to_string(),
@ -38,9 +38,9 @@ impl Command for AllFalse {
},
Example {
description: "Checks the result from a comparison",
example: r#"let s = ([5 6 2 10] | dfr to-df);
example: r#"let s = ([5 6 2 10] | to-df);
let res = ($s > 9);
$res | dfr all-false"#,
$res | all-false"#,
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"all_false".to_string(),
@ -53,6 +53,14 @@ impl Command for AllFalse {
]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -3,7 +3,7 @@ use super::super::values::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
#[derive(Clone)]
@ -11,7 +11,7 @@ pub struct AllTrue;
impl Command for AllTrue {
fn name(&self) -> &str {
"dfr all-true"
"all-true"
}
fn usage(&self) -> &str {
@ -26,7 +26,7 @@ impl Command for AllTrue {
vec![
Example {
description: "Returns true if all values are true",
example: "[true true true] | dfr to-df | dfr all-true",
example: "[true true true] | to-df | all-true",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"all_true".to_string(),
@ -38,9 +38,9 @@ impl Command for AllTrue {
},
Example {
description: "Checks the result from a comparison",
example: r#"let s = ([5 6 2 8] | dfr to-df);
example: r#"let s = ([5 6 2 8] | to-df);
let res = ($s > 9);
$res | dfr all-true"#,
$res | all-true"#,
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"all_true".to_string(),
@ -53,6 +53,14 @@ impl Command for AllTrue {
]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -3,7 +3,7 @@ use super::super::values::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
use polars::prelude::{IntoSeries, NewChunkedArray, UInt32Chunked};
@ -12,7 +12,7 @@ pub struct ArgMax;
impl Command for ArgMax {
fn name(&self) -> &str {
"dfr arg-max"
"arg-max"
}
fn usage(&self) -> &str {
@ -26,7 +26,7 @@ impl Command for ArgMax {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Returns index for max value",
example: "[1 3 2] | dfr to-df | dfr arg-max",
example: "[1 3 2] | to-df | arg-max",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"arg_max".to_string(),
@ -38,6 +38,14 @@ impl Command for ArgMax {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -3,7 +3,7 @@ use super::super::values::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
use polars::prelude::{IntoSeries, NewChunkedArray, UInt32Chunked};
@ -12,7 +12,7 @@ pub struct ArgMin;
impl Command for ArgMin {
fn name(&self) -> &str {
"dfr arg-min"
"arg-min"
}
fn usage(&self) -> &str {
@ -26,7 +26,7 @@ impl Command for ArgMin {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Returns index for min value",
example: "[1 3 2] | dfr to-df | dfr arg-min",
example: "[1 3 2] | to-df | arg-min",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"arg_min".to_string(),
@ -38,6 +38,14 @@ impl Command for ArgMin {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -4,7 +4,8 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type,
Value,
};
use polars::prelude::{DataType, IntoSeries};
@ -44,7 +45,7 @@ pub struct Cumulative;
impl Command for Cumulative {
fn name(&self) -> &str {
"dfr cumulative"
"cumulative"
}
fn usage(&self) -> &str {
@ -61,7 +62,7 @@ impl Command for Cumulative {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Cumulative sum for a series",
example: "[1 2 3 4 5] | dfr to-df | dfr cumulative sum",
example: "[1 2 3 4 5] | to-df | cumulative sum",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0_cumulative_sum".to_string(),
@ -79,6 +80,14 @@ impl Command for Cumulative {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -4,7 +4,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, SyntaxShape,
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type,
};
use polars::prelude::{IntoSeries, Utf8Methods};
@ -13,7 +13,7 @@ pub struct AsDate;
impl Command for AsDate {
fn name(&self) -> &str {
"dfr as-date"
"as-date"
}
fn usage(&self) -> &str {
@ -37,11 +37,19 @@ impl Command for AsDate {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Converts string to date",
example: r#"["2021-12-30" "2021-12-31"] | dfr to-df | dfr as-datetime "%Y-%m-%d""#,
example: r#"["2021-12-30" "2021-12-31"] | to-df | as-datetime "%Y-%m-%d""#,
result: None,
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -5,7 +5,7 @@ use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value,
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use polars::prelude::{IntoSeries, TimeUnit, Utf8Methods};
@ -14,7 +14,7 @@ pub struct AsDateTime;
impl Command for AsDateTime {
fn name(&self) -> &str {
"dfr as-datetime"
"as-datetime"
}
fn usage(&self) -> &str {
@ -46,7 +46,7 @@ impl Command for AsDateTime {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Converts string to datetime",
example: r#"["2021-12-30 00:00:00" "2021-12-31 00:00:00"] | dfr to-df | dfr as-datetime "%Y-%m-%d %H:%M:%S""#,
example: r#"["2021-12-30 00:00:00" "2021-12-31 00:00:00"] | to-df | as-datetime "%Y-%m-%d %H:%M:%S""#,
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"datetime".to_string(),
@ -75,6 +75,14 @@ impl Command for AsDateTime {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -3,7 +3,7 @@ use super::super::super::values::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
use polars::prelude::{DatetimeMethods, IntoSeries};
@ -12,7 +12,7 @@ pub struct GetDay;
impl Command for GetDay {
fn name(&self) -> &str {
"dfr get-day"
"get-day"
}
fn usage(&self) -> &str {
@ -27,8 +27,8 @@ impl Command for GetDay {
vec![Example {
description: "Returns day from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
let df = ([$dt $dt] | dfr to-df);
$df | dfr get-day"#,
let df = ([$dt $dt] | to-df);
$df | get-day"#,
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(),
@ -40,6 +40,14 @@ impl Command for GetDay {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -3,7 +3,7 @@ use super::super::super::values::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
use polars::prelude::{DatetimeMethods, IntoSeries};
@ -12,7 +12,7 @@ pub struct GetHour;
impl Command for GetHour {
fn name(&self) -> &str {
"dfr get-hour"
"get-hour"
}
fn usage(&self) -> &str {
@ -27,8 +27,8 @@ impl Command for GetHour {
vec![Example {
description: "Returns hour from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
let df = ([$dt $dt] | dfr to-df);
$df | dfr get-hour"#,
let df = ([$dt $dt] | to-df);
$df | get-hour"#,
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(),
@ -40,6 +40,14 @@ impl Command for GetHour {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -3,7 +3,7 @@ use super::super::super::values::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
use polars::prelude::{DatetimeMethods, IntoSeries};
@ -12,7 +12,7 @@ pub struct GetMinute;
impl Command for GetMinute {
fn name(&self) -> &str {
"dfr get-minute"
"get-minute"
}
fn usage(&self) -> &str {
@ -27,8 +27,8 @@ impl Command for GetMinute {
vec![Example {
description: "Returns minute from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
let df = ([$dt $dt] | dfr to-df);
$df | dfr get-minute"#,
let df = ([$dt $dt] | to-df);
$df | get-minute"#,
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(),
@ -40,6 +40,14 @@ impl Command for GetMinute {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -3,7 +3,7 @@ use super::super::super::values::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
use polars::prelude::{DatetimeMethods, IntoSeries};
@ -12,7 +12,7 @@ pub struct GetMonth;
impl Command for GetMonth {
fn name(&self) -> &str {
"dfr get-month"
"get-month"
}
fn usage(&self) -> &str {
@ -27,8 +27,8 @@ impl Command for GetMonth {
vec![Example {
description: "Returns month from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
let df = ([$dt $dt] | dfr to-df);
$df | dfr get-month"#,
let df = ([$dt $dt] | to-df);
$df | get-month"#,
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(),
@ -40,6 +40,14 @@ impl Command for GetMonth {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -3,7 +3,7 @@ use super::super::super::values::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
use polars::prelude::{DatetimeMethods, IntoSeries};
@ -12,7 +12,7 @@ pub struct GetNanosecond;
impl Command for GetNanosecond {
fn name(&self) -> &str {
"dfr get-nanosecond"
"get-nanosecond"
}
fn usage(&self) -> &str {
@ -27,8 +27,8 @@ impl Command for GetNanosecond {
vec![Example {
description: "Returns nanosecond from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
let df = ([$dt $dt] | dfr to-df);
$df | dfr get-nanosecond"#,
let df = ([$dt $dt] | to-df);
$df | get-nanosecond"#,
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(),
@ -40,6 +40,14 @@ impl Command for GetNanosecond {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -3,7 +3,7 @@ use super::super::super::values::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
use polars::prelude::{DatetimeMethods, IntoSeries};
@ -12,7 +12,7 @@ pub struct GetOrdinal;
impl Command for GetOrdinal {
fn name(&self) -> &str {
"dfr get-ordinal"
"get-ordinal"
}
fn usage(&self) -> &str {
@ -27,8 +27,8 @@ impl Command for GetOrdinal {
vec![Example {
description: "Returns ordinal from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
let df = ([$dt $dt] | dfr to-df);
$df | dfr get-ordinal"#,
let df = ([$dt $dt] | to-df);
$df | get-ordinal"#,
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(),
@ -40,6 +40,14 @@ impl Command for GetOrdinal {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -3,7 +3,7 @@ use super::super::super::values::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
use polars::prelude::{DatetimeMethods, IntoSeries};
@ -12,7 +12,7 @@ pub struct GetSecond;
impl Command for GetSecond {
fn name(&self) -> &str {
"dfr get-second"
"get-second"
}
fn usage(&self) -> &str {
@ -27,8 +27,8 @@ impl Command for GetSecond {
vec![Example {
description: "Returns second from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
let df = ([$dt $dt] | dfr to-df);
$df | dfr get-second"#,
let df = ([$dt $dt] | to-df);
$df | get-second"#,
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(),
@ -40,6 +40,14 @@ impl Command for GetSecond {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -3,7 +3,7 @@ use super::super::super::values::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
use polars::prelude::{DatetimeMethods, IntoSeries};
@ -12,7 +12,7 @@ pub struct GetWeek;
impl Command for GetWeek {
fn name(&self) -> &str {
"dfr get-week"
"get-week"
}
fn usage(&self) -> &str {
@ -27,8 +27,8 @@ impl Command for GetWeek {
vec![Example {
description: "Returns week from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
let df = ([$dt $dt] | dfr to-df);
$df | dfr get-week"#,
let df = ([$dt $dt] | to-df);
$df | get-week"#,
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(),
@ -40,6 +40,14 @@ impl Command for GetWeek {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -3,7 +3,7 @@ use super::super::super::values::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
use polars::prelude::{DatetimeMethods, IntoSeries};
@ -12,7 +12,7 @@ pub struct GetWeekDay;
impl Command for GetWeekDay {
fn name(&self) -> &str {
"dfr get-weekday"
"get-weekday"
}
fn usage(&self) -> &str {
@ -27,8 +27,8 @@ impl Command for GetWeekDay {
vec![Example {
description: "Returns weekday from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
let df = ([$dt $dt] | dfr to-df);
$df | dfr get-weekday"#,
let df = ([$dt $dt] | to-df);
$df | get-weekday"#,
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(),
@ -40,6 +40,14 @@ impl Command for GetWeekDay {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -3,7 +3,7 @@ use super::super::super::values::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
use polars::prelude::{DatetimeMethods, IntoSeries};
@ -12,7 +12,7 @@ pub struct GetYear;
impl Command for GetYear {
fn name(&self) -> &str {
"dfr get-year"
"get-year"
}
fn usage(&self) -> &str {
@ -27,8 +27,8 @@ impl Command for GetYear {
vec![Example {
description: "Returns year from a date",
example: r#"let dt = ('2020-08-04T16:39:18+00:00' | into datetime -z 'UTC');
let df = ([$dt $dt] | dfr to-df);
$df | dfr get-year"#,
let df = ([$dt $dt] | to-df);
$df | get-year"#,
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"0".to_string(),
@ -40,6 +40,14 @@ impl Command for GetYear {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -3,7 +3,7 @@ use super::super::super::values::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
use polars::prelude::{IntoSeries, SortOptions};
@ -12,7 +12,7 @@ pub struct ArgSort;
impl Command for ArgSort {
fn name(&self) -> &str {
"dfr arg-sort"
"arg-sort"
}
fn usage(&self) -> &str {
@ -30,7 +30,7 @@ impl Command for ArgSort {
vec![
Example {
description: "Returns indexes for a sorted series",
example: "[1 2 2 3 3] | dfr to-df | dfr arg-sort",
example: "[1 2 2 3 3] | to-df | arg-sort",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"arg_sort".to_string(),
@ -48,7 +48,7 @@ impl Command for ArgSort {
},
Example {
description: "Returns indexes for a sorted series",
example: "[1 2 2 3 3] | dfr to-df | dfr arg-sort -r",
example: "[1 2 2 3 3] | to-df | arg-sort -r",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"arg_sort".to_string(),
@ -67,6 +67,14 @@ impl Command for ArgSort {
]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

View File

@ -3,7 +3,7 @@ use super::super::super::values::{Column, NuDataFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Value,
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
use polars::prelude::IntoSeries;
@ -12,7 +12,7 @@ pub struct ArgTrue;
impl Command for ArgTrue {
fn name(&self) -> &str {
"dfr arg-true"
"arg-true"
}
fn usage(&self) -> &str {
@ -26,7 +26,7 @@ impl Command for ArgTrue {
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Returns indexes where values are true",
example: "[false true false] | dfr to-df | dfr arg-true",
example: "[false true false] | to-df | arg-true",
result: Some(
NuDataFrame::try_from_columns(vec![Column::new(
"arg_true".to_string(),
@ -38,6 +38,14 @@ impl Command for ArgTrue {
}]
}
fn input_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn output_type(&self) -> Type {
Type::Custom("dataframe".into())
}
fn run(
&self,
engine_state: &EngineState,

Some files were not shown because too many files have changed in this diff Show More