Compare commits

...

2228 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
6c07bc10e2 feat: Refactor and optimize the github release workflow: deliver binary package for more targets (#5649) 2022-05-28 10:41:47 +08:00
6365ba0286 Add search terms for all?, any?, length, and keybindings (#5665)
* Add search terms for `all?`

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

* Add search terms for `any?`

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

* Add search terms for `length`

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

* Add search terms for `keybindings`

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

* add throw

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

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

* Add expected result for `columns` example

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

* Add example test harness to `reject`

* Test and fix `wrap` example

* Test and fix `drop column` example

* Update `from ods` examples

* Update `from xlsx` examples

* Run `to nuon` examples

* Run `hash base64` examples

* Add example output to `path parse`

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

* add -p to not follow symbolic link

* change comment

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

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

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

* a more helpful error for let in pipeline fmt

* changed help message

* type-o

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2022-05-25 19:13:14 -05:00
a42d419b66 nu-cli/completions: fix filter for variable completions (#5641) 2022-05-25 19:10:46 -05:00
9602e82029 make sure no duplicate records exists during eval and merge (#5633) 2022-05-25 19:10:31 -05:00
JT
8e98df8b28 bump to dev version (#5635) 2022-05-25 19:09:44 -05:00
2daf8ec72d cargo update (#5639) 2022-05-25 13:13:14 -04:00
afcacda35f Change embed-resource dep to slimmer winres (#5630) 2022-05-24 23:28:10 -04:00
JT
06cf3fa5ad Bump to 0.63 (#5627) 2022-05-25 11:33:28 +12:00
9a482ce284 Overlay keep (#5629)
* Allow env vars to be kept from removed overlay

* Rename --keep to --keep-custom; Add new test

* Rename some symbols

* (WIP) Start working on --keep for defs and aliases

* Fix decls/aliases not melting properly

* Use id instead of the whole cloned overlay

* Rewrite overlay remove for no reason

Doesn't fix the bug but at least looks better.

* Rename variable

* Fix adding overlay env vars

* Add more tests; Fmt + Clippy
2022-05-25 09:22:17 +12:00
8018ae3286 Pin reedline v0.6.0 for the nushell v0.63.0 release (#5620)
Release notes: https://github.com/nushell/reedline/releases/tag/v0.6.0

This release contains several bug fixes and improvements to the vi-emulation and documentation.

- Improvements to the vi-style keybindings (@sadmac7000):
  - `w` now correctly moves to the beginning of the word.
  - `e` to move to the end of the word.
- Bugfixes:
  - Support terminal emulators that erroneously report a size of 0x0 by assuming a default size to avoid panics and draw nevertheless (@DhruvDh)
  - Fix `ListMenu` layout calculations. Avoids scrolling bug when wrapping occurs due to the line numbering (@ahkrr)
  - Avoid allocating to the total history capacity which can cause the application to go out of memory (@sholderbach)
- Documentation improvements including addition of documentation intended for reedline developers (@petrisch, @sholderbach)
2022-05-24 00:39:55 +02:00
ef322a24c5 fix date format (#5619) 2022-05-23 09:59:34 -07:00
a8db4f0b0e load config when requried (#5618) 2022-05-23 15:47:08 +03:00
98a4280c41 Add octal binary literals (#5604)
Schema `0o[77]` with the same padding behavior as the other binary literals

- this updates #5551
- test for parsing binary from octal
- test for string parsing
2022-05-23 11:01:15 +02:00
0e1bfae13d Fallback for config.buffer_editor from EDITOR (#5614)
For the reedline `buffer_editor` use the `EDITOR` and `VISUAL`
environment variables as fallback.

Same resolution order as #5607

Closes #5430
2022-05-23 05:32:52 +12:00
6ff717c0ba Add meta command for the config subcommands (#5616)
When using `config` without the `config nu` or `config env` subcommands
introduced by #5607 display basic usage like `str`.
2022-05-23 05:31:57 +12:00
d534a89867 Make flatten works better and predictable (#5611)
* only want to flatten at most one column which contains a list

* make flatten works better

* more readable
2022-05-22 06:22:38 -05:00
5bc9246f0f Allow for test_iteration_errors to work when run as root (#5609)
* allow for test_iteration_errors to work when run as root

* Add comment to skip condition

Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>
2022-05-22 11:47:03 +02:00
1e89cc3578 fix typo for version command (#5610) 2022-05-22 16:48:39 +08:00
06f5199570 Add config command (#5607)
* Add config command

* Format code

Co-authored-by: Frank Zhang <v-frankz@microsoft.com>
2022-05-22 15:13:58 +12:00
9e5e9819d6 adjust flatten default behavior (#5606) 2022-05-21 08:32:51 -05:00
1f8ccd8e5e Add search term to str substring command. (#5603) 2022-05-21 11:40:37 +03:00
e9d8b19d4d feat: add search terms to network (#5602)
Co-authored-by: Leyoh Li <leyohli@LeyohdeMacBook-Air.local>
2022-05-20 23:19:17 -04:00
7c63ce15d8 attempts to allow the test to work when run as root (#5601) 2022-05-20 21:48:36 -05:00
JT
a3a9571dac Add environment change hook (#5600)
* add environment change hook

* clippy
2022-05-21 09:49:42 +12:00
2cc5952c37 Fix cp bug (#5462)
* Cleanup - remove old commented code

* Force a / or \ to distinguish between folders and files for cp

* Force a / or \ to distinguish between folders and files for cp

* Remove unneeded code

* Add cp test for checking copy to non existing directory

* Fix warning in test
2022-05-21 09:49:29 +12:00
aa88449f29 Refer to the span of error make if not given (#5599)
* Refer to the span of `error make` if not given

Implements #5591

Currently the span of the "throwing" `error make`

Also allow to set `msg` and `label` without an additional span.

* Message plus "originates from here" label
2022-05-21 09:48:36 +12:00
06199d731b Use bleeding edge reedline, with fix for #5593 (#5598)
Fixes #5593 (OOM introduced with #5587 when no config was present and an attempt was
made to allocate all memory in advance)

Includes also other changes to reedline:

- Vi word definition fixed and `w` and `e` work as expected
2022-05-20 17:35:25 +02:00
0ba86d7eb8 Fix #5578, assume pipe file be zero-sized (#5594)
* Fix #5578, assume pipe file be zero-sized

* rust fmt
2022-05-20 09:27:21 -05:00
6efd1bcb3f Don't report error when cwd is not exists. (#5590)
* only set cwd for child process if cwd exists, and avoid showing error when pwd is not exists

* better comment text

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2022-05-20 07:03:03 -05:00
0d06b6259f Change miette theme based on ANSI config (#5588)
* Change miette theme based on ANSI config

Use the base ansi colors to simplify the use of the terminal emulator
theming.
Turn of most eye-candy (including unicode) when using
`$config.use_ansi_coloring: false`

Addresses #5582

* Fix error test affected by changed styling
2022-05-19 13:59:14 -05:00
8fdc272bcc Use effectively unlimited history size if not set (#5587)
Fixes #5586
2022-05-19 12:42:41 -05:00
0ea7a38c21 Move help menu to canonical F1 binding (#5510)
Currently the fully fledged help menu is bound to `Ctrl-Q`.
Help is widely associated with `F1`.

Before merging check that it is passed through on all platforms and
terminal emulators
2022-05-19 08:24:04 -05:00
1999e0dcf3 Fix flatten behavior (#5584)
* one step closer to flatten

* integration code is passing, but still need to do one more level flatten for table

* fix flatten

* using match instead of several if let

* make better comment

* fmt code

* better comment
2022-05-19 06:46:48 -05:00
ac30b3d108 Fix menu panic for empty examples. (#5581) 2022-05-19 10:04:56 +02:00
2b1e05aad0 add quantile column (#5583) 2022-05-18 20:47:26 -05:00
6c56829976 Allowing for flags with '=' in them to register as flags. (#5579)
* hacky fix for registering flags with '='

* fmt
2022-05-18 11:26:58 -05:00
2c58beec13 cp, mv, and rm commands need to support -i flag (#5523)
* restored interactive mode to rm command

* removed unnecessary whitespace in rm file

* removed unnecessary whitespace in rm file

* fixed python-vertualenv build issue

* moved interactive logic to utils file

* restored interactive mode to cp command

* interactive mode for mv wip

* finished mv implementation

* removed unnecessary whitespace

* changed unwrap to expect
2022-05-18 09:53:46 -05:00
9c779b071b feat: apply the --numbered option to acc in reduce command. (#5575)
* feat: apply the `-n` option to acc

* feat: update tests and examples
2022-05-18 09:49:34 -05:00
1e94793df5 Add str title-case (#5573)
Co-authored-by: kyle <kyle@archtop.local>
2022-05-18 08:57:20 -05:00
7d9a77f179 fix select tests (#5577) 2022-05-18 06:20:26 -05:00
bb079608dd fix move test (#5576)
* fix move test

* remove ignore
2022-05-18 06:18:21 -05:00
5fa42eeb8c Make format support nested column and use variable (#5570)
* fix format for nested structure

* make little revert

* add tests

* fix format

* better comment

* make better comment
2022-05-18 06:08:43 -05:00
3e09158afc Move capitalize, downcase, upcase to /cases; fix some example descriptions; clarify usage text (#5572)
Co-authored-by: kyle <kyle@archtop.local>
2022-05-18 00:55:43 -04:00
7a78171b34 move items to showcase (#5569) 2022-05-17 18:21:14 -05:00
633ebc7e43 Revert "Enable backtraces by default (#5562)" (#5568)
This reverts commit 8004e8e2a0.
2022-05-17 15:02:45 -07:00
f0cb2f38df refactor all write_alls to ensure flushing (#5567) 2022-05-17 13:28:18 -05:00
f26d3bf8d7 make print flush (#5566) 2022-05-17 09:27:12 -05:00
498672f5e5 feat(errors): more explicit module_or_overlay_not_found_error help message (#5564) 2022-05-17 06:22:31 -05:00
038391519b Upgrade trash crate for faster non-Windows builds (#5563) 2022-05-16 17:48:41 -07:00
8004e8e2a0 Enable backtraces by default (#5562) 2022-05-16 17:04:41 -07:00
JT
e192684612 Revert "Try to do less work during capture discovery (#5560)" (#5561)
This reverts commit 5d40fc2726.
2022-05-17 10:49:59 +12:00
JT
5d40fc2726 Try to do less work during capture discovery (#5560) 2022-05-17 09:05:26 +12:00
a22d70718f Add search terms to build-string command. (#5557) 2022-05-16 12:21:01 -07:00
24a49f1b0a Remove doctests action (#5556)
We're no longer using `cargo nextest` for our main test job. The separate action for doctests was only necessary because `cargo nextest` does not support doctests, it can be removed.

Hoping this will result in less data cached but we'll see.
2022-05-16 09:10:00 -07:00
04473a5593 Update pull request template for faster clippy+tests
Updating the Clippy and `cargo test` instructions to be more similar to what we do in CI. Will speed things up a bit for contributors.
2022-05-16 08:42:38 -07:00
d1e7884d19 table refactor for readability (#5555) 2022-05-16 10:35:57 -05:00
2b96c93b8d Sync resources version (#5554)
Fix line ending
2022-05-16 09:15:10 -05:00
fc41a0f96b use reverse iter on value search (#5553) 2022-05-16 06:29:40 -05:00
8bd68416e3 Lazy dataframes (#5546)
* lazyframe definition

* expressions and lazy frames

* new alias expression

* more expression commands

* updated to polars main

* more expressions and groupby

* more expressions, fetch and sort-by

* csv reader

* removed open csv

* unique function

* joining functions

* join lazy frames commands with eager commands

* corrected tests

* Update .gitignore

* Update .gitignore

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
2022-05-16 08:27:43 +01:00
2062e33c37 CI: bust caches (#5550)
* bust test cache to see if that fixes issue

* bust all caches
2022-05-15 22:24:51 -07:00
JT
c6383874e9 Try removing debuginfo for ci builds (#5549)
* Try removing debuginfo for ci builds

* oops, wrong inherits

* extra flag

* nextest doesn't support --profile in the same way

* try to allow for a ci-specific target

* Oops, run more tests
2022-05-16 16:02:11 +12:00
d90b25c633 Look up git commit hash ourselves, drop libgit2 dependency (#5548) 2022-05-16 13:57:25 +12:00
44bcfb3403 fix zip test (#5536) 2022-05-15 16:44:32 -05:00
c047fd4778 nu-cli/completions: add custom completion test (#5543) 2022-05-14 15:09:41 -05:00
16bd7b6d0d Fix Value::Record compare logic, and pass uniq tests. (#5541)
* fix record compare logic

* add more comment
2022-05-14 06:04:09 -05:00
3cef94ba39 nu-glob: add fs::symlink_metadata to detect broken symlinks (#5537)
* nu-glob: add fs::symlink_metadata to detect broken symlinks

* fix join result
2022-05-13 17:56:26 -07:00
f818193b53 Change history menu keybinding from ctrl+x to ctrl+r (#5507)
* Change history menu keybinding to ctrl+r from ctrl+x

* Remove menupage actions from default config

* remove trailing whitespace

* re-add next+previous page keybindings

* Remove hardcoded menu keybindings

* Hardcode new keybindings
2022-05-13 09:26:14 -05:00
1aec4a343a Made a change to completion resolution order (#5440)
* Made a change to completion resolution order

* Potential fix for completion (remove file paths from command completer)

* Updating formatting

* Removed commented out code for readability

* Fixed compile error on merge
2022-05-13 08:15:24 -05:00
852de79212 Implement histogram command (#5518)
* finish histogram

* adjust comment

* add test for histogram

* add Date to test

* move hashable value back inside chart package
2022-05-13 06:48:47 -05:00
06f40405fe add rename (#5534) 2022-05-13 06:47:11 -05:00
65bac77e8a More CI work (#5527)
* Add cache+docs to plugin CI job

* CI perf: don't statically link OpenSSL

* Run Clippy in plugin job

* comment

* bust cache

* trigger build

* remove nextest, split plugins better

* trigger CI

* try disabling embed-resource

* try disabling libgit2 in shadow-rs

* use lld linker on Windows

* Skip embedding Windows resource (slow) during tests

* disable shadow-rs git integration during tests

* go back to simpler shadow-rs and embed-resources setup

* some renaming

* forgot nextest

* trigger ci

* Remove Clippy and unnecessary build

* trigger CI

* disable lld

* reenable lld

* cleanup

* revert embed_resource change
2022-05-13 06:40:46 -05:00
32d1939a95 nu-command/filesystem: fix rm .sock file (#5524) 2022-05-12 19:25:21 -05:00
53e35670ea add the ability to change table mode when running script (#5520) 2022-05-12 07:27:44 -05:00
a92567489f nu-cli/completions: verify case for matching dir, .nu, file and command (#5506)
* nu-cli/completions: verify case for matching dir, .nu, file and command

* avoid copy

* fix clippy
2022-05-11 16:16:52 -05:00
2145feff5d feat: add tutor list support, remove tutor engine-q, fix: #4950 (#5511)
* feat: add `tutor list` support, remove tutor `engine-q`, fix: #4950

* cs

* fmt
2022-05-11 16:16:01 -05:00
0b95465ea1 add --table_mode -m parameter (#5513)
* add `--table_mode` `-m` parameter

* underscores to dashes
2022-05-11 16:15:31 -05:00
ec804f4568 nu-command ls - bump umask crate to 2.0.0 (#5514) 2022-05-11 16:13:45 -05:00
4717ac70fd Add verbose (#5512)
Co-authored-by: Frank Zhang <v-frankz@microsoft.com>
2022-05-11 11:46:13 -05:00
9969fbfbb1 Add feedback to cp (#5482)
Co-authored-by: Frank Zhang <v-frankz@microsoft.com>
2022-05-11 20:06:30 +08:00
5f39267a80 Make $nothing | into string == "" (#5490)
* Make $nothing | into string == ""

* Fix up existing into string tests

* Add $nothing | into string test

* Formatting

* Windows line endings test fix
2022-05-11 12:26:43 +03:00
94a9380e8b adjust where prompt markers go (#5491)
* adjust where prompt markers go

* marks are working, yipee!
2022-05-10 16:33:18 -05:00
1d64863585 nu-cli/completions: add variable completions test + refactor tests (#5504)
* refactor tests

* removed old test file
2022-05-10 15:17:07 -05:00
8218f72eea nu-cli/completions: added tests for dotnu completions (#5460) 2022-05-10 13:18:18 -05:00
c0b99b7131 Enable converting dates to ints (#5489) 2022-05-10 13:15:28 -05:00
75c033e4d1 refactor for legibility (#5503)
* refactor for legibility

* clippy
2022-05-10 12:49:34 -05:00
d88d057bf6 keep metadata while format filesize (#5502) 2022-05-10 11:24:06 -05:00
b00098ccc6 opt: improve ls by call get_file_type only one time (#5500)
* opt: improve ls by call get_file_type only one time

* fmt

* cs
2022-05-10 08:01:06 -05:00
7e5e9c28dd Fix #3899, make mv and rm to be quiet by default (#5501) 2022-05-10 08:00:27 -05:00
8ffffe9bcc Improve #4975 of filtering ls output by size issue (#5494)
* Improve #4975 of filtering `ls` output by size issue

* cargo fmt
2022-05-10 06:39:37 -05:00
8030f7e9f0 add format filesize (#5498)
* add format filesize

* add comment

* add comment

* remove comment
2022-05-10 06:35:14 -05:00
e4959d2f9f Update comment in default_config.nu [skip ci] (#5496) 2022-05-10 06:21:01 -05:00
f311da9623 Adds fix for when multiple flags are in one line. (#5493) 2022-05-10 06:13:19 -05:00
14d80d54fe Parse timestamps as UTC by default (#5488)
* Parse timestamps as UTC by default

* Fix up flags and examples
2022-05-09 13:57:28 -05:00
23b467061b Display range values better (#5487) 2022-05-09 12:18:37 -05:00
8d8f25b210 Fixing the flag issue (#5447)
* Fixing the flag issue

* whoops, forgot the original point of the function

* Update deparse.rs

* Update deparse.rs

* Update deparse.rs

* maybe this might work

* fmt

* quotation marks works now due to a rigorous check for args.

* fmt and clippy

* kept the original escape_quote_string(), escaped " and \

* removed script.nu

* Added appropriate comments.
2022-05-09 07:01:58 -05:00
7ee22603ac Fix #5469, making $nothing or null convert to filesize of 0B (#5485) 2022-05-09 06:19:28 -05:00
4052a99ff5 Handle int input in into datetime (#5484) 2022-05-09 06:16:01 -05:00
ccfa35289b Fix to csv and to tsv for simple list, close: #4780 (#5483)
* Fix `to csv` and `to tsv` for simple list, close: #4780

* ci skip
2022-05-09 06:14:42 -05:00
JT
54fc164e1c Allow hooks to be lists of blocks (#5480) 2022-05-09 13:56:48 +12:00
JT
3a35bf7d4e Add hooks to cli/repl (#5479)
* Add hooks to cli/repl

* Clippy

* Clippy
2022-05-09 07:28:39 +12:00
a61d09222f document out positional argument type (#5461) 2022-05-08 08:11:28 -05:00
07ac3c3aab Add Nushell REPL simulator; Fix bug in overlay add (#5478)
* Add Nushell REPL simulator; Fix bug in overlay add

The `nu_repl` function takes an array of strings and processes them as
if they were REPL lines entered one by one. This helps to discover bugs
due to the state changes between the parse and eval stages.

* Fix REPL tests on Windows
2022-05-08 16:09:39 +03:00
061e9294b3 join and from derived tables (#5477) 2022-05-08 11:12:03 +01:00
JT
374757f286 Bump to the 0.62.1 dev version (#5473) 2022-05-08 08:38:12 +12:00
ca75cd7c0a nu-cli/completions: add tests for flag completions (#5468) 2022-05-07 15:19:48 -05:00
d08c072f19 feat: add disable field type inferencing for from csv and from tsv, fix: #3485 and #4217 (#5467) 2022-05-07 15:04:31 -05:00
9b99b2f6ac Overlays (#5375)
* WIP: Start laying overlays

* Rename Overlay->Module; Start adding overlay

* Revamp adding overlay

* Add overlay add tests; Disable debug print

* Fix overlay add; Add overlay remove

* Add overlay remove tests

* Add missing overlay remove file

* Add overlay list command

* (WIP?) Enable overlays for env vars

* Move OverlayFrames to ScopeFrames

* (WIP) Move everything to overlays only

ScopeFrame contains nothing but overlays now

* Fix predecls

* Fix wrong overlay id translation and aliases

* Fix broken env lookup logic

* Remove TODOs

* Add overlay add + remove for environment

* Add a few overlay tests; Fix overlay add name

* Some cleanup; Fix overlay add/remove names

* Clippy

* Fmt

* Remove walls of comments

* List overlays from stack; Add debugging flag

Currently, the engine state ordering is somehow broken.

* Fix (?) overlay list test

* Fix tests on Windows

* Fix activated overlay ordering

* Check for active overlays equality in overlay list

This removes the -p flag: Either both parser and engine will have the
same overlays, or the command will fail.

* Add merging on overlay remove

* Change help message and comment

* Add some remove-merge/discard tests

* (WIP) Track removed overlays properly

* Clippy; Fmt

* Fix getting last overlay; Fix predecls in overlays

* Remove merging; Fix re-add overwriting stuff

Also some error message tweaks.

* Fix overlay error in the engine

* Update variable_completions.rs

* Adds flags and optional arguments to view-source (#5446)

* added flags and optional arguments to view-source

* removed redundant code

* removed redundant code

* fmt

* fix bug in shell_integration (#5450)

* fix bug in shell_integration

* add some comments

* enable cd to work with directory abbreviations (#5452)

* enable cd to work with abbreviations

* add abbreviation example

* fix tests

* make it configurable

* make cd recornize symblic link (#5454)

* implement seq char command to generate single character sequence (#5453)

* add tmp code

* add seq char command

* Add split number flag in `split row` (#5434)

Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com>

* Add two more overlay tests

* Add ModuleId to OverlayFrame

* Fix env conversion accidentally activating overlay

It activated overlay from permanent state prematurely which would
cause `overlay add` to misbehave.

* Remove unused parameter; Add overlay list test

* Remove added traces

* Add overlay commands examples

* Modify TODO

* Fix $nu.scope iteration

* Disallow removing default overlay

* Refactor some parser errors

* Remove last overlay if no argument

* Diversify overlay examples

* Make it possible to update overlay's module

In case the origin module updates, the overlay add loads the new module,
makes it overlay's origin and applies the changes. Before, it was
impossible to update the overlay if the module changed.

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com>
Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
Co-authored-by: WindSoilder <WindSoilder@outlook.com>
Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-08 07:39:22 +12:00
1cb449b2d1 Database commands (#5466)
* change query to statement

* internal functions and over definitions

* cargo fmt
2022-05-07 13:33:33 +01:00
6cc66c8afd complete some commands tests (#5464)
* complete hash test

* unignore source relative tests
2022-05-07 06:23:49 -05:00
08e495ea67 Enable string interpolation for environment shorthand (#5463) 2022-05-07 06:21:29 -05:00
b0647f780d nu-cli/completions: send original line to custom completer (#5459) 2022-05-06 16:58:42 -05:00
2dfd975940 add -n flag to print to print without a newline (#5458)
* add -n flag to print to print without a newline

* clippy
2022-05-06 15:33:00 -05:00
fbdb125141 Add split number flag in split row (#5434)
Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-06 10:53:02 -05:00
c2ea993f7e implement seq char command to generate single character sequence (#5453)
* add tmp code

* add seq char command
2022-05-06 10:40:02 -05:00
e14e60dd2c make cd recornize symblic link (#5454) 2022-05-06 10:39:48 -05:00
768ff47d28 enable cd to work with directory abbreviations (#5452)
* enable cd to work with abbreviations

* add abbreviation example

* fix tests

* make it configurable
2022-05-06 07:58:32 -05:00
78a1879e36 fix bug in shell_integration (#5450)
* fix bug in shell_integration

* add some comments
2022-05-05 10:10:03 -05:00
0b9c0fea9d Adds flags and optional arguments to view-source (#5446)
* added flags and optional arguments to view-source

* removed redundant code

* removed redundant code

* fmt
2022-05-05 06:37:56 -05:00
Tom
02a3430ef0 Use correct ParseError (#5431) 2022-05-05 07:41:32 +12:00
6623ed9061 sometimes you want a text output (#5441) 2022-05-04 14:12:23 -05:00
48cf103439 Allowed for view-source to include entire custom command definition (#5435)
* allowed for view-source to include entire custom command definition

* fmt

* clippy
2022-05-04 06:35:09 -05:00
1bcb87c48d Update rust version (#5432) 2022-05-04 13:56:31 +12:00
JT
da104050e6 Update release.yml 2022-05-04 09:50:33 +12:00
JT
d306b834ca Bump to 0.62 (#5422) 2022-05-04 09:01:27 +12:00
d4371438d1 Pin reedline to v0.5.0 for the next release (#5427)
Release notes: https://github.com/nushell/reedline/releases/tag/v0.5.0

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
2022-05-04 08:11:31 +12:00
6a972312d4 added open editor event in config parsing (#5426) 2022-05-04 07:52:53 +12:00
ac48f5a318 Fix coloring when string has spaces (#5425)
* Replace ansi-cut with ansi-str

There's no issues with it we just need to use it later.

Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>

* Fix color losing in string spliting into Sublines

Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>
2022-05-03 09:48:43 -05:00
JT
e36649f74b Update path completions to handle spaces (#5419) 2022-05-03 12:37:38 +12:00
1a52460695 Database commands (#5417)
* dabase access commands

* select expression

* select using expressions

* cargo fmt

* alias for database

* database where command

* expression operations

* and and or operators

* limit and sort by commands
2022-05-03 06:38:18 +12:00
ab98ecd55b Fix erroneous removal of "./" folder prefix (#5416) 2022-05-02 12:36:18 -05:00
9a8e939cbe remove ctrl-l from config.nu (#5415) 2022-05-02 08:31:52 -07:00
bb27b9f371 Don't resuggest accepted completions (#5369)
To avoid resuggesting the same completion, add a space after commands or flags that have been accepted via `Enter`. Don't do that for filepaths or external completions

* Add append_whitespace choice for suggestion

Signed-off-by: gipsyh <gipsyh.icu@gmail.com>

* Fixed `test <path>` appending space.

* Update reedline

Co-authored-by: sholderbach <sholderbach@users.noreply.github.com>
2022-05-02 11:35:37 +02:00
1ca3063ac3 Fix CI to run doctests again (#5410)
The faster `cargo nextest` currently doesn't support running the doctests.

Thus, add an additional step for them with cargo's default test runner.

- Fix doctests for the `nu-pretty-hex` crate
2022-05-02 11:32:57 +02:00
7c9a78d922 Fixed ctrl-c in recursion loop bug #5362 (#5409) 2022-05-02 20:18:25 +12:00
49cbc30974 Add ends-with operator and fix dataframe operator behavior (#5395)
* add ends-with operator

* escape needles in dataframe operator regex patterns
2022-05-02 20:02:38 +12:00
07a7bb14bf Fixed interrupting a for-loop over a list bug #5378 (#5408)
Signed-off-by: gipsyh <gipsyh.icu@gmail.com>
2022-05-02 19:56:37 +12:00
74f1c5b67b CI: Add plugins job (#5406) 2022-05-02 19:20:57 +12:00
3b0151aba6 event ClearScrollback is now working in reedline / update default config.nu (#5405) 2022-05-02 19:20:24 +12:00
JT
4a69819f9a Rename =^ to 'starts-with' (#5407) 2022-05-02 19:20:07 +12:00
1f7d3498cd Bump reedline (#5404)
- Fix to the `ClearScrollback` command
- Fix of vi mode `x` so it adds the character to the clipboard
- Vi mode shorthands `s` and `S`
2022-05-02 13:14:24 +12:00
f0b9dc9da1 CI: build virtualenv tests in dev profile for speed (#5396) 2022-05-02 10:01:36 +12:00
JT
96f8691c8d More escaping/unescaping fixes (#5403) 2022-05-02 09:49:31 +12:00
07255e576d Add Miette "fancy" feature to fix plugin builds (#5402) 2022-05-02 08:52:49 +12:00
260be40774 Update reedline to use partial completion changes (#5401) 2022-05-02 08:41:25 +12:00
JT
14c9bd44ef Adds error printing back in a couple places (#5400) 2022-05-02 08:40:46 +12:00
JT
92785ab92c Add unescaping to external command parsing (#5399) 2022-05-02 07:26:29 +12:00
JT
98ab31e15e Move uses of trim_quotes to unescape for filenames (#5398)
* Move uses of trim_quotes to unescape for filenames

* Fix Windows tests
2022-05-02 06:37:20 +12:00
80d57d70cd a little database cleanup (#5394) 2022-05-01 07:44:29 -05:00
8dc199d817 Fix PATH update example (#5393) 2022-05-01 14:53:59 +03:00
435693a8bb Line buffer keybinding (#5390)
* dabase access commands

* select expression

* select using expressions

* cargo fmt

* change keybinding
2022-05-01 08:59:49 +01:00
5077242892 Error printing changes for watch (#5389)
* Move CliError to nu-protocol

clean up comment

* Enable printing errors instead of just returning them

* Nicer Miette error printing in watch command
2022-05-01 19:33:41 +12:00
7a7aa310aa Remove 'empty' block support reminders, for now. (#5214) 2022-04-30 22:32:30 -05:00
07893e01c1 Remove "./" prefix for file path completions (#5387) 2022-04-30 16:54:04 -05:00
JT
f16401152b Make if else more lazy (#5386) 2022-05-01 09:13:21 +12:00
3df03e2e6d nu-cli/completions: complete external args as filepath (#5385) 2022-05-01 08:07:09 +12:00
7c6f976d65 nu-cli/completions: apply correctly nesting for env vars (#5382) 2022-04-30 14:14:04 -05:00
ae9c0fc138 Fix quoting for command line args (#5384)
* Fix quoting for command line args

* Replace custom quoting with escape_quote_string

* Use raw string for now
2022-04-30 13:23:05 -05:00
9da2e142b2 Line buffer editor (#5381)
* allow line editing

* cargo fmt
2022-04-30 15:40:41 +01:00
5999506f87 allows for nushell to have tables without the index column (#5380) 2022-04-30 09:07:46 -05:00
1fc7abcc38 Faster CI (#5374)
* More-parallel CI

* Split all+default caches

* Rename ci job to build-clippy

* cargo nextest

* Remove fmt from tests
2022-04-29 22:48:04 +03:00
2659ea3dbd Revert "nu-cli/completions: better fix for files with special characters (#5254)" (#5372)
This reverts commit 3cf3329e49.
2022-04-29 13:11:41 -05:00
fa27110651 Avoid using time conversion methods that may panic (#5365) 2022-04-29 06:03:39 -05:00
b4f8798a3a rust-cache fix (#5359)
* Enable CI on merges to main

* Re-enable rust-cache for virtualenv tests
2022-04-28 17:57:26 -05:00
7714956276 CI: remove rust-cache from virtualenv tests (#5358) 2022-04-28 15:27:18 -05:00
8e5cc655e9 cleanup version command and add in database feature (#5356)
* cleanup version command and add in database feature

* static-link-openssl
2022-04-28 15:25:04 -05:00
c78e28511d CI: make Clippy reuse build artifacts, other cleanup (#5357)
* CI: move clippy after build so it can reuse build artifacts

* CI: Remove unused rustfmt+clippy from venv
2022-04-28 14:39:21 -05:00
f189369fd7 Change description of sort (#5355) 2022-04-28 14:33:26 -05:00
2516305fa8 CI: enable rust-cache, remove minimal (#5354)
* Enable rust-cache

Add cache buster key

Add rust-cache to python venv

* Remove minimal CI
2022-04-28 13:18:27 -05:00
f2d7454330 Add watch command (#5331) 2022-04-28 09:26:34 -05:00
3cf3329e49 nu-cli/completions: better fix for files with special characters (#5254)
* nu-cli/completions: fix paths with special chars

* add backticks

* fix replace

* added single quotes to check list

* check escape using fold

* fix clippy errors

* fix comment line

* fix conflicts

* change to vec

* skip sort checking

* removed invalid windows path

* remove comment

* added tests for escape function

* fix fn import

* fix fn import error

* test windows issue fix

* fix windows backslash path in the tests

* show expected path on error

* skip test for windows
2022-04-28 08:36:32 -05:00
d2bc2dcbb2 Openssl feature (#5352)
* Move statically linked OpenSSL behind a feature

* Re-add README.txt for releases
2022-04-28 06:33:17 -05:00
4ec4649903 mute false import warning for nu-command test where_ (#5350) 2022-04-27 22:45:39 -07:00
55e5106695 Statically link OpenSSL (#5349) 2022-04-28 12:25:09 +12:00
5f35e4ad1e improve inc plugin docs (#5346)
This is a convenience for anyone using GitHub features to copy paste directly into your local shell
2022-04-27 18:56:32 -05:00
e7831d38ae fixes an issue with an empty selector panic (#5345)
* fixes an issue with an empty selector panic

* missed web_tables

* oops, missed a test
2022-04-27 07:38:36 -05:00
5c9fe85ec4 Database commands (#5343)
* dabase access commands

* select expression

* select using expressions

* cargo fmt
2022-04-27 11:52:31 +01:00
cd5199de31 db info tweaks (#5338)
* Rename db info to db schema

* Change db schema to take db as input
2022-04-26 18:16:46 -05:00
5319544481 db info command (#5335)
* db info WIP

* working now

* clippy
2022-04-26 14:20:59 -05:00
JT
be3f0edc97 Fix 'range' range exclusive (#5334) 2022-04-26 13:39:38 -05:00
fb8f7b114e Fix use of export/alias --help bug (#5332)
* fix alias --help bug

Signed-off-by: SuYuheng <yuheng.su@motiong.com>

* fix export --help bug

Signed-off-by: SuYuheng <yuheng.su@motiong.com>

Co-authored-by: SuYuheng <yuheng.su@motiong.com>
2022-04-26 11:51:49 -05:00
187f2454c8 Move print_pipeline_data to nu-protocol (#5328) 2022-04-26 11:44:57 +12:00
JT
3492d4015d Allow bare words to interpolate (#5327)
* Allow bare words to interpolate

* fix highlighting
2022-04-26 11:44:44 +12:00
190f379ff3 activates optional trim in 'from csv' and 'from tsv' (#5326) 2022-04-25 12:54:14 -05:00
5c2bc73d7b Allows cd (and other commands that depend on current working directory) to use path of type '~user' (#5323)
* Added search terms to math commands

* Attempts to add ~user.

From: // Extend this to work with "~user" style of home paths

* Clippy recommendation

* clippy suggestions, again.

* fixing non-compilation on windows and macos

* fmt apparently does not like my imports

* even more clippy issues.

* less expect(), single conversion, match. Should work for MacOS too.

* Attempted to add functionality for windows: all it does is take the home path of current user, and replace the username.

* silly mistake in Windows version of user_home_dir()

* Update tilde.rs

* user_home_dir now returns a path instead of a string - should be smoother with no conversions to string

* clippy warnings

* clippy warnings 2

* Changed user_home_dir to return PathBuf now.

* Changed user_home_dir to return PathBuf now.

* forgot to fmt

* fixed windows build errors from modifying pathbuf but not returning it

* fixed windows clippy errors from returning () instead of pathbuf

* forgot to fmt

* borrowed path did not live long enough.

* previously, path.push did not work because rest_of_path started with "/" - it was not relative. Removing the / makes it a relative path again.

* Issue fixed.

* Update tilde.rs

* fmt.

* There is now a zero chance of panic. All expect()s have been removed.

* Patched join_path_relative to accommodate ~user paths. Previously, /some/path/~user might have been passed on; now, ~user is taken as absolute.

* fmt

* clippy errors
2022-04-25 06:01:48 -05:00
aeed8670f1 add database feature to extra (#5322) 2022-04-24 18:26:56 -05:00
b38f90d4c7 Adding ~user tilde recognition in file paths (#5251)
* Added search terms to math commands

* Attempts to add ~user.

From: // Extend this to work with "~user" style of home paths

* Clippy recommendation

* clippy suggestions, again.

* fixing non-compilation on windows and macos

* fmt apparently does not like my imports

* even more clippy issues.

* less expect(), single conversion, match. Should work for MacOS too.

* Attempted to add functionality for windows: all it does is take the home path of current user, and replace the username.

* silly mistake in Windows version of user_home_dir()

* Update tilde.rs

* user_home_dir now returns a path instead of a string - should be smoother with no conversions to string

* clippy warnings

* clippy warnings 2

* Changed user_home_dir to return PathBuf now.

* Changed user_home_dir to return PathBuf now.

* forgot to fmt

* fixed windows build errors from modifying pathbuf but not returning it

* fixed windows clippy errors from returning () instead of pathbuf

* forgot to fmt

* borrowed path did not live long enough.

* previously, path.push did not work because rest_of_path started with "/" - it was not relative. Removing the / makes it a relative path again.

* Issue fixed.

* Update tilde.rs

* fmt.

* There is now a zero chance of panic. All expect()s have been removed.
2022-04-24 17:12:57 -05:00
9771270b38 Fuzzy completion matching (#5320)
* Implement fuzzy match algorithm for suggestions

* Use MatchingAlgorithm for custom completions
2022-04-24 16:43:18 -05:00
f6b99b2d8f update build status badge (#5321) 2022-04-24 16:28:54 -05:00
JT
ec611526ac Warn if we see let config = ../.. (#5318) 2022-04-25 08:40:55 +12:00
cd2df83ddc nu-command/filesystem: clean whitespaces from paths in cd and open (#5310) 2022-04-25 07:15:33 +12:00
3eb447030b update contrib to max=500 (#5317) 2022-04-24 13:03:20 -05:00
f2a45b3eac Update ci.yml 2022-04-24 08:03:21 -05:00
e94d13da1b Database commands (#5307)
* database commands

* db commands

* filesystem opens sqlite file

* clippy error

* corrected error in ci file

* removes matrix flag from ci

* flax matrix for clippy

* add conditional compile for tests

* add conditional compile for tests

* correct order of command

* correct error msg

* correct typo
2022-04-24 10:29:21 +01:00
c20ba95885 fix: remove println!() from exec builtin (#5311) 2022-04-24 15:24:44 +12:00
8eab311565 consolidate shell integration behind config setting (#5302)
* consolidate shell integration behind config setting

* write output differently
2022-04-24 12:53:12 +12:00
e2b510b65e update sys with new items, add kernel version to os-info (#5308)
* update sys with new items, add kernel version to os-info

* clippy
2022-04-23 16:33:27 -05:00
e6a70f9846 Add MatchAlgorithm for completion suggestions (#5244)
* Pass completion options to each fetch() call

* Add MatchAlgorithm to CompletionOptions

* Add unit test for MatchAlgorithm

* Pass completion options to directory completer
2022-04-23 10:01:19 -05:00
667eb27d1b feat: add search terms to date (#5306)
* add search terms

* add search terms

* add search terms

* add search terms

* add search terms

* add search terms

* add search terms

* add search terms

* add search patterns

* run cargo fmt --all
2022-04-23 08:54:03 -05:00
b9eb213f36 nu-cli/completions: added completion for $nu (#5303) 2022-04-23 11:49:17 +12:00
JT
cc78446ffd Fix cd - (#5301) 2022-04-23 11:48:10 +12:00
5ff2ae628b nu-cli: directory syntax shape + completions (#5299) 2022-04-22 15:18:51 -05:00
661283c4d2 nu-cli/completions: support record for custom completions (#5298) 2022-04-22 15:17:08 -05:00
JT
ee29a15119 Add 'and' and 'or' operators (#5297) 2022-04-23 07:14:31 +12:00
2a18206771 add virtualenv to integrations (#5280) 2022-04-21 06:50:32 -05:00
a26272b44b Clean up tests and unused documentation code (#5273)
* Delete unused documentation code+test

* Fix up test to account for new select behavior
2022-04-21 06:13:58 -05:00
7e730e28bb Delete obsolete+unused files (#5272) 2022-04-21 17:56:56 +12:00
JT
96253c69fb Use better quoting for commandline args (#5271) 2022-04-21 15:31:52 +12:00
JT
ded9d1cedb Some cleanups for clippy (#5266) 2022-04-21 12:08:12 +12:00
d1cc70fc4a update os-info os to name (#5265) 2022-04-21 10:36:39 +12:00
18c9b62b00 git completion: 'git fetch' for remotes (#5253) 2022-04-21 07:52:44 +12:00
1295495758 typo: seach -> search (#5264) 2022-04-21 07:38:24 +12:00
e97ba9b74c feat: add search terms for conversions (#5259) 2022-04-20 11:48:32 -05:00
09b972f1dc add newlines to end of the default configs (#5256) 2022-04-20 07:56:15 -07:00
0fb6f8f93c refactor html module (#5246)
* refactor around html module

* Update html.rs

fix clippy warning

* minify json
2022-04-20 08:50:14 -05:00
995d8db1fe Set to reedline main branch for development cycle (#5249)
Changes to reedline since `v0.4.0`:

- vi normal mode `I` for inserting at line beginning
- `InsertNewline` edit command that can be bound to `Alt-Enter` if
desired to have line breaks without relying on the `Validator`
- `ClearScreen` will directly clear the visible screen. `Signal::CtrlL` has been
removed.
- `ClearScrollback` will clear the screen and scrollback. Can be used to
mimic macOS `Cmd-K` screen clearing. Helps with #5089
2022-04-20 21:10:33 +12:00
7e97be1dd4 Handle custom values in describe command (#5248) 2022-04-20 16:59:53 +12:00
b501db673a SQLite overhaul: custom value, query db command (#5247)
Clean up query errors
2022-04-20 16:58:21 +12:00
c0ce1e9057 nu-cli/completions: fix file completions with quotes (#5242)
* nu-cli/completions: fix file completions with quotes

* wrap with backticks
2022-04-20 16:54:37 +12:00
4d7b86f278 nu-cli: added tests for file completions (#5232)
* nu-cli: added tests for file completions

* test adding extra sort

* Feature/refactor completion options (#5228)

* Copy completion filter to custom completions

* Remove filter function from completer

This function was a no-op for FileCompletion and CommandCompletion.
Flag- and VariableCompletion just filters with `starts_with` which
happens in both completers anyway and should therefore also be a no-op.
The remaining use case in CustomCompletion was moved into the
CustomCompletion source file.

Filtering should probably happen immediately while fetching completions
to avoid unnecessary memory allocations.

* Add get_sort_by() to Completer trait

* Remove CompletionOptions from Completer::fetch()

* Fix clippy lints

* Apply Completer changes to DotNuCompletion

* add os to $nu based on rust's understanding (#5243)

* add os to $nu based on rust's understanding

* add a few more constants

Co-authored-by: Richard <Tropid@users.noreply.github.com>
Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2022-04-20 16:54:00 +12:00
f2d47f97da add os to $nu based on rust's understanding (#5243)
* add os to $nu based on rust's understanding

* add a few more constants
2022-04-19 14:11:58 -05:00
0de289f6b7 Feature/refactor completion options (#5228)
* Copy completion filter to custom completions

* Remove filter function from completer

This function was a no-op for FileCompletion and CommandCompletion.
Flag- and VariableCompletion just filters with `starts_with` which
happens in both completers anyway and should therefore also be a no-op.
The remaining use case in CustomCompletion was moved into the
CustomCompletion source file.

Filtering should probably happen immediately while fetching completions
to avoid unnecessary memory allocations.

* Add get_sort_by() to Completer trait

* Remove CompletionOptions from Completer::fetch()

* Fix clippy lints

* Apply Completer changes to DotNuCompletion
2022-04-19 13:59:10 -05:00
JT
ae674bfaec move config back to config.nu (#5237) 2022-04-19 20:54:25 +12:00
JT
76079d5183 Move config to be an env var (#5230)
* Move config to be an env var

* fix fmt and tests
2022-04-19 10:28:01 +12:00
409f1480f5 allow par-each to receive $in (#5229)
Co-authored-by: Yethal <nosuchemail@email.com>
2022-04-19 10:02:58 +12:00
e206555d9d add custom_completion field to .scope command (#5227) 2022-04-19 10:02:03 +12:00
88ec4186ec Added search terms to math commands (#5224) 2022-04-19 09:33:32 +12:00
dd1d9b7623 nu-cli/completions: completion for use and source (#5210)
* nu-cli/completions: completion for use and source

* handle subfolders for different base dirs

* fix clippy errors
2022-04-19 00:59:13 +12:00
1314a87cb0 update miette and switch to GenericErrors (#5222) 2022-04-19 00:34:10 +12:00
cf65f77b02 Simplify known external tests (#5219)
* Simplify known external tests

* Cargo fmt
2022-04-17 14:31:03 -05:00
c9f05f074a nth -> select command (#5217) 2022-04-17 09:54:24 -05:00
7710317224 Add known external tests (#5216)
* Add known external tests

* Add some documentation to the tests

* Document test_hello example

* Set PWD in run_test
2022-04-17 05:39:56 -05:00
0a990ed105 Simplify known external name recovery (#5213)
Prior to this change we would recover the names for known
externals by looking up the span in the engine state. This would fail
when using an alias for two reasons:

1. In cases where we don't have a subcommand, like this:

```
>>> extern bat [filename: string]
>>> alias b = bat
>>> bat some_file
'b' is not recognized as an internal or external command,
operable program or batch file.
```

The problem is that after alias expansion, we replace the span of the
expanded name with the original alias (this is done to alleviate
non-related issues). The span contents we look up therefore contain `b`,
the alias, instead of the expanded command name.

2. In cases where there's a subcommand:
```
>>> alias g = git
>>> g push
thread 'main' panicked at 'internal error: span missing in file contents cache', crates\nu-protocol\src\engine\engine_state.rs:474:9
note: run with `RUST_BACKTRACE=1` environment variable to display a
backtrace
```

In this case, the span in call starts where the expansion for the `g`
alias is defined and end after `push` on the last command entered. This
is not a proper span and causes a panic when we try to look it up. Note
that this is the case for all expanded aliases that involve a
subcommand, but we never actually try to retrieve the contents for that
span in other cases.

Anyway, the new way of looking up the name is arguably cleaner
regardless of the issues mentioned above. But it's nice that it fixes
them too.

Co-authored-by: Hristo Filaretov <h.filaretov@protonmail.com>
2022-04-16 22:07:38 -05:00
a35b975d84 Shell Integration (#5162)
This commit renders ANSI chars in order to provide shell integrations
such Kitty's opening feature that captures the output of the last
command in a pager such as less.

Fixes #5138
2022-04-16 22:03:02 -05:00
6e85b04923 [ls, path relative-to] Fix use of ls ~ | path relative-to ~ (#5212)
* [ls] implement 1b.

> `ls ~` does not return paths relative to the current directory.

We now return `/Users/blah` instead of `../../blah`

* expand lhs and rhs on `path relative-to`

/Users/nimazzuc/projects/nushell〉'~' | path relative-to '~'
/Users/nimazzuc/projects/nushell〉'~/foo' | path relative-to '~'
foo
/Users/nimazzuc/projects/nushell〉'/Users/nimazzuc/foo' | path relative-to '~'
foo
/Users/nimazzuc/projects/nushell〉'~/foo' | path relative-to '/Users/nimazzuc'
foo

* format
2022-04-16 15:05:42 -05:00
4d31139a44 add hex color parsing to ansi (#5209) 2022-04-16 10:44:04 -05:00
1bad40726d cleanup nu-command, remove redundant code (#5208) 2022-04-16 18:16:46 +12:00
cb3276fb3b nu-cli/completions: removed unnecessary bool (#5207) 2022-04-16 13:34:38 +12:00
c17129a92a Fix env capture (#5205)
* Fix env capture

* Add test for env capture
2022-04-16 10:38:27 +12:00
JT
5bf1c98a39 Move to dev version 0.61.1 (#5206) 2022-04-16 09:29:30 +12:00
13b371ab58 nu-cli/completions: add completion for record vars (#5204) 2022-04-16 08:24:41 +12:00
2a3991cfdb nu-cli/completions: add completion for $env. (#5199)
* nu-cli/completions: add completion for $env.

* use stack to avoid showing hidden env vars
2022-04-15 16:17:53 +03:00
583b7b1821 fix: reduce command have not redirected block's evaluation output (#5193)
fixes https://github.com/nushell/nushell/issues/5190
2022-04-15 07:03:16 -05:00
581afc9023 updated cargo.lock with cargo update (#5201) 2022-04-15 06:04:15 -05:00
8e2847431e Avoid duplicating post headers (#5200)
* Avoid duplicating post headers

This should fix #5194

* Update post.rs

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2022-04-15 06:02:22 -05:00
6a1378c1bb Update README.md 2022-04-15 05:27:42 -05:00
2fe14a7a5a fix timestamp parsing on 32-bit platforms (#5192)
Fixes #5191
2022-04-14 08:52:32 -05:00
7490392eb9 Add char -i for chars from integers (#5183)
* Revert "Allow integer to `char -u` (#5174)"

This reverts commit cfefb65d55.

* Add `char -i`

* Reword example
2022-04-14 08:34:02 -05:00
9844e6125b Fix completions for git push and git checkout close: #5021 and #4599 (#5188) 2022-04-14 08:17:58 -05:00
56af7e8d5f tweak badge (#5187)
added `?branch=main?event=push` to see if it makes any difference.
2022-04-14 06:48:17 -05:00
dc612e7ffb documented ShellError errors. (#5172)
* documented ShellError errors.

* just a few touch-ups

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
2022-04-14 17:08:46 +12:00
1d1dbfd04c update crate chrono-tz to its latest version (#5184) 2022-04-13 21:16:08 -07:00
c150e11cb4 Initial SQLite functionality (#5182)
* Add SQLite functionality to open

* Add in-memory SQLite tests

* clippy fixes

* Fix up old SQLite-related tests
2022-04-13 20:15:02 -07:00
87c684c7da don't join paths to cwd ever in calls to external functions (#5180)
This is a follow-up to #5131, since I don't personally like the way it worked.
2022-04-13 21:42:57 +03:00
10792a29f7 allow default color shortcut names (#5177)
* allow default color shortcut names

* clippy
2022-04-13 07:02:15 -05:00
257290acc2 Add a dockerfile example based on debian bullseye-slim (#5176)
* feat: add nu dockerfile, based on debian bullseye

* use aria2 instead of wget for bad network

* some small fix
2022-04-13 14:48:54 +03:00
cfefb65d55 Allow integer to char -u (#5174) 2022-04-13 13:33:08 +03:00
3783c19d02 bump miette to 4.4.0 (#5167)
This fixes an issue where docsrs error links were not working.

Ref: https://github.com/zkat/miette/issues/147
2022-04-13 08:38:15 +12:00
1f6e0255c0 Fix typo in link (#5168)
skip-checks:true
2022-04-12 22:13:40 +02:00
JT
b61af9a26a Update README.md 2022-04-13 06:24:46 +12:00
JT
6e2f6c71fe Update README.md 2022-04-13 06:15:34 +12:00
JT
f51d5789a3 Update README.md 2022-04-13 06:15:09 +12:00
JT
933cee27ae Update README.md 2022-04-13 06:12:33 +12:00
JT
4566c904d0 Bump 0.61 (#5166) 2022-04-13 05:42:26 +12:00
9b020c056b Pin reedline version for 0.61 release (#5164) 2022-04-13 04:38:36 +12:00
JT
60b5863058 Remove the im crate dependency (#5161) 2022-04-12 07:01:05 +12:00
836f914163 Clean REPL code, hide Hints without ANSI coloring (#5157)
- With a change to reedline hints can now be hidden. This is useful when
no ANSI coloring is available as hints become indistinguishable from the
actual buffer
- remove commented out code
- order the logging calls according to the implementation
2022-04-12 06:19:42 +12:00
594006cfa0 Fix failing unit tests on Windows (#5142) (#5143)
* Fix failing unit tests on Windows (#5142)

Fix let_env_expressions failing on Windows:
The env expression uses PATH, but on windows Path is used.

Fix correctly_escape_external_arguments, execute_binary_in_string
failing on Windows:
Using cococo now to make sure testresults are platform independent

* Update macros.rs

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
2022-04-12 06:18:46 +12:00
57761149f4 Update incorrect crate descriptions (#5159) 2022-04-12 06:17:06 +12:00
521e28dcdc fix #5131 (#5153)
I don't personally agree with this; I'd prefer less magic,
and not expanding _anything_ except `~` as an initial path element

Co-authored-by: nicole mazzuca <mazzucan@outlook.com>
2022-04-11 20:05:39 +12:00
a30930324d Support binary literals with binary format (#5149)
* 4924 Support binary literals with binary format

* 4924 Support automatic padding for binary literals
2022-04-11 19:58:57 +12:00
625e807a35 Support unbinding a particular key event (#5152)
To remove a default keybinding for a particular edit mode, set the `event: null`:

e.g. to disable screen clearing with Ctrl-L

```
let $config = {keybindings: [{
        modifier: control
        keycode: char_l
        mode: [emacs, vi_normal, vi_insert]
        event: null
      } ]}

```
2022-04-10 23:54:09 +02:00
d18f34daa4 Allow overriding of menu keybindings (#5148)
Keybindings that were attached to menus like `Ctrl-x` or `Ctrl-q` could not be replaced with custom bindings
2022-04-10 22:48:55 +02:00
JT
4fd73ef54a Allows aliases in use lists (#5150) 2022-04-11 07:37:22 +12:00
58f395989a Remove unused dependencies (#5145)
* Remove unused packages from base Cargo.toml

* Remove unused crossterm_winapi from nu-cli

* Remove unused dependencies from nu-system

* Remove unused dependencies from nu-test-support
2022-04-10 09:14:55 +12:00
791e8a0e59 enable ls to output datetime in local time vs utc (#5141)
* enable `ls` to output datetime in local time vs utc

* clippy
2022-04-09 11:39:41 -05:00
JT
14066ccc30 Fix known externals, fix operator spans (#5140) 2022-04-09 17:17:48 +12:00
683b912263 Track call arguments in a single list (#5125)
* Initial implementation of ordered call args

* Run cargo fmt

* Fix some clippy lints

* Add positional len and nth

* Cargo fmt

* Remove more old nth calls

* Good ole rustfmt

* Add named len

Co-authored-by: Hristo Filaretov <h.filaretov@protonmail.com>
2022-04-09 14:55:02 +12:00
3bac480ca0 rename menu/fix type-o (#5139) 2022-04-08 20:22:33 -05:00
JT
97eb8492a3 Improve $in handling (#5137)
* Simplify in logic

* Add tests

* more tests, and fixes
2022-04-09 09:41:05 +12:00
JT
0892a16a3d Let 'each' also send input to block (#5136) 2022-04-09 07:57:43 +12:00
JT
0b85938415 Soften the block arity checking (#5135) 2022-04-09 07:57:27 +12:00
aaec840b91 doc change from engine-q to nushell (#5134) 2022-04-08 10:29:21 -07:00
74d0f19291 added ability to opt in to normal string replacement in replace cmd (#5133)
* added ability to opt in to normal string replacement in `replace` cmd

* type-o
2022-04-08 12:23:16 -05:00
JT
7ce570e52c Update LICENSE
this isn't our crate originally, we adapted it
2022-04-08 21:53:29 +12:00
JT
3a0eded0b8 Delete LICENSE
this is dual-licensed, there can't be just one LICENSE file
2022-04-08 21:51:25 +12:00
JT
5afd45414e Revert "nu-cli/completions: cache layer for fetching (#5114)" (#5132)
This reverts commit e86c1b118e.
2022-04-08 21:48:27 +12:00
6ed033737d Include license text in all crates (#5094)
* Include license text in all crates

Three crates already have license texts, so I'm keeping them, but
symlinking the `LICENSE` from the top level to the rest of the crate
directories. This works as long as `cargo publish` is done on a Unix-y
system and not Windows.

Also bump the copyright year to end in 2022.

Signed-off-by: Michel Alexandre Salim <salimma@fedoraproject.org>

* Replace symlinks

Co-authored-by: sholderbach <sholderbach@users.noreply.github.com>
2022-04-08 10:47:13 +02:00
d38a3a8b4e Fix command descriptions+examples (#5129)
* Fix exit usage

* Move dfr as-date* format examples to extra_usage

* Update command usage and examples

* More docs on `str trim`

Co-authored-by: sholderbach <sholderbach@users.noreply.github.com>
2022-04-08 10:30:49 +02:00
6b4cb8b0e0 short descriptions (#5130) 2022-04-08 07:57:39 +01:00
48fa25fd42 nu-cli/completions: removed default filter for command (#5126) 2022-04-07 18:45:04 -05:00
bdfad6b1de add keep deprecated commands (#5124) 2022-04-08 10:10:46 +12:00
JT
4f974efeba Move 'keep' to 'take' (#5123) 2022-04-08 08:49:28 +12:00
e86c1b118e nu-cli/completions: cache layer for fetching (#5114) 2022-04-08 07:36:16 +12:00
5e177fe8e7 nu-cli/completions: fix file completions filtering (#5122) 2022-04-08 07:31:56 +12:00
4129f15eb9 update str find-replace to str replace (#5120) 2022-04-07 08:41:09 -05:00
690ec9abfa Implement rest of touch flags (#5119)
* Add timestamp flag to `touch` command

* Add modify flag to `touch` command

* Add date flag to `touch` command

* Remove unnecessary `touch` test and fix tests setups

* Change `touch` flags descriptions

* Update `touch` example

* Add reference flag to `touch` command

* Add access flag to `touch` command

* Add no-create flag to `touch` command

* Replace `unwrap` with `expect`
2022-04-07 06:44:05 -05:00
b2c52b51b7 Change string contains operators to regex (#5117) 2022-04-07 18:23:14 +12:00
JT
888369022f Add datetime to math-like (#5118)
* Add datetime to math-like

* add test
2022-04-07 18:02:28 +12:00
JT
4409185e1b Improve describe to be more accurate (#5116) 2022-04-07 16:34:09 +12:00
JT
ef1934a7ee Remove external name exceptions (#5115) 2022-04-07 14:01:31 +12:00
JT
591fb4bd36 Add unary not (#5111) 2022-04-07 07:10:25 +12:00
12d3e4e424 Add env.nu file for environment config (#5099)
* Add env.nu file for environment config

* Add missing flag

* Add $nu.env-path variable

Prints `env.nu` path

* Add example of adding entries to PATH
2022-04-07 05:11:51 +12:00
c3bed1352a nu-cli/completions: prioritize non hidden folders (#5108) 2022-04-06 16:56:43 +01:00
3ceb39c82c use arc to avoid cloning entire engine for menus (#5104)
* use arc to avoid cloning entire engine for menus

* remove complete import path

* remove stack clone

* reference in completer
2022-04-06 13:25:02 +01:00
13869e7d52 nu-cli: refactor completions (#5102) 2022-04-06 19:58:55 +12:00
JT
121a4f06fb Load plugins for scripts and commands, too (#5105) 2022-04-06 19:45:26 +12:00
d0e636ae7a Trim newline from input results (#5097) 2022-04-05 12:52:09 -05:00
6e7e2dbb97 enables find to search records with regex (#5100)
* enables find to search records with regex

* clippy
2022-04-05 12:26:11 -05:00
d64cf1687e Fix Format for non-basic data types (#5095) 2022-04-05 07:45:38 -05:00
657b631fdc Add search terms to many commands (#5096) 2022-04-05 07:01:21 -05:00
fa6ed7a40b allow record as text style (#5092) 2022-04-04 22:36:48 +01:00
80f21d37e0 Update reedline to mut Completer API 2022-04-04 23:35:31 +02:00
e2cf4cc7d6 new glob command (#5087) 2022-04-05 08:45:01 +12:00
JT
abe028f930 Add raw strings, use raw strings for env (#5090) 2022-04-05 08:42:26 +12:00
ef1cf7e634 feature: Add some context to completions (#5078)
* send current line and position

* copy current line

* fix error

* deleted test completion
2022-04-05 06:31:40 +12:00
1e4b33b9c6 Add quiet and feedback to mv command (#5073)
* Add quiet and feedback to mv command

* replaced filter and map with filter_map
2022-04-05 06:30:51 +12:00
4654f03d31 update shadow-rs, update git2, remove indexmap from version (#5086) 2022-04-04 09:59:59 -05:00
608b6f3634 Generic menus (#5085)
* updated to reedline generic menus

* help menu with examples

* generic menus in the engine

* description menu template

* list of menus in config

* default value for menu

* menu from block

* generic menus examples

* change to reedline git path

* cargo fmt

* menu name typo

* remove commas from default file

* added error message
2022-04-04 15:54:48 +01:00
a86e6ce89b Set LAST_EXIT_CODE on parse error (#5084) 2022-04-04 06:11:27 -05:00
c4cfbaec2d Fix Python plugin (missing search terms) (#5083)
* Add search_terms to Python plugin

* Clean up Python plugin comments
2022-04-03 20:00:53 -05:00
d40109f210 Tweak append+prepend help (#5080) 2022-04-03 17:50:22 -05:00
20be8a4987 Fix for search terms in help --find (#5081)
* Fix search terms in help --find

* Update help --find description
2022-04-03 17:37:22 -05:00
d6dd4078b1 Remove enqine-q from issue template (#5075)
The notice is not necessary anymore since engine-q is merged now
2022-04-03 06:52:42 -05:00
JT
6649da3f5d Add support for single value row conditions (#5072) 2022-04-03 10:41:36 +12:00
62901573d0 update the readme in the docs folder (#5065)
* update docs/Readme

* tweak readme
2022-04-01 13:48:09 -07:00
JT
80c9888f82 Add command descriptions to completions (#5063) 2022-04-02 08:18:11 +13:00
19c3570cf9 Allow open to work with 'from ...' block commands (#5049)
* Remove panic from BlockCommands run function

Instead of panicing, the run method now returns an error to prevent
nushell from unexpected termination.

* Add ability to open command to run with blocks

The open command tries to parse the content of the file
if there is a command called 'from (file ending)'.  This works
fine if the command was 'built in' because the run method doesn't
fail in this case.  It did fail on a BlockCommand, though.

This change will first probe if the command contains a block and
evaluate it, if this is the case.  If there is no block, it will run
the command the same way as before.

* Add test open files with BlockCommands

* Update open.rs

* Adjust file type on open with BlockCommand parser

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
2022-04-02 07:52:32 +13:00
2cb815b7b4 Add starts with operator (#5061)
* add starts_with operator

* added a test
2022-04-01 13:35:46 -05:00
a088081695 update reedline (#5062) 2022-04-01 19:22:40 +01:00
JT
4bb95a880f let a simple last be a single value (#5060) 2022-04-01 23:12:31 +13:00
JT
9beecff736 Add 'date to-record' (#5058) 2022-04-01 21:09:30 +13:00
JT
fa0400c3f2 Fix sort signature (#5055) 2022-04-01 13:03:07 +13:00
JT
1d2d31580b Allow strings for prompt env vars (#5052) 2022-04-01 12:00:50 +13:00
JT
834f993547 Sort command (#5054) 2022-04-01 11:43:16 +13:00
2193910579 Update reedline to new constructor API (#5051) 2022-04-01 11:16:28 +13:00
f692da487e Fix load-env unsupported input error message (#5039) 2022-04-01 10:59:04 +13:00
0986c61a5d Lift line editor construction out of loop (#5041)
Enables the use of some features on reedline

- Keeping the line when clearing the screen with `Ctrl-L`
- Using the internal cut buffer between lines
- Submitting external commands via keybinding and keeping the line

Additional effect:

Keep the history around and do basic syncs (performance improvement
minimal as session changes have to be read and written)

Additional change:

Give the option to defer writing/rereading the history file to the
closing of the session ($config.sync_history_on_enter)
2022-03-31 23:25:48 +02:00
msp
6a6471b04b feat: add --suppress-output (-s) to input command (#5017)
* feat: add --suppress-output (-s) to input command

* Don't handle cursor position since existing impl doesn't

* Handle all raw mode outcomes
2022-03-31 14:20:31 -05:00
05f7d7d38b finish hooking up completion descriptions (#5047) 2022-03-31 11:13:16 -05:00
d89ad4fafd Add record, list, and table to signature types (#5040) 2022-03-31 11:11:03 +03:00
385bc40627 evaluate indicators as commands (#5026)
* evaluate indicators are commands

* default strings in config

* default multiline

* removed build string command
2022-03-31 06:22:55 +01:00
e2d24c5956 Fix which-support feature (#5038) 2022-03-30 13:37:31 -05:00
82633e2df7 update nu-glob README (#5037) 2022-03-30 10:44:23 -07:00
31a4fc41eb Fix env var shorthand when value contains = (#5022) 2022-03-30 09:56:55 +13:00
79182db587 Clean up which/which-support Cargo feature (#5019)
* Rename "which" feature to "which-support"

* Ignore currently broken environment tests
2022-03-29 06:10:43 -05:00
a2872b4ccc Strip '+ ' decoration in git branch list (#5016)
- '+' is the prefix for the current branch in some worktree

Closes #5014
2022-03-28 16:07:55 -05:00
JT
0afa18ac4a Use real stack during custom completion (#5010) 2022-03-29 06:49:41 +13:00
1aef3a730a fix: pass metadata to more filter commands for ls_colors (#5009)
* fix(filters): pass metadata for select

* fix(filters): pass metadata for group, window

* fix(filters): pass metadata for each, every

* fix(filters): pass metadata for collect, compact, flatten

* fix(filters): pass metadata for get

* fix: get rid of necessary `.clone()``

* style: rename closure call to be consistent w/ others

* fix(filters): pass metadata for par-each, prepend

* fix(filters): pass metadata for range

* fix(filters): pass metadata for reject

* fix(filters): pass metadata for more commands

* style: run cargo fmt
2022-03-28 06:43:09 -05:00
e934062542 corrects menu selection (#5004) 2022-03-28 20:43:27 +13:00
JT
2e3b74f1b2 Fix for loop ctrlc not terminating (#5003) 2022-03-28 19:13:43 +13:00
JT
a87f53072a See if levenshtein sorting feels goofor completions (#5001) 2022-03-28 13:31:31 +13:00
047081fa72 Add a README about changing capnp schema (#4998)
* Add a README about changing schema

* Add example PRs
2022-03-27 19:02:19 -05:00
5586d4a0a0 did_you_mean: case-insensitive edit distance, tests (#4999) 2022-03-27 17:11:56 -05:00
JT
911fba8a8a Help menu improvements (#4997)
* Help menu improvements

* default config
2022-03-27 15:21:40 -05:00
2873e943b3 Add search terms to Command and Signature (#4980)
* Add search terms to command

* Rename Signature desc to usage

To be named uniformly with extra_usage

* Throw in foldl search term for reduce

* Add missing usage to post

* Add search terms to signature

* Try to add capnp Signature serialization
2022-03-27 22:25:30 +03:00
0c9dd6a29a Update README.md for Rust 1.59 (#4995)
Since `Cargo.toml` now specifies `strip = ...`, and `strip` is only available in cargo >=1.59, specify that at least this version is required.
2022-03-28 07:28:04 +13:00
a4410fef40 Help menu (#4992)
* nu-completer with suggestions

* help menu with scrolling

* updates description rows based on space

* configuration for help menu

* update nu-ansi-term

* corrected test for update cells

* changed keybinding
2022-03-27 14:01:04 +01:00
0011f4df56 Check same-string-different-case in did_you_mean (#4991) 2022-03-27 19:21:39 +13:00
ee5064abed Nu ansi term update (#4988)
* WIP: Testing 0.45.1 nu-ansi-term with the new Default colors

* point reedline to git in cargo.toml
2022-03-27 16:57:31 +13:00
JT
82e3bb0f38 Bump nushell to 0.60.1 (#4987) 2022-03-27 16:18:47 +13:00
319930a1b9 Add streaming support to save for ExternalStream data (#4985)
* Add streaming support to save for ExternalStream data

Prior to this change, save would collect data from an ExternalStream (data
originating from externals) consuming memory for the full amount of data piped
to it,

This change adds streaming support for ExternalStream allowing saving of
arbitrarily large files and bounding memory usage.

* Remove broken save test

This test passes but not for the right reasons, since this test was
written filename has become a required parameter.  The parser outputs
an error but the test still passes as is checking the original un-mutated
file assuming save has re-written the contents.

This change removes the test.

```
running 1 test
=== stderr
Error: nu::parser::missing_positional (https://docs.rs/nu-parser/0.60.0/nu-parser/enum.ParseError.html#variant.MissingPositional)

  × Missing required positional argument.
   ╭─[source:1:1]
 1 │ open save_test_1/cargo_sample.toml | save
   ·                                          ▲
   ·                                          ╰── missing filename
   ╰────
  help: Usage: save {flags} <filename>

test commands::save::figures_out_intelligently_where_to_write_out_with_metadata ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 515 filtered out; finished in 0.10s
```
2022-03-27 15:39:27 +13:00
a64e0956cd Support binary data to stdin of run-external (#4984)
* Add test for passing binary data through externals

This change adds an ignored test to confirm that binary data is passed
correctly between externals to be enabled in a later commit along with
the fix.

To assist in platform agnostic testing of binary data a couple of
additional testbins were added to allow testing on `Value::Binary` inside
`ExternalStream`.

* Support binary data to stdin of run-external

Prior to this change, any pipeline producing binary data (not detected
as string) then feed into an external would be ignored due to
run-external only supporting `Value::String` on stdin.

This change adds binary stdin support for externals allowing something
like this for example:

  〉^cat /dev/urandom | ^head -c 1MiB | ^pv -b | ignore
  1.00MiB

This would previously output `0.00 B [0.00 B/s]` due to the data not
being pushed to stdin at each stage.
2022-03-27 15:35:59 +13:00
91e17d2f9f Limit mem usage + back-pressure via bounded channels (#4986)
Prior to this change, a pipeline of externals would result in high memory
usage if any of the producers in the chain, produced data faster than
the consumers.

For example a pipeline:

  > fast-producer | slow-consumer

Would cause a build up of `Value::{String,Binary}`'s in the mpsc channels
between each command as values are added to the channels faster than they
are consumed, eventually OOM'ing depnding on system resources, the volume
of data and speed diff. between fast v's slow.

This change replaces the unbounded channels with bounded channels
to limit the number of values that can build up and providing
back-pressure to limit ram usage.
2022-03-27 15:34:34 +13:00
56a546e73d fix ls when file is a socket on mac (#4983) 2022-03-26 21:26:39 -05:00
JT
cf88c8eef3 Improve escaping in string interpolation (#4982) 2022-03-27 12:52:09 +13:00
3484e0defd Add parser keyword note to help and $nu.scope (#4978) 2022-03-26 21:22:45 +02:00
79e4d35f01 Remove is_private from $nu.scope.commands (#4979) 2022-03-26 21:22:35 +02:00
71dd857926 Termux/Android target support for v0.60.0 (#4956)
* Add android as target os for procfs-based ps

* Turn off code for dealing with trash on platforms which are known to not support a standard trash protocol

* Update lib.rs

* Update lib.rs

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
2022-03-27 07:21:19 +13:00
7a789d68a2 Don't include trailing separator when expanding tilde (#4974)
* Fix path when expanding tilde

Expanding tilde with no other relative paths would result in:
`$HOME/` instead of `$HOME`. This occurs when users run `cd` with
no extra arguments. In that case, the user's PWD would include the
trailing separator. This does not happen when explicitly passing
a value, such as `cd ~`, because in that case, the path would be
canonicalized.

This happens because std::path::PathBuf::push always adds a separator,
even if adding an empty path, which is what happens when `cd` is
invoked.

* Add test

* Fix test on Windows

Co-authored-by: Hristo Filaretov <h.filaretov@protonmail.com>
2022-03-27 06:28:31 +13:00
8a9cc33aac Fix alias import (#4968)
* Fix alias import

Alias importing was registering the alias id as a decl instead of alias.
This caused issues when hiding and then reimporting the alias.

* Clippy format

Co-authored-by: Hristo Filaretov <h.filaretov@protonmail.com>
2022-03-25 17:56:40 -05:00
JT
66087b01e6 Improve the 'use' and 'source' errors (#4966)
* Improve the 'use' and 'source' errors

* Add register
2022-03-26 10:43:46 +13:00
JT
19fa41b114 Fix single quote environment values (#4960)
* Fix single quote external values

* Try to fix windows

* fix test

* fix test
2022-03-26 09:14:48 +13:00
JT
91cd1717e9 Add escapes to 'to nuon' (#4964) 2022-03-26 08:35:37 +13:00
JT
12b85beecc Fix path join on streams (#4959) 2022-03-26 07:46:48 +13:00
2252833917 bump cargo crate sys-locale to the latest version (#4957) 2022-03-25 10:00:35 -07:00
JT
4e9c1067fb Fix 4946 (#4951)
* Fix reject

* test

* clippy
2022-03-25 20:48:01 +13:00
e505e57a7a align all of the serde_json crates to the same version (#4949) 2022-03-25 18:54:49 +13:00
JT
d122827a30 Fix operator precedence parser (#4947) 2022-03-25 16:23:08 +13:00
b007290a4e Fix #4942, and add a table sorting example for sort-by command (#4948)
* Fix #4942, and add a table sorting example for `sort-by` command

* ci skip
2022-03-25 16:22:57 +13:00
7c92791eed add .mailmap to .gitignore 2022-03-24 20:36:52 -05:00
80769b7197 Set the minimum Rust version to 1.59 (#4940)
nushell uses the strip option in two of its profiles in Cargo.toml.
This option is new in Rust 1.59[0], so this commit adjusts Cargo.toml to
mark 1.59 as the minimum supported Rust version[1].

[0] https://blog.rust-lang.org/2022/02/24/Rust-1.59.0.html
[1] https://doc.rust-lang.org/cargo/reference/manifest.html#the-rust-version-field

Signed-off-by: Randy Barlow <randy@electronsweatshop.com>
2022-03-25 08:08:34 +13:00
9b5dff828d bump csv crate to the latest 1.1.6 (#4939) 2022-03-24 12:59:27 -05:00
90013295aa Fix parse_string_strict() to detect unbalanced quotes properly (#4928) 2022-03-25 05:57:03 +13:00
ea7c8c237e CantConvert improvements (#4926)
* CantConvert improvements

* cargo fmt
2022-03-24 07:04:31 -05:00
JT
5d5b02d8dc Don't assume external ls (#4925) 2022-03-24 16:42:41 +13:00
00b67d338d added missing metadata for drop and uniq #4763 (#4908)
* added missing metadata for drop and uniq #4763

* added missing metadata for keep #4763

* added missing metadata for append #4763

* added missing metadata for shuffle #4763
2022-03-24 07:27:01 +13:00
d32e878868 rename export def to export alias (#4912)
copy-n-paste error
2022-03-23 07:53:10 -05:00
41af2e4b30 update link (#4915) 2022-03-23 07:52:49 -05:00
e9f9aab79f chore: Update default register examples (#4904) 2022-03-23 20:41:58 +13:00
e826540037 Pass /D flag to cmd.exe to disable AutoRun (#4903)
* Pass `/D` flag to `cmd.exe` to disable AutoRun

* Pass `/D` flag before `/c`

This avoids running the command '/D <&self.name.item>' in cmd
2022-03-23 19:05:06 +13:00
a435a9924c add ability to execute on demand (#4896) 2022-03-22 21:09:58 -05:00
JT
02ed15b932 Update Cargo.toml 2022-03-23 09:44:24 +13:00
JT
81e269c483 Update Cargo.toml 2022-03-23 09:44:03 +13:00
JT
eceae26b0a Update Cargo.toml 2022-03-23 09:39:03 +13:00
JT
ec5fd62f9f Add licenses (#4893)
* Add licenses

* Add licenses
2022-03-23 09:25:38 +13:00
JT
74af31a42f Update release.yml 2022-03-23 08:07:11 +13:00
JT
1c964cdfe7 Bump to 0.60 (#4892)
* WIP

* semi-revert metadata change
2022-03-23 07:32:03 +13:00
352cf31db2 update comments, add other targets (#4891)
keep these other targets in case we need them in the future
2022-03-22 08:27:48 -05:00
JT
66e736dab4 Externals shouldn't expand aliases (#4889) 2022-03-22 11:57:48 +13:00
18067138aa created an alternate way to determine line count (#4887) 2022-03-21 11:56:14 -05:00
bd7a506897 update size command to be more accurate (#4885) 2022-03-20 17:09:30 -05:00
1d38ff071e fix: typo (#4882)
Fix a typo in the default config
2022-03-20 07:49:00 -05:00
JT
e6a5011fdb Allow 'error make' to make simple errors (#4881)
* Allow 'error make' to make simple errors

* Add example
2022-03-20 16:25:45 +13:00
JT
d5f23ab592 Put completions in their own module (#4880) 2022-03-20 12:03:58 +13:00
JT
bd5778fa24 remove the boolean vars (#4879) 2022-03-20 08:12:10 +13:00
JT
f3bb1d11d3 Add export alias and export extern (#4878)
* export alias

* export extern
2022-03-20 07:58:01 +13:00
285f91e67a add module name to $nu.scope.commands info (#4877) 2022-03-19 10:58:56 -05:00
01c1e5e8b0 commands are either custom or builtin, not both (#4876)
* commands are either custom or builtin, not both

* clippy
2022-03-19 09:52:50 -05:00
d6669d3f33 Polars update (#4875)
* update to polars 0.20

* add to date parser for series
2022-03-19 11:13:34 +00:00
3db608eb5c Re-enable virtualenv tests (#4755) 2022-03-19 00:36:38 +02:00
JT
b293282e9b Add insert/update to lists (#4873) 2022-03-19 10:12:54 +13:00
JT
983d115bc0 Add an alias denylist for expansions (#4871) 2022-03-19 08:03:57 +13:00
5a1af4d661 fixed a couple more tests (#4870) 2022-03-18 12:35:28 -05:00
4f05e9f4a6 add a display of what the colors look like in ansi --list (#4866)
* add a display of what the colors look like in `ansi --list`

* change 'color' to 'preview' - add the ability to turn it off via config with use_ansi_coloring
2022-03-18 06:27:33 -05:00
JT
7773c4cd4d Fix single quote external interpolation (#4867) 2022-03-18 19:59:28 +13:00
JT
d0cbb2d12c Allow expanding aliases before keywords, improve hiding (#4858)
* Allow aliasing source

* Add test

* improve hiding

* Finish adding tests

* fix test
2022-03-18 11:35:50 +13:00
JT
0986eefb64 Add insert and update back (#4864) 2022-03-18 06:55:02 +13:00
6e69d40bb9 some tweaks to main for testing (#4862) 2022-03-17 11:32:54 -05:00
9db356e174 Remove nu-ansi-term from the tree, use reedline 0.3 (#4850)
To simplify use of nu-ansi-term in both nushell/nushell and
nushell/reedline remove it from the workspace to have a separate
progression of version numbers.

This allows reedline to use the latest published version and nushells
workspace to use the same most recent version

Changes the `Cargo.toml`s to use reedline from crates.io

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
2022-03-17 15:29:52 +13:00
6700fbeed7 rename update to upsert to mirror what it really does (#4859)
* rename `update` to `upsert` to mirror what it really does

* change to latest reedline and nu-ansi-term
2022-03-16 19:13:34 -05:00
ca12f39db3 added nu-utils crate, fixed issue where externals turn off vt processing (#4857)
* added `nu-utils` crate, fixed issue where externals turn off vt processing

* hopefully make work in non-windows environments

* clippy
2022-03-16 17:21:06 -05:00
460d635ed0 update so that --log-level will work properly (#4856) 2022-03-17 08:58:11 +13:00
1a16b9a2c4 Move repl loop and command/script execution to nu_cli (#4846)
* Refactor usage of is_perf_true to be a parameter passed around

* Move repl loop and command/script execution to nu_cli

* Move config setup out of nu_cli

* Update config_files.rs

* Update main.rs

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
2022-03-17 07:17:06 +13:00
JT
0bd8664f33 Fix string interpolation escaping (#4854) 2022-03-16 05:09:30 +13:00
762da0989c now that docs/commands is gone delete make_docs.nu as it is no longer needed (#4853) 2022-03-14 20:50:46 -07:00
65baeaecd4 delete docs/commands (#4851) 2022-03-14 21:00:30 -05:00
cb5d997adf Change update help+examples for creating new columns (#4849)
* Change update help/examples for creating new column

* Enable example tests for update command
2022-03-14 15:32:33 -05:00
10d805c1fa feat: fix and update some examples (#4844) 2022-03-14 07:41:09 -05:00
JT
54d9fff4f2 Revert "Alias to keywords (eg source) (#4835)" (#4841)
This reverts commit c023d4111a.
2022-03-13 13:38:16 -07:00
6e65aef9bf remove cmd from edit (#4840) 2022-03-13 20:05:13 +00:00
72daf8c64e Fix reporting of which and $nu.scope (#4836)
* Refactor & fix which

Instead of fetching all definitions / aliases, only show the one that is
visible.

* Fix $nu.scope to show only visible definitions

* Add missing tests file; Rename one which test
2022-03-13 21:32:46 +02:00
JT
c023d4111a Alias to keywords (eg source) (#4835)
* Allow aliasing source

* Add test
2022-03-13 11:30:37 -07:00
JT
ff3dffd813 Nu glob (#4818)
* Fork glob. Normalise license holder

* Fix more licenses

* unwraps

* bad doc test
2022-03-13 11:30:27 -07:00
30bb090cd4 str to datetime dfr (#4833)
* str to datetime dfr

* change description
2022-03-13 13:53:13 +00:00
dfffd45bcd Streaming support for lines with raw streams (#4832) 2022-03-13 04:52:55 -07:00
c73d8d5f95 Add LIB_DIRS and PLUGIN_DIRS (#4829)
* Add LIB_DIRS and PLUGIN_DIRS

* Put plugin dirs behind plugin feature
2022-03-12 22:12:15 +02:00
0ff9cc679e add $nu.pid (#4828) 2022-03-12 10:54:59 -06:00
b342270112 update edit: cmd: undo syntax (#4826) 2022-03-12 09:37:19 -06:00
ccc85a2979 remove $nu.cwd (#4824) 2022-03-12 09:11:19 -06:00
005301647a equal comparisson series string (#4823) 2022-03-12 13:15:30 +00:00
5fcc670860 allow list to keybinding mode (#4821)
* allow list to keybinding mode

* added comments to default.nu
2022-03-12 11:51:08 +00:00
90b2ec537f Do not pass non-string env vars to externals (#4748)
* Do not pass non-string env vars to externals

Also misc cleanup

* Add note to default config

* Add a test

* Ensure PATH/Path conversion list <-> string
2022-03-12 00:18:39 +02:00
f3626f7c3a Update docs for open and decode command, regenerate all docs (#4815)
* Update docs for open and decode command, regenerate all docs

* Update open.rs

* Update open.md

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
2022-03-11 05:39:54 -05:00
7debb27d78 corrected history menu (#4814) 2022-03-10 20:58:11 +00:00
675d30d980 Icon for .nu files' mimetype (#4813)
* Icon for .nu files' mimetype

Icon that should be displayed at every .nu script in a file explorer.

Later, a post-install script will be submitted; this script will install the mimetype+icon and the handler for doubleclicking/openning .nu files.

Signed-off-by: Daniell Mesquita <daniellmesquita@protonmail.com>

* Complement previous commit

As per request, using author name in icon. Also, using the updated name.

Signed-off-by: Daniell Mesquita <daniellmesquita@protonmail.com>
2022-03-10 13:33:21 -06:00
2f70442165 nushell icons contributed by the community (#4812) 2022-03-10 12:05:01 -06:00
ce690ed18f Bump sysinfo version from v0.22.2 to v0.23.5, close #3909 (#4810) 2022-03-10 11:38:32 -05:00
14dc662e50 reorganize features a bit (#4807) 2022-03-10 07:37:24 -06:00
JT
ffa3aaaa56 bump reedline (#4806) 2022-03-10 08:22:49 -05:00
JT
2b3843c7c0 ensure exit codes in more cases (#4804) 2022-03-10 07:32:46 -05:00
JT
9abb14b5fd ensure exit codes in more cases (#4803) 2022-03-10 06:29:23 -05:00
JT
12bf23faa6 Move completions to DeclId (#4801)
* Move completions to DeclId

* fmt

* fmt
2022-03-10 09:49:02 +02:00
643cce8a6f Mark match as deprecated command (#4802) 2022-03-09 20:58:42 -06:00
JT
3bdd924349 Fixes the panic when using externs + string interpolation (#4799) 2022-03-09 13:01:23 -05:00
JT
be43b3c5fc Allow passing block literals to do (#4798) 2022-03-09 09:56:19 -05:00
JT
355b1d9929 Simplify empty?, improve default (#4797)
* Simplify empty?, improve default

* improve test
2022-03-09 08:46:28 -05:00
0d82d7df60 Update documents for commands (#4796)
* Update documents of commands

* Change plugin names for register command examples

* Remove unused docs [ci skip]
2022-03-09 08:05:35 -05:00
JT
8fcf51908a Fix expansion of row condition implied it (#4795) 2022-03-09 08:05:03 -05:00
JT
0835073d85 Adds the proper workarounds for short flags (#4794) 2022-03-09 08:04:50 -05:00
JT
925e9f4dcb Allow quotes in a register call (#4793) 2022-03-09 07:06:44 -05:00
JT
e0fac7bc72 Change select to match 0.44 (#4792) 2022-03-09 07:05:55 -05:00
JT
fac086c826 Make reduce -n more sensible (#4791) 2022-03-09 05:56:08 -05:00
JT
088d19ad47 Make date values more readable (#4790) 2022-03-09 05:43:04 -05:00
JT
99f7636b03 Remove duplicate code (#4789) 2022-03-09 05:21:11 -05:00
JT
2ac990655e Add support for var decl spans (#4787) 2022-03-09 04:42:19 -05:00
4ddf24269a changed cargo.toml so plugins don't build with features=extra (#4788)
* changed cargo.toml so plugins don't build with features=extra

* remove comments
2022-03-08 20:05:58 -06:00
b73af3b8df add ability to check if value does not contain something (#4783) 2022-03-08 09:10:01 -06:00
JT
dc0c5a9772 Revert "Make if blocks work like a def-env (#4656)" (#4782)
This reverts commit 477f3be8df.
2022-03-08 08:29:12 -05:00
JT
477f3be8df Make if blocks work like a def-env (#4656)
* Make `if` work like a def-env

* Add some tests

* Add an example
2022-03-08 07:45:47 -05:00
ae7c0b1097 Fix broken link in readme, should close #4776 [ci skip] (#4778) 2022-03-08 06:30:11 -05:00
cede9b3156 reedline bump (#4779) 2022-03-08 09:20:28 +00:00
JT
299fea8538 Fix external extra (#4777)
* Fix empty table from externals

* Fix empty table from externals
2022-03-07 20:17:33 -05:00
35ff1076f3 add ansi escape (#4772)
* add ansi escape

* also add the ability to escape parens

* add a few more escapes that could be problematic for the nushell lang
2022-03-07 16:39:16 -06:00
073f8655eb Remove unused ntdef.h include (#4767) 2022-03-07 15:11:45 -06:00
JT
1837bf775c Default values (#4770) 2022-03-07 15:08:56 -05:00
a3df2e5631 reedline bump (#4766)
* reedline bump

* reedline bump
2022-03-07 17:51:14 +00:00
0a95bc7e60 Add serialization for JSON and form bodies in post (#4764)
* Add serialization for JSON and form bodies in `post`

* Reuse code from `to json` instead of duplicating

* Fix formatting. Oops
2022-03-07 10:49:45 -06:00
JT
a2723c2ba4 Fix rest parsing (#4765)
* More nuon tests, fix table print

* Fix rest type parsing
2022-03-07 11:44:27 -05:00
JT
0b6b321ad6 More nuon tests, fix table print (#4762) 2022-03-07 08:39:02 -05:00
JT
4f43d75130 Simplify group/window into their own commands (#4760) 2022-03-06 20:01:29 -05:00
fbbbde1489 Update the Readme for the dataframe directory (#4757)
* update dataframe readme

* update df readme
2022-03-06 11:05:55 -08:00
7701c6b1d4 added real index column to history (#4756) 2022-03-06 17:22:18 +00:00
5ae5ef5146 enable to-nu to include the whole dfr if rows is not specified (#4753) 2022-03-06 09:04:41 -06:00
JT
69fd777120 Bump reedline (#4747) 2022-03-05 19:55:37 -05:00
fa7d66347f Add basic resource file for Windows binary (#4745) 2022-03-05 15:56:23 -06:00
4aa9a18c63 Allow save to accept a list of strings (#4743) 2022-03-05 15:56:04 -06:00
1527b34d9c Add back --append flag to save command (#4744) 2022-03-05 13:36:58 -06:00
JT
a4a8f5df54 Add more multiline pipeline forms (#4740) 2022-03-05 08:20:13 -05:00
32601bb352 just make install-all.sh executable (#4739) 2022-03-05 06:44:24 -06:00
6a1e504a50 Update build & install sh scripts, add install script for windows (#4736)
* Update build & install sh scripts, add install script for windows

* Rename install scripts [ci skip]
2022-03-05 06:41:28 -05:00
488f81d012 history bang (#4735)
* history bang

* change of char
2022-03-05 09:38:35 +00:00
bc119a5e98 Update build and install scripts (#4733)
* Update build and install scripts

* Add build-all.nu and uninstall-all.sh
2022-03-05 00:10:33 -05:00
JT
9c17c73d5f Add more exit code support (#4730) 2022-03-04 17:46:18 -05:00
cd721fc363 build script for mac and linux (#4732) 2022-03-04 16:17:33 -06:00
5b3cc73ac6 remove the hard coded escaping from split row and split column (#4731) 2022-03-04 15:09:35 -06:00
02dfb57ed1 partial completions bug (#4728) 2022-03-04 17:53:00 +00:00
fbb2e7136c match is now in the find command (#4727) 2022-03-04 11:29:45 -06:00
b714e034aa remove some old documentation, relocate others (#4726)
* remove some old documentation, relocate others

* small tweak to default config
2022-03-04 11:37:08 -05:00
JT
e64ca97fe2 move scope variable into nu variable (#4725) 2022-03-04 11:36:11 -05:00
JT
eef3de2d05 Move old plugins (#4721) 2022-03-04 09:36:03 -05:00
89b7f4d57c add windows build script (#4720) 2022-03-04 08:00:11 -06:00
JT
7c205d7a3a Remove the pack-in plugins (#4719) 2022-03-04 08:57:38 -05:00
1157fcf372 fix typo, update some examples and regenerate docs (#4718) 2022-03-04 06:10:09 -06:00
eeef9f27eb Add installation instructions using Chocolatey (#4714)
Add installation instructions for Nushell on Windows using the
Chocolatey package manager.
2022-03-03 15:26:06 -06:00
47d5501f9f Add aliases to command completions (#4708) 2022-03-03 15:07:13 -05:00
97b3e4a233 Fix aliases to known externals (#4707) 2022-03-03 14:05:55 -05:00
52f4c4ba7e Adds tab indentation option for JSON files. (#4705) 2022-03-03 13:15:13 -05:00
JT
7d0531d270 Add support for escape characters, make nuon a JSON superset (#4706)
* WIP

* Finish adding escape support in strings

* Try to fix windows
2022-03-03 13:14:03 -05:00
13f2048ffb Add completion options for custom completions (#4674)
* Add completion options for custom completions

* Make clippy happy

* Refactor options for clarity

* Make return type of filtering explicit
2022-03-03 09:45:35 -05:00
210d25f2a0 Add into duration (#4683)
* Add `into duration` command

* Avoid using unwrap()

* Use existing logic to parse duration strings
2022-03-03 08:16:04 -05:00
2fd42d25b1 partial completions (#4704) 2022-03-03 11:13:44 +02:00
d90b7953dd Use Nushell's PATH in which (#4690)
* Make which use our path instead of std::env

* Unignore which test

* Fix wrong fn signature without which feature
2022-03-03 10:38:31 +02:00
50399c349f relocate default config in sample_config folder (#4678)
* relocate default config in sample_config folder

* relocate config file
2022-03-02 19:22:15 -06:00
JT
96a1bf5f8d Experiment: Allow both $true/true and $false/false (#4696)
* Change true/false to keywords

* oops, clippy

* Both kinds of bools

* Add in some boolean variables

* disable py virtualenv test for now
2022-03-02 19:55:03 -05:00
JT
fd88920a9d Make sure we have text before json parse (#4697) 2022-03-02 15:58:56 -05:00
JT
88d7b50e37 Pass redirects into call (#4694)
* Pass redirects into call

* Oops, format
2022-03-02 07:52:24 -05:00
0da9213de6 document environment variable for starship prompt (#4691)
It would appear that starship needs an environment variable set to output the prompt correctly on a per shell basis.
2022-03-01 18:38:35 -05:00
JT
4965f4cbf4 Bump to 0.59.1 (#4689) 2022-03-01 16:55:51 -05:00
fef7f38da8 removed decode from pipeline for vivid (#4688) 2022-03-01 09:20:02 -06:00
42f1874a3a Update some examples and docs (#4682)
* Update some examples and docs

* Update now.rs

* Update date_now.md

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
2022-03-01 08:05:29 -05:00
JT
2a89936bee Move to latest stable crossterm, with fix (#4684) 2022-03-01 07:05:46 -05:00
ece5e7dbb7 dataframe list command (#4681) 2022-03-01 06:41:13 -05:00
JT
a6a96b29cb Add binary literals (#4680) 2022-02-28 18:31:53 -05:00
e3100e6afd Fix alias in docs/sample_config/config.toml (#4669) 2022-02-28 15:47:14 -06:00
JT
cb5c61d217 Fix open ended ranges (#4677)
* Make open ended ranges more open ended

* Add test
2022-02-28 11:15:31 -05:00
b09acdb7f9 Fix unsupported type message for some math related commands (#4672)
* Fix unsupported type message of some math related commands

* changing the error form for UnsupportedInput

* cargo fmt
2022-02-28 10:14:33 -05:00
JT
0924975b4c Use default_config.nu by default (#4675)
* Use default_config.nu by default

* Fix default color
2022-02-28 10:12:08 -05:00
JT
d6a6c4b034 Add back in default keybindings (#4673)
* Add back in default keybindings

* Add support for edit commands, add in undo
2022-02-28 08:54:40 -05:00
eec1730449 Add profiling build profile and symbol strip (#4630)
* Add profiling build profile and symbol strip

Stripping the symbols for the release build improves the size of the
binary significantly

Adds a custom build profile for performance profiling that includes all
symbols for analysis.

Can be used via

```
cargo build --profile profiling
```

* Retain a minimal backtrace
2022-02-28 07:13:24 -05:00
JT
10364c4f22 don't use table compaction in to nuon if not a table (#4671)
* don't use table compaction in to nuon if not a table

* Make a proper nuon conversion test

* more nuon tests
2022-02-28 07:10:02 -05:00
ef70c8dbe4 Date parse refactor (#4661)
* More flexible and DRY datetime parsing

* Update error messages

* cargo fmt

* clippy

* Add DatetimeParseError
2022-02-27 20:21:46 -05:00
0f437589fc add last exit code to starship parameters (#4670) 2022-02-27 17:26:15 -06:00
796d4920ab add char separators (#4667)
* add char separators

* sir clipster

* unclippy
2022-02-27 16:03:21 -06:00
JT
7819210037 Add shortcircuiting boolean operators (#4668) 2022-02-27 17:02:53 -05:00
4ebbe07d27 Polars upgrade (#4665)
* polars upgrade

* Update describe.rs

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
2022-02-27 11:10:29 -05:00
10ceac998e menu keybindings in default file (#4651)
* menu keybindings in default file

* remove print

* change keybinding
2022-02-27 08:41:04 -05:00
JT
446c2aab17 Lets internals also have exit codes (#4664) 2022-02-27 08:16:19 -05:00
995757c055 flags for find (#4663) 2022-02-27 06:17:13 -05:00
799fa98411 Update reedline, revert crossterm (#4657)
At the moment `crossterm` apparently has a regression decoding certain important key combinations on Windows.
Thus reedline reverted to the previous version.

Some changes are necessary to remove the need for `crossterm` in the use of `lscolors`.
Introduces two local conversion traits.

Additionally update the `Highlighter` API to support the cursor
position.
This will enable brace/statement match highlighting.
2022-02-26 11:23:05 -06:00
d2bd71d2aa add LAST_EXIT_CODE variable (#4655) 2022-02-26 08:57:45 -05:00
11bc056576 Find with regex flag (#4649)
* split find functions

* find command with regex

* corrected message

* cargo fmt
2022-02-26 04:19:19 -05:00
3eca43c0bb Plugins without file (#4650)
* adding plugin location in script

* adding plugin location in script
2022-02-26 08:57:51 +00:00
ed46f0ea17 fix: add missing metadata for ls_colors (#4603)
* feat: add metadata to roll

* chore: apply clippy

* fix: apply clippy

* fix: revert clippy
2022-02-25 17:31:02 -05:00
JT
0c3ea636fb Add support for stderr and exit code (#4647) 2022-02-25 14:51:31 -05:00
2b377391c2 make message more readable (#4646)
* make message more readable

* monsieur clippy
2022-02-25 12:58:47 -06:00
c6a3066103 Document Visual C++ requirement on Windows. (#4641)
Should fix #4563.
2022-02-25 13:04:10 -05:00
JT
977ef66356 Fix Windows doc comments (#4643)
* WIP windows doc comments

* WIP windows doc comments

* WIP windows doc comments

* actual fix this time
2022-02-25 13:03:39 -05:00
e6570b41ca Fix some examples and regenerate docs, should fix: #4455 (#4639) 2022-02-25 08:14:15 -05:00
JT
2126bef052 clean table text before rendering (#4638) 2022-02-25 08:13:55 -05:00
JT
e8a6458f0d finish up with examples (#4637) 2022-02-25 05:19:25 -05:00
JT
2b1e4dd242 Use external exceptions in path strings (#4636) 2022-02-25 05:00:30 -05:00
JT
70009c015d Use metadata with lists (#4635)
* Windows external exceptions

* Also use metadata with lists
2022-02-25 04:27:50 -05:00
JT
cbad648d0e Windows external exceptions (#4632) 2022-02-24 18:01:32 -05:00
JT
3c62d27c28 Try again with math-like externals (#4629)
* Try again with math-like externals

* clippy 1.59

* clippy 1.59

* clippy 1.59
2022-02-24 14:02:28 -05:00
2c9d8c4818 fix: #3809, try to fix the source -h not work issue (#4627) 2022-02-24 10:32:10 -05:00
JT
c984ce9dc9 Check for external exceptions more often (#4628) 2022-02-24 10:31:24 -05:00
JT
308ab91aff Speed up the parser and nuon parser a bit more (#4626) 2022-02-24 07:58:53 -05:00
c3979ef1cf Add example for command n,g,p and grid, update date now examples (#4622) 2022-02-24 06:17:05 -06:00
784382edde 30 web_tables tests are now passing (#4623) 2022-02-24 06:58:20 -05:00
feb4f5c347 replace ValueStream with ListStream (#4621) 2022-02-24 06:57:31 -05:00
21c0f7d738 allow int and float as strings for arguments (#4615)
* allow int and float as strings for arguments

* consume iterator
2022-02-24 05:09:02 +00:00
JT
4b18fdcc6e Date literals (#4619)
* Date literals

* update deps

* Add date+duration
2022-02-23 21:02:48 -05:00
63487941fb add back in the tests for query_web in the nu_plugin_query (#4614)
* fix first test

* fix 2nd query_web test
2022-02-23 10:43:36 -06:00
JT
676457acd3 Better ls paths (#4612)
* Fix ls paths... again

* Fix ls paths... again

* Always expand paths inside of glob_from

* Expand in ls before we check for directory info
2022-02-23 10:54:47 -05:00
f507613b38 fixed some more tests (#4607) 2022-02-22 11:32:29 -05:00
JT
25712760ba Add support for math-like externals (#4606) 2022-02-22 10:55:28 -05:00
d054a724d1 Add example for enter, shells and view-source, update some docs (#4604) 2022-02-22 09:16:56 -06:00
c2bad71123 remove repeated function (#4600)
* remove repeated function

* name in signature
2022-02-22 08:13:38 -05:00
b448d1dbe1 fix strip trailing whitespace for make_docs script (#4597) 2022-02-22 08:11:46 -05:00
JT
3e8a41fbc9 Speedup unit parse (#4598)
* Compact nuon tables

* Speed up unit parsing a bit
2022-02-22 04:50:49 -05:00
JT
31925c3d40 Compact nuon tables (#4596) 2022-02-21 20:48:42 -05:00
JT
9888f8f298 Add pipeline redirection support (#4594)
* redirection

* Remove commented-out

* fix tests

* more fixes
2022-02-21 17:22:21 -05:00
739e403cd5 Do not set visibility to true automatically (#4591)
Adding it by default grows the size of the visibility structure a lot.
2022-02-21 16:42:31 -05:00
359bb6eebe Look up predecl only in the working set (#4592)
Previously, the parser tried to look up the predecl also in the
permanent state and if a definition with that name already existed, it
would try to update it, which is illegal.
2022-02-21 16:05:20 -05:00
JT
6d4784a7c1 Make 'each' implicitly filter out nothings (#4546)
* Make 'each' implicitly filter out nothings

* another example
2022-02-21 15:49:08 -05:00
e4dcdcb254 this little hack allows the color to be whatever the default is (#4590) 2022-02-21 12:46:04 -06:00
88fa40d698 rename flatshape_* to shape_* (#4589) 2022-02-21 12:27:21 -06:00
JT
24fc9c657e Add binary support to 'skip' (#4588)
* Add binary support to 'skip'

* add streaming
2022-02-21 13:23:43 -05:00
JT
6670b77b27 Fix shorthand env duplicates (#4587) 2022-02-21 12:58:04 -05:00
c0a1d18e3d update #4455, regenerate commands' docs and update make_docs script (#4586)
* feat: update #4455, regenerate commands' docs

* chore: update make_docs script
2022-02-21 11:26:00 -06:00
JT
2e167ea0c6 Update ci.yml 2022-02-21 10:47:57 -05:00
JT
41fa1ab656 Show errors when a prompt fails (#4585) 2022-02-21 10:46:19 -05:00
53b5012f1e feat: update: #4518, Add examples for command: use,module,export def,export env and export def-env (#4584) 2022-02-21 09:32:31 -06:00
JT
07cd8f483e Make sure to apply captures when setting prompt (#4583) 2022-02-21 09:48:05 -05:00
d1ec05b12b fix: lose ls_colors in some filters commands (#4525)
* feat: add metadata to first

* feat: add metadata to last and skip

* feat: add metadata to reverse

* fix: apply clippy
2022-02-21 08:29:51 -06:00
JT
a2c4c92fce Remove record iteration (#4582)
* Remove record iteration

* Remove test
2022-02-21 09:12:04 -05:00
917886f8ad feat: update: #4518, Add examples for command: hide, history, from yml, def-env, and table (#4581) 2022-02-21 07:52:50 -06:00
4f367a59de Strip trailing whitespace in files (#4575)
* Strip trailing whitespace in rs files

* Strip trailing whitespace in toml files

* Strip trailing whitespace in md files

* Strip trailing whitespace in nu files
2022-02-21 08:38:15 -05:00
968427c4e9 feat: update: #4518, Add example for register,source,save,shuffle and from tsv (#4577) 2022-02-21 06:25:41 -06:00
JT
d454fad4dc Improve json errors a bit (#4579)
* Improve json errors a bit

* typo
2022-02-21 07:08:09 -05:00
JT
a96f8b891e more strict nuon handling, better nuon errors (#4576)
* more strict nuon handling, better nuon errors

* Improve errors a bit more
2022-02-20 22:31:50 -05:00
JT
5befa6f80a Add auto-cancelling previous PRs (#4573)
* Add auto-cancelling previous PRs

* Update ci.yml
2022-02-20 20:41:51 -05:00
5bf2ffeaf5 Add indent flag to to json (first draft) (#4571)
* Add indent flag to `to json` (first draft)

* Run cargo fmt

* Update examples / tests

* Change order of examples
2022-02-20 16:29:19 -06:00
9b2a022f5b tweak default config to amplify theme-ability (#4572)
* tweak default config to amplify theme-ability

* missed default of auto
2022-02-20 16:05:36 -06:00
JT
fd22211737 Add nuon format for fun (#4401)
* Add nuon format for fun

* more fun

* More nuon fixes, allow comments, improve errors
2022-02-20 16:26:41 -05:00
JT
2ba12afb01 A few fixes to docs generation and default config (#4570)
* A few fixes to docs generation and default config

* A few more fixes
2022-02-20 15:20:41 -05:00
JT
6024a17a5b Remove stray println (#4568)
* Default config improvements

* Finish cleanup

* Add some comments

* remove println
2022-02-20 09:41:16 -05:00
56aacc4852 Use environment variable for env_conversions (#4566)
* Handle string->value env conv. with env. var.

Also adds the environment variable for Path/PATH and removes it from
config.

* Simplify getting the string->value conversion

* Refactor env conversion into its own function

* Use env var for to_string conversion; Remove conf

* Fix indentation in default config
2022-02-20 16:27:59 +02:00
JT
643c5097d6 Default config improvements (#4565)
* Default config improvements

* Finish cleanup

* Add some comments
2022-02-20 07:48:46 -05:00
52ee1917ba default config file (#4554)
* default config file

* fmt on files

* default file in separate file

* log level flag for performance logs

* clippy error
2022-02-20 05:08:53 -05:00
JT
9ea5a2ecd3 Improve missing param error span (#4560) 2022-02-19 21:30:29 -05:00
JT
a32ce93c79 Improve full help for flags (#4559) 2022-02-19 21:25:52 -05:00
b92aaf0432 add custom header ability to post command (#4558) 2022-02-19 19:27:48 -06:00
2ecae0ef43 Update #4455, Regenerate all commands' docs (#4557) 2022-02-19 19:13:33 -06:00
aea4355d04 refactor: change column names from 'Column*' to 'column*' (#4556) 2022-02-19 19:26:47 -05:00
a6c565ed4e change wording on config file (#4555) 2022-02-19 19:25:07 -05:00
7163721571 a few more ansi escape sequences (#4553) 2022-02-19 16:47:52 -06:00
965cea3af5 flag to pass config file in nu (#4552)
* flag to pass config file in nu

* return when no folder is created

* simple syntax for function
2022-02-19 14:54:43 -06:00
efd62f917f Reduce code duplication in to json command (#4551) 2022-02-19 14:46:20 -06:00
ac99ac003a Add example for cd,transpose,detect columns,split column and split row (#4549) 2022-02-19 09:24:48 -06:00
3ecf17e7af Fix ps command to show process name only (#4544)
* Fix `ps` command to show process name only

* Remove `command_only` -  it is no longer being used
2022-02-18 19:48:52 -06:00
JT
da42100374 Update README.md 2022-02-18 20:30:58 -05:00
JT
dfc478e074 Update README.md 2022-02-18 20:30:23 -05:00
28b5399fb7 Use join over custom join code (#4548) 2022-02-18 19:07:11 -06:00
3f14b75153 feat: add examples for length,lines,reject,benchmark and drop column (#4547) 2022-02-18 19:03:24 -06:00
0f4f660759 better keybinding parsing (#4543) 2022-02-18 19:00:23 -06:00
JT
d53eaac7a1 Improve comparison errors (#4541) 2022-02-18 17:11:27 -05:00
JT
f085bd97f6 Add some more builtin var completions (#4540) 2022-02-18 14:34:40 -05:00
c893cc1485 Add config to NuCompleter (#4538) 2022-02-18 13:54:13 -05:00
e5bf56a7dd port post (#4537)
This restores a basic version of the `post` command.
Some source types have been omitted from this first take.
I copied from `fetch` and from `post`@0.40.0.
Part of #4356
2022-02-18 13:53:10 -05:00
JT
06f9047be4 Add an explicit 'print' command (#4535) 2022-02-18 13:43:34 -05:00
JT
786e4ab971 Make 'for' implicitly filter out nothings (#4536)
* Make 'for' implicitly filter out nothings

* Fix test
2022-02-18 13:41:41 -05:00
f65955ccc5 Fix wrong FlatShape name of List (#4532) 2022-02-18 18:31:28 +02:00
1235d516a5 Add examples for env,let-env,rm,touch and date list-timezone (#4531)
* feat: update #4518, add examples for env,let-env,rm,touch and date list-timezone

* fix typo

* update example for `date list-timezone` command
2022-02-18 18:19:37 +02:00
dd11be03be feat: update #4518, add command examples for def, do, cp, mv, mkdir and ls (#4528) 2022-02-18 08:30:16 -06:00
a967854332 Fix stream printing on Windows (#4527)
Co-authored-by: Genna Wingert <wingertge@gmail.com>
2022-02-18 08:10:20 -06:00
a5f9ad2a43 Add or update examples for some commands (#4521)
* chore: add or update examples for some commands

* chore: code formatting
2022-02-18 07:06:52 -06:00
1377693f0f standardize char nf terms (#4520) 2022-02-18 05:52:48 -05:00
bccce0ab46 Use overlay ID for module import lookup (#4514)
* Add id to import pattern

* Finish testing importing in a block
2022-02-17 20:58:24 -05:00
c7c427723b Test support fixes (#4517)
* Fix failing pipeline()

The `skip(1)` was there likely to remove the welcome message.

* Fix typo

* Fix nu! test macro to enter cwd correctly

Nushell's current working directory is determined primarily by the PWD
environment variable.
2022-02-18 00:23:04 +02:00
d4cd3f9578 allow dfr open to open tsv files (#4516) 2022-02-17 14:15:17 -06:00
9415352447 remove $nu.keybinding-path (#4515) 2022-02-17 14:36:08 -05:00
8f5b857fcf Fix ignore to run side effects of previous command (#4510)
Co-authored-by: Genna Wingert <wingertge@gmail.com>
2022-02-17 12:49:54 -05:00
JT
fa75c93765 Slight cleanup of 'from json' line-at-a-time (#4512) 2022-02-17 12:49:31 -05:00
JT
393cb7ca6f Treat ls for absolute paths as-is (#4513)
* Absolute paths in ls are treated as-in

* Better fix
2022-02-17 12:49:20 -05:00
JT
f5f9d56c37 Move to a standard kebab/snake style (#4509) 2022-02-17 09:55:17 -05:00
d50ccdf083 Add newline after version printout (#4508) 2022-02-17 06:29:58 -06:00
JT
6e733f49bc Require block params (#4505)
* Require block params

* Improve errors
2022-02-17 06:40:24 -05:00
f169a9be3b Add version as a flag (#4507) 2022-02-17 05:02:46 -06:00
b8b2737890 make find case insensitive (#4502) 2022-02-16 19:42:40 -06:00
JT
d620f76a21 Make comparisons/sort-by more 'global' (#4500)
* Make comparisons/sort-by more 'global'

* Let custom values do their own comparisons
2022-02-16 13:30:37 -06:00
b64ac9eb7b more test fixes (#4499)
* more test fixes

* update multi-os err messages
2022-02-16 12:24:45 -06:00
JT
5b6156687e Use partial_cmp and make -i case insensitive (#4498)
* Use partial_cmp and make -i case insensitive

* Insensitive sort multiple columns
2022-02-16 11:12:49 -05:00
JT
c4e1559f89 Another batch of command tests (#4496)
* Add a batch of command tests

* More tests
2022-02-16 07:38:02 -05:00
JT
644435bfe3 Move and enable with-env test (#4489) 2022-02-16 04:59:44 -05:00
bd96ce4e9c add more examples to the sys command (#4491) 2022-02-15 21:06:38 -08:00
7e6430def0 a few more tests (#4488) 2022-02-15 20:48:32 -05:00
JT
e763a8dcef Auto-hide aliases to prevent recursion (#4487) 2022-02-15 17:36:24 -05:00
JT
df07e8e410 Fix view-source command (#4486) 2022-02-15 17:03:06 -05:00
f824388f63 Date format list (#4485)
* Add `date format --list`, and make format string optional (providing default)

* Make DRY

`into datetime --list` now uses `generate_strfttime_list` from `date format --list`

* refactor strftime to use current datetime

* Fix formatting of specification descriptions

Fixes issues caused when copying directly from docs.rs

* Change default format to rfc2822

Perhaps to make it more DRY, functions from `into datetime` can be used. However, currently `into datetime` is a bit tricky to use as it needs a separate time zone argument.

* Tweak in-shell docs to match modified behavior

* Show %#z format specifier in `into datetime --list` only

* cargo fmt

* Satisfy clippy
2022-02-15 15:13:40 -06:00
f11fa99d30 check to make sure we have data first (#4484) 2022-02-15 15:08:11 -06:00
JT
56b3fc61a3 Remove statements, replaced by pipelines (#4482) 2022-02-15 14:31:14 -05:00
JT
66669d7839 Fix more command tests (#4481) 2022-02-15 10:08:07 -05:00
JT
5c1a1be02b Don't error on failed external expansion (#4480) 2022-02-15 08:47:25 -05:00
JT
9114a2d31d Ensure that reduce has a valid span (#4479) 2022-02-15 07:59:51 -05:00
JT
84f85ff9ae Fix to json escape logic (#4478) 2022-02-15 06:55:57 -05:00
JT
a743db8e8f Improve alias expansion, again (#4474) 2022-02-14 21:09:21 -05:00
JT
fbaafaa459 Make param parsing more resilient, correct missing param error (#4470) 2022-02-14 12:33:47 -05:00
JT
f3d3e819fb Fix main in scripts with captures (#4468)
* Fix main in scripts with captures

* Remove old comments
2022-02-14 10:53:48 -05:00
63a2c2bc2d remove ignore for sort_by command test by_column which is now passing (#4465) 2022-02-13 20:46:12 -08:00
JT
8c0a2d3c15 Auto-generate markdown command docs (#4451)
* Finish updating

* a couple improvements

* Update renames

* cleanup examples
2022-02-13 21:22:51 -05:00
06f5affc0b add in the Value List to the sort-by Ordering (#4464) 2022-02-13 10:20:50 -08:00
7a3aeaf080 sort_by: coerce_compare now returns an Ordering (#4461)
* coerce_compare now returns an Ordering which will enable mixed type comparison

* arbitrary nushell sort order of Float / Int / String / Bool
2022-02-13 09:23:54 -08:00
JT
3576350b4b Update README.md 2022-02-13 07:57:38 -05:00
JT
0fc03dbb00 Add files via upload 2022-02-13 07:57:20 -05:00
4fdfc76d04 Prune the testing matrix (#4456) 2022-02-13 14:45:53 +02:00
a520599fa0 fix: fix with-env example with pipeline input (#4458) 2022-02-13 06:40:01 -06:00
77eb4c4188 Fix default duplicates column (#4452)
* Add test to ensure default not adding dup. columns

* Fix for default adding duplicate columns
2022-02-13 05:38:46 -05:00
e82ffc4dee sort_by error processing return ShellError instead of static String (#4453)
* sort_by error processing part I return ShellError instead of static Strings

* more explicit details on what types are failing

* clippy fixes
2022-02-12 21:30:57 -08:00
6fc082f6e9 fix case insensitive sort (#4449)
* fix case insensitive search

* fixed test

* tweak
2022-02-12 20:48:50 -06:00
560be6e73e feat: mark str to-datetime as deprecated command (#4448) 2022-02-12 20:30:37 -06:00
c5e7bccee5 Fixed printing of builtin kill command #4392 (#4447)
* Fixed printing of builtin kill command

* Fixed fmt and clippy issues for kill command

* Uncommented unintentional comments

* Fixed wrong code added in kill command

* Fixed more fmt issues with kill command
2022-02-12 20:18:27 -06:00
73f94105a5 Bump follow-redirects from 1.14.7 to 1.14.8 in /samples/wasm (#4446)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.7 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.7...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-12 16:10:59 -05:00
94a0e3060a Update CI (#4445)
* Add different features combinations

* Specify styles manually

* Fix args

* Fix typo

* Let other CI jobs finish if one fails

* Fix unused symbols without plugin feature

* Put "which" tests behind "which" feature

* Add Python virtualenv job

* Oops forgot git command

* Install Nushell in virtualenv tests

* Add names to steps; Test v.env in separate step

* cd into virtualenv

* Do not run on Python 2.7

* Build Nushell after formatting and clippy checks
2022-02-12 22:48:17 +02:00
JT
eceb2d5106 Early return on subcommands (#4443)
* Early return on subcommands

* More streamlining
2022-02-12 11:39:38 -05:00
JT
9829e449e3 Update bug_report.yml
Put example pipeline in the placeholder also
2022-02-12 10:24:38 -05:00
baf6348e66 feat: add unalias to deprecated command (#4440) 2022-02-12 17:06:52 +02:00
JT
cc171b6ad4 Improve completions with no starting characters (#4433)
* Improve completions with no starting characters

* Fix subexpressions, crashes, and differentiate externals
2022-02-12 10:04:10 -05:00
0256e42e3b tweak plugin names in cargo.toml (#4441) 2022-02-12 08:14:17 -06:00
48f4766a5f forgot some plugins (#4439) 2022-02-12 06:55:20 -06:00
8ccc8e445f tweak the wix (#4438) 2022-02-12 06:43:52 -06:00
1fd7b9ac38 roll commands (#4437)
* roll commands

* removed repeated funtion
2022-02-12 06:11:54 -05:00
b4b7524206 changed example description (#4434) 2022-02-12 06:10:41 -05:00
328f7e92a0 Hide alias (#4432)
* Add alias interning

Now, AliasId is used to reference aliases stored in EngineState, similar
to decls, blocks, etc.

* Fix wrong message

* Fix using decl instead of alias

* Extend also alias id visibility

* Merge also aliases from delta

* Add alias hiding code

Does not work yet but passes tests at least.

* Fix wrong alias lookup and visibility appending

* Add hide alias tests

* Fmt & Clippy

* Fix random clippy warnings in "which" command
2022-02-12 11:50:37 +02:00
fcc13224c1 headers command (#4414)
* headers command

* correct behaviour headers
2022-02-11 21:06:49 -05:00
926177235c Added quiet flag rm command #4423 (#4430)
* rm now uses -f flag to not print anything

* changed quiet flag to q not f

* Changed value passed to Value::Nothing in rm command
2022-02-12 01:22:40 +02:00
85d1a681c7 Remove stringification for binary values in save command (#4428)
* Remove stringification for binary values in `save`

* Fix typo and clippy warning
2022-02-11 14:26:36 -05:00
968ef1e953 add parameter to set thread count for parallel commands (#4424) 2022-02-11 12:46:36 -06:00
JT
a16e485cce Add support for defining known externals with their own custom completions (#4425)
* WIP for known externals

* Now completions can work from scripts

* Add support for definiing externs

* finish cleaning up old proof-of-concept
2022-02-11 13:38:10 -05:00
JT
a767fa369c Improve quote path completions with drill-down (#4422) 2022-02-11 09:42:15 -05:00
JT
886ed5ab2d Fix captures (#4421)
* Fix rowcondition and import captures

* Only check extra blocks if not yet seen
2022-02-11 07:37:10 -05:00
JT
e16d6ae00c Improve external command completions with spaces (#4420) 2022-02-11 07:05:48 -05:00
ba4d8ae8c3 tweak wording (#4415) 2022-02-10 17:27:51 -06:00
JT
e6db37bc82 Fix multi-command variable captures (#4413) 2022-02-10 18:15:15 -05:00
0e5f4d88c5 turn down the volume a little bit (#4412) 2022-02-10 15:22:39 -06:00
JT
2e3b2a48ee Fix string interpolation paren cases (#4410) 2022-02-10 11:09:08 -05:00
5cf91cb30d deprecated commands (#4405)
* deprecated commands

* deprecated insert command
2022-02-10 12:55:19 +00:00
28947ff9a9 fix broken -w param for grid (#4397) 2022-02-10 07:29:53 -05:00
JT
c2118e7505 Fix help flag (#4398)
* Match 'help command' to 'command --help'

* Fix tests
2022-02-09 21:24:29 -05:00
e1f98c1bfd Fix trash-support feature flag (#4394)
Pass it through to be inclued with `--all-features`

Make clippy without `--all-features` happy
2022-02-09 18:20:46 -05:00
12d4c2986c Fix docs for kill command in engine-q (#4393) 2022-02-09 18:20:20 -05:00
f275644e13 add --perf cli param (#4391)
* add `--perf` cli param

* clippy

* fixed 2 `cp` tests on windows
2022-02-09 16:08:16 -06:00
JT
fc88a8538b Make let-env work like let (#4389)
* Make let-env work like let

* Fix tests
2022-02-09 13:41:41 -05:00
JT
5d18e07b7d Bump reedline (#4388) 2022-02-09 11:04:31 -05:00
JT
5a1d81221f Move 'nth' into 'select' (#4385) 2022-02-09 09:59:40 -05:00
JT
43850bf20e Re-port filesystem commands (#4387)
* Re-port the filesystem commands

* Remove commented out section
2022-02-09 09:56:27 -05:00
94ab981235 Fix "Index out of bounds" when input to the group-by filter is empty. #4369 (#4382)
* Fix "index out of bounds" when input to group-by is empty #4369

* Fix formatting #4369

* Adds test for empty input

Co-authored-by: Ray Henry <ray.henry@thermofisher.com>
2022-02-09 08:47:47 -06:00
JT
f9e1c4ef50 Use 'table' on scripts and -c commands (#4377)
* Use 'table' on scripts and -c commands

* Fix tests

* Oops, missed a spot
2022-02-09 05:58:54 -05:00
659da3c4a4 Make ANSI stripping lazy in more places (#4380)
Same rationale as in #4378

Also accelerate `grid`

before:

```
Command being timed: "./eager_nu -c for i in 0..100000 { echo whatever } | grid"
        User time (seconds): 0.21
        System time (seconds): 0.05
        Percent of CPU this job got: 36%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.71
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 48112
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 0
        Minor (reclaiming a frame) page faults: 10580
        Voluntary context switches: 266
        Involuntary context switches: 2595
        Swaps: 0
        File system inputs: 0
        File system outputs: 0
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0
```

after:

```
Command being timed: "./lazy_nu -c for i in 0..100000 { echo whatever } | grid"
        User time (seconds): 0.14
        System time (seconds): 0.05
        Percent of CPU this job got: 33%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.60
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 48272
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 1
        Minor (reclaiming a frame) page faults: 10582
        Voluntary context switches: 286
        Involuntary context switches: 831
        Swaps: 0
        File system inputs: 56
        File system outputs: 0
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0
```
2022-02-08 18:25:31 -06:00
9c7feb2b19 Reduce table allocs: only strip ANSI if necessary (#4378)
For the width calculations for table layout the `strip_ansi` function
has to be called frequently. By checking for the ASCII control chars
(0x00 to 0x1f) except `\n` that are stripped by `strip_ansi_escapes` the number of
necessary allocations can be reduced significantly for the simple case
of text not containing ANSI escapes.

**Benchmark:**

```
nu -c "for i in 0..1000 { ls } | flatten | table"
```

**Allocation reduction**

Running on the nushell repo root as the directory, this change reduces the
allocation volume by approximately 400 MB

(Measured run via KDE heaptrack)
**Speed improvement to output**

Measured via `/usr/bin/time -v`

*before*

```
Command being timed: "./eager_nu -c for i in 0..1000 {ls} | flatten | table"
	User time (seconds): 0.87
	System time (seconds): 0.14
	Percent of CPU this job got: 87%
	Elapsed (wall clock) time (h:mm:ss or m:ss): 0:01.16
	Average shared text size (kbytes): 0
	Average unshared data size (kbytes): 0
	Average stack size (kbytes): 0
	Average total size (kbytes): 0
	Maximum resident set size (kbytes): 18888
	Average resident set size (kbytes): 0
	Major (requiring I/O) page faults: 0
	Minor (reclaiming a frame) page faults: 4809
	Voluntary context switches: 38
	Involuntary context switches: 14
	Swaps: 0
	File system inputs: 0
	File system outputs: 0
	Socket messages sent: 0
	Socket messages received: 0
	Signals delivered: 0
	Page size (bytes): 4096
	Exit status: 0
```

*after*

```
Command being timed: "./lazy_nu -c for i in 0..1000 {ls} | flatten | table"
	User time (seconds): 0.63
	System time (seconds): 0.14
	Percent of CPU this job got: 80%
	Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.97
	Average shared text size (kbytes): 0
	Average unshared data size (kbytes): 0
	Average stack size (kbytes): 0
	Average total size (kbytes): 0
	Maximum resident set size (kbytes): 18660
	Average resident set size (kbytes): 0
	Major (requiring I/O) page faults: 0
	Minor (reclaiming a frame) page faults: 5149
	Voluntary context switches: 24
	Involuntary context switches: 5
	Swaps: 0
	File system inputs: 0
	File system outputs: 0
	Socket messages sent: 0
	Socket messages received: 0
	Signals delivered: 0
	Page size (bytes): 4096
	Exit status: 0
```
2022-02-08 17:43:32 -06:00
cf20eed7bc Support records in reject command (#4373)
* support records in reject command

* add reject command tests
2022-02-08 15:57:46 -05:00
6d303f2ca3 update starship docs (#4375) 2022-02-08 13:08:02 -06:00
JT
b16e72f0a5 Update README.md 2022-02-08 13:59:08 -05:00
JT
56ba57c74a Update README.md 2022-02-08 13:57:40 -05:00
baceb54660 update ls_colors defaults (#4371) 2022-02-08 11:13:04 -06:00
JT
19caef260d Fix 'enter' to expand path before checking for it (#4370) 2022-02-08 11:21:17 -05:00
565be6aaef change pivot to transpose 2022-02-08 09:32:27 -06:00
JT
7242e52faa Merge pull request #4364 from nushell/merge-engine-q
Merge engine-q into Nushell (second try)
2022-02-08 10:02:28 -05:00
JT
101f4f62a8 gitignore conflict fix 2022-02-08 09:23:41 -05:00
JT
5fabfda57b merge main 2022-02-08 08:28:21 -05:00
JT
a660720b68 Bump to 0.44 (#4365) 2022-02-07 20:15:46 -05:00
JT
d70d91e559 Remove old nushell/merge engine-q 2022-02-07 14:54:06 -05:00
10c4c50f1f removed old files 2022-02-07 19:28:22 +00:00
dbcadbc12c moved folders 2022-02-07 19:23:12 +00:00
fdce6c49ab engine-q merge 2022-02-07 19:11:34 +00:00
JT
9259a56a28 Update README.md 2022-02-07 08:22:31 -05:00
265ee1281d Drop with iter range (#4242)
* Allow range in 'drop nth'

* Unit tests for drop nth range

* Add range case to the description

* Fix description 2

* format fixes

* Fix example and some refactoring

* clippy fixes
2022-02-07 08:02:35 -05:00
JT
a78c82d811 Make PipelineData helpers collect rawstreams (#969) 2022-02-07 07:44:18 -05:00
JT
3ab55f7de9 bump reedline (#970) 2022-02-07 07:40:17 -05:00
JT
84d3620d9b Oops, match semantics of each group/window (#967) 2022-02-06 21:26:01 -05:00
JT
8a373dd554 Add each window (#966) 2022-02-06 20:23:18 -05:00
JT
c3e0e8eb5c Add par-each group (#965) 2022-02-06 19:28:09 -05:00
JT
de4449c3ee Fix completion duplicates (#964) 2022-02-06 16:33:33 -05:00
796b7a1962 Reedline bump (#962)
* reedline bump

* reedline bump

* reedline bump
2022-02-06 18:18:32 +00:00
JT
a911b21256 Switch more commands to redirecting blocks (#956) 2022-02-05 21:03:06 -05:00
80306f9ba6 Update reedline to race-condition-free history (#955) 2022-02-05 18:16:21 -06:00
2dd32c2b88 Rename some files (#952)
* renamed some files

* clippy

* update tests
2022-02-05 12:35:02 -05:00
JT
3eba90232a Port each group (#953) 2022-02-05 12:34:35 -05:00
JT
c4858fb202 Remove broken error make examples (#951) 2022-02-05 12:01:08 -05:00
JT
8a93548de2 Error make (#948)
* Add `error make` and improve `metadata`

* Allow metadata to work on just a pipeline
2022-02-05 09:39:51 -05:00
e45e8109aa fix test math/avg.rs can_average_bytes (#946) 2022-02-05 07:01:10 -05:00
709927cee4 Sort keystuff (#945)
* sort things

* reorg
2022-02-04 17:20:54 -06:00
abaeffab91 default keybindings command (#943) 2022-02-04 17:20:40 -06:00
73dcec8ea1 fix some of the sort_by tests several more left to do (#942) 2022-02-04 13:51:49 -08:00
b26acf97bd a few more tests (#941) 2022-02-04 15:42:18 -06:00
JT
f29dbeddd7 Allow let-env to be dynamic (#940) 2022-02-04 16:19:13 -05:00
8204cc4f28 fix ls and ls tests (#931)
* fix `ls` and ls tests

* tweak to ls so it doesn't scream on empty dirs

* clippy

* reworked `ls` to put in what was left out
2022-02-04 14:32:13 -06:00
c2f6dfa75c add nth tests to mod.rs (#934) 2022-02-04 12:08:25 -08:00
JT
90f6b6aedf Simplify describe (#933) 2022-02-04 14:51:36 -05:00
ece1e43238 fix into filesize tests and filesize (#932)
* fix into filesize tests and filesize

* tweaks

* added span back for like the 10th time

* Update filesize.rs

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
2022-02-04 13:26:08 -06:00
fefd5fef12 Allow def-env to hide environment variables (#921) 2022-02-04 20:02:03 +02:00
dd2d601471 fix lines tests (#930) 2022-02-04 11:34:01 -06:00
c6dad0d5eb fix find tests (#928) 2022-02-04 10:47:24 -06:00
JT
522a53af68 Add support for quick completions (#927) 2022-02-04 10:30:21 -05:00
JT
1a246d141e Improve subcommand completions (#926) 2022-02-04 08:38:23 -05:00
b86c6db400 fix cal tests (#925)
* fix 1 test

* missed 1 test
2022-02-04 07:24:36 -06:00
1e86af2fb9 list keybinding options (#906)
* list keybinding optins

* list keybinding options

* clippy error
2022-02-04 06:47:18 +00:00
JT
a008f1aa80 Command tests (#922)
* WIP command tests

* Finish marking todo tests

* update

* update

* Windows cd test ignoring
2022-02-03 21:01:45 -05:00
ac0b331f00 Update reedline to paste multiple command lines (#920)
* Update reedline to paste multiple command lines

* Remove comments for non-user events
2022-02-03 16:56:39 -06:00
3d3298290a add case-insensitive sorting (#919) 2022-02-03 15:18:18 -06:00
e1c28cf06b add --du to ls command (#917) 2022-02-03 13:58:32 -06:00
2f0bbf5adb du command (#916)
* wip on `du` command

* working
2022-02-03 11:35:06 -06:00
0043b9da74 added defaults for colors (#915) 2022-02-03 07:03:47 -06:00
b9c2bf226f Obligatory reedline bump (#914)
- Keybinding related improvements
- internals
- Vi insert should know more keybindings
2022-02-02 20:24:24 -05:00
JT
cc1b784e3d Add initial nu-test-support port (#913)
* Add initial nu-test-support port

* finish changing binary name

* Oops, these aren't Windows-safe tests
2022-02-02 15:59:01 -05:00
cbdc0e2010 Windows ps update (#909)
* query command with json, web, xml

* query xml now working

* clippy

* comment out web tests

* Initial work on query web

For now we can query everything except tables

* Support for querying tables

Now we can query multiple tables just like before, now the only thing
missing is the test coverage

* Revert "Query plugin"

* augment `ps -l` on windows to display more info

Co-authored-by: Luccas Mateus de Medeiros Gomes <luccasmmg@gmail.com>
2022-02-01 15:05:26 -06:00
004d7b5ff0 query command with json, web, xml (#870)
* query command with json, web, xml

* query xml now working

* clippy

* comment out web tests

* Initial work on query web

For now we can query everything except tables

* Support for querying tables

Now we can query multiple tables just like before, now the only thing
missing is the test coverage

* finish off

* comment out web test

Co-authored-by: Luccas Mateus de Medeiros Gomes <luccasmmg@gmail.com>
2022-02-01 12:45:48 -06:00
ebaa584c5e Reedline bump (#905)
* reedline bump

* reedline bump
2022-01-31 19:17:23 -05:00
c80a15cdfe should be inclusive (#904)
* should be inclusive

* changed tests due to spans being different
2022-01-31 17:02:36 -06:00
JT
4c9df9c7c1 Add a fallback if Windows external spawn fails (#902)
* Add a fallback if Windows external spawn fails

* Remove path workaround

* More fixes

* More fixes

* Be more flexible with error tests
2022-01-31 12:42:12 -05:00
JT
96fedb47ee Wait on the plugin child to prevent zombies (#901) 2022-01-31 10:20:11 -05:00
b1aa8f4edf Add strftime cheatsheet for into datetime (#869) (#883)
* Add strftime cheatsheet for `into datetime` (#869)

* proper table for strftime cheatsheet of `into datetime` (#883)
2022-01-31 07:32:35 -06:00
JT
d62716c83e Use 'table' during internal->external (#898)
* Use 'table' during internal->external

* Preserve more of config
2022-01-31 07:52:05 -05:00
def5869c1c command(split-by) (#897) 2022-01-30 18:29:21 -05:00
76a4455255 reedline bump (#896) 2022-01-30 22:15:34 +00:00
2fbd182993 Allow viewing the source code of blocks (#894)
* Add spans to blocks and view command

* Better description; Cleanup

* Rename "view" command to "view-source"
2022-01-31 00:05:25 +02:00
67cb720f24 Port update cells command (#891)
* Port update cells command

Clean up, nicer match statements in UpdateCellsIterator

Return columns flag into HashSet errors

Add FIXME: for update cell behavior on nested lists

* Fix: process cells for Record when no columns are specified

* Fix: address clippy lints for unwrap and into_iter

* Fix: don't step into lists and don't bind $it var
2022-01-30 23:41:05 +02:00
JT
a51d45b99d Ignore clippy's erroneous warnings (#895) 2022-01-30 16:12:41 -05:00
1fd0ddb52c Maybe solve the none bug? (#860)
* Maybe solve the none bug?

* cargo fmt

* use nothing, not string

* check at last

* I check it at last

* Use error which has span

* use not found error

* fix error

* use a empty value length?

* * Add commit about what I change and fmt

Now all test passed, but I do not know if it is right

* update the test

* check if it is nothing

* update commit

* Rename test

Co-authored-by: Jakub Žádník <kubouch@gmail.com>
2022-01-30 15:23:28 +02:00
JT
060a4b3f48 Port detect columns (#892) 2022-01-30 07:52:24 -05:00
95a5e9229a add help --find to help doc (#890) 2022-01-30 05:54:15 -05:00
3c8716873e Port rotate (#880)
* Add rotate command

* Add rotate counter clockwise

* Fix comments in the code

* Fix clippy warnings

* Fix comment

* Fix wrong step for non even table sizes

* Fix comment for moving through array

* Refactor rotate and have only one command with a --ccw flag for counter-clockwise rotation. By default, rotate is clockwise

* Update usage description
2022-01-29 15:47:28 -05:00
JT
44821d9941 Add support for def-env and export def-env (#887) 2022-01-29 15:45:46 -05:00
bffb4950c2 add in a table test with multiple columns (#886) 2022-01-29 09:45:16 -08:00
dc6f1c496b fixes process path being truncated (#885) 2022-01-29 08:50:48 -06:00
JT
65ae3160ca Variables should error on use rather than value span (#881) 2022-01-29 08:00:48 -05:00
1a25970645 Port rename (#877)
* Port rename

* Update description

* Fix fmt issues

* Refactor the code a bit and move things around
2022-01-29 05:26:47 -05:00
9450bcb90c Update 3rd_Party_Prompts.md (#878)
`decode utf-8` not required now
2022-01-28 19:41:48 -05:00
JT
e91d8655c6 Only trim prompt (#876)
* Only trim the output for prompts

* Only remove the last newline
2022-01-28 18:22:09 -05:00
JT
4c029d2545 Automatically trim ends of stdin/stdout strings (#874) 2022-01-28 16:59:00 -05:00
c37f844644 Bump reedline (#873)
Should remove the need for manual `str find-replace -a (char newline) (char crlf)` in `PROMPT_COMMAND`

Fixes #575
2022-01-28 16:26:19 -05:00
JT
86eeb4a5e7 Fix a bad slice into erroring utf-8 buffer (#872) 2022-01-28 15:32:46 -05:00
JT
020ad24b25 "maybe text codec" version 2 (#871)
* Add a RawStream that can be binary or string

* Finish up updating the into's
2022-01-28 13:32:33 -05:00
3f9fa28ae3 Add F1-F12 key support (#866)
* Add F1-F12 key support

* Fix error reporting: keybinding parser

* Reject more than one character
2022-01-28 13:14:51 -05:00
JT
e11ac9f6f8 Harden highlighter against alias spans (#867) 2022-01-28 07:29:45 -05:00
JT
fd9e380a1e Move history search to ctrl-x (#864) 2022-01-28 06:44:12 +11:00
bfb9822475 Accomodate reedline#270 (#863)
Rename `ContextMenu` to `CompletionMenu`

Supply the completer directly to the line editor
2022-01-28 05:44:35 +11:00
9926561dd7 Fix into datetime example parameter type (#862) 2022-01-28 00:06:07 +11:00
267ff4b0cf using menu trait (#861) 2022-01-27 07:53:23 +00:00
JT
04395ee05c Allow equals to sep long flag and arg (#858) 2022-01-27 12:20:12 +11:00
JT
6f4b7efd3e Also set $in-variable with input (#856)
* Also set in-variable with input

* Fix test

* Add more tests
2022-01-27 10:46:13 +11:00
a4421434d9 add support for Floats for sort-by (#857) 2022-01-26 14:44:37 -08:00
e8b8836977 Add suport for Filesize and Date for sort-by command (#855) 2022-01-26 13:54:31 -08:00
JT
78b5da8255 Allow let/let-env to see custom command input (#854) 2022-01-27 06:00:25 +11:00
JT
83ec374995 Add -c flag and others to cmdline args (#853)
* Add -c flag and others to cmdline args

* finish a little bit of cleanup

* Oops, forgot file
2022-01-26 12:26:43 -05:00
JT
8ee619954d Start support for commandline args to nu itself (#851)
* cmdline args wip

* WIP

* redirect working

* Add help and examples

* Only show flags in signature of more than help
2022-01-27 01:42:39 +11:00
JT
cdc8e67d61 Remove unused repo parts (#4271)
* Remove unused repo parts

* Update README

* cargo fmt
2022-01-26 07:31:04 +11:00
JT
285f65ba34 Port exec command (#849)
* Port exec command

* fix windows

* lint
2022-01-26 04:27:35 +11:00
JT
3023af66fd Port default command (#848) 2022-01-26 02:02:15 +11:00
JT
1ca3e03578 Fix expanding external args (#847) 2022-01-26 00:11:35 +11:00
f4c0538653 Flatten records. Not thoroughly tested though (#845) 2022-01-25 23:07:37 +11:00
69954a362d history-menu (#846) 2022-01-25 09:39:22 +00:00
JT
0cecaf82b1 Delete TODO.md 2022-01-25 13:53:55 +11:00
5c749fcc63 allow fetch command to add custom headers (#840) 2022-01-25 13:19:29 +11:00
JT
6e44012a2f Fix bug in date comparison (#842) 2022-01-24 16:55:45 -05:00
JT
988a873466 Allow open to read its filename from input (#841)
* Allow `open` to read its filename from input

* Add examples
2022-01-25 08:04:28 +11:00
ec94ca46bb Update pull_request_template.md 2022-01-24 21:45:20 +02:00
53f41c1985 Port move (#833)
* Remove comment

* Fix merge not retaining LS_COLORS

* Add move command

* Add checking for non-existent columns

* Add move command examples; Disallow flag shorthand
2022-01-24 21:43:38 +02:00
JT
12189d417b Update pull_request_template.md 2022-01-25 06:01:03 +11:00
JT
0875d0451b Create pull_request_template.md 2022-01-25 05:58:09 +11:00
JT
62e9698b11 Allow external args to expand globs (#839)
* Allow external args to expand globs

* WIP

* A bit of cleanups and refactor to glob_from

* oops, add file
2022-01-25 05:26:56 +11:00
JT
3d0b1ef1ce Highlight help tutor (#838)
* WIP

* Syntax highlight help, add tutor
2022-01-25 02:05:19 +11:00
JT
525ed7653f Add var vals and alias expansions to scope var (#837)
* Add var vals and alias expansions to scope var

* Fix test
2022-01-25 01:19:38 +11:00
8a1b2d0812 fix several cases where sort-by was crashing engine-q (#836) 2022-01-23 20:52:19 -08:00
d4fb95a98c allow find to respect ls_colors (#834) 2022-01-24 12:23:03 +11:00
f82e2fbac6 Port find command (#658)
* Add `Find` command

* Complete rustdoc for test `Value` constructors

* Use `Option::unwrap_or` instead of match

* Add `Value::test_filesize` constructor

* Handle searching for terms in `find`

* Fix `find` command signature

* Return multiple elements when `find`ing by predicate

* Do not accept rest parameter with predicate

* Handle `CellPath` in `r#in` and `not_in` for `Find`

* Use `PipelineData::filter`
2022-01-23 16:32:02 -06:00
e11a030780 capture keyboard event (#832)
* capture keyboard event

* try a different strategy - still not working right

* fixed up
2022-01-23 16:09:39 -06:00
4e171203cc Fix cd-ing into a file (#831)
* Add custom error for path not being a directory

* Fix cd issue with cd-ing into a file

* Keep formatting style as before

* Check if path is not a directory and return error if that's the case
2022-01-23 15:02:12 +02:00
be0d221d56 ansi cut 2.0 (#827) 2022-01-23 13:35:25 +11:00
fd3eec81b5 Bump ansi-cut version to 0.2.0 (#822)
Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>
2022-01-22 18:36:40 -05:00
3d40e169ce fix to retain ls_colors coloring from ls (#824)
fixes #823
2022-01-22 18:36:27 -05:00
JT
bf9340ec48 Only escape backslash on windows (#825) 2022-01-22 18:35:52 -05:00
JT
310ecb79b6 Add flag completions (#817) 2022-01-22 16:18:31 -05:00
89d852f76c port sort_by without float (yet) (#814) 2022-01-22 12:49:50 -08:00
JT
af52def93c Fix doc comments for custom commands (#815) 2022-01-22 13:24:47 -05:00
6a446f708d add hash base64 (#813) 2022-01-22 10:23:55 -06:00
afe83104c6 Fix flatten's dropping column issue #756 (#805)
* Fix flatten's dropping column issue, and do some cleanup - better variable naming.

* Fix failing test

* Fix failing tests
2022-01-23 01:19:40 +11:00
JT
b58aad5eb0 Make external app error uniform (#812) 2022-01-23 01:12:34 +11:00
47d004ae24 added 3rd party prompt docs (#811) 2022-01-22 05:12:34 -06:00
446f160320 Add how to setup oh-my-posh with engine-q document (#810) 2022-01-22 16:05:45 +11:00
564c2dd7d1 Port merge command from Nushell (#808)
* Add example test to zip

* Port merge command from Nushell

On top of the original merge, this one should not collect a stream
returned from the merged block and allows merging records.
2022-01-22 01:50:26 +02:00
e1272f3b73 lint: remove trailing whitespace (#806) 2022-01-22 10:29:10 +11:00
JT
6fa022b0a8 Add group-by and transpose (aka pivot) (#803) 2022-01-21 15:28:21 -05:00
2df37d6ec2 seed cmd_duration_ms (#798)
* seed cmd_duration_ms

* tweak
2022-01-21 13:50:44 -06:00
0651e2b31f Upgrade reedline for partial hint completion (#802) 2022-01-22 06:21:22 +11:00
0ef0277882 allow use to parse quoted paths (#800) 2022-01-21 13:20:13 -06:00
JT
939745ad67 Support recursive functions in capture (#797) 2022-01-21 11:39:55 -05:00
JT
f44954da68 Add CMD_DURATION_MS (#794) 2022-01-22 01:53:49 +11:00
846a048bba menu-performance (#793) 2022-01-21 08:59:29 +00:00
057bfff0cb add term size command (#792)
* add `term-size` command

* Update term_size.rs

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
2022-01-21 14:31:33 +11:00
JT
ac07d93b02 let prompt env vars take strings (#790)
* let prompt env vars take strings

* clippy

* clippy
2022-01-21 13:22:03 +11:00
JT
91883bd572 Better help search (#789) 2022-01-20 18:58:58 -05:00
JT
69b2ed5566 bump reedline (#788) 2022-01-20 18:58:48 -05:00
JT
b4e61a056c add cd - support (#787) 2022-01-21 07:51:44 +11:00
JT
724cfaa890 Bump reedline (#785) 2022-01-20 13:57:47 -05:00
65ef7b630b PATH for completions for each os (#784) 2022-01-20 13:46:52 -05:00
JT
45b3592739 add some more division for units (#783) 2022-01-21 05:23:26 +11:00
JT
33ffb2c39a Add which command, add external completions, and builtin var completions (#782)
* Add which and external completions

* WIP

* Finish up external and var completions

* fix windows
2022-01-21 05:02:53 +11:00
d4b6b4b09a update all cargo crates to edition 2021 (#781) 2022-01-21 00:13:45 +11:00
54ed82a19a completeness, make case-insensitive (#780) 2022-01-20 06:20:00 -06:00
JT
be8c905ca7 Show error on bad config, but keep going (#778) 2022-01-20 03:42:12 +11:00
JT
d2d22815fb Improve env shorthand parse (#777) 2022-01-20 01:58:12 +11:00
6514a30b5d general keybindings (#775)
* general keybindings

* get value function

* check error for keybinding

* cmd and send for keybingins

* better error message
2022-01-19 07:28:08 -06:00
JT
73ad862042 Update README.md 2022-01-19 13:33:04 +11:00
JT
71feacf46c Update README.md 2022-01-19 13:32:45 +11:00
JT
db704ebaed Update README.md 2022-01-19 13:32:25 +11:00
ff9d88887b simple event keybinding (#773) 2022-01-18 19:32:45 +00:00
JT
4e8e03867c Update release.yml 2022-01-19 04:51:21 +11:00
JT
49e8af8ea5 Bump to 0.43 (#4264) 2022-01-18 12:06:12 -05:00
JT
d5d61d14b3 Tutor eq (#4263)
* Fix clippy lints

* Fix clippy lints

* Fix clippy lints

* Add e-q tutor page
2022-01-19 03:22:23 +11:00
6d554398a7 added prompt_command_right to docs 2022-01-18 07:45:19 -06:00
60cbb7e75d another type-o 2022-01-18 07:43:40 -06:00
efd9c5c7c3 type-o 2022-01-18 07:42:12 -06:00
JT
f562a4526c Fix clippy lints (#4262)
* Fix clippy lints

* Fix clippy lints

* Fix clippy lints
2022-01-18 23:33:28 +11:00
e6c09f2dfc Update sysinfo version (#4261) 2022-01-18 22:37:52 +11:00
73a68954c4 Bump follow-redirects from 1.14.4 to 1.14.7 in /samples/wasm (#4258)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.4 to 1.14.7.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.4...v1.14.7)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-18 22:37:06 +11:00
20eb348896 simple keybinding parsing (#768) 2022-01-18 08:48:28 +00:00
2c75aabbfc allow size and other to count bytes from binary with as_string() (#769) 2022-01-17 17:41:59 -06:00
01e691c5ba Fix unicode word wrapping with ansi-cut (#767)
Ansi-cut expects ranges of character numbers (of the non-ansi control
sequence characters) instead of byte indices.
This fixes the panics when wrapping of non-unicode lines (which exceed
the demanded number of characters as byte indices).
Also rectifies some wrong wrapping of unicdoe containing lines that
don't panic
2022-01-17 15:31:21 -05:00
ac36f32647 remove dialoguer completions in favor of reedline's (#766) 2022-01-17 09:51:44 -06:00
085a7c18cb fix signature (#765) 2022-01-17 09:14:33 -06:00
JT
0f85646d8e Let 'to toml' output block source (#763) 2022-01-17 19:25:12 +11:00
c55b6c5ed5 fix list formatting (#762) 2022-01-16 16:40:40 -06:00
JT
283a615ecc Enter now requires a directory (#761) 2022-01-17 03:14:34 +11:00
JT
9b128b7a03 Add rest to get, bump reedline (#760) 2022-01-17 02:40:11 +11:00
bfe3c50dce Fix empty entry in ls (#759) 2022-01-17 02:40:00 +11:00
5fae96a6b1 Fix not equal returning error when same things are compared in some cases (#709)
* Fix not equal returning error when same things are compared in some cases

* Equality operators supports all type combinations
2022-01-17 01:34:20 +11:00
3b4baa31b6 Fix ls relative path & command argument path expansion (#757)
* Switch to short-names when the path is a relative_path (a dir) and exit with an error if the path does not exist

* Remove debugging print line

* Show relative filenames... It does not work yet for ls ../

* Try something else to fix relative paths... it works, but the ../ code part is not very pretty

* Add canonicalize check and remove code clones

* Fix the canonicalize_with issue pointed out by kubouch. Not sure the prefix_str is what kubouch suggested

* Fix the canonicalize_with issue pointed out by kubouch. Not sure the prefix_str is what kubouch suggested

* Add single-dot expansion to nu-path

* Move value path expansion from parser to eval

Fixes #745

* Remove single dot expansion from parser

It is not necessary since it will get expanded anyway in the eval.

* Fix ls to display globs with relative paths

* Use pathdiff crate to get relative paths for ls

Co-authored-by: Stefan Stanciulescu <contact@stefanstanciulescu.com>
2022-01-17 00:55:56 +11:00
746641edae Port seq command (#755)
Signed-off-by: nibon7 <nibon7@163.com>
2022-01-17 00:52:41 +11:00
JT
fa5aab8170 Add simple stdin input command (#754)
* Add simple stdin input command

* Add binary input

* Tweak binary view
2022-01-16 15:28:28 +11:00
JT
b78924c777 Add support for load-env (#752) 2022-01-15 18:50:11 -05:00
JT
75db4a75bc Save (#750)
* Add support for save

* Add support for binary filetypes
2022-01-16 07:44:20 +11:00
JT
8f4ee14d85 Hide Windows ps status, bump reedline (#749) 2022-01-16 06:44:24 +11:00
89d99db94f menu options (#748) 2022-01-15 17:01:44 +00:00
JT
f9c0d223c1 Improve keyword parsing, including for (#747)
* Improve keyword parsing, including for

* touchup
2022-01-16 02:26:52 +11:00
21a7278259 Revert "Fix ls relative path and erroring on fake dir (#697)" (#744)
This reverts commit bee5ba3deb.
2022-01-15 12:58:24 +02:00
bee5ba3deb Fix ls relative path and erroring on fake dir (#697)
* Switch to short-names when the path is a relative_path (a dir) and exit with an error if the path does not exist

* Remove debugging print line

* Show relative filenames... It does not work yet for ls ../

* Try something else to fix relative paths... it works, but the ../ code part is not very pretty

* Add canonicalize check and remove code clones

* Fix the canonicalize_with issue pointed out by kubouch. Not sure the prefix_str is what kubouch suggested

* Fix the canonicalize_with issue pointed out by kubouch. Not sure the prefix_str is what kubouch suggested
2022-01-15 12:30:39 +02:00
a7241f9899 add seq_date command (#743)
* add `seq_date` command

* fixed a reedline type-o

* copy-n-paste error
2022-01-14 16:07:28 -06:00
40484966c3 Make env var eval order during "use" deterministic (#742)
* Make env var eval order during "use" deterministic

Fixes #726.

* Merge delta after getting config

To make sure env vars are all in the engine state and not in the stack.
2022-01-15 08:06:32 +11:00
7c23ae5cb0 update to final merge checklist #735 (#741) 2022-01-14 10:06:34 -06:00
JT
ca215c1152 Add nu-system and rewrite ps command (#734)
* Add nu-system and rewrite ps command

* Add more deps

* Add more deps

* clippy

* clippy

* clippy

* clippy

* clippy

* clippy
2022-01-14 17:20:53 +11:00
JT
2b6ce4dfe5 Bump reedline again (#732) 2022-01-14 07:03:29 +11:00
JT
bc1e1aa944 Clippy fixes for Rust 1.58 (#733)
* Clippy fixes for Rust 1.58

* Try different message
2022-01-14 06:40:25 +11:00
1ecbebb24a Add instructions to run engine-q (#731)
* Add instructions to run engine-q

* Include mention of feature flags
2022-01-14 04:28:35 +11:00
JT
82d90f4930 Add support for var/string interp for external names (#729) 2022-01-13 19:17:45 +11:00
d0f9943709 expose a few more types to custom commands (def) (#725) 2022-01-12 09:59:07 -06:00
58c5ea4937 menu with tab (#724) 2022-01-12 10:57:37 +00:00
JT
186da4d725 Fixing captures (#723)
* WIP fixing captures

* small fix

* WIP

* Rewrite to proof-of-concept better parse_def

* Add missing file

* Finish capture refactor

* Fix tests

* Add more tests
2022-01-12 15:06:56 +11:00
47495715a6 context menu with nucompleter (#722) 2022-01-11 21:53:42 +00:00
ffb086d56f a little better table alignment (#720) 2022-01-11 08:49:15 -06:00
74fd78e02c reedline bump (#717) 2022-01-11 07:21:28 +00:00
160339bd1f add in a new select test that exercises a different match arm of the select command (#718) 2022-01-10 13:29:52 -08:00
JT
d3bfc61524 Don't panic on alias errors (#713) 2022-01-10 13:52:01 +11:00
733b2836f1 Cleanup parsing of use and hide commands (#705) 2022-01-10 12:39:25 +11:00
3a17b60862 new command fmt to format numbers (#707)
* new command `fmt` to format numbers

* remove comments
2022-01-09 19:19:41 -06:00
JT
7970e71bd4 bump reedline (#712) 2022-01-10 12:06:25 +11:00
b49885bb85 Revert "added a better default for ls_colors (#703)" (#711)
This reverts commit d63eac69e5.
2022-01-09 16:48:29 -06:00
JT
4860014cec silly keymap addition for quick shell changing (#710) 2022-01-10 09:17:58 +11:00
476d543dee Update descriptions for crates split out from nu-cli (#4247)
`nu-command` and `nu-data` were split out, but the descriptions still
say 'CLI'.

Signed-off-by: Michel Alexandre Salim <salimma@fedoraproject.org>
2022-01-09 06:05:50 -06:00
d63eac69e5 added a better default for ls_colors (#703) 2022-01-08 08:30:48 -06:00
38e0527083 add more chars (#701)
* add more chars

* group nerdfonts with nf- prefix

* labeled unicode weather symbols
2022-01-08 07:19:51 -06:00
3b467bedd9 Add reduce command (#700)
* Add reduce command

* Fix example and missing test commands

* Add forgotten file
2022-01-08 02:40:40 +02:00
f964ce9bc0 Add repository name and current tag to gstat (#692)
* Add repository name to gstat

* Fix getting repo name; Add tag as well
2022-01-07 05:44:05 -06:00
JT
f016a5cb72 Fix short flags with extra (#696) 2022-01-07 08:06:54 +11:00
JT
3478f35330 Default the values of named params (#695) 2022-01-07 07:32:47 +11:00
eab6b322bb Add CR, LF and CRLF to char command (#691) 2022-01-06 20:52:43 +02:00
8a0d2b4e32 double prompt (#686)
* double prompt

* prompt env var name
2022-01-06 12:57:55 +00:00
JT
e44789556b Fix path external (#684)
* Fix external invocation/expansion

* clippy
2022-01-06 21:20:31 +11:00
JT
d39e8c15fe Expand external command names (#682) 2022-01-06 10:32:56 +11:00
47544ad219 Move fetch to extra and clean up some code (#664)
* Move fetch to extra

* Move byte stream code to a function instead of copying it twice

* Fix formatting issues

* Make fetch a default command

* Fix formatting
2022-01-06 10:06:16 +11:00
d0c280f6cc Fixes how environment is cloned inside tight loops (#678)
* Improve cd IO error

* Fix environment cloning in loops

* Remove debug print

* Fmt
2022-01-06 09:21:26 +11:00
JT
14cd798f00 Make ls more forgiving (#681) 2022-01-06 09:21:15 +11:00
JT
cc1ae969fe Allow int/float to coerce in type checker (#679) 2022-01-06 07:58:58 +11:00
JT
3c2a336ef9 Each much clone its env (#675) 2022-01-05 23:08:03 +11:00
JT
f71e16685c Add shells support to auto-cd (#674) 2022-01-05 21:48:55 +11:00
JT
058738c48c More shell fixes (#673) 2022-01-05 17:36:42 +11:00
JT
affb9696c7 Fix directory change lag (#672) 2022-01-05 16:50:27 +11:00
JT
c158d29577 Add shells support (#671) 2022-01-05 15:35:50 +11:00
JT
b4c72e85e1 Limit when we expand external args (#668) 2022-01-05 12:09:53 +11:00
JT
41dbc641cc Some cleanups for cd/PWD (#667)
* Some cleanups for cd/PWD

* Some cleanups for cd/PWD
2022-01-05 11:26:01 +11:00
4584d69715 tweak source parsing to allow quotes around string (#666) 2022-01-05 10:44:48 +11:00
74dcd91cc3 Use only $nu.env.PWD for getting the current directory (#587)
* Use only $nu.env.PWD for getting current directory

Because setting and reading to/from std::env changes the global state
shich is problematic if we call `cd` from multiple threads (e.g., in a
`par-each` block).

With this change, when engine-q starts, it will either inherit existing
PWD env var, or create a new one from `std::env::current_dir()`.
Otherwise, everything that needs the current directory will get it from
`$nu.env.PWD`. Each spawned external command will get its current
directory per-process which should be thread-safe.

One thing left to do is to patch nu-path for this as well since it uses
`std::env::current_dir()` in its expansions.

* Rename nu-path functions

*_with is not *_relative which should be more descriptive and frees
"with" for use in a followup commit.

* Clone stack every each iter; Fix some commands

Cloning the stack each iteration of `each` makes sure we're not reusing
PWD between iterations.

Some fixes in commands to make them use the new PWD.

* Post-rebase cleanup, fmt, clippy

* Change back _relative to _with in nu-path funcs

Didn't use the idea I had for the new "_with".

* Remove leftover current_dir from rebase

* Add cwd sync at merge_delta()

This makes sure the parser and completer always have up-to-date cwd.

* Always pass absolute path to glob in ls

* Do not allow PWD a relative path; Allow recovery

Makes it possible to recover PWD by proceeding with the REPL cycle.

* Clone stack in each also for byte/string stream

* (WIP) Start moving env variables to engine state

* (WIP) Move env vars to engine state (ugly)

Quick and dirty code.

* (WIP) Remove unused mut and args; Fmt

* (WIP) Fix dataframe tests

* (WIP) Fix missing args after rebase

* (WIP) Clone only env vars, not the whole stack

* (WIP) Add env var clone to `for` loop as well

* Minor edits

* Refactor merge_delta() to include stack merging.

Less error-prone than doing it manually.

* Clone env for each `update` command iteration

* Mark env var hidden only when found in eng. state

* Fix clippt warnings

* Add TODO about env var reading

* Do not clone empty environment in loops

* Remove extra cwd collection

* Split current_dir() into str and path; Fix autocd

* Make completions respect PWD env var
2022-01-05 09:30:34 +11:00
JT
8f6843c600 Move $nu.env to $env (#665)
* Move env from nu builtin to its own

* update samples/tests
2022-01-05 08:34:42 +11:00
JT
4d1ce6c27b Use default prompt as fallback (#663) 2022-01-05 06:49:04 +11:00
JT
857ecda050 Let describe know about binary (#662) 2022-01-04 14:05:24 +11:00
JT
36079f1a3d Port fetch (with fixes) (#660)
* Port fetch to engine-q

* Fix check for path as a string

* Add a timeout flag and fix some span issues

* Add a temporary fetch command that returns byte streams. Got rid of async stuff as we're using the blocking feature of tokio

* More tweaks for the bytestream

* Rewrite fetch using ByteStreams

* buffer read on bytes directly

Co-authored-by: Stefan Stanciulescu <contact@stefanstanciulescu.com>
2022-01-04 13:01:18 +11:00
JT
b6fcd46075 Some error improvements (#659) 2022-01-04 10:14:33 +11:00
JT
cb8b7e08a5 Lex comment spans correctly (#657) 2022-01-04 08:37:45 +11:00
JT
681e37cec6 bump reedline (#655) 2022-01-04 06:38:24 +11:00
91d807b1d2 add docs about coloring and theming (#654) 2022-01-03 13:06:49 -06:00
JT
fe5f65a247 Highlight block and record (#653) 2022-01-03 16:21:26 +11:00
JT
9535e2c309 Fix list and table print (#652)
* Fix list printing

* Fix list and table highlighting
2022-01-03 14:18:23 +11:00
398502b0d6 fix docs/sample_config/config.toml: use env.PROMPT_COMMAND (#4241) 2022-01-02 17:35:07 -06:00
JT
850f66aa9d Fix build breakage - bump ansi term (#651)
* Fix build breakage - bump ansi term

* Remove e-q ansi term
2022-01-03 09:36:32 +11:00
JT
354d51a3a6 Fix perf regression with stmts (#650) 2022-01-03 07:18:48 +11:00
JT
c9dcd212ba Allow pipelines across multiple lines if end in pipe (#643)
* Allow pipelines across multiple lines if end in pipe

* Add validation support
2022-01-02 16:27:58 +11:00
JT
ffaaa53526 Plugin before config (#642)
* Add fuzzy/ignore flag to get

* Handle plugins before config
2022-01-02 14:20:33 +11:00
JT
f7e3d4de24 Add fuzzy/ignore flag to get (#641) 2022-01-02 13:18:39 +11:00
a56994ccc5 make prompt indicators configurable (#639)
* make prompt indicators configurable

* seems to be working now
2022-01-02 09:53:16 +11:00
JT
ac487dfcbc Add parser tracing, fix 629 (#638) 2022-01-02 08:42:50 +11:00
JT
4383b372f5 Cleanup binary stream print a little (#637) 2022-01-01 21:42:15 +11:00
JT
7fa1ad010b Bump reedline, again (#636) 2022-01-01 16:30:59 +11:00
5d58f68c59 port over from nushell the column flag for the length command (#617)
* port over from nushell the column flag for the length command

* fix clippy error

* refactor with the get_columns now centrally located
2022-01-01 15:27:20 +11:00
f734995170 move get_columns from the table_viewer to a central location (#628)
* get_columns is working in the columns command

* the new location of the get_columns method is nu-protocol/src/column.rs

* reference the new location of the get_columns method

* move get_columns to nu-engine
2021-12-31 17:39:58 -08:00
JT
44791b5835 Bump reedline, again (#635) 2022-01-01 12:27:45 +11:00
JT
15b979b06e Bump reedline (#634) 2022-01-01 09:41:29 +11:00
18ddcdcb97 type-o in signature (#633) 2021-12-31 09:54:30 -06:00
JT
2320987862 Bump reedline (#627) 2021-12-31 11:36:01 +11:00
822309be8e Port the every command (#626) 2021-12-31 10:41:18 +11:00
15b0424d73 Create config directory if it does not exist (#625)
Signed-off-by: nibon7 <nibon7@163.com>
2021-12-30 21:47:51 +11:00
56ae07adb9 Ported ignore command to engine-q (#621)
* Ported `ignore` command to engine-q

* Format ignore command
2021-12-30 15:54:33 +11:00
JT
80649f2341 Fix flattening of in-variable (#624) 2021-12-30 14:26:40 +11:00
7faa4fbff4 revert file_types to lowercase (#623)
* revert file_types to lowercase

* fix test
2021-12-29 21:16:50 -06:00
7d1d6f075c ignore .DS_Store files on Mac (#622) 2021-12-29 12:42:11 -06:00
JT
832a801c11 Preserve metatdata in where (#618) 2021-12-29 22:17:20 +11:00
JT
c8330523c8 Don't read config in a tight loop (#614) 2021-12-29 07:06:53 +11:00
JT
62011b6bcc Bump to 0.42 (#4234) 2021-12-28 20:56:59 +11:00
JT
e94b8007c1 Allow update to also insert (#610) 2021-12-28 10:11:20 +11:00
0c1a7459b2 Update to the latest reedline (#608)
* update to the latest reedline

* update to latest reedline
2021-12-27 14:16:34 -06:00
JT
384ea111eb Allow for and other commands missing positionals near keywords (#606)
* Allow for and other commands missing positionals near keywords

* A bit more resilience
2021-12-28 07:04:48 +11:00
5c94528fe2 create history file if it doesnt exit (#605) 2021-12-28 06:14:23 +11:00
53330c5676 def argument check (#604)
* def argument check

* corrected test

* clippy error
2021-12-28 06:13:52 +11:00
1837acfc70 add ability to specify an ansi style (#595)
* add ability to specify an ansi style

* remove comments

* remove more debug code

* some cleanup and refactoring
2021-12-27 08:59:55 -06:00
JT
1dbf351425 Handle external redirects better (#598)
* Handle external redirects better

* fix warnings
2021-12-27 08:58:53 -06:00
f50f37c853 fix issue #559: to json -r serializes datetime without spaces (#596)
* fix issue #559: to json -r serializes datetime without spaces

* add in a third test which checks spaces in both keys and values

* fix clippy error
2021-12-27 21:51:38 +11:00
JT
3706bef0a1 Require let to be a statement (#594) 2021-12-27 14:04:22 +11:00
JT
de30236f38 Fix ls listing (#593) 2021-12-27 12:46:32 +11:00
JT
e1c92e90ca Add line ending autodetect to 'lines' (#589) 2021-12-27 10:11:18 +11:00
39f03bf5e4 Decode escaped newlines in history command (#592)
Reedline currently encodes newlines as `<\n>`
2021-12-27 10:11:08 +11:00
JT
e62e0fb679 Flush stmts (#584)
* Flush the stmt via table to the screen

* Fix test
2021-12-27 07:21:24 +11:00
JT
89a000a572 Fix some 'open' signature stuff (#583) 2021-12-26 09:13:43 +11:00
JT
ca6baf7a46 Add single tick string interpolation (#581)
* Add single tick string interpolation

* give string interpolation its own highlighting
2021-12-26 07:50:02 +11:00
JT
d603086d2f Fix custom call scope leak, refactor tests (#580)
* Fix custom call scope leak, refactor tests

* Actually add tests
2021-12-26 06:39:42 +11:00
JT
a811eee6b8 Add support for 'open' (#573) 2021-12-25 06:24:55 +11:00
JT
1efae6876d Wire hex viewing into a few more places (#572) 2021-12-25 05:15:01 +11:00
1214cd57e8 bat: use regex-onig instead of regex-fancy (#4226)
Fixes #4224

Signed-off-by: nibon7 <nibon7@163.com>
2021-12-24 08:34:59 -06:00
JT
3522bead97 Add string stream and binary stream, add text decoding (#570)
* WIP

* Add binary/string streams and text decoding

* Make string collection fallible

* Oops, forgot pretty hex

* Oops, forgot pretty hex

* clippy
2021-12-24 18:22:11 +11:00
JT
7f0921a14b Add metadata command (#569)
* Add metadata command

* Add string interpolation to testing
2021-12-24 11:16:50 +11:00
JT
b719f8d4eb Add missing flags to existing commands (#565)
* Add missing flags to existing commands

* fmt
2021-12-24 08:41:29 +11:00
29c8b826d4 add configuration point for hint coloring (#564) 2021-12-23 15:02:57 -06:00
ba1ff4cf6c add configuration of maximum history size (#563) 2021-12-23 13:59:00 -06:00
5c83f4d405 update to latest reedline (#562) 2021-12-23 13:39:54 -06:00
f3c175562d vi mode (#561) 2021-12-23 09:31:16 +00:00
c33104c4ae Ported compact command to engine-q (#558)
* :Interm work porting compact to engine-q

* Port 'compact' command from nushell to engine-q

* Fixed example
2021-12-23 14:08:39 +11:00
JT
ef59b4aa51 Some multiline fixes (#557) 2021-12-23 09:53:19 +11:00
JT
3389baa392 Improve multiline history (#556) 2021-12-23 07:44:05 +11:00
5d3b63fa90 add in a raw flag in the command to json (#555)
* add in the method to_string_raw

* add in a raw flag to json

* add in a test
2021-12-23 06:56:49 +11:00
6cd124ddb2 allow insecure server connections when using SSL (#4219)
Fixes #4211

Signed-off-by: nibon7 <nibon7@163.com>
2021-12-23 06:48:43 +11:00
061c822c5d Add environment variables doc page (#554)
* Fix typos

* Add environment variables doc page

* Remove Breaking Changes page
2021-12-23 06:44:14 +11:00
JT
0c920f7d05 Add history command (#553) 2021-12-22 22:19:38 +11:00
JT
43dd0960a0 Use latest history hint (#552) 2021-12-22 20:39:35 +11:00
JT
9fb12fefb0 Improve history hinting (#551) 2021-12-22 20:12:24 +11:00
8ba3e3570c Interpret lists as series of args for externals (#550)
* Interpret lists as series of args for externals

* Fix clippy warnings
2021-12-22 10:13:05 +02:00
ea6912c3f7 missing commands (#549) 2021-12-22 10:35:02 +11:00
deeb1da359 Allow having only one env conversion (#548)
Allows setting only `from_string` or `to_string` in `env_conversions`
config. Previously, both were required.
2021-12-22 00:32:38 +02:00
52dba91e1a Wrap captured env var names into quotes as well (#546) 2021-12-21 23:31:30 +02:00
JT
266fac910a Signature improves, sorted completions (#545) 2021-12-22 07:50:18 +11:00
3ad5d4af66 sort env vars (#544) 2021-12-22 07:27:19 +11:00
a93a9b9029 Add skip-empty flag to lines command (#543)
* Add skip-empty flag to lines command

* Fix failing length test
2021-12-22 07:24:11 +11:00
6a35e6b7b6 Dataframe commands (#542)
* groupby object

* aggregate command

* eager commands

* rest of dataframe commands
2021-12-22 05:32:09 +11:00
JT
c3a16902fe Fix list printing (#540) 2021-12-21 20:05:16 +11:00
JT
fc7ed1bfe4 switch substring to bytes (#538)
* switch substring to bytes

* Add a test
2021-12-21 11:49:02 +11:00
d32aec5906 Don't panic if the other end of std{out,err} is closed (#4179)
* fix #4161

println! and friends will panic on BrokenPipe. The solution is to use
writeln! instead, and ignore the error (or do we want to do something else?)

* test that nu doesn't panic in case of BrokenPipe error

* fixup! test that nu doesn't panic in case of BrokenPipe error

* make do_not_panic_if_broken_pipe only run on UNIX systems
2021-12-21 10:08:41 +11:00
1609101e62 Fix capturing environment variables with " or ' (#537)
* Fix path expand error span

* Fix capturing env vars containing ' or "; Rustfmt
2021-12-20 23:19:43 +02:00
JT
0571a6ee34 Merged heterogeneous tables (#536)
* Merged heterogeneous tables

* switch emoji
2021-12-21 08:03:47 +11:00
JT
152467a858 Flatten should flatten embedded table (#534) 2021-12-21 06:03:18 +11:00
JT
caf73c36f2 Finish adding support for optional params (#530) 2021-12-20 17:58:09 +11:00
e949658381 nothing variable (#527)
* nothing variable

* corrected comments

* added color to nothing like bool

* compare nothing with values

* comparison tests
2021-12-20 12:05:33 +11:00
ff5b7e5ad2 feat(into): add into-bool command (#499)
* feat(into): add example of into-bool

* feat(into): add convert from int and float

* feat(into): add converting string to bool

* feat(into): add converting value in table

* fix(into): update error

* fix(into): update span for example

* chore(into): update signature description

* float comparison using epsilon

* Update bool.rs

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
2021-12-20 07:11:28 +11:00
JT
cf5048205f Allow empty span slice for now (#529) 2021-12-20 06:25:02 +11:00
c37bdcd119 port empty command (#528)
* port empty command

* Pull upstream and use test_data() function for example tests
2021-12-20 06:11:57 +11:00
038ad951da name change (#526) 2021-12-19 10:00:31 +00:00
JT
2883d6cd1e Remove Span::unknown (#525) 2021-12-19 18:46:13 +11:00
JT
b54e9b6bfd Fix completion crash (#521) 2021-12-19 07:10:40 +11:00
ebf57c70e0 Plugin signature (#520)
* calling plugin without shell

* spelling error

* option on register to select a shell

* help in plugin example signature
2021-12-18 19:25:17 +00:00
00bb203756 add in a new command called columns (#519) 2021-12-18 12:14:28 -06:00
8933dde324 Plugin option for shell (#517)
* calling plugin without shell

* spelling error

* option on register to select a shell
2021-12-18 12:13:56 -06:00
b3b328d19d add lp and rp (#518) 2021-12-18 12:13:10 -06:00
46b86f3541 Migration of series commands (#515)
* corrected missing shellerror type

* batch dataframe commands

* removed option to find declaration with input

* ordered dataframe folders

* dataframe command name
* series commands

* date commands

* series commands

* series commands

* clippy correction

* rename commands
2021-12-18 17:45:09 +00:00
d8847f1082 Calling plugin without shell (#516)
* calling plugin without shell

* spelling error
2021-12-18 09:52:27 -06:00
ada9c742c6 Fix broken env var reading on startup (#513) 2021-12-17 23:09:44 +02:00
6f6340186a Port flatten (#512)
* A first working version of flatten. Needs a lot of cleanup. Committing to have a working version

* Typo fix

* Flatten tests pass

* Final cleanup, ready for push

* Final cleanup, ready for push

* Final cleanup, ready for push

* Final cleanup, ready for push

* Update flatten.rs

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
2021-12-18 07:44:51 +11:00
6ba1e6172c Port 'ansi strip' command from nushell to engine-q (#511)
* Port 'ansi strip' command from nushell to engine-q

* added example
2021-12-18 07:32:03 +11:00
438c2df8b6 Porting 'ansi gradient' command from nushell to engine-q (#509)
* Porting  'ansi gradient' command from nushell to engine-q

* passed correct span variable
2021-12-18 04:40:47 +11:00
6a0f404558 Treating environment variables as Values (#497)
* Proof of concept treating env vars as Values

* Refactor env var collection and method name

* Remove unnecessary pub

* Move env translations into a new file

* Fix LS_COLORS to support any Value

* Fix spans during env var translation

* Add span to env var in cd

* Improve error diagnostics

* Fix non-string env vars failing string conversion

* Make PROMPT_COMMAND a Block instead of String

* Record host env vars to a fake file

This will give spans to env vars that would otherwise be without one.
Makes errors less confusing.

* Add 'env' command to list env vars

It will list also their values translated to strings

* Sort env command by name; Add env var type

* Remove obsolete test
2021-12-17 12:04:54 +11:00
342584e5f8 Port keep, keep while and keep until commands (#384)
* Add `KeepUntil` sub-command

* Add `KeepWhile` sub-command

* Add `Keep` command

* Fix error type
2021-12-17 11:57:02 +11:00
efb4a9f95c Fix Ctrl-D exit in cli (#508)
Clears to a new line for the potentially hosting process
Remove the output for `Ctrl-C`
2021-12-16 15:40:12 -06:00
bf6780967b Make dialoguer completion abortable (#507)
Fixes #505
2021-12-16 15:11:06 -06:00
a148ad8697 added a 'list' option to the ansi command (#504) 2021-12-16 12:36:07 -06:00
9a864b5017 allow flatshape (command line syntax) theming (#502)
* allow flatshape (command line syntax) theming

* renamed crate, organized
2021-12-16 06:17:29 -06:00
JT
17a7a85c78 Bump some deps (#503) 2021-12-16 20:40:05 +11:00
89e2169521 Porting 'char' command from nushell to engine-q (#500)
* Port 'char' command from nushell to engine-q

* fixed unit tests

* Actually fixed unit tests
2021-12-16 10:08:12 +11:00
e289630920 Porting 'ansi' command from nushell to engine-q (#494)
* Porting 'ansi' command from nushell to engine-q

* Added StrCollect to example_test.rs to allow example tests to run

* Run 'cargo fmt' to fix formatting

* Update command.rs

* Update command.rs

* Update command.rs

* Added a category

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
2021-12-16 10:06:35 +11:00
JT
1d74d9c5ae Fix comment issue and shadowing issue (#501) 2021-12-16 09:56:12 +11:00
aea2adc44a Update Beaking_Changes.md 2021-12-15 23:39:22 +02:00
0450cc25e0 port over from nushell drop nth (#498) 2021-12-15 06:26:15 -06:00
JT
e9525627e6 Fix a couple crlf issues (#496) 2021-12-15 07:17:02 +11:00
1cbb785969 port over from nushell drop column (#495)
* port over from nushell drop column

* fix clippy
2021-12-15 06:54:27 +11:00
a41ae72bc1 Fix error propagration across hash commands (#493) 2021-12-15 06:49:48 +11:00
a5c1dd0da5 allow fg, bg, attributes to be set for all colors in color_config (#489)
* allow fg, bg, attributes to be set for all colors in color_config

* no need for comma between each key value
2021-12-14 13:34:39 -06:00
e919f9a73b use heck for string casing (#4081)
I removed the Inflector dependency in favor of heck for two reasons:
- to close #3674.
- heck seems simpler and actively maintained

We could probably alter the structure of the `str_` module to expose the
individual casing behaviors better.
I did not feel as confident on changing those signatures.

So I took a lazier approach of a macro in the `mod.rs` that creates the public
shimming function to heck's traits.
2021-12-14 09:43:48 -06:00
a3c349746f ci: update macOS agent (#4207)
10.14 has been deprecated: https://github.com/Azure/azure-sdk-for-cpp/issues/3168

This hopefully fixes recent CI failures!
2021-12-14 08:55:51 -06:00
JT
04a9c8f3fd Fix bug in chained boolean typecheck (#490) 2021-12-14 16:19:16 +11:00
JT
673fe2b56a Bump to use latest git reedline (#488) 2021-12-14 06:54:43 +11:00
b5f8f64d79 ci: fix macOS agent (#4203)
I noticed the agent documentation uses uppercase: https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops&tabs=yaml
2021-12-13 13:08:03 -06:00
930cb26e99 Fix hiding of import patterns with globs (#487)
* Fix glob hiding

* Remove docs comment
2021-12-13 20:35:35 +02:00
3701fd1d76 allow user to use hex colors in config (#486) 2021-12-13 09:02:54 -06:00
ee6ab17fde Update Beaking_Changes.md 2021-12-13 13:47:01 +02:00
486f91e3a7 Start documenting breaking changes 2021-12-13 12:14:03 +02:00
JT
906c0e6bca Better filepath completions (#485) 2021-12-13 17:46:30 +11:00
JT
1336acd34a Seems ps still needs a delay to be accurate (#484) 2021-12-13 16:28:35 +11:00
JT
2013e9300a Make config default if broken (#482)
* Make config default if broken

* Make config default if broken
2021-12-13 14:16:51 +11:00
90ddb23492 Add Path commands (#280)
* Add Path command

* Add `path basename`

* Refactor operate into `mod`

* Add `path dirname`

* Add `path exists`

* Add `path expand`

* Remove Arc wrapper for args

* Add `path type`

* Add `path relative`

* Add `path parse`

* Add `path split`

* Add `path join`

* Fix errors after rebase

* Convert to Path in `operate`

* Fix table behavior in `path join`

* Use conditional import in `path parse`

* Fix missing cases for `path join`

* Update default_context.rs

* clippy

* Fix tests

* Fix tests

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
Co-authored-by: JT <jonathan.d.turner@gmail.com>
2021-12-13 12:47:14 +11:00
JT
bee7ef21eb Add in variable and sub-command completions (#480)
* WIP

* wip

* Add in variable and subcommand completions

* clippy
2021-12-13 10:18:31 +11:00
1576b959f9 update feat template (#4201) 2021-12-12 16:15:31 -06:00
4096f52003 update templates2 (#4200) 2021-12-12 16:11:27 -06:00
7ceb668419 Revert "try out title change (#4198)" (#4199)
This reverts commit 420aee18ca.
2021-12-12 16:06:07 -06:00
420aee18ca try out title change (#4198) 2021-12-12 16:05:24 -06:00
JT
d1d1402512 Add in auto-cd if you pass just a directory (#479)
* Add in auto-cd if you pass just a directory

* clippy
2021-12-13 08:41:34 +11:00
c33d082ecc Add docs page about modules and overlays (#478) 2021-12-12 23:21:04 +02:00
6f53912655 Fix: add missing bind commands (#477)
* chore(random): update naming convention

* fix: add missing bind commands
2021-12-12 21:42:04 +02:00
34a8a897c5 Plugin json (#475)
* json encoder

* thread to pass messages

* description for example

* check for help flag
2021-12-12 14:00:07 +00:00
4d7dd23779 Plugin json (#474)
* json encoder

* thread to pass messages

* description for example
2021-12-12 11:50:35 +00:00
f8e6620e48 tweak version output as a list vs table (#472) 2021-12-11 14:40:16 -06:00
7cbeebaac1 Port version (#467)
* First iteration of the version command

* Cleanup

* Fix the installed plugins bug

* Fix fmt check issue

* Fix clippy warning

* Fixing all clippy warnings

* Remove old code
2021-12-11 14:08:17 -06:00
9d7685e565 add temp-path to $nu (#471) 2021-12-11 14:00:29 -06:00
c2aa6c708d add cwd to $nu (#469)
* add `cwd` to `$nu`

* oops
2021-12-11 13:38:36 -06:00
626b1b99cd add keybinding-path to $nu (#470) 2021-12-11 13:29:56 -06:00
4103abc685 add home-path to $nu (#468) 2021-12-11 13:12:30 -06:00
d0119ea05d Sort default context items categorically (#465)
* Sort default context items categorically

* Separate commands in multiple statements

* Use curly braces instead of square brackets

This prevents undesired reformatting.
2021-12-10 21:07:39 -06:00
3df5e63c05 updated to 2021 edition (#466) 2021-12-10 18:05:39 -06:00
e77c6bb284 Port hash, hash md5 and hash sha256 commands (#464)
`hash` by itself is only printing the help message.

The other two are simply using the same generic implementation.
2021-12-10 17:14:28 -06:00
95841e3489 to xml and to yaml (#463) 2021-12-10 14:46:43 -06:00
c2c4a1968b Add zip-support to extra (#462) 2021-12-10 07:16:59 -06:00
2e2d5ef0eb fix 1 off table wrapping for help commands (#460) 2021-12-09 19:16:50 -06:00
7a892ec5d7 To html and to md (#453)
* MathEval Variance and Stddev

* Fix tests and linting

* Typo

* Deal with streams when they are not tables

* First draft of these commands

* To MD

* To md and to html

* Fixed cargo and to_md

* `into_abbreviated_string` instead of `into_string`

* Changed how inner tables are displayed
2021-12-09 19:16:35 -06:00
865906e450 Dataframe commands name (#457)
* corrected missing shellerror type

* batch dataframe commands

* removed option to find declaration with input

* ordered dataframe folders

* dataframe command name
2021-12-09 18:17:11 -06:00
7319b6b168 port over the nth command from nushell (#454)
* port over the nth command from nushell

* remove a line of redundant code

* must sort the rows or else if the rows are not from low to high this crashes engine-q
2021-12-09 18:16:04 -06:00
c3b6e07de6 Port network/url command (#452)
* feat: add url command

* feat(network/url): add sub-command for url
2021-12-09 18:09:30 -06:00
5c27ffa42e update to latest reedline, change config point name, enable output without ansi (#458) 2021-12-09 16:06:26 -06:00
3dc19d4179 Filesize formatting (#456)
* configure the format of filesize

* type-o

* removed some comments

* updated tests

* accomodated filesize_metric better, added test
2021-12-09 13:19:36 -06:00
a8e5cb871e optionally remove table output color (#455) 2021-12-09 10:00:26 -06:00
pin
15e9c11849 Fix build on NetBSD (#4192) 2021-12-09 14:23:40 +02:00
9fd680ae2b fix: Implicit coercion of boolean false and empty value #4094 (#4120)
Signed-off-by: closetool <c299999999@qq.com>
2021-12-09 14:19:51 +02:00
ad94ed5e13 Fix Configuration section in bug report template (#4181)
* Fix Configuration section in bug report template

Change the placeholder content to actually match the `to md` output, and add `--pretty`

* Don't omit data in placeholder configuration table

* Remove blank line in bug_report.yml
2021-12-08 13:32:28 -06:00
a7a213b3f2 add default-run so cargo r works (#451) 2021-12-08 05:09:12 -06:00
1bdcdcca70 fix: change into column_path to into column-path (breaking change) (#4185) (#4189) 2021-12-08 11:04:55 +02:00
512dcf0988 enable cargo build --features=extra to build plugins (#448) 2021-12-07 14:06:34 -06:00
8d027a0617 allow decimals/floats to be formatted with precision (#449)
* allow decimals/floats to be formatted with precision

* better error message
2021-12-07 14:06:14 -06:00
JT
610e3911f6 Bump to 0.41 (#4187) 2021-12-08 06:21:00 +13:00
11a781fc36 Add uniq command (#447) 2021-12-07 21:47:48 +13:00
a42bbea98d port over the prepend command from nushell (#446) 2021-12-07 21:46:21 +13:00
c8b9913718 introducing gstat, a new command to get the git status (#443)
* wip - preliminary checking

* updated to latest pluging

* i think it's all working now, except bare words

* clippy
2021-12-06 11:28:11 -06:00
1fd26727c5 Batch of dataframe commands (#442)
* corrected missing shellerror type

* batch dataframe commands

* removed option to find declaration with input

* ordered dataframe folders
2021-12-06 17:09:49 +13:00
ee9eddd851 avoid unnecessary allocation (#4178) 2021-12-06 07:38:58 +13:00
JT
fdde95f675 Update clippy to check all features (#441)
* Update clippy to check all features

* Fix tests

* oops
2021-12-06 07:23:43 +13:00
9548e5ef5b feat(random): add random-integer and random-uuid (#440)
* feat(randome): add random-integer

* feat(random): add random-uuid
2021-12-06 06:22:50 +13:00
29efbee285 corrected missing shellerror type (#439) 2021-12-05 13:25:37 +00:00
22469a9cb1 Improved labeled error from plugins (#437)
* improved labeled error from plugins

* corrected span
2021-12-05 16:11:19 +13:00
03e22b071a port over the reject command from nushell (#419)
* port over reject

* add some tests to src/tests
2021-12-05 16:09:45 +13:00
71a8eb6f8e Add signature to $scope.commands (#434)
* Add signature to $scope.commands

* Change signature command column name
2021-12-04 22:01:51 +02:00
JT
ddd8c3d9dc Improve running main (#431) 2021-12-05 07:02:53 +13:00
c6aff972da Cal command (#429)
* Add calendar (cal) command

* Move options into arguments to avoid clippy warnings

* Remove commented line

* Fix formatting issues

* Fix clippy warning
2021-12-05 06:15:03 +13:00
82aa84706e feat(random): add random-dice (#428) 2021-12-05 06:14:24 +13:00
JT
3e0c5e55b6 Add simple commandline args for scripts (#427) 2021-12-05 06:06:17 +13:00
8a06ea133b removed unwraps (#430) 2021-12-04 12:38:21 +00:00
JT
eed22605ef Fix the failure if the prompt breaks (#426) 2021-12-04 18:24:38 +13:00
JT
8cf4402e6c Reset ansi more often when showing errors (#425) 2021-12-04 18:02:57 +13:00
df5ac9b71c Port str datetime to into datetime (#424)
* Port str datetime to into datetime

* Fix the span issue and some other small cleanups
2021-12-04 16:41:02 +13:00
bef138232c this fixes garbage ansi when externals turn off vt processing (#422)
* this fixes garbage ansi when externals turn off vt processing

* clippy

* changes are only for windows

* type-o
2021-12-03 13:49:25 -06:00
ee45755ea9 Add canonicalization to source & use paths (#421)
Also added file path print to FileNotFound error
2021-12-03 21:49:11 +02:00
405a4e58c7 Fix 'help commands'; Add 'is_custom' column (#420)
* Fix fetching commands; Add is_custom column

* Remove old comment
2021-12-03 20:45:29 +02:00
f3c8d35eb7 Plugin repeated (#417)
* not repeated decl in file and help

* implemented heashmap for repeated

* sorted scope commands
2021-12-03 14:29:55 +00:00
JT
a28d38b05f Try some fixes for external paths (#415) 2021-12-03 20:40:31 +13:00
JT
574d7f6936 Add table streaming (#413) 2021-12-03 19:15:23 +13:00
3d8394a909 to csv and to tsv (#412)
* MathEval Variance and Stddev

* Fix tests and linting

* Typo

* Deal with streams when they are not tables

* ToTsv and ToCsv
2021-12-03 15:02:22 +13:00
349e83abd0 Port str to-decimal to into decimal command. (#408)
* Port str to-decimal to into decimal command. Add also a Value::test_float function for tests only

* Add support for handling integers into decimals and fix issues with error span
2021-12-03 15:01:19 +13:00
bf82417d52 Port str upcase (#404)
* Port str upcase

* Switch to to_uppercase to support more characters than only ASCII
2021-12-03 15:00:32 +13:00
JT
c5297d2b64 First step (#411) 2021-12-03 12:11:25 +13:00
JT
d9bedaae2f Fix plurals in abbrevations (#409) 2021-12-03 10:36:54 +13:00
JT
19766556f3 Add value abbreviations (#407) 2021-12-03 10:07:44 +13:00
687fefd791 Remove Arc from Arguments (#405) 2021-12-03 10:07:36 +13:00
JT
ccd5f59314 Update external spawn (#406)
* Simplify external spawn, improve arg cleaning

* Fix tests

* Fix windows test
2021-12-03 09:55:16 +13:00
JT
c08e145501 Fix clippy warnings (#4176) 2021-12-03 07:05:38 +13:00
ff673ba0ba Add the support of str to-int to the into int command (#389) 2021-12-03 06:54:47 +13:00
c00853a473 Seems like accessing $it outside each is not possible now (#4000) 2021-12-03 06:49:24 +13:00
JT
f57d629b55 Default prompt animations to off (#403) 2021-12-03 06:26:23 +13:00
43972db131 feat(random): add random-decimal (#402) 2021-12-03 06:26:12 +13:00
f2aa952e86 add back debug --raw switch (#401)
* add back debug --raw switch

* tweak some debug and other settings
2021-12-02 08:32:12 -06:00
JT
071066b6d9 Move prompt animation setting to config (#400) 2021-12-02 20:10:40 +13:00
79c7b20cfd add login shell flag (#4175) 2021-12-02 20:05:04 +13:00
JT
ac2afab40b Fix parse error metadata (#399) 2021-12-02 19:36:30 +13:00
99de2b1d77 plugin path for $nu (#398) 2021-12-02 06:35:32 +00:00
JT
45eba8b922 Introduce metadata into the pipeline (#397) 2021-12-02 18:59:10 +13:00
56307553ae Plugin with evaluated call (#393)
* plugin trait

* impl of trait

* record and absolute path

* plugin example crate

* clippy error

* correcting cargo

* evaluated call for plugin
2021-12-02 05:42:56 +00:00
2bbba3f5da Port str trim (#394) 2021-12-02 17:38:44 +13:00
34e0fd622b to url and to toml (#396)
* MathEval Variance and Stddev

* Fix tests and linting

* Typo

* Deal with streams when they are not tables

* ToUrl and ToToml

* Linting
2021-12-02 17:38:00 +13:00
124561ff12 Rename add_decls() to use_decls() (#395)
To reflect better what the method actually does.
2021-12-02 00:25:51 +02:00
JT
89cbfd758d Remove 'arboard' (#4174) 2021-12-02 08:48:03 +13:00
d8c721282b add optional footer to table (#392)
* add optional footer to table

* missed a draw_table
2021-12-01 13:20:23 -06:00
d2a1564b94 feat(random): add random-chars (#390) 2021-12-02 07:58:10 +13:00
7cf96c6597 added row_index coloring (#391) 2021-12-01 09:17:50 -06:00
b8f1fea7fe Port str substring command (#388)
* Port str substring command

* Fix issue signaled by cargo fmt
2021-12-01 19:42:57 +13:00
e6e6b730f3 Bye bye upx sorry (#4173)
* bye bye upx, let's try stripping alone

* remove all stripping - not sure it's even working
2021-11-30 13:34:16 -06:00
0fe6a7c1b5 bye bye upx, let's try stripping alone (#4172) 2021-11-30 12:11:01 -06:00
3916ac4165 Fix busy poll with reedline (#387)
Fixes #386

Makes the changes to accept https://github.com/nushell/reedline/pull/188

Change CLI option EQ_PROMPT_ANIMATE_MS to binary EQ_PROMPT_ANIMATE
2021-11-30 09:59:54 -06:00
c17e1473db Hiding of environment variables (#362)
* Remember environment variables from previous scope

* Re-introduce env var hiding

Right now, hiding decls is broken

* Re-introduce hidden field of import patterns

All tests pass now.

* Remove/Address tests TODOs

* Fix test typo; Report hiding error

* Add a few more tests

* Fix wrong expected test result
2021-11-30 19:14:05 +13:00
21ddfc61f4 add random commands (#366)
* feat: add random command

* feat: add bool sub-command
2021-11-30 19:12:19 +13:00
ce4d9dc7c6 allow icons to be used in grid -c (#378)
* add icons to grid output. still needs cleanup

* working but adds a dependency on ansi_term - need to fix that

* update styling, added lots of green code to icons

* clippy

* add config point for grid icons
2021-11-29 14:37:09 -06:00
414ed4877a From ssv from xml (#383)
* MathEval Variance and Stddev

* Fix tests and linting

* Typo

* Deal with streams when they are not tables

* From xml and from ssv

* linting
2021-11-30 08:22:13 +13:00
5de12da765 Port over the kill command from nushell (#381)
* Port over the kill command from nushell

* Update formatting

* Improve error message by combining signal spans
2021-11-30 07:21:55 +13:00
1794ad51bd Sanitize arguments to external commands a bit better (#4157)
* fix #4140

We are passing commands into a shell underneath but we were not
escaping arguments correctly. This new version of the code also takes
into consideration the ";" and "&" characters, which have special
meaning in shells.

We would probably benefit from a more robust way to join arguments to
shell programs. Python's stdlib has shlex.join, and perhaps we can
take that implementation as a reference.

* clean up escaping of posix shell args

I believe the right place to do escaping of arguments was in the
spawn_sh_command function. Note that this change prevents things like:

^echo "$(ls)"

from executing the ls command. Instead, this will just print

$(ls)

The regex has been taken from the python stdlib implementation of shlex.quote

* fix non-literal parameters and single quotes

* address clippy's comments

* fixup! address clippy's comments

* test that subshell commands are sanitized properly
2021-11-29 09:46:42 -06:00
bab8f6bd28 Port skip, skip while and skip until commands (#380)
* Add `Skip` command

* Add `SkipUntil` sub-command

* Add `SkipWhile` sub-command

* Add and use `Expression::as_row_condition_block`
2021-11-29 19:52:23 +13:00
ee239a0d37 testing suite for dataframes (#379) 2021-11-29 19:50:57 +13:00
e07ce57423 Port over the sleep command from nushell (#371)
* Port over the sleep command from nushell

* Fix clippy warning

* Remove unused variable
2021-11-29 10:15:32 +13:00
6d58e2b51e enable env setting for prompt animation (#376)
* enable env setting for prompt animation

* default to on

* updated comment
2021-11-28 15:09:52 -06:00
c8b16c14d5 Option to replace command same name (#374)
* option to replace command same name

* moved order of custom value declarations

* arranged dataframe folders and objects

* sort help commands by name

* added dtypes function for debugging

* corrected name for dataframe commands

* command names using function
2021-11-28 19:35:02 +00:00
e1e7e94261 Port over the clear command from nushell (#373)
* Port over the clear command from nushell

* cargo fmt
2021-11-28 08:32:44 +00:00
8c0fa0d26e Add Any command (#375) 2021-11-28 08:29:35 +00:00
JT
f7f8b0dbff A few help cleanups (#372) 2021-11-28 07:16:20 +13:00
63c3d19c67 Port all? command (#365)
* Implement `From<bool>` for `Value`

* Add `All` command

* Change `IntoPipelineData` and `IntoInterruptiblePipelineData` bounds

* Refactor `PipelineIterator` impls

* Add `PipelineData::into_interruptible_iter`

* Use `into_interruptible_iter` instead of `all` helper

* Merge imports

* Refactor `PipelineData::{filter, map}`

* Change comment pronoun

* Treat `RowCondition` as a block

* Remove unnecessary braces

* Address cluppy warning
2021-11-28 06:49:03 +13:00
JT
0ba0daa2c4 Update TODO.md 2021-11-27 20:18:40 +13:00
fb197f562a save --append: create file if it doesn't exist (#4156)
* have save --append create file if not exists

Currently, doing:

echo a | save --raw --append file.txt

will fail if file.txt does not exist. This PR changes that

* test that `save --append` will create new file
2021-11-26 12:27:41 -06:00
91c270c14a fix markup (#4155) 2021-11-26 07:37:50 -06:00
JT
5d88ed6c75 Add better exit command (#369) 2021-11-26 21:00:57 +13:00
JT
f052b3313d Move row condition to block (#368) 2021-11-26 16:49:03 +13:00
3e93ae8af4 Correct spelling (#4152) 2021-11-25 11:11:20 -06:00
8043516d75 from vcf from ics and from ini (#367)
* MathEval Variance and Stddev

* Fix tests and linting

* Typo

* Deal with streams when they are not tables

* `from toml` command

* From ods

* From XLSX

* From ics

* From ini

* From vcf

* Forgot a eprintln!
2021-11-26 06:10:56 +13:00
JT
6a1942b18f Update reedline for multiline prompt (#364) 2021-11-24 20:28:29 +13:00
76019f434e Dataframe feature (#361)
* custom value trait

* functions for custom value trait

* custom trait behind flag

* open dataframe command

* command to-df for basic types

* follow path for dataframe

* dataframe operations

* dataframe not default feature

* custom as default feature

* corrected examples in command
2021-11-23 08:14:40 +00:00
a2aaeb38ed port over the drop command from nushell (#358) 2021-11-22 08:04:20 +13:00
JT
143855b662 Add better comment skipping (#359) 2021-11-22 07:13:09 +13:00
d30dfc63c4 Fix reading of LS_COLORS; ls display symlink (#357)
Also a swing-by fix removing a redundant call to 
std::fs::symlink_metadata().
2021-11-21 01:14:42 +02:00
250743f60f add coloring by primitive, bring in nu-ansi-term crate (#353)
* add coloring by primitive, bring in nu-ansi-term crate

* clippy
2021-11-20 07:12:35 -06:00
e06df124ca upgrading dependencies (#4135)
* upgrade dependencies
num-bigint 0.3.1 -> 0.4.3
bigdecimal-rs 0.2.1 -> bigdecimal 0.3.0
s3hander 0.7 -> 0.7.5
bat 0.18 -> 0.18, default-features = false

* upgrade arboard 1.1.0 -> 2.0.1

* in polars use comfy-table instead of prettytable-rs
the last release of prettytable-rs was `0.8.0 Sep 27, 2018`
and it uses `term 0.5` as a dependency

* upgrade dependencies

* upgrade trash -> 2.0.1

Co-authored-by: ahkrr <alexhk@protonmail.com>
2021-11-20 07:11:11 -06:00
00aac850fd from xlsx from ods and from toml (#352)
* MathEval Variance and Stddev

* Fix tests and linting

* Typo

* Deal with streams when they are not tables

* `from toml` command

* From ods

* From XLSX
2021-11-20 08:23:35 +13:00
JT
e01e73cb67 Add debug and describe (#351)
* Add debug and describe

* Fix test
2021-11-19 18:00:29 +13:00
JT
ff43ca4d24 Better record types (#350) 2021-11-19 17:30:27 +13:00
88988dc9f4 Plugins signature load (#349)
* saving signatures to file

* loading plugin signature from file

* is_plugin column for help command
2021-11-19 15:51:42 +13:00
JT
aa7226d5f6 Expand globs and filepaths (#348) 2021-11-19 08:32:27 +13:00
adb7eeb740 port over the append command from nushell (#345) 2021-11-19 08:16:04 +13:00
JT
96bdcc4ff7 Fix term width for the table (#346) 2021-11-18 18:48:15 +13:00
f8f437b060 Separate Overlay into its own thing (#344)
It's no longer attached to a Block. Makes access to overlays more
streamlined by removing this one indirection. Also makes it easier to
create standalone overlays without a block which might come in handy.
2021-11-17 17:23:55 +13:00
b35914bd17 Category option for signature (#343)
* category option for signature

* category option for signature

* column description for $scope
2021-11-17 17:22:37 +13:00
JT
2590fcbe5c Bump to 0.40 (#4129) 2021-11-16 21:53:03 +13:00
JT
09691ff866 Delete docker-publish.yml 2021-11-16 14:19:35 +13:00
6fbe02eb21 Port str startswith (#342)
Co-authored-by: Stefan Stanciulescu <contact@stefanstanciulescu.com>
2021-11-16 12:16:56 +13:00
5459d30a24 Add environment variable support for modules (#331)
* Add 'expor env' dummy command

* (WIP) Abstract away module exportables as Overlay

* Switch to Overlays for use/hide

Works for decls only right now.

* Fix passing import patterns of hide to eval

* Simplify use/hide of decls

* Add ImportPattern as Expr; Add use env eval

Still no parsing of "export env" so I can't test it yet.

* Refactor export parsing; Add InternalError

* Add env var export and activation; Misc changes

Now it is possible to `use` env var that was exported from a module.

This commit also adds some new errors and other small changes.

* Add env var hiding

* Fix eval not recognizing hidden decls

Without this change, calling `hide foo`, the evaluator does not know
whether a custom command named "foo" was hidden during parsing,
therefore, it is not possible to reliably throw an error about the "foo"
name not found.

* Add use/hide/export env var tests; Cleanup; Notes

* Ignore hide env related tests for now

* Fix main branch merge mess

* Fixed multi-word export def

* Fix hiding tests on Windows

* Remove env var hiding for now
2021-11-16 12:16:06 +13:00
16db368232 upgrade polars to 0.17 (#4122) 2021-11-16 12:01:02 +13:00
JT
df87d90b8c Add 'detect columns' command (#4127)
* Add 'detect columns' command

* Fix warnings
2021-11-16 11:29:54 +13:00
f2f01b8a4d missed from_mp4, added back (#4128) 2021-11-15 16:19:44 -06:00
6c0190cd38 added upx and strip to mac and windows (#4126) 2021-11-15 15:32:48 -06:00
b26246bf12 trying upx and strip (#4125) 2021-11-15 15:01:25 -06:00
36a4effbb2 tweaked strip ci (#4124) 2021-11-15 14:30:32 -06:00
ab22619f4a enable ls_colors for the ls command (#340)
* enable ls_colors for the `ls` command

* added wrapping with ansi-cut so the ansi sequences don't bleed over

* clippy
2021-11-15 14:09:17 -06:00
9fca417f8c update release to allow running manually (#4123) 2021-11-15 14:04:00 -06:00
d09e1148b2 add the ability to strip the debug symbols for smaller binaries on mac and linux 2021-11-15 13:47:46 -06:00
JT
42367ddf6d Add support for crlf for line continuations (#341) 2021-11-16 07:33:33 +13:00
e324c1a078 Port parse command (#338) 2021-11-16 07:27:15 +13:00
4fd020ab7f delete the file row.rs in nu-protocol/value which has references to RowStream (#339) 2021-11-15 18:43:11 +13:00
50cbd16ec7 Port str reverse (#337)
Co-authored-by: Stefan Stanciulescu <contact@stefanstanciulescu.com>
2021-11-15 14:43:40 +13:00
JT
be827e5628 Fix multiword imports/exports (#336) 2021-11-15 08:40:26 +13:00
f1b2ab0b27 Port str lpad and str rpad (#334)
* Port str lpad and str rpad

* Remove useless comment

Co-authored-by: Stefan Stanciulescu <contact@stefanstanciulescu.com>
2021-11-15 08:36:24 +13:00
JT
0f107b2830 Add a config variable with engine support (#332)
* Add a config variable with engine support

* Add a config variable with engine support

* Oops, cleanup
2021-11-15 08:25:57 +13:00
493bc2b1c9 Update README (#4118)
`winget install nu` fails because there's other options for "nu" now.
Using the full `nushell` word solved it for me.

[Imgur](https://imgur.com/aqz2qNp)
2021-11-14 19:34:57 +13:00
74b812228c upgrade dependencies (#4116)
* remove unused dependencies

* upgrade dependency bytes 0.5.6 -> 1.1.0

* upgrade dependency heapless 0.6.1 -> 0.7.8

* upgrade dependency image 0.22.4 -> 0.23.14

* upgrade dependency mp4 0.8.2 -> 0.9.0

* upgrade dependency bson 0.14.1 -> 2.0.1

Bson::Undefined, Bson::MaxKey, Bson::MinKey and Bson::DbPointer
weren't present in the previous version.

Co-authored-by: ahkrr <alexhk@protonmail.com>
2021-11-14 19:32:21 +13:00
JT
e76451866d 'update' command (#333) 2021-11-14 12:02:54 +13:00
08d316f6a7 Port str length command (#330)
Co-authored-by: Stefan Stanciulescu <contact@stefanstanciulescu.com>
2021-11-14 10:25:55 +13:00
JT
14a2918bba Fix some nightly clippy warnings (#329) 2021-11-13 13:42:13 +13:00
db2bca56c9 from url and from eml (#324)
* MathEval Variance and Stddev

* Fix tests and linting

* Typo

* Deal with streams when they are not tables

* FromEml and FromUrl

Added tests for from eml
2021-11-13 09:46:39 +13:00
e756a9ea04 Port str indexof (#327)
* Port str indexof

* Fix clippy warning

Co-authored-by: Stefan Stanciulescu <contact@stefanstanciulescu.com>
2021-11-12 08:45:39 +13:00
JT
568e566adf Add record literal syntax (#326) 2021-11-11 12:14:00 +13:00
586c6d9fa8 Port str find replace (#325)
* Port str find_replace command

* Add regex crate as dependency

Co-authored-by: Stefan Stanciulescu <contact@stefanstanciulescu.com>
2021-11-11 12:11:34 +13:00
f5b20f0e3b try to match most of nushell syntax coloring (#323) 2021-11-11 06:55:10 +13:00
75cfee28b2 from yaml and from yml (#322)
* MathEval Variance and Stddev

* Fix tests and linting

* Typo

* Deal with streams when they are not tables

* `from yaml` and `from yml`

`from yaml` and `from yml`

from yaml and from yml

* Fix collect_string

* Fix tests and linting
2021-11-10 14:02:33 +13:00
d094f654c3 Port str endswith (#321)
* Port str endswith command

* Fix clippy warnings

* Styling

Co-authored-by: Stefan Stanciulescu <contact@stefanstanciulescu.com>
2021-11-10 13:51:55 +13:00
JT
bb1740d733 Add from csv and from tsv (#320) 2021-11-10 09:17:37 +13:00
0f516a0830 Port str downcase and str contains (#319)
* Port str contains command

* Add another test case / example for str contains

* Port str downcase to engine-q

Co-authored-by: Stefan Stanciulescu <contact@stefanstanciulescu.com>
2021-11-10 09:16:53 +13:00
ef20b5f1ef Port str capitalize (#317)
* Port str capitalize command

* Keep consistent naming for str commands

Co-authored-by: Stefan Stanciulescu <contact@stefanstanciulescu.com>
2021-11-09 20:40:56 +13:00
JT
e1468c0440 Add some more cell path support for fun (#316) 2021-11-09 20:13:05 +13:00
JT
6f4993618d Bump crossterm (#315) 2021-11-09 19:47:22 +13:00
JT
2103294d11 Update TODO.md 2021-11-09 19:28:41 +13:00
JT
9c3c7b82c8 Try to simplify ci (#314) 2021-11-09 19:14:14 +13:00
JT
0a20052799 Fix external output threading and ctrlc (#313) 2021-11-09 19:14:00 +13:00
JT
34617fabd9 Do some str collect cleanup (#312) 2021-11-09 17:46:26 +13:00
JT
47628946b6 Add str collect (#311)
* Add str collect

* Oops, missing file
2021-11-09 14:59:44 +13:00
JT
ce714f098f Update TODO.md 2021-11-09 06:51:58 +13:00
JT
066afb059e Add magic in variable, part 2 (#310) 2021-11-08 20:13:55 +13:00
JT
e9a7def183 Add magic $in variable (#309)
* Add magic in variable

* Oops, missing file
2021-11-08 19:21:24 +13:00
JT
e0a26cd048 Finish operator overflow checking (#308) 2021-11-08 17:44:59 +13:00
JT
b5bade6187 Let list and table exprs get indexed (#307) 2021-11-08 12:18:00 +13:00
JT
fcee3c65bd Bump some deps (#306) 2021-11-08 11:09:30 +13:00
JT
19645575d6 Add 'did you mean' error (#305) 2021-11-08 10:48:50 +13:00
dd6452dfaa capnp proto change schema (#304)
* capnp proto change schema

* format schema file
2021-11-08 10:43:32 +13:00
cfd40ffaf5 Port over the reverse command from nushell (#303)
* initial commit of reverse
* reverse is working, now move on to the examples
* add in working examples for reverse
* #[allow(clippy::needless_collect)]
2021-11-07 18:18:27 +00:00
JT
00a8752c76 Move where to helper (#302) 2021-11-07 15:40:44 +13:00
7e070e2e5b Fix "math sum doesn't support streams" (#301)
* MathEval Variance and Stddev

* Fix tests and linting

* Typo

* Deal with streams when they are not tables
2021-11-07 14:20:58 +13:00
573cb38bab Port over the shuffle command from nushell (#300)
* initial commit of shuffle

* port the shuffle command from nushell
2021-11-07 14:19:57 +13:00
a1f141d18a Port str case commands (#287)
* Port camel case and kebab case

* Port pascal case

* Port snake case and screaming snake case

* Cleanup before PR

* Add back cell path support for str case commands

* Add cell path tests for str case command

* Revert "Add cell path tests for str case command"

This reverts commit a0906318d95fd2b5e4f8ca42f547a7e4c5db381a.

* Add cell path test cases for str case command

* Move cell path tests from tests.rs to Examples in each of the command's file

Co-authored-by: Stefan Stanciulescu <contact@stefanstanciulescu.com>
2021-11-07 06:55:25 +13:00
JT
6c31377c21 Fix precedence parse (#298) 2021-11-06 20:31:28 +13:00
JT
d401ed64ed Add range to the math reductions (#296) 2021-11-06 20:12:08 +13:00
JT
02b8027749 Improve external output in subexprs (#294) 2021-11-06 18:50:33 +13:00
c7d159a0f3 Last three math commands, eval, variance and stddev (#292)
* MathEval Variance and Stddev

* Fix tests and linting

* Typo
2021-11-06 06:58:40 +13:00
649b3804c1 fix: panic! during parsing (#4107)
Typing `selector -qa` into nu would cause a `panic!`
This was the case because the inner loop incremented the `idx`
that was only checked in the outer loop and used it to index into
`lite_cmd.parts[idx]`
With the fix we now break loop.

Co-authored-by: ahkrr <alexhk@protonmail.com>
2021-11-05 21:46:46 +13:00
JT
345b51b272 Merge pull request #290 from nushell/update_cell_path
Add updating cell paths
2021-11-05 18:06:41 +13:00
JT
5837cdb3f1 Update the rest of into 2021-11-05 17:57:24 +13:00
JT
183d200b9f Add updating cell paths 2021-11-05 16:59:12 +13:00
JT
8c43f60e2e Merge pull request #288 from elferherrera/plugins
Multiple commands per plugin
2021-11-05 15:22:33 +13:00
f8e48aa0af renamed cargo file 2021-11-04 22:22:20 +00:00
44fad9e698 deleted cargo file 2021-11-04 22:20:46 +00:00
14f30287f1 cargo toml 2021-11-04 22:17:10 +00:00
ae1109139d Merge branch 'main' of https://github.com/nushell/engine-q into plugins 2021-11-04 22:04:31 +00:00
1d356276c2 simple inc plugin implementation 2021-11-04 22:04:21 +00:00
JT
4a1df604c9 Merge pull request #282 from luccasmmg/engine-q-math
math: floor, ceil, median and mode
2021-11-05 07:10:26 +13:00
JT
d23929fc80 Update mode.rs
trying a switch to native endian
2021-11-05 07:04:02 +13:00
JT
df6a53f52e Update stale.yml (#4106) 2021-11-04 21:25:44 +13:00
JT
cfd24bc2ad Merge pull request #285 from nushell/env_shorthand
Add env shorthand
2021-11-04 15:43:10 +13:00
JT
f6d7df5a45 Merge pull request #284 from onthebridgetonowhere/port_first_command
Add back binary support for the first command
2021-11-04 15:42:57 +13:00
JT
2b03748681 Merge pull request #283 from aslynatilla/porting-format
Porting format
2021-11-04 15:41:45 +13:00
JT
1949ba080e Add env shorthand 2021-11-04 15:32:35 +13:00
260838e5ea Switch next_if to next as we already know it's of type Binary 2021-11-03 22:48:12 +01:00
112ebe1842 Add back binary support for first command 2021-11-03 22:44:30 +01:00
47ebde4087 Added MathMedian
Added MathMedian

Fix tests
2021-11-03 18:28:16 -03:00
bfae75ca2e Clean-up and adding comments 2021-11-03 20:05:24 +01:00
806cd4851f Format implementation, fix on Echo
Now, Echo converts multiple values in a ValueStream, but it simply
forwards a single Value; if no PipelineData is detected as an input, an
empty string is returned as a single Value.
2021-11-03 19:57:30 +01:00
JT
ea27300ca0 Merge pull request #278 from onthebridgetonowhere/port_into_string
Port into string command
2021-11-04 05:59:56 +13:00
d3e5c5a342 Fix tests 2021-11-03 09:19:28 -03:00
5ae823612f MathCeil, MathFloor and MathMode 2021-11-03 08:59:08 -03:00
20f3b8b274 Remove unnecessary crate imports 2021-11-03 10:41:01 +01:00
6906de7c48 Ooops fix the wrong naming 2021-11-03 08:48:13 +01:00
bf6c3e53a0 Remove BigDecimal and use i64/f64 instead 2021-11-03 08:38:31 +01:00
af5799c702 Merge remote-tracking branch 'origin/main' into porting-format 2021-11-03 08:02:51 +01:00
756773a6ed MathFloor done and MathMode still left work
Math mode final form currently

MathMode and MathFloor
2021-11-02 22:33:45 -03:00
JT
8192ba8d88 Merge pull request #281 from nushell/more_docs
Add more api docs
2021-11-03 13:33:08 +13:00
JT
86e1092785 Add more api docs 2021-11-03 13:26:09 +13:00
e193bf43fb multiple functions in plugin 2021-11-02 21:51:11 +00:00
12eed1f98a plugin feature flag 2021-11-02 20:56:00 +00:00
d134774f4b Merge remote-tracking branch 'origin' into porting-format 2021-11-02 21:23:50 +01:00
JT
dfb846dec6 Merge pull request #279 from nushell/some_docs_and_cleanup
Documenting some code and doing cleanups
2021-11-03 08:59:21 +13:00
JT
5e42b14026 Documenting some code and doing cleanups 2021-11-03 08:53:48 +13:00
78cc3452df Fix clippy warnings for into string command 2021-11-02 20:51:03 +01:00
070067b75e Add into string command 2021-11-02 20:39:16 +01:00
52cb50b937 Base Command implementation for Format
Note that run is not implemented yet
2021-11-02 18:13:06 +01:00
JT
b53570ceaa Merge pull request #277 from onthebridgetonowhere/port_first_command
Port first command
2021-11-02 21:23:46 +13:00
ce54764bea Fix test case for first command 2021-11-02 09:06:51 +01:00
6e49d0f84b Fix first command to display the first item not as a table 2021-11-02 09:05:03 +01:00
e1ea0d42a9 Merge branch 'main' of https://github.com/nushell/engine-q into port_first_command 2021-11-02 08:32:38 +01:00
JT
8368b52ac7 Merge pull request #276 from nushell/epsilon
Fix some machine epsilon warnings
2021-11-02 19:53:12 +13:00
JT
19301751ee Fix some machine epsilon warnings 2021-11-02 19:37:53 +13:00
JT
7b2116dc29 Merge pull request #270 from elferherrera/plugins
Plugins for engine q
2021-11-02 19:07:45 +13:00
JT
732ff317f0 Merge pull request #275 from nushell/zip
Add zip command
2021-11-02 18:38:31 +13:00
JT
25846d3c1e Add zip command 2021-11-02 18:28:28 +13:00
JT
bc8d90672e Merge pull request #274 from nushell/simple_scope_var
Add a simple scope variable
2021-11-02 16:17:36 +13:00
JT
d856cebebd Add a simple scope variable 2021-11-02 16:08:05 +13:00
JT
3c1b3473ae Merge pull request #273 from luccasmmg/engine-q-math
New math commands(product, round, sqrt and sum)
2021-11-02 11:20:35 +13:00
JT
89b8ee6ad8 Merge pull request #268 from onthebridgetonowhere/date_enqine_q
Port date commands to enqine-q
2021-11-02 11:18:46 +13:00
4a68c989e4 Fix test for date to-table 2021-11-01 23:05:53 +01:00
e16b0e7b01 New math commands(product, round, sqrt and sum) 2021-11-01 18:29:34 -03:00
JT
e14945fdf5 Merge pull request #271 from aslynatilla/porting-echo
Porting echo command
2021-11-02 07:35:11 +13:00
1c2741c598 Fixing run implementation for Echo
Values to echo need to be extracted from the call, and then converted
into PipelineData.

I also updated the first example so that its result is a List,
as in the reference implementation.
2021-11-01 15:43:16 +01:00
89225cf55c Adding examples and test for Echo 2021-11-01 09:37:07 +01:00
1f4c34fa04 adding span to value encoding 2021-11-01 08:16:56 +00:00
f4ed4fa7e3 Implementing Command for Echo, no examples
Referring to:

https://github.com/nushell/nushell/blob/main/crates/nu-command/src/commands/core_commands/echo.rs

as the original implementation.
2021-11-01 09:12:48 +01:00
c56a233808 formating schema file 2021-11-01 07:56:10 +00:00
468b9affde move run_plugin command location 2021-11-01 07:40:05 +00:00
ef94c71866 Merge branch 'main' of https://github.com/nushell/engine-q into plugins 2021-11-01 07:24:33 +00:00
43c3cfecf7 plugin call function 2021-11-01 07:20:33 +00:00
JT
3176f60b5b Merge pull request #243 from kubouch/module-files
Loading modules from files
2021-11-01 11:08:03 +13:00
ef56d482b2 Port first command to engine-q 2021-10-31 22:53:37 +01:00
304c7a0c92 Remove old code before fixing clippy's warning 2021-10-31 21:08:40 +01:00
8707fbee33 Address clippy's warnings when porting date to engine-q 2021-10-31 21:06:58 +01:00
032356bfb7 Address clippy's warnings when porting date to engine-q 2021-10-31 21:06:44 +01:00
3437dacf0b Change output of date to-table to be a one-row table 2021-10-31 20:53:23 +01:00
JT
80a4a5eb28 Merge pull request #266 from luccasmmg/engine-q-math-2
Added math and min commands
2021-11-01 06:45:16 +13:00
b340672331 Remove leftover test from previous iteration 2021-10-31 18:01:15 +02:00
73ae3daf85 Add invalid UTF-8 error to use and source
Also changed the error message to be more universal.
2021-10-31 17:53:53 +02:00
f182524298 Add TODO notes 2021-10-31 17:46:37 +02:00
b7c0ba104f Fix hiding module; Fmt
This fixes the case when you call `hide spam`. It will now hide all
commands you'd call like `spam foo` etc.
2021-10-31 17:38:00 +02:00
7112664b3f Fix wrong spans of multiple files
The introduction of `use <file.nu>` added the possibility of calling
`working_set.add_file()` more than once per parse pass. Some of the
logic handling the file contents offsets prevented it from working and
hopefully, this commit fixes it.
2021-10-31 17:22:10 +02:00
5add6035a4 Added math and min commands
typo

Added op span
2021-10-31 08:06:32 -03:00
a390f66dbf call and response serializers 2021-10-31 08:17:01 +00:00
fa8a0958e4 Merge branch 'main' of https://github.com/nushell/engine-q into date_enqine_q 2021-10-31 07:56:32 +01:00
20c770370b Port date commands to engine-q 2021-10-31 07:54:51 +01:00
JT
c4af5df828 Update stale.yml (#4102) 2021-10-31 16:48:58 +13:00
JT
e549c1112b Merge pull request #267 from stormasm/range3
port the filter command range from nushell
2021-10-31 16:33:03 +13:00
f94a3e15f5 Get rid of header bold option (#4076)
* refactor(options): get rid of 'header_bold' option

* docs(config): remove 'header_bold' from docs

* fix(options): replicate logic to apply true/false in bold

* style(options): apply lint fixes
2021-10-31 06:59:19 +13:00
da515b1c9d port the filter command range from nushell 2021-10-30 10:51:20 -07:00
37f7a36123 syntax serializers 2021-10-30 14:21:59 +01:00
9838154ad1 round trip call info 2021-10-30 11:19:16 +01:00
f301f686b5 Merge branch 'main' of https://github.com/nushell/engine-q into plugins 2021-10-30 11:01:49 +01:00
2dcfecbbd7 Add test for multi-word alias 2021-10-29 23:57:33 +03:00
751595e72e Add multi-word name calling support 2021-10-29 23:50:28 +03:00
JT
a160d480b1 Merge pull request #265 from nushell/nu_var
Add some support for $nu
2021-10-30 08:23:49 +13:00
JT
cf3f3fde92 Add some support for 2021-10-30 07:15:17 +13:00
JT
6e6df46469 Merge pull request #264 from nushell/to_json
Add 'to json'
2021-10-29 19:58:10 +13:00
JT
624edce4f7 Add 'to json' 2021-10-29 19:26:29 +13:00
75782f0f50 Fix #4070: Inconsistent file matching rule for ls and rm (#4099) 2021-10-28 15:05:07 +03:00
51e48bee53 Merge branch 'main' of https://github.com/nushell/engine-q into plugins 2021-10-28 07:12:40 +01:00
d853127c2e plugin crate 2021-10-28 07:12:33 +01:00
JT
520d9e1fb6 Merge pull request #262 from nushell/ctrlc
Add initial ctrl-c support
2021-10-28 17:22:48 +13:00
JT
37150af970 Merge pull request #260 from luccasmmg/engine-q-math-2
Added math avg
2021-10-28 17:14:49 +13:00
JT
bac8b8a450 Add initial ctrl-c support 2021-10-28 17:13:10 +13:00
40ad9acbc3 Added math avg
Linting

Fix clippy warning

Fix list of records
2021-10-27 22:13:55 -03:00
JT
1308eb45d5 Merge pull request #261 from nushell/history_path
Make the history path more central
2021-10-28 13:37:01 +13:00
JT
f92e9d25a5 Make the history path more central 2021-10-28 13:30:58 +13:00
4fc533340b Add function that searches for multi-word commands
It doesn't do anything right now.
2021-10-28 00:53:28 +03:00
JT
c998bbbe6d Merge pull request #259 from stormasm/last2
working on implementing the filters/last command
2021-10-28 07:00:40 +13:00
c114f41545 clippy fix 2021-10-27 08:35:42 -07:00
9baf720156 add in an example 2021-10-27 08:07:37 -07:00
4b31fe1924 code cleanup 2021-10-27 07:25:30 -07:00
656e86a7ca got it working by turning it into a vec 2021-10-27 07:19:33 -07:00
5d62f1a9c1 compile error to show issue 2021-10-26 21:04:48 -07:00
6d6b850911 switched to a working function called rows_to_skip 2021-10-26 20:48:31 -07:00
b5329fe4ec Cleanup; Remove redundant UTF-8 check 2021-10-27 00:34:39 +03:00
78256b4923 Fix syntax highlighting for new import patterns 2021-10-27 00:30:39 +03:00
bd6c550470 Change import pattern delimiter to space
Subcommands and module imports will have the same syntax now.
2021-10-27 00:13:39 +03:00
95628bef16 sending off for JT to review 2021-10-26 13:45:10 -07:00
ca7ff37697 add in dbg info so I can see what is being matched on 2021-10-26 13:06:26 -07:00
af02c8f6ea call info encoder 2021-10-26 20:50:39 +01:00
0f27249319 Merge branch 'main' into last2 2021-10-26 12:49:08 -07:00
JT
1eb93e5c07 Merge pull request #257 from GabrielBG0/ls-type-lowercase
`ls` type lowercase
2021-10-27 08:46:45 +13:00
JT
2b06ce27d3 Bump to 0.39 (#4097) 2021-10-27 08:36:41 +13:00
3625324bad last is working also with the hard coded length, need to figure out how to get the length of the input 2021-10-26 11:46:03 -07:00
7e66aca18e going to have to figure out how to clone input or some other solution 2021-10-26 11:29:00 -07:00
595fc7a7f6 Switch to cross-platform fail message 2021-10-26 21:03:12 +03:00
402a4acd7a Fix leftover test 2021-10-26 21:03:12 +03:00
a240aead8c Add loading module from file
Currently, `use spam.nu` creates a module `spam`. Therefore, after the
first `use`, it is possible to call both `use spam.nu` and `use spam`
with the same effect.
2021-10-26 21:03:12 +03:00
75b3b3e090 Add comments 2021-10-26 21:03:12 +03:00
5163dbb7a1 Add tests and cover edge cases of the :: delim. 2021-10-26 21:03:12 +03:00
cbda1b1650 Change import pattern delimiter to :: 2021-10-26 21:03:12 +03:00
e66fd91045 Move module block parsing into its own function 2021-10-26 21:03:12 +03:00
a29c333cb1 ls type lowercase 2021-10-26 15:02:45 -03:00
JT
0c7ec03ba0 Merge pull request #255 from nushell/par_each_sig
Fix par-each signature
2021-10-26 21:21:55 +13:00
JT
6b14f9d6b0 Fix par-each signature 2021-10-26 21:16:15 +13:00
JT
29dde84394 Merge pull request #254 from nushell/iter_perf
Some iter perf improvements
2021-10-26 16:28:42 +13:00
JT
543c566ccc Some iter perf improvements 2021-10-26 16:22:37 +13:00
JT
9995cbc03b Merge pull request #253 from nushell/par_each_example
Fix par-each example
2021-10-26 15:08:34 +13:00
JT
abb6d9f10f Fix par-each example 2021-10-26 14:49:25 +13:00
JT
e039e5f6a4 Merge pull request #252 from nushell/par_each
Add a simple parallel each
2021-10-26 14:37:56 +13:00
JT
9b67899f8d Merge pull request #248 from luccasmmg/engine-q-math
Engine q math(just one command)
2021-10-26 14:32:03 +13:00
JT
5455270446 Add a simple parallel each 2021-10-26 14:30:53 +13:00
11d8e6c71f Just removed a few comments 2021-10-25 21:11:20 -03:00
2ce034d0f0 linting 2021-10-25 20:57:45 -03:00
017b1d8996 Updated to new PipeLineData and made the tests run 2021-10-25 20:56:22 -03:00
JT
a2c2a07638 Merge pull request #251 from nushell/better_split_column
Use different helper functions for split column
2021-10-26 12:47:19 +13:00
3a5b943d11 Merge branch 'nushell:main' into engine-q-math 2021-10-25 20:40:41 -03:00
JT
766726d0fa Use different helper functions for split column 2021-10-26 12:35:51 +13:00
JT
798552b1b3 Merge pull request #250 from nushell/oops
Remove debug message
2021-10-26 12:20:03 +13:00
JT
df07ed5bf6 Remove debug message 2021-10-26 12:12:27 +13:00
JT
301d1f6f87 Merge pull request #249 from nushell/pipeline_data_capture
Pipeline data + capture
2021-10-26 12:04:53 +13:00
JT
962adf5a12 add threading 2021-10-26 11:56:29 +13:00
JT
c18f0dcc84 range display touchup 2021-10-26 11:24:10 +13:00
JT
4be61ce604 Tests pass 2021-10-26 11:18:45 +13:00
JT
85a69c0a45 WIP 2021-10-26 10:14:21 +13:00
JT
d29208dd9e WIP 2021-10-26 09:04:23 +13:00
JT
f84582ca2b WIP 2021-10-26 06:46:26 +13:00
JT
5d19017603 WIP 2021-10-26 05:58:58 +13:00
3f313da4c3 Fix test 2021-10-25 08:10:17 -03:00
JT
baac60a5a7 WIP 2021-10-25 19:42:38 +13:00
JT
b5965ee8ef WIP 2021-10-25 19:31:39 +13:00
JT
397a31e69c WIP 2021-10-25 17:24:10 +13:00
JT
b6d269e90a WIP 2021-10-25 17:01:02 +13:00
aa5ab8a666 final math abs 2021-10-24 20:58:18 -03:00
JT
ab9d6b206d Merge pull request #246 from stormasm/interactive_helper
clean up filesystem by moving get_interactive_confirmation into util.rs
2021-10-25 05:36:46 +13:00
JT
ffb361833b Merge pull request #245 from stormasm/readme
update readme with the issue 242 where people can sign up for commands to port
2021-10-25 05:35:59 +13:00
36a834c1e3 encode list 2021-10-24 13:20:01 +01:00
90c750285c Merge branch 'main' into readme 2021-10-23 18:10:57 -07:00
4bb2406772 Merge branch 'main' into interactive_helper 2021-10-23 18:09:20 -07:00
JT
4887b5e4fd Merge pull request #247 from nushell/clippy
Clippy fixes
2021-10-24 12:48:02 +13:00
JT
1296100d31 Clippy fixes 2021-10-24 12:40:27 +13:00
5a1d99cefb plugin command 2021-10-23 21:11:19 +01:00
232790f488 plugin command 2021-10-23 21:08:54 +01:00
297f3ba575 clean up filesystem by moving get_interactive_confirmation into util.rs 2021-10-23 10:57:45 -07:00
7bd5f887d1 update readme 2021-10-21 20:18:51 -07:00
66dad40092 update readme with the issue 242 where people can sign up for commands to port 2021-10-21 20:16:18 -07:00
72c241348b Remove dependencies (#4087)
* fix regression

* Removed the nipper dependency

* fix linting

* fix clippy
2021-10-22 06:58:40 +13:00
JT
ab2d2db987 Fix clippy warnings (#4088)
* Fix clippy warnings

* Fix clippy warnings
2021-10-22 06:57:51 +13:00
51bea2e884 still not working 2021-10-21 12:29:57 -03:00
b1d7e3aa49 starting to build this 2021-10-21 11:52:26 -03:00
JT
1c52919103 Merge pull request #244 from nushell/more_helpers
Add more helper functions
2021-10-20 19:11:58 +13:00
JT
b322a12f58 Add more helper functions 2021-10-20 18:58:25 +13:00
07e05ef183 fix regression (#4086) 2021-10-19 13:39:23 -05:00
11070ffbbe Merge pull request #238 from fdncred/allow_esc_q
allow esc and q to get out of completions
2021-10-15 15:59:17 -05:00
7ef5a7945f clippy take2 2021-10-15 15:52:03 -05:00
e330fdabb7 updated theme + clippy 2021-10-15 15:42:36 -05:00
c9439c962b allow esc and q to get out of completions 2021-10-15 15:33:56 -05:00
JT
b7ad4dc78a Merge pull request #237 from nushell/select_completions
little cleanup
2021-10-16 07:56:42 +13:00
JT
1b745015c3 little cleanup 2021-10-16 07:51:25 +13:00
JT
2be26127c9 Merge pull request #236 from nushell/select_completions
Try out select completions from dialoguer
2021-10-16 07:50:20 +13:00
JT
68601629c0 Fix warning 2021-10-16 07:39:36 +13:00
JT
82b0415d92 Try out select completions from dialoguer 2021-10-16 07:37:58 +13:00
JT
bd5009a865 Merge pull request #235 from GabrielBG0/interactive-flag
cp, mv, and rm commands need to support -i flag
2021-10-16 07:17:03 +13:00
5bd20e4d36 fix clippy warnings 2021-10-15 12:12:17 -03:00
28b26ca44d supress warnings 2021-10-14 18:14:59 -03:00
b3192ddc97 fix operating more than 2 file at the same time 2021-10-14 17:03:39 -03:00
8c2ae1eed1 -i flag finished, lacking tests 2021-10-14 14:54:51 -03:00
9807b4a484 Merge pull request #234 from fdncred/cleanup_lscolors_todos
clean up some todo comments in grid
2021-10-14 08:13:14 -05:00
fdf6bbb6fc clean up some todo comments in grid 2021-10-14 08:03:20 -05:00
JT
68b7aa9470 Merge pull request #233 from nushell/remove_bad_fixmes
Remove bad fixmes
2021-10-14 17:48:54 +13:00
JT
0d7b10fd0b Remove bad fixmes 2021-10-14 17:43:49 +13:00
9ea7cdfc33 -i flag on signaure 2021-10-13 19:29:08 -03:00
JT
87d57108e6 Merge pull request #232 from nushell/add_help_flag
Add help flag
2021-10-14 07:07:30 +13:00
JT
dcda7a4e50 Touchups to help 2021-10-14 06:58:39 +13:00
JT
fdd2c35fd9 Add the default help flag 2021-10-14 06:53:27 +13:00
JT
ff6cc2cbdd Merge pull request #231 from nushell/load_config
Load config
2021-10-13 17:23:39 +13:00
JT
5c46138563 Some touchups to size 2021-10-13 17:15:37 +13:00
JT
ef58348ea2 Merge branch 'main' into load_config 2021-10-13 16:59:09 +13:00
JT
e473bdb26d Merge pull request #230 from xiuxiu62/main
add size command
2021-10-13 16:58:59 +13:00
JT
9b60f76d04 Check TODO 2021-10-13 16:57:30 +13:00
JT
a760e46c1c Add config file loading 2021-10-13 16:57:05 +13:00
f5ce63ad55 Merge branch 'nushell:main' into main 2021-10-12 14:56:45 -07:00
151bdc8910 drop unused imports 2021-10-12 14:56:29 -07:00
2b99e49792 add strings/size command 2021-10-12 14:55:29 -07:00
94d00b28b7 add unicode-segmentation crate 2021-10-12 14:55:07 -07:00
8fee0b32e7 impl Value::Record from HashMap<String, Value> 2021-10-12 14:54:28 -07:00
97d7157773 Merge pull request #134 from fdncred/parse_kib_str_filesize
add ability to parse strings like "100kib" and "100 kib"
2021-10-12 15:56:49 -05:00
ffd922f393 add ability to parse strings like "100kib" and "100 kib" 2021-10-12 15:22:12 -05:00
JT
1ea124a65b Merge pull request #133 from nushell/todo_fixme
Clarify todo/fixmes
2021-10-13 07:20:45 +13:00
JT
6024a001b4 Clarify todo/fixmes 2021-10-13 06:44:23 +13:00
JT
67b8438bda Merge pull request #131 from nushell/invalid_var
Prevent invalid var names
2021-10-12 18:14:18 +13:00
JT
270e4fdd4c Merge pull request #130 from nushell/custom_switch
Custom switch support
2021-10-12 18:09:14 +13:00
JT
aea8627c30 Prevent invalid var names 2021-10-12 18:08:55 +13:00
JT
5f14faf4b4 Custom switch support 2021-10-12 17:49:17 +13:00
JT
60f0394106 Merge pull request #129 from nushell/do_rest_args
Do rest args
2021-10-12 16:34:21 +13:00
JT
c8277a3da9 Do rest args 2021-10-12 16:28:39 +13:00
JT
9f02307bd7 Merge pull request #128 from nushell/fix_missing_params
Fix missing param error and custom flag values
2021-10-12 10:22:34 +13:00
JT
96419f168b Also fix the flag params 2021-10-12 10:17:45 +13:00
JT
1f45304cf9 Fix parser when def has missing params 2021-10-12 09:58:38 +13:00
JT
db62bce6aa Merge pull request #127 from nushell/add_missing_operators
Add the remaining missing operators
2021-10-12 09:42:58 +13:00
JT
63e3552eef Add the remaining missing operators 2021-10-12 09:35:12 +13:00
JT
ce81cd6e2f Merge pull request #126 from nushell/missing_column_error
Give error on missing column during cell path
2021-10-12 09:02:46 +13:00
JT
0d031636a9 Error on missing column during cell path 2021-10-12 08:55:14 +13:00
JT
1a15f30eb8 Error on missing column during cell path 2021-10-12 08:51:54 +13:00
JT
6e92812cdf Merge pull request #125 from nushell/earlier_errors
Earlier errors
2021-10-12 08:38:29 +13:00
JT
0676f32509 Merge branch 'main' into earlier_errors 2021-10-12 08:33:19 +13:00
JT
576471cc3c Fix test 2021-10-12 08:33:09 +13:00
JT
e0433076ff Merge pull request #124 from nushell/jntrnr-patch-2
Try #2 - Mac/Windows CI
2021-10-12 08:24:09 +13:00
JT
a67be074e6 Try #2 - Mac/Windows CI 2021-10-12 08:19:43 +13:00
dada7a9867 Merge pull request #122 from fdncred/fix_windows_compiling
fix to allow windows to compile
2021-10-11 14:13:45 -05:00
ea9aad9b5d fix to allow windows to compile 2021-10-11 13:58:10 -05:00
JT
38bc394a12 Expose errors early when possible 2021-10-12 07:45:31 +13:00
JT
020143d050 Merge pull request #120 from nushell/serialize_stream
Add serialize/deserialize for streams
2021-10-12 07:18:41 +13:00
JT
d33a9549b5 Add serialize/deserialize for streams 2021-10-12 07:12:47 +13:00
JT
c4fe190cee Merge pull request #119 from nushell/error_improvement
Error improvement
2021-10-12 07:08:16 +13:00
JT
ba73e0eb06 Another early emit 2021-10-12 06:37:22 +13:00
JT
0504a7a776 Make errors emit first 2021-10-12 06:35:40 +13:00
1b9b709dec Merge pull request #118 from nushell/fdncred_separator
type-o in code
2021-10-11 09:47:00 -05:00
0e36b4b1bd type-o
changes seperator to separator
2021-10-11 09:32:06 -05:00
JT
acb0360180 Merge pull request #117 from nushell/conversions
Conversions
2021-10-11 15:01:30 +13:00
JT
4d0a253924 Merge main 2021-10-11 14:57:39 +13:00
JT
c3a032950d Add initial batch of into conversions 2021-10-11 14:56:19 +13:00
JT
b4344b3964 Merge pull request #114 from xiuxiu62/main
add `rm`
2021-10-11 09:58:01 +13:00
491efab09b remove open and save 2021-10-10 13:24:54 -07:00
7cafdc9675 Merge branch 'nushell:main' into main 2021-10-10 13:15:54 -07:00
JT
89267df9eb Merge pull request #115 from kubouch/hiding-rehaul
Hiding rehaul
2021-10-11 07:38:53 +13:00
JT
ecee5a9845 Update chars.rs 2021-10-11 07:28:33 +13:00
77c520e10b Make predeclarations scoped; Add hiding tests
In some rare cases, the global predeclarations would clash, for example:

  > module spam { export def foo [] { "foo" } }; def foo [] { "bar" }

In the example, the `foo [] { "bar" }` would get predeclared first, then
the predeclaration would be overwritten and consumed by `foo [] {"foo"}`
inside the module, then when parsing the actual `foo [] { "bar" }`, it
would not find its predeclaration.
2021-10-10 14:31:13 +03:00
40741254f6 Rewrite hiding system
Hiding definitions now should work correctly with repeated use of 'use',
'def' and 'hide' keywords.

The key change is that 'hide foo' will hide all definitions of foo
that were defined/used within the scope (those from other scopes are
still available). This makes the logic simpler and I found it leads to a
simpler mental map: you don't need to remember the order of defined/used
commands withing the scope -- it just hides all.
2021-10-10 13:18:47 +03:00
0b35905ce9 revert temp val 2021-10-09 22:43:50 -07:00
beb15dcc77 cleanup + clippy suggestions 2021-10-09 21:17:08 -07:00
97ca242634 add rm command + stubs for open and save 2021-10-09 21:13:15 -07:00
a986de8ad0 Update stale.yml (#4073)
add labels that can exempt from stale bot
2021-10-09 14:50:27 -05:00
JT
53f3d2572c Merge pull request #107 from arthur-targaryen/in-not-in-operators
Add `in` and `not-in` operators support
2021-10-10 07:09:25 +13:00
a0a63c966f Add inline attribute and address warning 2021-10-09 19:44:03 +02:00
d5fdfdb614 Add missing test attribute 2021-10-09 19:40:47 +02:00
75de7f7e61 Implement PartialOrd for Value::Stream 2021-10-09 19:40:47 +02:00
4e443b2088 Change helper method visibility 2021-10-09 19:40:47 +02:00
9e7e8ed48f Handle not-in operator 2021-10-09 19:40:47 +02:00
5f9ad0947d Fix Range::contains 2021-10-09 19:40:47 +02:00
4235cf1191 Implement and use PartialOrd for Value 2021-10-09 19:40:45 +02:00
357b9ccaa9 Remove unused import 2021-10-09 19:27:54 +02:00
d1f0740765 Refactor in operator for Range 2021-10-09 19:27:54 +02:00
29cbcb8459 Implement RangeIterator::contains 2021-10-09 19:27:54 +02:00
7f06d6144f Support in operator for record and value stream 2021-10-09 19:27:54 +02:00
7db6b876ab Simplify Result<Value, _> comparaison using matches! 2021-10-09 19:27:54 +02:00
d3bc096d47 Handle reverse ranges
This is really ugly and should be refactored.
2021-10-09 19:27:54 +02:00
8783cf0138 Add basic in operator support 2021-10-09 19:27:54 +02:00
JT
563a0b92b5 Merge pull request #113 from nushell/more_test
Add a couple more tests to for, add stream/list PartialEq
2021-10-10 06:03:09 +13:00
JT
8df9ea6c68 Add a couple more tests to for 2021-10-10 05:58:33 +13:00
JT
b28f876095 Merge pull request #112 from nushell/fix_for
Fix the for loop to create vars
2021-10-10 05:24:05 +13:00
JT
5d36d37d20 Merge branch 'main' into fix_for 2021-10-10 05:20:50 +13:00
JT
789fc30bf9 oops forgot file 2021-10-10 05:14:02 +13:00
JT
2c01901fcf Merge pull request #111 from elferherrera/unit-test
Example unit test
2021-10-10 05:13:22 +13:00
JT
e4ce41ba15 Fix the for loop to create vars 2021-10-10 05:10:46 +13:00
a1bfa2788c not found message for windows 2021-10-09 16:44:45 +01:00
8756e88e3c command split 2021-10-09 14:28:09 +01:00
41366f6cc4 Merge branch 'main' of https://github.com/nushell/engine-q into unit-test 2021-10-09 14:17:07 +01:00
e3e4ae0591 example unit test 2021-10-09 14:10:10 +01:00
JT
9a3b0312d2 Merge pull request #110 from nushell/better_value_map
Add map and flat_map to value
2021-10-09 19:24:16 +13:00
JT
2cd1f634d0 Add map and flat_map to value 2021-10-09 19:20:32 +13:00
JT
ddea4b416d Merge pull request #109 from nushell/split_column_row
Port split column and split row
2021-10-09 17:18:12 +13:00
JT
5c29a83a7a Add tests 2021-10-09 15:45:25 +13:00
JT
60f9fe1aa4 Port split column and split row 2021-10-09 15:41:39 +13:00
JT
44fbf0fce3 Merge pull request #108 from nushell/help_and_start_split
Port help and start porting split
2021-10-09 14:07:13 +13:00
JT
4ddc953e38 Port help and start porting split 2021-10-09 14:02:01 +13:00
JT
6c5a99b1a5 Merge pull request #106 from nushell/cleaner_extern
More external cleanup
2021-10-09 11:34:40 +13:00
JT
64d83142c3 More external cleanup 2021-10-09 11:30:10 +13:00
JT
b654415494 Merge pull request #105 from nushell/improve_external_args
Allow vars and subexprs in extern args
2021-10-09 10:56:24 +13:00
JT
dea9c1482b Allow vars and subexprs in extern args 2021-10-09 10:51:47 +13:00
JT
c79dca999c Merge pull request #104 from nushell/improved_alias_expand
Improve the alias expansion
2021-10-09 08:43:54 +13:00
JT
1b977c658c Improve the alias expansion 2021-10-09 08:38:42 +13:00
ed9fa2b4c3 Merge pull request #103 from fdncred/grid_custom_sep
allow one to specify a custom separator for the grid
2021-10-08 10:21:35 -05:00
42113a767a allow one to specify a custom separator 2021-10-08 10:15:07 -05:00
7f3f41ff14 Merge pull request #102 from fdncred/ls_colors_grid
respect lscolors env var; measure width minus ansi
2021-10-08 10:01:23 -05:00
c636c30a19 added a switch to enable coloring 2021-10-08 09:53:26 -05:00
5ddf0d209d respect lscolors env var; measure width minus ansi 2021-10-08 09:40:20 -05:00
1a3a837f3e Merge pull request #96 from fdncred/ls_grid_output
output `ls` as a grid vs table
2021-10-08 08:23:15 -05:00
c4dabe8327 some cleanup, extra_usage 2021-10-08 08:14:32 -05:00
JT
a2eba38e81 Merge pull request #101 from xiuxiu62/main
add touch command
2021-10-08 20:11:10 +13:00
bdfe8c0888 add mkdir command 2021-10-07 15:20:23 -07:00
c4977ae143 clippy 2021-10-07 16:59:01 -05:00
54a41c535b only print items with name column 2021-10-07 16:50:27 -05:00
8550f50522 substitute idiomatic call flag check 2021-10-07 14:36:47 -07:00
e8e1ead99d change diagnostic code on CreateNotPossible 2021-10-07 14:20:03 -07:00
adabc839bf add touch command 2021-10-07 14:18:03 -07:00
698f768a06 Merge branch 'main' into ls_grid_output 2021-10-07 11:07:21 -05:00
ae8b315e76 added list output 2021-10-07 11:00:49 -05:00
58d73d4c23 moved grid to it's own crate named nu-term-grid 2021-10-07 10:32:39 -05:00
22cfe4391e remove history file after clearing it (#4069) 2021-10-07 10:09:31 -05:00
JT
5021d61800 Update TODO.md 2021-10-07 08:43:00 +13:00
JT
97d17311f4 Update LICENSE (#4067) 2021-10-07 08:42:07 +13:00
JT
06d819ecc8 Merge pull request #100 from nushell/add-license-1
Create LICENSE
2021-10-07 06:42:02 +13:00
JT
bb126e8e09 Create LICENSE 2021-10-07 06:36:28 +13:00
0f6fd30619 stale.yml: mention time to close in stale message (#4066) 2021-10-06 09:05:29 -05:00
JT
248decc546 Merge pull request #99 from nushell/source_command
Source command
2021-10-06 15:36:28 +13:00
JT
2500f23fcb Delete example.nu 2021-10-06 15:30:36 +13:00
JT
7eb022b58c Adapt tk's work for a source command 2021-10-06 15:29:05 +13:00
d481d5ca96 Merge branch 'main' of https://github.com/nushell/engine-q into source-command 2021-10-05 22:16:07 -04:00
996ee363b7 comments 2021-10-05 22:03:18 -04:00
011ad2e4e6 Merge branch 'source-command' of https://github.com/moonrise-tk/engine-q into source-command 2021-10-05 21:59:26 -04:00
d6d0bad7aa reverted 2021-10-05 21:59:16 -04:00
JT
b35d47c500 Merge pull request #98 from xiuxiu62/main
port `cp` to fs commands
2021-10-06 11:20:18 +13:00
b3b51a2ed6 drop redundant iter -> vec -> iter 2021-10-05 15:09:51 -07:00
JT
c7de1ee13a Merge pull request #97 from stormasm/wrap_to_get
The signature of the get command was mistakenly named wrap
2021-10-06 11:06:11 +13:00
cc8a470668 clean up unused imports 2021-10-05 14:13:23 -07:00
74d4c501a8 add move, recursive fill, and recursive create procedures 2021-10-05 14:08:39 -07:00
5cc7fbcde7 jntrnr to nushell 2021-10-05 13:03:43 -07:00
48f534cd3b change location of reedline to nushell from the jt repo 2021-10-05 13:02:56 -07:00
8536c12bd9 change signature name to get, it was (I believe) incorrectly named wrap 2021-10-05 12:59:17 -07:00
8dc3ebd6e2 start cp command 2021-10-05 12:55:46 -07:00
5da1310696 add fs utils 2021-10-05 12:55:33 -07:00
9d49618e87 add impl From io::Error and dyn Error for ShellError 2021-10-05 12:54:30 -07:00
7697f7bdce fix doc-test 2021-10-05 12:58:48 -05:00
JT
e1ebd461d2 Bump to 0.28 (#4064) 2021-10-06 06:35:25 +13:00
JT
f000d5d0a1 Remove the broken scrolling support (#4063)
* Remove the broken scrolling support

* Remove the broken scrolling support
2021-10-06 05:57:14 +13:00
51a43f5617 mayve fix ci 2021-10-05 11:14:31 -05:00
11b40a6c31 clippy 2021-10-05 10:30:49 -05:00
3c843f7f61 renamed nu_grid to grid 2021-10-05 10:22:57 -05:00
e402adbba0 WIP: output ls as a grid vs table 2021-10-05 08:43:20 -05:00
JT
c4ea398160 Merge pull request #88 from xiuxiu62/main
port the mv command
2021-10-05 18:48:13 +13:00
27dcbe5c8a fix SyntaxShape::Filepath build error 2021-10-04 22:08:15 -07:00
4eb43adef2 Merge branch 'nushell:main' into main 2021-10-04 22:02:43 -07:00
0ef0588e29 mv clippy suggestions 2021-10-04 21:40:26 -07:00
JT
80e7a8d594 Update mv.rs 2021-10-05 16:58:49 +13:00
1b96da5e5b add custom filesystem shell errors 2021-10-04 20:43:07 -07:00
JT
e3ce58475b Merge pull request #95 from nushell/var_compl_better_ls
Variable completions and better ls
2021-10-05 16:06:06 +13:00
JT
31ce8c1e33 Variable completions and better ls 2021-10-05 15:46:24 +13:00
JT
14426433aa Merge pull request #93 from nushell/units
Add unit parsing and eval support
2021-10-05 15:32:14 +13:00
JT
535ece4e76 Add unit parsing and eval support 2021-10-05 15:27:39 +13:00
574c5961c8 Add -c flag to select command (#4062)
See cc3653cfd9 for more on the `-c` flag.

Co-authored-by: Andrés N. Robalino <andres@androbtech.com>

Co-authored-by: Andrés N. Robalino <andres@androbtech.com>
2021-10-05 13:23:37 +13:00
JT
75ec0d123a Merge pull request #92 from nushell/better_external_completion
Better completions for external args
2021-10-05 10:54:36 +13:00
JT
c884d5ca31 Better completions for external args 2021-10-05 10:50:46 +13:00
JT
f80e9d4b60 Merge pull request #91 from nushell/list_completions
Use list completions and better expansion
2021-10-05 10:44:26 +13:00
JT
26166192e5 Merge pull request #89 from kubouch/hide-import-patterns
Add import patterns to 'hide'
2021-10-05 10:44:13 +13:00
JT
7c2bf68d45 Use list completions and better expansion 2021-10-05 10:37:32 +13:00
6f5f1fa43a Clippy 2021-10-04 22:37:43 +03:00
JT
58b0e571d3 Merge pull request #90 from nushell/path_completion
Add path completions
2021-10-05 08:28:47 +13:00
JT
a88058006a Add path completions 2021-10-05 08:21:31 +13:00
1e1e12b027 Fmt 2021-10-04 22:17:18 +03:00
9737d4a614 Change comments 2021-10-04 20:33:27 +03:00
0fe525de87 Add test with TODO note 2021-10-04 20:16:43 +03:00
4dacfaa44a Add import pattern support to 'hide' 2021-10-04 20:08:24 +03:00
b2148e32b8 make mv parameters required 2021-10-04 05:13:47 -07:00
e325fd114d port the mv command 2021-10-04 04:32:08 -07:00
dfd321a679 Merge branch 'main' into source-command 2021-10-03 14:25:00 -04:00
909b7d2160 no-op 2021-10-03 14:23:23 -04:00
JT
2b5cc63118 Merge pull request #87 from nushell/lines_no_trim
Lines shouldn't trim
2021-10-03 11:00:04 +13:00
JT
75e323ee35 Lines shouldn't trim 2021-10-03 10:56:11 +13:00
JT
758fce8ae3 Merge pull request #86 from nushell/add_cd
Add simple cd
2021-10-03 09:20:28 +13:00
JT
91090e1db1 Add simple cd 2021-10-03 09:16:37 +13:00
JT
5bf51b5a7a Update TODO.md 2021-10-03 08:33:30 +13:00
JT
69708f7244 update wasm deps (#4061) 2021-10-03 07:19:54 +13:00
JT
1d7ab28a0f Merge pull request #74 from kubouch/module-export
Modules: export & hide
2021-10-03 06:25:43 +13:00
JT
eba3484611 Update tests.rs 2021-10-03 06:17:51 +13:00
JT
b5ec9e0360 Update mod.rs 2021-10-03 06:16:02 +13:00
JT
0cc121876b Update tests.rs
Update test errors to be more portable
2021-10-03 06:12:05 +13:00
JT
e4e1b7a11e Merge pull request #85 from stormasm/cargo-serde-derive
add serde derive to Cargo.toml so nu-protocol compiles standalone
2021-10-03 06:09:11 +13:00
be68b84473 add serde derive feature to Cargo.toml so nu-protocol compiles stand alone 2021-10-02 10:02:11 -07:00
JT
ae34a34e00 Merge pull request #84 from elferherrera/prompt
Prompt with env variable
2021-10-03 06:00:10 +13:00
81cd03626d Merge branch 'main' into module-export 2021-10-02 18:53:35 +03:00
6f4df31927 removed comments 2021-10-02 14:16:37 +01:00
03339beae1 prompt with env variable 2021-10-02 14:10:28 +01:00
62c5df5fc6 expand tilde when reading plugin_dirs (#4052) 2021-10-02 21:38:21 +13:00
92c855a412 Fixed two typos in the tutor. (#4051) 2021-10-02 21:37:59 +13:00
JT
9a64f1bff3 Merge pull request #83 from nushell/string_cell_path
Let strings be cell paths
2021-10-02 18:51:40 +13:00
JT
63a0aa6088 Let strings be cell paths 2021-10-02 18:43:43 +13:00
JT
a8f9e6dcc2 Merge pull request #82 from nushell/add_select
Add select
2021-10-02 18:00:18 +13:00
JT
6b76dd7cd7 Add select 2021-10-02 17:55:05 +13:00
JT
7899745c4b Merge pull request #81 from nushell/wrap_get
Add wrap and get and cell_path parsing
2021-10-02 17:23:57 +13:00
JT
5843acec02 Add wrap and get and cell_path parsing 2021-10-02 15:59:11 +13:00
9e7285ad46 Delete example.nu 2021-10-01 22:26:52 -04:00
8ef16c6da6 add source command 2021-10-01 22:25:35 -04:00
e1a0ad2987 fix more merge conflicts 2021-10-01 22:24:43 -04:00
2d4e471052 fix more merge conflicts 2021-10-01 22:17:32 -04:00
16c60f44d5 merge w/ upstream 2021-10-01 22:09:16 -04:00
adb92b970e nothing 2021-10-01 22:07:17 -04:00
6595c06598 Relax panic into error
Convert the panic when declaration cannot find predeclaration into an
error. This error is already covered and reported in the predeclaration
phase.
2021-10-02 03:42:35 +03:00
JT
3567bbbf32 Merge pull request #80 from nushell/early_help
add ps and early help
2021-10-02 10:59:58 +13:00
JT
c5e9ff5f14 add ps and early help 2021-10-02 10:53:13 +13:00
2c1b074bdc Add test for double def 2021-10-02 00:21:08 +03:00
fb0f83e574 Disallow hiding the same def twice; Add tests
Tests got removed after rebase.
2021-10-02 00:12:30 +03:00
891d79d2aa Fmt and misc fixes after rebase 2021-10-01 23:30:56 +03:00
25b05dec9e Fix panic on double def; Tests; Double def error
* Fixes a panic with defining two commands with the same name caused by
  declaration not found after predeclaration.
* Adds a new error if a custom command is defined more than once in one
  block.
* Add some tests
2021-10-01 23:25:24 +03:00
2af8116f50 Fix hiding logic; Fix hiding with predecls
* Hiding logic is simplified and fixed so you can hide and unhide the
  same def repeatedly.
* Separates predeclared ids into its own data structure to protect them
  from hiding. Otherwise, you could hide the predeclared variable and
  the actual def would panic.
2021-10-01 23:24:57 +03:00
aa06a71e1f Move new commands to the new structure 2021-10-01 23:24:57 +03:00
8ed6afe1e5 Fix tests failing without export 2021-10-01 23:24:57 +03:00
244289c901 Add missing file 2021-10-01 23:24:57 +03:00
7488254cca Implement a rough version of 'hide'
'hide' command is used to undefine custom commands
2021-10-01 23:24:54 +03:00
3cbf99053f Throw an error if using export outside of module 2021-10-01 23:21:30 +03:00
93521da9d8 Add 'export def' command 2021-10-01 23:21:28 +03:00
561feff365 Introduce 'export' keyword 2021-10-01 23:19:39 +03:00
1b89ccf25b Add comment 2021-10-01 23:19:39 +03:00
JT
5b3b74ebec Merge pull request #79 from kubouch/disable-raw-mode
Disable crossterm raw mode
2021-10-02 06:01:48 +13:00
a16144baf1 Disable crossterm raw mode
Without this change, the output of panic messages by miette would ignore
newlines and become unreadable.
2021-10-01 19:42:23 +03:00
d395816929 remove ansi colors if this is not a tty (#4058) 2021-10-01 09:00:08 -05:00
JT
5a5205d5d9 Merge pull request #78 from nushell/sys
add sys command
2021-10-01 19:58:57 +13:00
JT
503939dcbe add sys command 2021-10-01 19:53:47 +13:00
JT
000db46618 Merge pull request #77 from nushell/record_view
add a vertical record view
2021-10-01 19:07:03 +13:00
JT
d6e24cceb4 add a vertical record view 2021-10-01 19:01:22 +13:00
JT
99666829e0 Merge pull request #76 from nushell/from_json
Add 'from json'
2021-10-01 18:26:49 +13:00
JT
db3e9efc4b fix warnings 2021-10-01 18:20:25 +13:00
JT
3e232a5db8 Add 'from json' 2021-10-01 18:11:49 +13:00
e00755a2e9 fix compile errors 2021-09-30 23:04:56 -04:00
JT
d34e083976 Merge pull request #75 from nushell/prepare_for_porting
Prepare nu_commands for porting
2021-09-30 07:27:56 +13:00
JT
8250b44ce5 moved commands 2021-09-30 07:25:05 +13:00
JT
f0d5e2dcf1 Prepare nu_commands for porting 2021-09-30 07:17:51 +13:00
5e34ef6dff new command: into column_path (#4048) 2021-09-29 07:23:34 -05:00
d567c58cc1 Add -c flag to update cells subcommand (#4039)
* Add `-c` flag to `update cells` subcommand

* Fix lints
2021-09-27 21:18:50 -05:00
JT
125c8c82c3 Update TODO.md 2021-09-28 12:40:08 +13:00
4e0d7bc77c Less deps (#4038)
* compiles on nightly now. (breaking change)

* less deps

* Switch over to new resolver

(it's been stable for a while.)

* let's leave num-format for another PR
2021-09-28 07:17:00 +13:00
2b5ef1b2d7 Removed extra file 2021-09-27 08:10:45 -04:00
719920fa37 tried to move source command into parser (still doesn't compile) 2021-09-27 08:10:18 -04:00
JT
3b134a1ae2 Merge pull request #73 from nushell/forgiving_def_parse
More forgiving def parse
2021-09-27 14:06:51 +13:00
JT
84d0e0a059 More forgiving def parse 2021-09-27 14:03:50 +13:00
JT
0a48bc973d Merge pull request #72 from nushell/import_patterns
Add import lists
2021-09-27 13:32:36 +13:00
JT
0108a935ed add import lists 2021-09-27 13:23:22 +13:00
JT
5ccbf4df67 Merge pull request #71 from kubouch/fix-module-error
Fix wrong error span
2021-09-27 10:28:21 +13:00
9ee4dc49ee Fix wrong error span 2021-09-27 00:02:20 +03:00
JT
756269ee8d Merge pull request #70 from nushell/import_patterns
Add support for module imports
2021-09-27 07:47:50 +13:00
JT
abb0d7bd22 Add support for module imports 2021-09-27 07:39:19 +13:00
JT
47421e9ca7 Merge pull request #69 from kubouch/simple-module
Primitive module implementation
2021-09-27 05:14:23 +13:00
3f8f3ecf9a Fmt 2021-09-26 14:12:39 +03:00
f57f7b2def Allow adding definitions from module into scope 2021-09-26 13:53:52 +03:00
9e176674a5 Start parsing 'use'; Add Use command 2021-09-26 13:25:52 +03:00
57a07385ac Add leftover Module command file 2021-09-26 13:25:37 +03:00
12cf1a8f83 Allow adding module blocks to engine state 2021-09-26 12:12:32 +03:00
e9f1575924 Add a module command 2021-09-26 01:59:18 +03:00
32581497ef Fix 90 degrees tables problem (#4043)
* fix 90 degrees tables problem

* linting

* clippy

* linting
2021-09-25 14:05:45 -05:00
JT
1015ea814c Merge pull request #68 from nushell/list_table2
improve table for lists
2021-09-26 07:37:49 +13:00
JT
abac7e3795 improve table for lists 2021-09-26 07:07:37 +13:00
JT
22c6ed4718 Merge pull request #66 from elferherrera/table
Table as string output
2021-09-26 07:00:59 +13:00
JT
3421a8b58b Merge pull request #67 from nushell/revert-65-list_table
Revert "improve table for lists"
2021-09-26 06:59:59 +13:00
JT
75510b172a Revert "improve table for lists" 2021-09-26 06:57:26 +13:00
JT
04a8280d51 Merge pull request #65 from nushell/list_table
improve table for lists
2021-09-26 06:56:29 +13:00
JT
139775dcce improve table for lists 2021-09-26 06:37:25 +13:00
d9c42eb194 contents declaration 2021-09-25 17:28:15 +01:00
6387401041 clippy error 2021-09-25 17:03:25 +01:00
dadc354847 move print to function 2021-09-25 16:58:50 +01:00
25a776c36b trim lines in command 2021-09-25 16:45:02 +01:00
637e4f6e6d simplify command call 2021-09-25 15:58:04 +01:00
b12a265f1e writing to stdout 2021-09-25 15:56:33 +01:00
cf60f72452 table as string output 2021-09-25 15:47:23 +01:00
a176f12c9e Start simple module parsing 2021-09-25 17:14:20 +03:00
d6df367c6b Corrected typo (#4040)
It is not BSON but SQLite
2021-09-25 04:25:00 -05:00
JT
a2996abd47 improve table for lists 2021-09-25 20:58:02 +12:00
JT
b8d218e65b Update TODO.md 2021-09-25 20:46:43 +12:00
4e6327de1d Added BigInt handling to the delimited file format for the 'to' command (#4034)
Co-authored-by: patrick <patrick@spol42069.hitronhub.home>
2021-09-25 09:47:16 +12:00
b3d8666db0 compiles on nightly now. (breaking change) (#4037) 2021-09-25 09:46:48 +12:00
JT
d1da75d315 Merge pull request #62 from elferherrera/lines
Better print out for stream output
2021-09-25 05:39:06 +12:00
1de7c3d033 Scraping multiple tables (#4036)
* Output error when ls into a file without permission

* math sqrt

* added test to check fails when ls into prohibited dir

* fix lint

* math sqrt with tests and doc

* trigger wasm build

* Update filesystem_shell.rs

* Fix Running echo .. starts printing integers forever

* Allow for multiple table scraping

* linting

* Fix clippy

* linting

Co-authored-by: Jonathan Turner <jonathandturner@users.noreply.github.com>
2021-09-24 08:08:13 -05:00
767d822cbf change line format for test 2021-09-24 13:20:50 +01:00
b4977f1515 better print out for stream output 2021-09-24 13:03:39 +01:00
JT
6c589affe7 Merge pull request #61 from elferherrera/externals
Externals with redirection
2021-09-24 10:26:38 +12:00
cb9db792a6 filtering empty lines 2021-09-23 20:44:50 +01:00
04990eeba4 allow collect warning 2021-09-23 20:39:42 +01:00
772f8598dd lines command 2021-09-23 20:03:08 +01:00
JT
95439f5e9c Merge pull request #60 from zkat/main
deps: bump to miette 3.0 mainline
2021-09-24 06:01:04 +12:00
36c32e9832 input from ValueStream 2021-09-23 18:01:20 +01:00
660e8b5b73 external with redirection 2021-09-23 17:42:03 +01:00
5d442a287f deps: bump to miette 3.0 mainline 2021-09-22 16:50:57 -07:00
962b258cc6 merge span (#4031) 2021-09-23 07:48:05 +12:00
59697cab63 force rebuild of dev container (#4033) 2021-09-23 07:47:28 +12:00
JT
984538555c Merge pull request #59 from nushell/validation
multiline validation
2021-09-22 17:34:48 +12:00
JT
0ccbebee7a multiline validation 2021-09-22 17:29:53 +12:00
JT
9f9bec38e1 Merge pull request #58 from nushell/entry_num
Show entry number in error
2021-09-22 15:43:39 +12:00
JT
d1474c0691 Show entry number in error 2021-09-22 15:14:57 +12:00
JT
673137be8b Merge pull request #57 from zkat/main
Fix multifile miette crash
2021-09-22 13:02:43 +12:00
180dafb84c Merge branch 'nushell:main' into main 2021-09-21 17:57:35 -07:00
2553da3dc4 bump miette to fix multi-file rendering bug 2021-09-21 17:57:16 -07:00
a7ecf7af90 add magical debugging code to SourceCode impl for future debugging 2021-09-21 17:54:20 -07:00
JT
ff1adbd346 Merge pull request #55 from zkat/main
use miette's new panic hook
2021-09-22 10:02:09 +12:00
32f39c2fb8 use miette's new panic hook 2021-09-21 12:47:52 -07:00
JT
923330aadd Merge pull request #54 from zkat/main
Fix issue with unexpected EOF rendering in miette
2021-09-22 06:30:12 +12:00
c87414e462 Fix issue with unexpected EOF rendering in miette 2021-09-21 09:30:43 -07:00
JT
dbfd2808ba Merge pull request #53 from nushell/error_improvements
Add some improvements to errors
2021-09-21 16:12:47 +12:00
JT
3c18cac134 use the fancy 2021-09-21 16:10:29 +12:00
JT
4841d62d76 Add some improvements to errors 2021-09-21 16:03:06 +12:00
JT
e5aa8b9d3f Merge pull request #52 from zkat/main
replace codespan-reporting with miette 3.0
2021-09-21 12:58:14 +12:00
a1d6cefdf8 replace codespan-reporting with miette 3.0 2021-09-20 17:14:20 -07:00
JT
d532f3f304 Merge pull request #51 from elferherrera/externals
External with input
2021-09-21 09:56:47 +12:00
349af05da8 Do not throw error for files not found in lib_dirs (#4029) 2021-09-20 13:44:47 -05:00
29771c7d23 clippy errors 2021-09-20 10:42:03 +01:00
cb0914ecb0 remove enter scope 2021-09-20 10:32:55 +01:00
JT
b3b3cf0689 Remove the docker instructions
Docker has been out of date for a long time, go ahead and remove.
2021-09-20 19:33:49 +12:00
672dd5a868 external with input 2021-09-19 22:48:33 +01:00
JT
cbe85cbeaf Merge pull request #50 from elferherrera/externals
Externals proposal
2021-09-20 09:37:12 +12:00
6731e3542d clippy errors 2021-09-19 22:05:24 +01:00
5d59234f8d Flexibility updating table's cells. (#4027)
Very often we need to work with tables (say extracted from unstructured data or some
kind of final report, timeseries, and the like).

It's inevitable we will be having columns that we can't know beforehand what their names
will be, or how many.

Also, we may end up with certain cells having values we may want to remove as we explore.

Here, `update cells` fundamentally goes over every cell in the table coming in and updates
the cell's contents with the output of the block passed. Basic example here:

```
> [

    [   ty1,       t2,       ty];

    [     1,        a, $nothing]
    [(wrap), (0..<10),      1Mb]
    [    1s,     ({}),  1000000]
    [ $true,   $false,   ([[]])]

] | update cells { describe }

───┬───────────────────────┬───────────────────────────┬──────────
 # │          ty1          │            t2             │    ty
───┼───────────────────────┼───────────────────────────┼──────────
 0 │ integer               │ string                    │ nothing
 1 │ row Column(table of ) │ range[[integer, integer)] │ filesize
 2 │ string                │ nothing                   │ integer
 3 │ boolean               │ boolean                   │ table of
───┴───────────────────────┴───────────────────────────┴──────────
```

and another one (in the examples) for cases, say we have a timeseries table generated and
we want to remove the zeros and have empty strings and save it out to something like CSV.

```
> [
    [2021-04-16, 2021-06-10, 2021-09-18, 2021-10-15, 2021-11-16, 2021-11-17, 2021-11-18];
    [        37,          0,          0,          0,         37,          0,          0]
] | update cells {|value| i
  if ($value | into int) == 0 {
    ""
  } {
    $value
  }
}

───┬────────────┬────────────┬────────────┬────────────┬────────────┬────────────┬────────────
 # │ 2021-04-16 │ 2021-06-10 │ 2021-09-18 │ 2021-10-15 │ 2021-11-16 │ 2021-11-17 │ 2021-11-18
───┼────────────┼────────────┼────────────┼────────────┼────────────┼────────────┼────────────
 0 │         37 │            │            │            │         37 │            │
───┴────────────┴────────────┴────────────┴────────────┴────────────┴────────────┴────────────
```
2021-09-19 15:37:54 -05:00
5a6aebfcb2 clippy errors 2021-09-19 21:09:11 +01:00
96af23f370 clippy errors 2021-09-19 20:41:35 +01:00
4e6b6a8902 Merge branch 'main' of https://github.com/nushell/engine-q into externals 2021-09-19 20:30:07 +01:00
bafc50fd5c external command 2021-09-19 20:29:58 +01:00
Tw
4f7b423f36 Support completion when cursor inside an argument (#4023)
* Support completion when cursor inside an argument

Bash supports completion even when cursor is in an argument, this is very useful for some fixup after the initial completion.
Let add this feature as well.

Signed-off-by: Tw <wei.tan@intel.com>

* Add test for when cursor inside an argument

To support test this case, let's also take the position into account.

Signed-off-by: Tw <wei.tan@intel.com>
2021-09-19 17:23:05 +12:00
f7043bf690 Fix #3090: let binding in command leaks when error occurs (#4022) 2021-09-19 14:57:20 +12:00
Tw
1297499d7a add command g to switch shell quickly (#4014)
Signed-off-by: Tw <tw19881113@gmail.com>
2021-09-17 10:39:14 +01:00
bd0baa961c add table selector for downloading web tables (#4004)
* add table selector for downloading web tables

* type-o

* updated debug mode to inspect mode
2021-09-16 09:02:30 -05:00
4ee536f044 fix: enable SIMD (#4021) 2021-09-16 20:01:42 +12:00
JT
8581bec891 bump 0.37.1 (#4019) 2021-09-16 13:32:22 +12:00
8bcbc8eeb3 Move nu-path tests to integration tests (#4015)
* Move nu-path tests to integration tests

To prevent circular dependency between nu-path and nu-test-support crates.

* Fmt
2021-09-16 07:11:28 +12:00
c164ef5489 Update to polars 0.16 (#4013)
* update to polars 0.16

* enabled features for polars
2021-09-16 07:10:12 +12:00
cc3653cfd9 Path commands: Put column path args behid flag; Allow path join appending without flag (#4008)
* Change path join signature

* Appending now works without flag
* Column path operation is behind a -c flag

* Move column path arg retrieval to a function

Also improves errors

* Fix path join tests

* Propagate column path changes to all path commands

* Update path command examples with columns paths

* Modernize path command examples by removing "echo"

* Improve structured path error message

* Fix typo
2021-09-15 21:03:51 +03:00
JT
c03324ec9c Update TODO.md 2021-09-16 05:08:40 +12:00
JT
7fc65067cf Temporarily remove the circular dep (#4009) 2021-09-15 09:17:31 +12:00
JT
f9ae882012 Update main.wxs (#4007)
Remove references to the old binaries
2021-09-15 07:45:30 +12:00
JT
1d80a68f4c bump to 0.37 (#4006) 2021-09-15 06:44:24 +12:00
1a9247b77f Merge branch 'main' of https://github.com/nushell/engine-q into externals 2021-09-14 07:19:31 +01:00
JT
22e30d5ea7 Merge pull request #49 from nushell/git_branch_completion
Very early proof-of-concept git branch completion
2021-09-14 17:09:21 +12:00
JT
b4f918b889 Very early proof-of-concept git branch completion 2021-09-14 16:59:46 +12:00
JT
7b54e5c4ab Merge pull request #48 from elferherrera/parse-error
Error check on def and alias
2021-09-14 15:03:18 +12:00
JT
c4d1c458a2 Merge pull request #47 from stormasm/test_buildstring
more block param and build string tests in concert with lists
2021-09-14 15:02:10 +12:00
fda69354db change name to command_prompt (#4003) 2021-09-14 08:02:10 +12:00
7aa1d8ac2a error check on def and alias 2021-09-13 20:59:11 +01:00
b6fdf611f6 more block param and build string tests 2021-09-13 09:32:03 -07:00
JT
c0bad7ab23 Merge pull request #46 from nushell/block_param_types
Block param types
2021-09-13 20:22:44 +12:00
JT
d7a3c7522b Fix test 2021-09-13 20:19:05 +12:00
JT
4dfde7393b Merge branch 'main' into block_param_types 2021-09-13 19:59:18 +12:00
JT
32c1f0c8d4 better it detection and block params in shapes 2021-09-13 19:54:13 +12:00
JT
eb67eab122 WIP 2021-09-13 19:31:11 +12:00
JT
d88e46d2d1 Merge pull request #45 from kubouch/left-unbounded-ranges
Allow parsing left-unbounded range (..10)
2021-09-13 05:01:07 +12:00
JT
caa6236f1f Merge pull request #44 from kubouch/float-ranges
Floating point ranges
2021-09-13 04:59:51 +12:00
JT
f459f77335 Merge pull request #40 from elferherrera/parse-error
Parse errors for def, let and alias
2021-09-13 04:58:25 +12:00
66c58217af change message 2021-09-12 16:36:16 +01:00
8f07f40f22 external call 2021-09-12 16:34:43 +01:00
e6a2e27e33 Fix failing compilation after rebase 2021-09-12 15:57:49 +03:00
8577d3ff41 Check for left-unbounded range before external cmd 2021-09-12 15:56:58 +03:00
78054a5352 Allow parsing left-unbounded range (..10)
It is implemented as a preliminary check when parsing a call and relies
on a fact that a token that successfully parses as a range is unlikely
to be a valid path or command name.
2021-09-12 15:56:58 +03:00
ce0b5bf4ab Add test for float ranges 2021-09-12 15:36:54 +03:00
9936946eb5 Fmt 2021-09-12 14:58:32 +03:00
013b12a864 Do not allow precision interval to rach < epsilon 2021-09-12 14:55:11 +03:00
2f04c172fe Add floating point support for ranges 2021-09-12 14:12:53 +03:00
cc5c4d38bb Small fixes and refactors to paths & source command (#3998)
* Expand path when converting value -> PathBuf

Also includes Tagged<PathBuf>.

Fixes #3605

* Expand path for PATH env. variable

Fixes #1834

* Remove leftover Cows after nu-path refactor

There were some unnecessary Cow conversions leftover from the old
nu-path implementation.

* Use canonicalize in source command; Improve errors

Previously, `source` used `expand_path()` which does not follow
symlinks.

As a follow up, I improved the source error messages so they now tell
why the source file could not be canonicalized or read into string.
2021-09-12 02:36:14 +03:00
JT
648fe052db Merge branch 'main' into wip 2021-09-12 09:26:47 +12:00
JT
55aa70c88a WIP 2021-09-12 09:26:35 +12:00
JT
aa7ebdc9ce Merge pull request #43 from kubouch/range-stepping
Add stepping support & reversing to ranges
2021-09-12 06:54:56 +12:00
9c98783917 clippy correcgtions 2021-09-11 13:16:40 +01:00
4b8ba29cdb check for = before internal parsing 2021-09-11 13:07:19 +01:00
4749776984 Add stepping to ranges & enable reverse ranges
Follows the following syntax: <start>..<next-value>..<end>
2021-09-11 14:28:46 +03:00
47ee50072e Merge branch 'main' of https://github.com/nushell/engine-q into parse-error 2021-09-11 08:26:29 +01:00
198c884158 change name in error 2021-09-11 08:22:41 +01:00
1d945d8ce3 added source command 2021-09-11 00:54:24 -04:00
JT
2d3a56f0d3 Merge pull request #41 from nushell/fix_inner_completions
Improve completions inside of a pipeline
2021-09-10 20:10:17 +12:00
JT
bfd05772ef Improve completions inside of a pipeline 2021-09-10 20:07:18 +12:00
9a16a8fd06 corrected error check 2021-09-10 08:44:31 +01:00
2ea19aeac0 Merge branch 'main' of https://github.com/nushell/engine-q into parse-error 2021-09-10 08:28:58 +01:00
0794ebf5fa error parsing for def, alias and let 2021-09-10 08:28:43 +01:00
JT
a8ba00b250 Merge pull request #39 from nushell/silly_table
Add a very silly table
2021-09-10 14:30:02 +12:00
JT
26d50ebcd5 Add a very silly table 2021-09-10 14:27:12 +12:00
JT
0fa0c25fb3 Fix clippy warnings (#3997) 2021-09-10 13:13:11 +12:00
JT
0694245ccd Merge pull request #38 from nushell/silly_ls
Add a very silly ls
2021-09-10 13:12:40 +12:00
JT
c1194b3d1e Add a very silly ls 2021-09-10 13:09:54 +12:00
JT
16baf5e16a Add a very silly ls 2021-09-10 13:06:44 +12:00
55eafadf02 Improve error message when bash-style alias syntax is mistakenly used (#3995) 2021-09-10 10:44:55 +12:00
51c74eebd0 Add general refactorings (#3996) 2021-09-10 10:44:22 +12:00
JT
5edcf3910d Merge pull request #37 from nushell/completions
Completions and Row Conditions
2021-09-10 10:14:30 +12:00
JT
abda6f148c Finish up completions 2021-09-10 10:09:40 +12:00
JT
f7333ebe58 Check box 2021-09-10 09:47:57 +12:00
JT
6b2f639095 Merge branch 'main' into completions 2021-09-10 09:47:36 +12:00
JT
bb6781a3b1 Add row conditions 2021-09-10 09:47:20 +12:00
JT
b821b14987 Add simple completions support 2021-09-09 21:06:55 +12:00
JT
56b3f119c0 Update README.md 2021-09-09 21:03:12 +12:00
JT
4ee1776ceb Update TODO.md 2021-09-09 20:53:24 +12:00
JT
90204bd0c8 Merge pull request #36 from jntrnr/parser_improvements
Add parser README, some parser fixups
2021-09-09 07:16:24 +12:00
JT
2d7192e390 Add parser README, some parser fixups 2021-09-09 06:54:27 +12:00
JT
1e09a8e5ff Merge pull request #34 from moonrise-tk/main
Move value into its own folder in nu-protocol and add some comments
2021-09-08 15:44:56 +12:00
85a45ccf6a Merge branch 'main' of https://github.com/moonrise-tk/engine-q 2021-09-07 22:32:35 -04:00
d35a58e05c Remove unused imports 2021-09-07 22:32:28 -04:00
5605678bab Merge branch 'jntrnr:main' into main 2021-09-07 22:27:29 -04:00
ecbe7bf8d7 move value into its own folder 2021-09-07 22:26:57 -04:00
JT
1e4146aec5 Merge pull request #33 from moonrise-tk/main
add readme and target dir to gitignore
2021-09-08 14:09:11 +12:00
3990120813 add readme and target dir to gitignore 2021-09-07 22:01:02 -04:00
JT
fa84205e31 Merge pull request #32 from jntrnr/record_iteration
Add an experimental record iteration
2021-09-08 10:47:42 +12:00
JT
6dd9f05ea1 Add an experimental record iteration 2021-09-08 10:00:20 +12:00
JT
ab3820890b Update TODO.md 2021-09-07 19:59:57 +12:00
JT
8e8ef83875 Update TODO.md 2021-09-07 19:54:48 +12:00
JT
ed6abced5b Merge pull request #31 from jntrnr/make_prompt_more_resilient
Make reedline prompt more resilient
2021-09-07 19:44:45 +12:00
JT
2904002008 Make reedline prompt more resilient 2021-09-07 19:41:52 +12:00
JT
eccf0b9903 Merge pull request #30 from jntrnr/cell_path_streams
Add cell paths for streams
2021-09-07 19:41:09 +12:00
JT
a8646f94ab Add cell paths for streams 2021-09-07 19:35:59 +12:00
JT
71bbd70a57 Merge pull request #29 from jntrnr/record_row
Switch tables to list/streams of records
2021-09-07 19:13:23 +12:00
JT
6af3affee2 add a test and update TODO 2021-09-07 19:09:49 +12:00
JT
b0ab78a767 Switch tables to list/streams of records 2021-09-07 19:07:11 +12:00
JT
2055b83c34 Merge pull request #28 from jntrnr/smoother_list_parse_fail
Fail more gently for bad list/table parses
2021-09-07 15:59:09 +12:00
JT
e00da070fd Fail more gently for bad list/table parses 2021-09-07 15:56:30 +12:00
JT
b8e8061787 Merge pull request #27 from jntrnr/custom_rest
Allow rest vars to have a custom name
2021-09-07 15:40:45 +12:00
JT
bdce34676a Allow rest vars to have a custom name 2021-09-07 15:37:02 +12:00
JT
8f54ba10aa Merge pull request #26 from jntrnr/cell_paths
Add cell paths
2021-09-07 10:13:34 +12:00
JT
8db844a8d0 Check off TODO item 2021-09-07 10:11:12 +12:00
JT
3b7d7861e3 Add cell paths 2021-09-07 10:02:24 +12:00
JT
f71b7e89e0 Merge pull request #25 from elferherrera/one-parse-fn
One parser function
2021-09-07 08:47:16 +12:00
f7a19d37c6 one parser function 2021-09-06 21:41:30 +01:00
JT
c027a14b9b Merge pull request #24 from jntrnr/concrete_var_assign
Concrete var assign
2021-09-07 06:15:54 +12:00
JT
f91d0d6d65 merge main 2021-09-07 06:07:41 +12:00
JT
4ce9a5c894 Make variable assignment convert streams to full values 2021-09-07 06:05:46 +12:00
JT
7191b08903 Merge pull request #23 from stormasm/build-string
some build-string tests
2021-09-07 05:05:19 +12:00
3534bd8a64 some build-string tests 2021-09-06 09:05:53 -07:00
JT
cdbd333c9b Merge pull request #22 from jntrnr/div_int
improve int division to be more nushell-like
2021-09-06 17:38:44 +12:00
JT
a1f7a3c17b improve int division to be more nushell-like 2021-09-06 17:35:58 +12:00
JT
76c92fc706 Merge pull request #21 from jntrnr/simple_value_iteration
Simple value iteration
2021-09-06 16:21:13 +12:00
JT
9b56221b5c Merge branch 'main' into simple_value_iteration 2021-09-06 16:16:48 +12:00
JT
3b99ce71a0 add simple value iteration 2021-09-06 16:16:32 +12:00
JT
5f4cc50ce7 Merge pull request #20 from jntrnr/range_iterators
Range iteration
2021-09-06 16:11:05 +12:00
JT
96b0edf9b0 range iteration 2021-09-06 16:07:48 +12:00
JT
9e7d96ea50 Update TODO.md 2021-09-06 14:40:55 +12:00
JT
faa53de893 Merge pull request #19 from jntrnr/block_params
Block params
2021-09-06 14:25:07 +12:00
JT
b930fc5d9d updated TODO 2021-09-06 14:22:58 +12:00
JT
979faf853a Block params 2021-09-06 14:20:02 +12:00
JT
aaee3a8b61 WIP 2021-09-06 11:16:27 +12:00
JT
036c6a9a52 Merge pull request #18 from elferherrera/update-dependencies
Updated dependencies
2021-09-06 07:09:24 +12:00
b3d287815d updated dependencies 2021-09-05 20:06:57 +01:00
JT
fda7e096cd Merge pull request #17 from jntrnr/fix_15
Fix #15
2021-09-06 06:48:59 +12:00
JT
57677a50b5 Fix #15 2021-09-06 06:44:18 +12:00
JT
6f17695891 Merge pull request #16 from kubouch/ranges-new
Implement positive integer ranges
2021-09-06 06:23:13 +12:00
JT
6ebc97dec2 Update parser.rs 2021-09-06 06:09:36 +12:00
56c8987e0f Add '.' and '-' to restricted characters
This means that commands cannot start with these characters.
However, we get the following benefits:
* Negative numbers               > -10
* Ranges with negative numbers   > -10..-1
* Left-unbounded ranges          > ..10
2021-09-05 20:33:53 +03:00
7ae4ca88b6 "Fix" failing CI 2021-09-05 11:03:04 +03:00
f0d469f1d4 Fix clippy warnings 2021-09-05 01:40:15 +03:00
6b4fee88c9 Fmt 2021-09-05 01:35:08 +03:00
672fa852b3 Add some tests to range parsing 2021-09-05 01:25:31 +03:00
0b412cd6b3 Add support for positive integer ranges
Including support for variables and subexpressions as range bounds.
2021-09-05 00:52:57 +03:00
Tw
ae9f4135c0 support appending when saving file (#3992)
This patch implements `>>` operation in bash.

Signed-off-by: Tw <tw19881113@gmail.com>
2021-09-05 06:12:08 +12:00
JT
2794556eaa Merge pull request #14 from elferherrera/similar-name
Similar name check to protocol
2021-09-04 20:26:46 +12:00
JT
a26c42a9b6 Update ci.yml 2021-09-04 20:22:49 +12:00
331ccd544f workflow on pull_request 2021-09-04 09:22:09 +01:00
d6b1ff932a Merge branch 'main' of https://github.com/jonathandturner/engine-q into similar-name 2021-09-04 09:20:35 +01:00
JT
26b1f022b7 fixup 2021-09-04 20:19:07 +12:00
ab307c8d38 Merge branch 'main' of https://github.com/jonathandturner/engine-q into similar-name 2021-09-04 09:10:38 +01:00
a3d4794341 moved test to protocol 2021-09-04 09:10:31 +01:00
JT
25c7d8ead6 Merge pull request #13 from jntrnr/ci
Add CI
2021-09-04 20:09:05 +12:00
JT
2834d71a12 improve ci 2021-09-04 20:05:36 +12:00
JT
bf9b6d8088 improve ci 2021-09-04 20:02:57 +12:00
JT
d9cff4238d clippy 2021-09-04 19:59:38 +12:00
JT
198a36b744 Add CI 2021-09-04 19:52:28 +12:00
JT
f259992b4b Merge pull request #12 from elferherrera/similar-name
Similar name check for signature
2021-09-04 19:49:36 +12:00
ca8d311c78 Merge branch 'main' of https://github.com/jonathandturner/engine-q into similar-name 2021-09-04 08:45:55 +01:00
acc035dbef signature check for similar name 2021-09-04 08:45:49 +01:00
JT
5e33b8536b Add discrete list/table 2021-09-04 18:52:28 +12:00
JT
74bb2af3e1 Fix up block parse recovery 2021-09-04 08:58:44 +12:00
JT
b20c4047d4 Some cleanup, better subexpressions 2021-09-03 19:35:29 +12:00
4e2d3ceaaf Allow knowing the command name tag given no input. (#3988)
```
tags
```
2021-09-03 01:46:15 -05:00
JT
82cf6caba4 Add do 2021-09-03 16:01:45 +12:00
JT
bc3f820227 Merge pull request #10 from jntrnr/value_streams_in_value
Value streams in value
2021-09-03 15:49:27 +12:00
JT
12d80c2732 Fix test 2021-09-03 15:49:14 +12:00
JT
6c0ce95d0f Add simple each 2021-09-03 15:45:34 +12:00
JT
750502c870 Fix up for_in 2021-09-03 14:57:18 +12:00
JT
df63490266 Fix up calls and pipelines 2021-09-03 14:15:01 +12:00
c9c6bd4836 Create errors from tables. (#3986)
```
> [
  [          msg,                 labels,                      span];
  ["The message", "Helpful message here", ([[start, end]; [0, 141]])]
] | error make

error: The message
  ┌─ shell:1:1
  │
1 │ ╭ [
2 │ │   [          msg,                 labels,                      span];
3 │ │   ["The message", "Helpful message here", ([[start, end]; [0, 141]])]
  │ ╰─────────────────────────────────────────────────────────────────────^ Helpful message here
```

Adding a more flexible approach for creating error values. One use case, for instance is the
idea of a test framework. A failed assertion instead of printing to the screen it could create
tables with more details of the failed assertion and pass it to this command for making a full
fledge error that Nu can show. This can (and should) be extended for capturing error values as well
in the pipeline. One could also use it for inspection.

For example: `.... | error inspect { # inspection here }`

or "error handling" as well, like so: `.... | error capture { fix here }`

However, we start here only with `error make` that creates an error value for you with limited support for the time being.
2021-09-02 21:07:26 -05:00
d90420ac4c Add subcommand into filesize (#3987)
* Add subcommand `into filesize`

It's currently not possible to convert a number or a string containing a number
into a filesize. The only way to create an instance of filesize type today is
with a literal in nushell syntax. This commit adds the `into filesize`
subcommand so that file sizes can be created from the outputs of programs
producing numbers or strings, like standard unix tools.

There is a limitation with this - it doesn't currently parse values like `10 MB`
or `10 MiB`, it can only look at the number itself. If the desire is there, more
flexible parsing can be added.

* fixup! Add subcommand `into filesize`

* fixup! Add subcommand `into filesize`
2021-09-02 18:19:54 -05:00
JT
7c8504ea24 Add commands 2021-09-03 10:58:15 +12:00
JT
94687a7603 Back to working state 2021-09-03 06:21:37 +12:00
JT
e1be8f61fc WIP 2021-09-02 20:25:22 +12:00
JT
3d252a9797 Add nu-protocol 2021-09-02 13:29:43 +12:00
JT
45683a53c9 Merge pull request #8 from elferherrera/lite-parser
Comments with a newline dont get together
2021-09-02 12:54:56 +12:00
JT
c4c4d82bf4 Try putting streams in Value 2021-09-02 09:20:53 +12:00
4ed79614ac removed unused empty function 2021-09-01 21:34:16 +01:00
73f6a57b12 upper comments get attached to command 2021-09-01 21:05:37 +01:00
260ff99710 feat: spawn the executables directly if possible (#3974)
* feat: spawn the executables directly if possible

This pull request changes nu-command so that it spawns the process directly if:
- They are a `.exe` on Windows
- They are not a `.sh` or `.bash` on not windows.

Benefits:
- As I explained in [this comment](https://github.com/nushell/nushell/issues/3898#issuecomment-894000812), this is another step towards making Nushell a standalone shell, that doesn't need to shell out unless it is running a script for a particular shell (cmd, sh, ps1, etc.).
- Fixes the bug with multiline strings
- Better performance due to direct spawning.

For example, this script shows ~20 ms less latency.
After:
```nu
C:\> benchmark { node -e 'console.log("sssss")' }
───┬──────────────────
 # │    real time
───┼──────────────────
 0 │ 63ms 921us 600ns
───┴──────────────────
```
Before
```nu
C:\> benchmark { node -e 'console.log("sssss")' }
───┬──────────────────
 # │    real time
───┼──────────────────
 0 │ 79ms 136us 800ns
───┴──────────────────
```

Fixes #3898

* fix: make which dependency optional

Also fixes clippy warnings

* refactor: refactor spawn_exe, spawn_cmd, spawn_sh, and spawn_any

* fix: use which feature instead of which-support

* fix: use which_in to use the cwd of nu

* fix: use case insensitive comparison of the extensions

Sometimes the case of the extension is uppercased by the "which_in" function

Also use unix instead of not windows. Some os might not have sh support
2021-09-01 09:38:52 -05:00
JT
fcc1cd3d57 Update TODO.md 2021-09-01 15:17:14 +12:00
JT
08014c6a98 Move sys, ps, fetch, post to internal commands (#3983)
* Move sys, ps, fetch, post to internal commands

* Remove old plugins

* clippy

Co-authored-by: JT <jonatha.d.turner@gmail.com>
2021-09-01 14:29:09 +12:00
5da2ab1b7d comments with a newline dont get together 2021-08-31 20:33:41 +01:00
JT
d0be193307 Merge pull request #7 from elferherrera/tests
Tests for lex and lite parser
2021-08-31 12:07:46 +12:00
b3fb106cce tests for lex and lite parser 2021-08-30 19:36:07 +01:00
66cedf0b3a Update char_.rs (#3975)
added a few more chars and abbreviations
2021-08-29 08:40:28 -05:00
707a4ebc15 added more escapes to support ansi art (#3973)
* added more escapes to support ansi art

* fixed some bugs
2021-08-28 14:58:59 -05:00
JT
46d2efca13 Fix table parsing 2021-08-29 07:17:30 +12:00
d95375d494 nu-path crate refactor (#3730)
* Resolve rebase artifacts

* Remove leftover dependencies on removed feature

* Remove unnecessary 'pub'

* Start taking notes and fooling around

* Split canonicalize to two versions; Add TODOs

One that takes `relative_to` and one that doesn't.
More TODO notes.

* Merge absolutize to and rename resolve_dots

* Add custom absolutize fn and use it in path expand

* Convert a couple of dunce::canonicalize to ours

* Update nu-path description

* Replace all canonicalize with nu-path version

* Remove leftover dunce dependencies

* Fix broken autocd with trailing slash

Trailing slash is preserved *only* in paths that do not contain "." or
"..". This should be fixed in the future to cover all paths but for now
it at least covers basic cases.

* Use dunce::canonicalize for canonicalizing

* Alow cd recovery from non-existent cwd

* Disable removed canonicalize functionality tests

Remove unused import

* Break down nu-path into separate modules

* Remove unused public imports

* Remove abundant cow mapping

* Fix clippy warning

* Reformulate old canonicalize tests to expand_path

They wouldn't work with the new canonicalize.

* Canonicalize also ~ and ndots; Unify path joining

Also, add doc comments in nu_path::expansions.

* Add comment

* Avoid expanding ndots if path is not valid UTF-8

With this change, no lossy path->string conversion should happen in the
nu-path crate.

* Fmt

* Slight expand_tilde refactor; Add doc comments

* Start nu-path integration tests

* Add tests TODO

* Fix docstring typo

* Fix some doc strings

* Add README for nu-path crate

* Add a couple of canonicalize tests

* Add nu-path integration tests

* Add trim trailing slashes tests

* Update nu-path dependency

* Remove unused import

* Regenerate lockfile
2021-08-28 15:59:09 +03:00
1c1c58e802 Remove duplicate dependencies (#3961)
* chore: Replace surf with reqwest

Removes a lot of older, duplication versions of some dependencies
(roughtly 90 dependencies removed in total)

* chore: Remove syn 0.11

* chore: Remove unnecessary features from ptree

Removes some more duplicate dependencies

* cargo update

* Ensure we run the fetch and post plugins on the tokio runtime

* Fix clippy warning

* fix: Github requires a user agent on requests

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2021-08-28 15:34:11 +12:00
JT
7fe05b8296 bump to 0.36.1 (#3972) 2021-08-27 20:48:58 +12:00
17ef531905 introducing the find command (#3971)
* introducing the `find` command

* added tests

* merged main to accomodate "rest" changes

* test fix
2021-08-27 20:48:41 +12:00
JT
24cd1b591c Update todo 2021-08-27 14:30:10 +12:00
JT
bb9e6731ea More parsing fixes with tests 2021-08-27 11:44:08 +12:00
JT
5dd5a89775 Fix condition parsing for if 2021-08-27 09:48:27 +12:00
b8e2bdd6b1 Allow different names for ...rest (#3954)
* Allow different names for ...rest

* Resolves #3945

* This change requires an explicit name for the rest argument in `WholeStreamCommand`,
  which is why there are so many changed files.

* Remove redundant clone

* Add tests
2021-08-27 05:58:53 +12:00
88817a8f10 Allow environment variables to be hidden (#3950)
* Allow environment variables to be hidden

This change allows environment variables in Nushell to have a value of
`Nothing`, which can be set by the user by passing `$nothing` to
`let-env` and friends.

Environment variables with a value of Nothing behave as if they are not
set at all. This allows a user to shadow the value of an environment
variable in a parent scope, effectively removing it from their current
scope. This was not possible before, because a scope can not affect its
parent scopes.

This is a workaround for issues like #3920.

Additionally, this allows a user to simultaneously set, change and
remove multiple environment variables via `load-env`. Any environment
variables set to $nothing will be hidden and thus act as if they are
removed. This simplifies working with virtual environments, which rely
on setting multiple environment variables, including PATH, to specific
values, and remove/change them on deactivation.

One surprising behavior is that an environment variable set to $nothing
will act as if it is not set when querying it (via $nu.env.X), but it is
still possible to remove it entirely via `unlet-env`. If the same
environment variable is present in the parent scope, the value in the
parent scope will be visible to the user. This might be surprising
behavior to users who are not familiar with the implementation details.

An additional corner case is the the shorthand form of `with-env` does
not work with this feature. Using `X=$nothing` will set $nu.env.X to the
string "$nothing". The long-form works as expected: `with-env [X
$nothing] {...}`.

* Remove unused import

* Allow all primitives to be convert to strings
2021-08-26 08:15:58 -05:00
3e8ce43dcb rename command and rename for melt (#3968) 2021-08-26 08:13:54 -05:00
9d8845d7ad Allow custom lib dir path for sourcing nu script libraries. (#3940)
Given we can write nu scripts. As the codebase grows, splitting into many smaller nu scripts is necessary.

In general, when we work with paths and files we seem to face quite a few difficulties. Here we just tackle one of them and it involves sourcing
files that also source other nu files and so forth. The current working directory becomes important here and being on a different directory
when sourcing scripts will not work. Mostly because we expand the path on the current working directory and parse the files when a source command
call is done.

For the moment, we introduce a `lib_dirs` configuration value and, unfortunately, introduce a new dependency in `nu-parser` (`nu-data`) to get
a handle of the configuration file to retrieve it. This should give clues and ideas as the new parser engine continues (introduce a way to also know paths)

With this PR we can do the following:

Let's assume we want to write a nu library called `my_library`. We will have the code in a directory called `project`: The file structure will looks like this:

```
project/my_library.nu
project/my_library/hello.nu
project/my_library/name.nu
```

This "pattern" works well, that is, when creating a library have a directory named `my_library` and next to it a `my_library.nu` file. Filling them like this:

```

source my_library/hello.nu
source my_library/name.nu
```

```

def hello [] {
  "hello world"
}
```

```

def name [] {
  "Nu"
end
```

Assuming this `project` directory is stored at `/path/to/lib/project`, we can do:

```
config set lib_dirs ['path/to/lib/project']
```

Given we have this `lib_dirs` configuration value, we can be anywhere while using Nu and do the following:

```
source my_library.nu

echo (hello) (name)

```
2021-08-26 02:04:04 -05:00
JT
2f91aca897 Merge branch 'main' of github.com:jonathandturner/engine-q 2021-08-26 07:29:50 +12:00
JT
35c3622405 Add a few operators. Needs parser work 2021-08-26 07:29:36 +12:00
52578ba483 tweak the version | pivot instructions (#3964) 2021-08-24 19:03:07 -05:00
JT
991a4801b1 Bump to 0.36 (#3963) 2021-08-25 06:01:17 +12:00
02b2c55146 Rolling and cumulative commands (#3960)
* rolling and cumulative operations

* update polars to 0.15.1

* change reference in function
2021-08-24 09:10:29 -05:00
0abe753003 update the config part (#3962) 2021-08-24 08:58:17 -05:00
JT
487fafbca3 Add a 'tutor' command (#3949)
* Add a 'tutor' command

* clippy
2021-08-21 19:41:54 +12:00
188a352c6f added help --find to search usage and extra_usage text for strings (#3948)
* added help --find to search usage and extra_usage text for strings

* changed my mind
2021-08-20 17:55:56 -05:00
e11b400a75 Allow source to accept paths with emojis (#3939)
* Allow sourcing paths with emojis

* Add source command tests for emoji paths

* Fmt

* Disable source tests on Windows with illegal paths

* Test sourcing also ASCII and single-quoted paths
2021-08-19 19:06:18 +12:00
6db5692be4 Only allow unaliasing in current scope, add tests (#3936)
* unalias only removes aliases in the current scope

* Add a test and fix previous ones which did not function as expected
2021-08-19 19:05:36 +12:00
JT
8ab7b27d4f Update TODO.md 2021-08-18 06:00:16 +12:00
JT
ead4029d49 Bump rustyline and add unalias test (#3935) 2021-08-18 05:55:34 +12:00
JT
9e76fb2231 Update TODO.md 2021-08-18 05:34:38 +12:00
JT
9c7d2ab8f2 Create TODO.md
Todo:
- [x] Env shorthand
- [x] String interpolation
- [x] Aliases
- [x] Env vars
- [x] Sub commands
- [x] Floats
- [x] Tests
- [x] Decl requires $
- [x] alias highlighting at call site
- [x] refactor into subcrates
- [x] subcommand alias
- [x] type inference from successful parse (eg not List<unknown> but List<int>)
- [x] variable type mismatch 
- [ ] finish operator type-checking
- [ ] Column path
- [ ] Ranges
- [ ] Source
- [ ] Autoenv
- [ ] Block params

# Maybe
- [ ] default param values?
- [ ] Unary not?
2021-08-18 05:34:08 +12:00
9bd408449e Add the ability to remove and list aliases (#3879)
* Add the ability to remove and list aliases

* Fix failing unit tests

* Add a test to check unalias shadowing blocks
2021-08-17 08:56:35 -05:00
JT
739425431a improve type inference 2021-08-17 12:26:05 +12:00
JT
dda6554990 Fix up subcommand alias colours 2021-08-17 11:04:45 +12:00
JT
2f43cc353b Fix some expects, add subcommand alias 2021-08-17 11:00:00 +12:00
JT
2b7390c2a1 Switch back to building for size (#3924) 2021-08-17 08:45:39 +12:00
ab961a78cb Add trailing slash in completion of symlinked dir (#3921) 2021-08-17 07:13:59 +12:00
65c639cf13 allow fetch to follow redirects (#3923) 2021-08-16 12:31:02 -05:00
0cf5dc11e3 Fix 'Inimplemented' typo. (#3922) 2021-08-16 09:17:31 -05:00
JT
ceea7e5aeb Remove lifetime from eval state 2021-08-16 14:30:31 +12:00
JT
579814895d Fix up eval params and refactor 2021-08-16 10:33:34 +12:00
b873fa7a5f The zip command. (#3919)
We introduce it here and allow it to work with regular lists (tables with no columns) as well as symmetric tables. Say we have two lists and wish to zip them, like so:

```
[0 2 4 6 8] | zip {
  [1 3 5 7 9]
} | flatten

───┬───
 0 │ 0
 1 │ 1
 2 │ 2
 3 │ 3
 4 │ 4
 5 │ 5
 6 │ 6
 7 │ 7
 8 │ 8
 9 │ 9
───┴───
```

In the case for two tables instead:

```
[[symbol]; ['('] ['['] ['{']] | zip {
  [[symbol]; [')'] [']'] ['}']]
} | each {
  get symbol | $'($in.0)nushell($in.1)'
}

───┬───────────
 0 │ (nushell)
 1 │ [nushell]
 2 │ {nushell}
───┴───────────
```
2021-08-14 23:36:08 -05:00
ee563ecf4e PROMPT_STRING env variable (#3918)
* prompt string env variable

* cargo clippy
2021-08-15 06:14:14 +12:00
183b35d683 Rustyline bug fixes (#3916)
* Mitigate history file bug in Rustyline

Rustyline's duplicate ignoring code has a bug that can cause data loss and
history file corruption. Testing seems to indicate that disabling this behavior
and allowing duplicates will prevent the bug from showing up. Many people have
complained about this issue, I think it is worthwhile to fix the bug at the cost
of permitting duplicate history entries.

Upstream bug: https://github.com/kkawakam/rustyline/issues/559

* Increase Rustyline historyfile limit

Rustyline will only store 100 history items by default. This is quite a small
limit for a shell that people use as a daily driver. Especially when the
deduplication code is removed, we will hit that limit quickly and start to lose
history. This commit bumps the limit up to 10k. We can discuss if this is an
inappropriate limit or if we should allow users to specify this setting in their
nushell config file instead.
2021-08-14 06:56:28 +12:00
463dd48180 Flexible dropping of rows (by desired row number) (#3917)
We very well support `nth 0 2 3 --skip 1 4` to select particular rows and skip some using a flag. However, in practice we deal with tables (whether they come from parsing or loading files and whatnot) where we don't know the size of the table up front (and everytime we have these, they may have different sizes). There are also other use cases when we use intermediate tables during processing and wish to always drop certain rows and **keep the rest**.

Usage:

```
... | drop nth 0
... | drop nth 3 8
```
2021-08-13 12:48:05 -05:00
1bd3fdd912 upgrade shadow-rs 0.6.8 (#3914) 2021-08-13 06:03:50 +12:00
JT
7655b070df fix tests 2021-08-11 06:57:08 +12:00
JT
1355a5dd33 refactor to subcrates 2021-08-11 06:51:08 +12:00
f62e3119c4 a little more progress on errors 2021-08-10 18:31:34 +12:00
828585a312 add more type helpers and span fixes 2021-08-10 17:55:25 +12:00
ef4af443a5 parser fixes for windows and pretty errors 2021-08-10 17:08:10 +12:00
JT
1a3e1e0959 touchup alias highlight 2021-08-09 20:00:16 +12:00
JT
40004e64a6 Merge branch 'main' of github.com:jonathandturner/engine-q 2021-08-09 19:55:22 +12:00
JT
50dc0ad207 aliases 2021-08-09 19:55:06 +12:00
JT
3da4f02ffa aliases 2021-08-09 19:53:06 +12:00
8a2bba4efb use storm's fix 2021-08-09 18:02:51 +12:00
1ba80224ad More gracefully handle reedline errors 2021-08-09 17:29:25 +12:00
JT
bf19918e3c begin aliases 2021-08-09 12:19:07 +12:00
JT
38fef28c84 Add subcommand test 2021-08-09 09:55:18 +12:00
JT
273f964293 slight improvement 2021-08-09 09:34:21 +12:00
JT
d2577acccd env vars 2021-08-09 09:02:47 +12:00
JT
d92e661253 Adding floating point 2021-08-09 08:21:21 +12:00
de71cbdd43 document engine-p porting (#3868)
* document engine-p porting

See #3390 for all the details.

* use static numbering
2021-08-08 05:57:32 +12:00
c9b87c4c03 Count the size of the directories when calculating the size in DirInfo (#3902)
* take dir entry size into consideration when calculting the size of a directory in DirInfo

* fmt check
2021-08-08 05:50:02 +12:00
38848082ae describe command (#3907) 2021-08-08 05:48:54 +12:00
JT
b6728efcd4 in/not-in for strings (#3906) 2021-08-07 09:49:37 +12:00
cd814851da Use bigdecimal-rs patch (#3905)
* Use bigdecimal-rs patch

* fix nu-serde's bigdecimal dependency
2021-08-07 09:27:19 +12:00
6646daab45 source config from $NU_CONFIG_DIR if it exists (#3883) 2021-08-06 11:47:11 -05:00
ba483155d7 Reimplement parsers with nu-serde (#3880)
The nu-serde crate allows us to become much more generic with respect to how we
convert output to `nu-protocol::Value`s. This allows us to remove a lot of the
special-case code that we wrote for deserializing JSON values.

Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2021-08-06 11:46:19 -05:00
63abe1cb3e Datetime commands (#3894)
* date and duration from nu

* date commands

* Import to feature flag

* corrected to-csv example

* corrected sample example
2021-08-05 17:18:53 -05:00
28db8022fe Update README.md
added integrations and mentions in supported section
2021-08-05 07:35:22 -05:00
7dcc08985c Implement PartialEq for ReturnSuccess (#3888)
This makes ReturnValue and ReturnSuccess usable in assert_eq!.
2021-08-05 14:55:41 +12:00
55acdaaf8c add officially supported by section (#3895) 2021-08-04 15:57:57 -05:00
575c07c9c4 Normalize capitalization in issue templates (#3891)
* Normalize capitalization in feature_request.yml

* Normalize capitalization in bug_report.yml
2021-08-03 18:49:03 -05:00
325f45fa66 Fix typo: patter → pattern (#3890) 2021-08-03 18:48:23 -05:00
JT
bc682066d8 Bump to 0.35 (#3884) 2021-08-03 20:01:09 +12:00
0a1cdc5107 Add the nu-serde crate (#3878)
* Add the nu-serde crate

nu-serde is a crate that can be used to turn a value implementing
`serde::Serialize` into a `nu-protocol::Value`. This has the potential to
significantly simplify plugin authorship.

This crate was the previously independent
[serde-nu](https://github.com/lily-mara/serde-nu) but the nushell maintainers
expressed an interest in having it added to the mainline nushell repository.

* fixup! Add the nu-serde crate
2021-07-31 22:03:13 -05:00
6984185e61 Better representation in nested dataframes (#3875)
* better dataframe representation in nested df

* Error message correction
2021-07-31 09:02:32 -05:00
5826126284 simple contains arguments (#3874) 2021-07-31 09:01:05 -05:00
JT
cb11f042ab Start env shorthand 2021-07-31 17:20:40 +12:00
JT
b82a4869d5 Add test 2021-07-31 16:25:26 +12:00
JT
c2be740ad4 def predecl 2021-07-31 16:04:42 +12:00
JT
61258d03ad add more tests 2021-07-31 09:57:22 +12:00
JT
79a05d63c8 add more tests 2021-07-31 09:26:05 +12:00
762e528ec5 Support equals sign in shorthand environment variable values (#3869)
Some environment variables, such as `RUST_LOG` include equals signs. Nushell
should support this in the shorthand environment variable syntax so that
developers using these variables can control them easily. We accomplish this by
swapping `std::str::split` for `std::str::splitn`, which ensures that we only
consider the first equals sign in the string instead of all of them, which we
did previously.

Closes #3867
2021-07-31 09:10:28 +12:00
JT
c3de9848b4 Revert "Unify use of the surf crate (#3855)" (#3871)
This reverts commit 7f7af2bbaa.
2021-07-31 09:04:01 +12:00
370ae8c20c Add support for mult-doc YAML files (#3870)
Single doc YAML files are returned as before. Multi-doc YAML files are
wrapped in an outer Table. Empty YAML files return Nothing.
2021-07-30 15:45:19 -05:00
JT
18752672d0 add more tests 2021-07-31 08:02:16 +12:00
69083bfca0 Adding parse fix for power operator error on negative integers and de… (#3821)
* Adding parse fix for power operator error on negative integers and decimal

* Adding correct formatting

* Changed is negative check to follow conventions

* Adding tests

* Added fix for the negatives and added tests

* Removed comments
2021-07-30 07:08:57 -05:00
JT
cdc37bb142 fix eval bug 2021-07-30 20:06:48 +12:00
JT
083dcd4541 Better for loop 2021-07-30 19:50:39 +12:00
JT
b6f00d07e8 Fix var decl. improve for loop 2021-07-30 19:30:11 +12:00
JT
b0ffaf1c91 add for loop and benchmark 2021-07-30 18:10:40 +12:00
JT
2af61bd07e add correct eval scope 2021-07-30 17:42:33 +12:00
JT
1caae90c02 cleanup some highlighting 2021-07-30 16:43:31 +12:00
JT
184125a70a cleanup some highlighting 2021-07-30 16:38:41 +12:00
JT
7cac5bb633 Merge pull request #5 from jntrnr/string_interp
String interp
2021-07-30 15:34:00 +12:00
JT
53314cb8b2 slightly better coloring 2021-07-30 15:33:33 +12:00
JT
b5e287e065 WIP string interp 2021-07-30 15:26:06 +12:00
1e15f26e98 fix interpolated strings when using unicode (#3866)
* fix interpolated strings when using unicode

* added test case
2021-07-29 19:07:34 -05:00
23ba01d89c add performance metrics for measuring startup time (#3854)
* add performance metrics for measureing startup time

* removed some comments

* update so tests pass

* update default.toml for tests, merged main

* fix clippy lints

* wording changes
2021-07-29 18:52:40 -05:00
JT
2eeceae613 fix clippy, add strings and concat 2021-07-30 10:56:51 +12:00
653cbe651f Going deeper (#3864)
* nuframe in its own type in UntaggedValue

* Removed eager dataframe from enum

* Dataframe created from list of values

* Corrected order in dataframe columns

* Returned tag from stream collection

* Removed series from dataframe commands

* Arithmetic operators

* forced push

* forced push

* Replace all command

* String commands

* appending operations with dfs

* Testing suite for dataframes

* Unit test for dataframe commands

* improved equality for dataframes

* moving all dataframe operations to protocol

* objects in dataframes

* Removed cloning when converting to row
2021-07-30 09:16:30 +12:00
JT
f3e487e829 Add named positionals to all (#3863) 2021-07-30 09:12:24 +12:00
9c016ad479 document compiling without openssl (#3862) 2021-07-30 08:21:20 +12:00
JT
e602647d4d Fix clippy lint and disable broken lint (#3865) 2021-07-30 08:11:47 +12:00
9696e4d315 Improve md5 and sha256 code (#3841)
* Refactor Hash code to simplify md5 and sha256 implementations

Md5 and Sha256 (and other future digests) require less boilerplate code
now. Error reporting includues the name of the hash again.

* Add missing hash sha256 test
2021-07-29 10:22:16 -05:00
7f7af2bbaa Unify use of the surf crate (#3855)
This brings the features used by the `nu_plugin_fetch` and
`nu_plugin_post` in line and drops the default-features, reducing
the number of pulled-in dependencies and avoiding a second round of
compilations.

Retry of #3777 but with different features, post and fetch plugin tested

Signed-off-by: Daniel Egger <daniel@eggers-club.de>
2021-07-29 19:26:38 +12:00
b190051e15 Fix select to insert nulls in sparse tables instead of ignoring absent values (#3857)
Select used to ignore absent values resulting in "squashing" where
columns for multiple rows could be squashed into a single row.

This fixes the problem by inserting null/nothing into absent value, thus
preserving the structure of rows. This makes sure that all selected
columns are present in each row.
2021-07-28 16:39:42 -05:00
83b28cad8d Remove dependencies (#3853)
* nuframe in its own type in UntaggedValue

* Removed eager dataframe from enum

* Dataframe created from list of values

* Corrected order in dataframe columns

* Returned tag from stream collection

* Removed series from dataframe commands

* Arithmetic operators

* forced push

* forced push

* Replace all command

* String commands

* appending operations with dfs

* Testing suite for dataframes

* Unit test for dataframe commands

* improved equality for dataframes

* moving all dataframe operations to protocol
2021-07-27 14:20:06 -05:00
ea42a84a4a Update implementing_a_command.md (#3848)
+  nu-command/src/command.rs has been modified to nu-command/src/mod.rs in nowable version
2021-07-27 09:03:52 -05:00
e4c282f0a6 added the ability to compare time units like 1hr < 2hr (#3845) 2021-07-26 15:19:32 -05:00
d54d7cc431 append dataframes (#3839) 2021-07-26 08:36:09 +12:00
111477aa74 Add sha256 to the hash command (#3836)
Hashers now uses on Rust Crypto Digest trait which makes it trivial to
implement additional hash functions.

The original `md5` crate does not implement the Digest trait and was
replaced by `md-5` crate which does. Sha256 uses already included `sha2`
crate.
2021-07-25 14:08:08 -05:00
JT
226739d13f Bump to 0.34.1 (#3835) 2021-07-25 22:58:33 +12:00
f1ee9113ac All is a DataFrame (#3812)
* nuframe in its own type in UntaggedValue

* Removed eager dataframe from enum

* Dataframe created from list of values

* Corrected order in dataframe columns

* Returned tag from stream collection

* Removed series from dataframe commands

* Arithmetic operators

* forced push

* forced push

* Replace all command

* String commands

* appending operations with dfs

* Testing suite for dataframes

* Unit test for dataframe commands

* improved equality for dataframes
2021-07-25 22:01:54 +12:00
9120a64cfb use chrono_humanize for datetime formatting (#3834)
* use chrono_humanize for datetime formatting

* fix tests
2021-07-25 20:38:45 +12:00
fcd624a722 add date humanize command (#3833)
* add `date humanize` command

* add docs
2021-07-25 17:33:31 +12:00
e6af7f75a1 Read from standard input in rm (#3763)
* Read from standard input in `rm`

With this change, rm falls back to reading from the standard input if no
arguments are supplied. This leads to more intuitive pipes as seen in
https://github.com/nushell/nushell/issues/2824

 ls | get name | sort-by | first 20 | each {rm $it} becomes
 ls | get name | sort-by | first 20 | rm

* [Fix] Run cargo fmt, make files a rest parameter, and fix cargo build warnings

* [Fix] Fix clippy suggestions
2021-07-25 15:01:53 +12:00
27f1e7b60c change describe so it doesn't output colored strings (#3832) 2021-07-25 06:34:11 +12:00
2e24de7f47 Support other variables than PATH in pathvar (2nd attempt) (#3828)
* Fix swapped PATH env var separators

* Support pathvar to manipulate other vars than PATH

* Add tests for pathvar and its subcommands

* Adjust pathvar tests to comply with env quirks

* Make pathvar tests work on non-Windows as well

* Compact the comments in pathvar tests

* Fix last failing test

Co-authored-by: Jakub Žádník <jakub.zadnik@tuni.fi>
2021-07-24 11:44:36 -05:00
e514204db0 Fix wrong path separator (#3829) 2021-07-24 08:42:50 -05:00
JT
a8366ebf15 Merge pull request #4 from jntrnr/wip
Wip
2021-07-24 18:44:57 +12:00
JT
ad48387aa0 WIP 2021-07-24 18:44:38 +12:00
JT
a4bcc1ff3d WIP 2021-07-24 17:57:17 +12:00
JT
fca3a6b75e Support adding variables 2021-07-24 09:46:55 +12:00
JT
6fcdc76059 Improve call eval and live check 2021-07-24 09:19:30 +12:00
0f9e55dac6 Revert "Support other variables than PATH in pathvar (#3791)" (#3827)
This reverts commit f9f39c0a1c.
2021-07-23 09:03:28 -05:00
5d7677dd07 Implement into path conversion (#3811)
This allows converting strings to filepaths without having to use
`path expand` roundtrip.

Filepaths are taken as-is without any validation/conversion.
2021-07-23 19:14:02 +12:00
57073cc6cf port capitalize to engine-p (#3794)
Part of #3390.
2021-07-23 19:13:11 +12:00
f9f39c0a1c Support other variables than PATH in pathvar (#3791)
* Fix swapped PATH env var separators

* Support pathvar to manipulate other vars than PATH

* Add tests for pathvar and its subcommands

* Fix PATH env name for Windows

Seems like Windows uses PATH as well.

Co-authored-by: Jakub Žádník <jakub.zadnik@tuni.fi>
2021-07-23 19:11:56 +12:00
JT
3eefa6dec8 start expanding eval 2021-07-23 17:14:49 +12:00
JT
8c6feb7e80 Fix up global span logic 2021-07-23 08:45:23 +12:00
JT
37f8ff0efc Add highlighting 2021-07-23 07:50:59 +12:00
d88d7f26e4 fix typo in release.yml (#3824) 2021-07-22 12:42:11 -05:00
aeaedd2e5e Convert templates to github forms (#3818)
* Create feature_request.yaml

* Rename feature_request.yaml to feature_request.yml

* Update feature_request.yml

* Update feature_request.yml

* Create bug_report.yml

* Update bug_report.yml

* Update bug_report.yml

* Update feature_request.yml

* Delete bug_report.md

* Delete feature_request.md
2021-07-23 05:39:20 +12:00
1f4ef3b606 Add worflow to publish package in winget (#3819)
Remove the job in release workflow to publish to winget.
Trigger winget workflow on published release.

Co-authored-by: Alexandre Nedelec <Alexandre.Nedelec@azeo.com>
2021-07-22 11:38:03 -05:00
9b5db297a6 Replace command (#3823)
* replace command

* cargo fmt

* Signature correction
2021-07-22 08:45:46 -05:00
JT
07c22c7e81 Start working on highlighter 2021-07-22 19:48:45 +12:00
JT
1ac0c0bfc5 Move to refcell for permanent parser state 2021-07-22 19:33:38 +12:00
JT
c25209eb34 Fix running multiple times, add reedline 2021-07-22 18:04:50 +12:00
b7215b5dde Fix expected age of mockup files in example tests (#3808) 2021-07-20 18:05:58 -05:00
411435d68f Dataframe Shape command (#3805)
* size command to get dataframe info

* change command name to shape

* apply lint to file
2021-07-20 07:07:42 -05:00
f656f906ff Update stale.yml
update days-before-issue-stale to 90 days
2021-07-19 15:03:24 -05:00
d0a7363e64 bat theme wasn't getting set properly (#3807) 2021-07-19 14:54:36 -05:00
7401fa2fa5 Fix docs for the config variable completion_type (#3804) 2021-07-19 07:20:56 -05:00
JT
4deed7c836 improve subcommand parse 2021-07-18 07:40:39 +12:00
JT
92f72b4103 add subcommand parsing 2021-07-18 07:34:43 +12:00
JT
30f54626d3 add companion short flags 2021-07-18 06:52:50 +12:00
JT
3a8206d1fb fix parser merge. start highlighter 2021-07-17 18:31:34 +12:00
JT
6b0b8744c1 Fix assignment parse 2021-07-17 17:28:25 +12:00
JT
0b8352049c Add pipelines 2021-07-17 15:42:08 +12:00
JT
c03f700662 Add rest param 2021-07-17 11:22:01 +12:00
JT
d08f2e73d0 Add optional params 2021-07-17 10:53:45 +12:00
JT
aa7f23e1e1 Simple short flag parse 2021-07-17 10:39:30 +12:00
JT
4249c5b3e0 Add param descriptions 2021-07-17 10:31:36 +12:00
JT
6f1a5c8e02 Remove lexmode 2021-07-17 10:11:15 +12:00
JT
03a93bd089 Improve colon sep 2021-07-17 10:00:41 +12:00
JT
6aef00ecff basic signature parse 2021-07-17 09:55:12 +12:00
JT
949c6a5932 intern blocks sooner 2021-07-17 08:26:40 +12:00
JT
7922bb4020 More decl parsing 2021-07-16 18:24:46 +12:00
JT
697bf16f26 Start moving towards decls and add a simple eval 2021-07-16 13:10:22 +12:00
181ee1dade Revert "Unify use of the surf crate (#3777)" (#3783)
This reverts commit 37612345f2.
2021-07-14 20:21:18 -05:00
3645a0f0e4 Updated polars version for faster CSV reader (#3781) 2021-07-14 15:33:21 -05:00
2864eaebae fixed show_hints option to allow hints to be turned off (#3780) 2021-07-14 09:47:33 -05:00
37612345f2 Unify use of the surf crate (#3777)
This brings the features used by the `nu_plugin_fetch` and
`nu_plugin_post` in line and drops the default-features, reducing
the number of pulled-in dependencies and avoiding a second round of
compilations.

Signed-off-by: Daniel Egger <daniel@eggers-club.de>
2021-07-14 08:47:49 -05:00
bb218b824e corrected position of dataframes (#3776) 2021-07-14 08:46:32 -05:00
279329bfaa Add the -s parameter to submit package to winget in pipeline (#3767)
Co-authored-by: Alexandre Nedelec <Alexandre.Nedelec@azeo.com>
2021-07-13 18:35:56 -05:00
JT
9916f35b22 cleanup 2021-07-09 18:23:20 +12:00
JT
0a6f62bc0e proper list/table guards 2021-07-09 09:45:56 +12:00
JT
bc974a3e7d cleanup 2021-07-09 09:31:08 +12:00
JT
1aa70c50aa refactor positional arg parse 2021-07-09 09:16:25 +12:00
JT
134b45dc03 refactor long/short flags 2021-07-09 08:29:00 +12:00
JT
96c0b933d9 Add parameterized list parsing 2021-07-08 19:49:17 +12:00
JT
7b51c5c49f Add alias and external 2021-07-08 19:20:01 +12:00
JT
eac02b55f6 some cleanup 2021-07-08 18:57:24 +12:00
JT
5d4ae4a2a4 drive let from internal call 2021-07-08 18:19:38 +12:00
JT
04cbef3aa8 Improve keyword detecting for call parsing 2021-07-08 17:30:36 +12:00
JT
e540f0ad26 start adding row expr parsing 2021-07-08 10:55:46 +12:00
JT
bf1a23afcf Add table parsing 2021-07-06 13:48:45 +12:00
JT
04a6a4f860 Add list parsing 2021-07-06 10:58:56 +12:00
JT
666bee61f7 Merge pull request #3 from jonathandturner/revert-2-revert-1-checkpiont
Revert "Revert "Removed file_id in Span, compact file sources""
2021-07-03 15:40:02 +12:00
JT
a6e0f0bb74 Revert "Revert "Removed file_id in Span, compact file sources"" 2021-07-03 15:35:15 +12:00
JT
03ce896f6f Merge pull request #2 from jonathandturner/revert-1-checkpiont
Revert "Removed file_id in Span, compact file sources"
2021-07-03 15:34:17 +12:00
JT
80e0cd4e00 Revert "Removed file_id in Span, compact file sources" 2021-07-03 15:11:24 +12:00
JT
049477a9bd Merge pull request #1 from jonathandturner/checkpiont
Removed file_id in Span, compact file sources
2021-07-03 13:39:14 +12:00
JT
d644a8d41f trimming structs 2021-07-03 13:37:27 +12:00
JT
e0c2074ed5 trimming structs 2021-07-03 13:29:56 +12:00
JT
d8bf48e692 minor change 2021-07-03 07:30:03 +12:00
JT
a91efc3cbd blocks 2021-07-02 19:32:30 +12:00
JT
fb42c94b79 parens 2021-07-02 19:15:30 +12:00
JT
ba2e3d94eb math 2021-07-02 18:44:37 +12:00
JT
4ef65f0983 Add some tests 2021-07-02 14:22:54 +12:00
JT
2675ad9304 Add some tests 2021-07-02 13:42:25 +12:00
JT
c1240f214c Remove warnings. Improve unknown flags 2021-07-02 10:54:04 +12:00
JT
7f3eab418f Add call parsing 2021-07-02 10:40:08 +12:00
JT
4f89ed5d66 little bits of progress 2021-07-01 18:09:55 +12:00
JT
43fd0b6ae9 Add var usage 2021-07-01 13:31:02 +12:00
JT
e3abadd686 Add stmt parsing 2021-07-01 12:01:04 +12:00
JT
3d2e227f11 fix import 2021-06-30 13:47:19 +12:00
JT
29d2449fb3 first commit 2021-06-30 13:42:56 +12:00
1832 changed files with 131206 additions and 96700 deletions

View File

@ -1,66 +0,0 @@
trigger:
- main
strategy:
matrix:
linux-stable:
image: ubuntu-18.04
style: 'unflagged'
linux-minimal:
image: ubuntu-18.04
style: 'minimal'
linux-extra:
image: ubuntu-18.04
style: 'extra'
linux-wasm:
image: ubuntu-18.04
style: 'wasm'
macos-stable:
image: macos-10.14
style: 'unflagged'
windows-stable:
image: windows-2019
style: 'unflagged'
fmt:
image: ubuntu-18.04
style: 'fmt'
pool:
vmImage: $(image)
steps:
- bash: |
set -e
if [ -e /etc/debian_version ]
then
sudo apt-get -y install libxcb-composite0-dev libx11-dev
fi
if [ "$(uname)" == "Darwin" ]; then
curl https://sh.rustup.rs -sSf | sh -s -- -y --no-modify-path --default-toolchain "stable"
echo "Installing clippy"
rustup component add clippy --toolchain stable-x86_64-apple-darwin
export PATH=$HOME/.cargo/bin:$PATH
fi
# rustup update
# rustc -Vv
# echo "##vso[task.prependpath]$HOME/.cargo/bin"
# rustup component add rustfmt
displayName: Install Rust
- bash: RUSTFLAGS="-D warnings" cargo test --all
condition: eq(variables['style'], 'unflagged')
displayName: Run tests
- bash: RUSTFLAGS="-D warnings" cargo clippy --all -- -D clippy::unwrap_used
condition: eq(variables['style'], 'unflagged')
displayName: Check clippy lints
- bash: cd samples/wasm && npm install wasm-pack && node ./node_modules/wasm-pack/run.js build
condition: eq(variables['style'], 'wasm')
displayName: Wasm build
- bash: RUSTFLAGS="-D warnings" cargo test --all --no-default-features --features=rustyline-support
condition: eq(variables['style'], 'minimal')
displayName: Run tests
- bash: RUSTFLAGS="-D warnings" cargo test --all --features=extra
condition: eq(variables['style'], 'extra')
displayName: Run tests
- bash: cargo fmt --all -- --check
condition: eq(variables['style'], 'fmt')
displayName: Lint

View File

@ -1,6 +1,14 @@
# use LLD as linker on Windows because it could be faster
# for full and incremental builds compared to default
[target.x86_64-pc-windows-msvc]
#linker = "lld-link.exe"
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
# set a 2 gb stack size (0x80000000 = 2147483648 bytes = 2 GB)
# [target.x86_64-unknown-linux-gnu]
# rustflags = ["-C", "link-args=-Wl,-z stack-size=0x80000000"]
# set a 2 gb stack size (0x80000000 = 2147483648 bytes = 2 GB)
# [target.x86_64-apple-darwin]
# rustflags = ["-C", "link-args=-Wl,-stack_size,0x80000000"]

View File

@ -1,165 +0,0 @@
# CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/configuration-reference/ for more details
# See https://circleci.com/docs/2.0/config-intro/#section=configuration for spec
#
version: 2.1
# Commands
commands:
pull_cache:
description: Pulls Quay.io docker images (latest) for our cache
parameters:
tag:
type: string
default: "devel"
steps:
- run: echo "Tag is << parameters.tag >>"
- run: docker pull quay.io/nushell/nu:<< parameters.tag >>
- run: docker pull quay.io/nushell/nu-base:<< parameters.tag >>
orbs:
# https://circleci.com/orbs/registry/orb/circleci/docker
docker: circleci/docker@0.5.13
workflows:
version: 2.0
# This builds on all pull requests to test, and ignores main
build_without_deploy:
jobs:
- docker/publish:
deploy: false
image: nushell/nu-base
tag: latest
dockerfile: docker/Dockerfile.nu-base
extra_build_args: --cache-from=quay.io/nushell/nu-base:devel
filters:
branches:
ignore:
- main
before_build:
- pull_cache
after_build:
- run:
name: Build Multistage (smaller) container
command: |
docker build -f docker/Dockerfile -t quay.io/nushell/nu .
- run:
name: Preview Docker Tag for Nushell Build
command: |
DOCKER_TAG=$(docker run quay.io/nushell/nu --version | cut -d' ' -f2)
echo "Version that would be used for Docker tag is v${DOCKER_TAG}"
- run:
name: Test Executable
command: |
docker run --rm quay.io/nushell/nu-base --help
docker run --rm quay.io/nushell/nu --help
# workflow publishes to Docker Hub, with each job having different triggers
build_with_deploy:
jobs:
# Deploy versioned and latest images on tags (releases) only - builds --release.
- docker/publish:
image: nushell/nu-base
registry: quay.io
tag: latest
dockerfile: docker/Dockerfile.nu-base
extra_build_args: --cache-from=quay.io/nushell/nu-base:latest,quay.io/nushell/nu:latest --build-arg RELEASE=true
filters:
branches:
ignore: /.*/
tags:
only: /^\d+\.\d+\.\d+$/
before_build:
- run: docker pull quay.io/nushell/nu:latest
- run: docker pull quay.io/nushell/nu-base:latest
after_build:
- run:
name: Build Multistage (smaller) container
command: |
docker build -f docker/Dockerfile -t quay.io/nushell/nu .
- run:
name: Test Executable
command: |
docker run --rm quay.io/nushell/nu --help
docker run --rm quay.io/nushell/nu-base --help
- run:
name: Publish Docker Tag with Nushell Version
command: |
DOCKER_TAG=$(docker run quay.io/nushell/nu --version | cut -d' ' -f2)
echo "Version for Docker tag is ${DOCKER_TAG}"
docker tag quay.io/nushell/nu-base:latest quay.io/nushell/nu-base:${DOCKER_TAG}
docker tag quay.io/nushell/nu:latest quay.io/nushell/nu:${DOCKER_TAG}
docker push quay.io/nushell/nu-base
docker push quay.io/nushell/nu
# publish devel to Docker Hub on merge to main (doesn't build --release)
build_with_deploy_devel:
jobs:
# Deploy devel tag on merge to main
- docker/publish:
image: nushell/nu-base
registry: quay.io
tag: devel
dockerfile: docker/Dockerfile.nu-base
extra_build_args: --cache-from=quay.io/nushell/nu-base:devel
before_build:
- pull_cache
filters:
branches:
only: main
after_build:
- run:
name: Build Multistage (smaller) container
command: |
docker build --build-arg FROMTAG=devel -f docker/Dockerfile -t quay.io/nushell/nu:devel .
- run:
name: Test Executable
command: |
docker run --rm quay.io/nushell/nu:devel --help
docker run --rm quay.io/nushell/nu-base:devel --help
- run:
name: Publish Development Docker Tags
command: |
docker push quay.io/nushell/nu-base:devel
docker push quay.io/nushell/nu:devel
nightly:
triggers:
- schedule:
cron: "0 0 * * *"
filters:
branches:
only:
- main
jobs:
- docker/publish:
image: nushell/nu-base
registry: quay.io
tag: nightly
dockerfile: docker/Dockerfile.nu-base
extra_build_args: --cache-from=quay.io/nushell/nu-base:nightly --build-arg RELEASE=true
before_build:
- run: docker pull quay.io/nushell/nu:nightly
- run: docker pull quay.io/nushell/nu-base:nightly
after_build:
- run:
name: Build Multistage (smaller) container
command: |
docker build -f docker/Dockerfile -t quay.io/nushell/nu:nightly .
- run:
name: Test Executable
command: |
docker run --rm quay.io/nushell/nu:nightly --help
docker run --rm quay.io/nushell/nu-base:nightly --help
- run:
name: Publish Nightly Nushell Containers
command: |
docker push quay.io/nushell/nu-base:nightly
docker push quay.io/nushell/nu:nightly

View File

@ -1 +0,0 @@
target

View File

@ -1,14 +0,0 @@
root = true
[*]
indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = false
end_of_line = lf
[*.{yml,yaml}]
indent_size = 2
charset = utf-8
insert_final_newline = true

View File

@ -1,47 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1.
2.
3.
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Configuration (please complete the following information):**
Run `version | pivot` and paste the output to show OS, features, etc.
```
> version | pivot
╭───┬────────────────────┬───────────────────────────────────────────────────────────────────────╮
│ # │ Column0 │ Column1 │
├───┼────────────────────┼───────────────────────────────────────────────────────────────────────┤
│ 0 │ version │ 0.24.1 │
│ 1 │ build_os │ macos-x86_64 │
│ 2 │ rust_version │ rustc 1.48.0 │
│ 3 │ cargo_version │ cargo 1.48.0 │
│ 4 │ pkg_version │ 0.24.1 │
│ 5 │ build_time │ 2020-12-18 09:54:09 │
│ 6 │ build_rust_channel │ release │
│ 7 │ features │ ctrlc, default, directories, dirs, git, ichwh, rich-benchmark, │
│ │ │ rustyline, term, uuid, which, zip │
╰───┴────────────────────┴───────────────────────────────────────────────────────────────────────╯
```
**Add any other context about the problem here.**

63
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@ -0,0 +1,63 @@
name: Bug Report
description: Create a report to help us improve
body:
- type: textarea
id: description
attributes:
label: Describe the bug
description: Thank you for your bug report.
validations:
required: true
- type: textarea
id: repro
attributes:
label: How to reproduce
description: Steps to reproduce the behavior
placeholder: |
1.
2.
3.
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected behavior
description: A clear and concise description of what you expected to happen.
placeholder: I expected nu to...
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: Screenshots
description: Please add any relevant screenshots here, if any
validations:
required: false
- type: textarea
id: config
attributes:
label: Configuration
description: "Please run `version | transpose key value | to md --pretty` and paste the output to show OS, features, etc."
placeholder: |
> version | transpose key value | to md --pretty
| key | value |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| version | 0.40.0 |
| build_os | linux-x86_64 |
| rust_version | rustc 1.56.1 |
| cargo_version | cargo 1.56.0 |
| pkg_version | 0.40.0 |
| build_time | 1980-01-01 00:00:00 +00:00 |
| build_rust_channel | release |
| features | clipboard-cli, ctrlc, dataframe, default, rustyline, term, trash, uuid, which, zip |
| installed_plugins | binaryview, chart bar, chart line, fetch, from bson, from sqlite, inc, match, post, ps, query json, s3, selector, start, sys, textview, to bson, to sqlite, tree, xpath |
validations:
required: false
- type: textarea
id: context
attributes:
label: Additional context
description: Add any other context about the problem here.
validations:
required: false

View File

@ -1,20 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@ -0,0 +1,34 @@
name: Feature Request
description: "When you want a new feature for something that doesn't already exist"
body:
- type: textarea
id: problem
attributes:
label: Related problem
description: Thank you for your feature request.
placeholder: |
A clear and concise description of what the problem is.
Example: I am trying to do [...] but [...]
validations:
required: false
- type: textarea
id: desired
attributes:
label: "Describe the solution you'd like"
description: A clear and concise description of what you want to happen.
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: "Describe alternatives you've considered"
description: "A clear and concise description of any alternative solutions or features you've considered."
validations:
required: false
- type: textarea
id: context
attributes:
label: Additional context and details
description: Add any other context or screenshots about the feature request here.
validations:
required: false

11
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,11 @@
# Description
(description of your pull request here)
# Tests
Make sure you've run and fixed any issues with these commands:
- [ ] `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes)
- [ ] `cargo clippy --workspace --features=extra -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style
- [ ] `cargo test --workspace --features=extra` to check that all the tests pass

183
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,183 @@
on:
pull_request:
push: # Run CI on the main branch after every merge. This is important to fill the GitHub Actions cache in a way that pull requests can see it
branches:
- main
name: continuous-integration
jobs:
nu-fmt-clippy:
strategy:
fail-fast: true
matrix:
platform: [windows-latest, macos-latest, ubuntu-latest]
rust:
- stable
runs-on: ${{ matrix.platform }}
env:
NUSHELL_CARGO_TARGET: ci
steps:
- uses: actions/checkout@v2
- name: Setup Rust toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ matrix.rust }}
override: true
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v1
with:
key: "v2" # increment this to bust the cache if needed
- name: Rustfmt
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
- name: Clippy
uses: actions-rs/cargo@v1
with:
command: clippy
args: --features=extra --workspace --exclude nu_plugin_* -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect
nu-tests:
env:
NUSHELL_CARGO_TARGET: ci
strategy:
fail-fast: true
matrix:
platform: [windows-latest, macos-latest, ubuntu-latest]
style: [extra, default]
rust:
- stable
include:
- style: extra
flags: "--features=extra"
- style: default
flags: ""
exclude:
- platform: windows-latest
style: default
- platform: macos-latest
style: default
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v2
- name: Setup Rust toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ matrix.rust }}
override: true
# 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
with:
command: test
args: --workspace --profile ci --exclude nu_plugin_* ${{ matrix.flags }}
python-virtualenv:
env:
NUSHELL_CARGO_TARGET: ci
strategy:
fail-fast: true
matrix:
platform: [ubuntu-latest, macos-latest, windows-latest]
rust:
- stable
py:
- py
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v2
- name: Setup Rust toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ matrix.rust }}
override: true
- uses: Swatinem/rust-cache@v1
with:
key: "2" # increment this to bust the cache if needed
- name: Install Nushell
uses: actions-rs/cargo@v1
with:
command: install
args: --path=. --profile ci --no-default-features
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: "3.10"
- run: python -m pip install tox
- name: Install virtualenv
run: |
git clone https://github.com/kubouch/virtualenv.git && \
cd virtualenv && \
git checkout engine-q-update
shell: bash
- name: Test Nushell in virtualenv
run: cd virtualenv && tox -e ${{ matrix.py }} -- -k nushell
shell: bash
# Build+test plugins on their own, without the rest of Nu. This helps with CI parallelization and
# also helps test that the plugins build without any feature unification shenanigans
plugins:
env:
NUSHELL_CARGO_TARGET: ci
strategy:
fail-fast: true
matrix:
platform: [windows-latest, macos-latest, ubuntu-latest]
rust:
- stable
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v2
- name: Setup Rust toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ matrix.rust }}
override: true
- name: Clippy
uses: actions-rs/cargo@v1
with:
command: clippy
args: --package nu_plugin_* ${{ matrix.flags }} -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect
- name: Tests
uses: actions-rs/cargo@v1
with:
command: test
args: --profile ci --package nu_plugin_*

View File

@ -1,118 +0,0 @@
name: Publish consumable Docker images
on:
push:
tags: ['v?[0-9]+.[0-9]+.[0-9]+*']
jobs:
compile:
runs-on: ubuntu-latest
strategy:
matrix:
arch:
- x86_64-unknown-linux-musl
- x86_64-unknown-linux-gnu
steps:
- uses: actions/checkout@v2
- name: Install rust-embedded/cross
env: { VERSION: v0.1.16 }
run: >-
wget -nv https://github.com/rust-embedded/cross/releases/download/${VERSION}/cross-${VERSION}-x86_64-unknown-linux-gnu.tar.gz
-O- | sudo tar xz -C /usr/local/bin/
- name: compile for specific target
env: { arch: '${{ matrix.arch }}' }
run: |
cross build --target ${{ matrix.arch }} --release
# leave only the executable file
rm -frd target/${{ matrix.arch }}/release/{*/*,*.d,*.rlib,.fingerprint}
find . -empty -delete
- uses: actions/upload-artifact@master
with:
name: ${{ matrix.arch }}
path: target/${{ matrix.arch }}/release
docker:
name: Build and publish docker images
needs: compile
runs-on: ubuntu-latest
env:
DOCKER_REGISTRY: quay.io/nushell
DOCKER_PASSWORD: ${{ secrets.DOCKER_REGISTRY }}
DOCKER_USER: ${{ secrets.DOCKER_USER }}
strategy:
matrix:
tag:
- alpine
- slim
- debian
- glibc-busybox
- musl-busybox
- musl-distroless
- glibc-distroless
- glibc
- musl
include:
- { tag: alpine, base-image: alpine, arch: x86_64-unknown-linux-musl, plugin: true, use-patch: false}
- { tag: slim, base-image: 'debian:stable-slim', arch: x86_64-unknown-linux-gnu, plugin: true, use-patch: false}
- { tag: debian, base-image: debian, arch: x86_64-unknown-linux-gnu, plugin: true, use-patch: false}
- { tag: glibc-busybox, base-image: 'busybox:glibc', arch: x86_64-unknown-linux-gnu, plugin: false, use-patch: true }
- { tag: musl-busybox, base-image: 'busybox:musl', arch: x86_64-unknown-linux-musl, plugin: false, use-patch: false}
- { tag: musl-distroless, base-image: 'gcr.io/distroless/static', arch: x86_64-unknown-linux-musl, plugin: false, use-patch: false}
- { tag: glibc-distroless, base-image: 'gcr.io/distroless/cc', arch: x86_64-unknown-linux-gnu, plugin: false, use-patch: true }
- { tag: glibc, base-image: scratch, arch: x86_64-unknown-linux-gnu, plugin: false, use-patch: false}
- { tag: musl, base-image: scratch, arch: x86_64-unknown-linux-musl, plugin: false, use-patch: false}
steps:
- uses: actions/checkout@v2
- uses: actions/download-artifact@master
with: { name: '${{ matrix.arch }}', path: target/release }
- name: Build and publish exact version
run: |-
export DOCKER_TAG=${GITHUB_REF##*/}-${{ matrix.tag }}
export NU_BINS=target/release/$( [ ${{ matrix.plugin }} = true ] && echo nu* || echo nu )
export PATCH=$([ ${{ matrix.use-patch }} = true ] && echo .${{ matrix.tag }} || echo '')
chmod +x $NU_BINS
echo ${DOCKER_PASSWORD} | docker login ${DOCKER_REGISTRY} -u ${DOCKER_USER} --password-stdin
docker-compose --file docker/docker-compose.package.yml build
docker-compose --file docker/docker-compose.package.yml push # exact version
env:
BASE_IMAGE: ${{ matrix.base-image }}
#region semantics tagging
- name: Retag and push with suffixed version
run: |-
VERSION=${GITHUB_REF##*/}
latest_version=${VERSION%%%.*}-${{ matrix.tag }}
latest_feature=${VERSION%%.*}-${{ matrix.tag }}
latest_patch=${VERSION%.*}-${{ matrix.tag }}
exact_version=${VERSION}-${{ matrix.tag }}
tags=( ${latest_version} ${latest_feature} ${latest_patch} ${exact_version} )
for tag in ${tags[@]}; do
docker tag ${DOCKER_REGISTRY}/nu:${VERSION}-${{ matrix.tag }} ${DOCKER_REGISTRY}/nu:${tag}
docker push ${DOCKER_REGISTRY}/nu:${tag}
done
# latest version
docker tag ${DOCKER_REGISTRY}/nu:${VERSION}-${{ matrix.tag }} ${DOCKER_REGISTRY}/nu:${{ matrix.tag }}
docker push ${DOCKER_REGISTRY}/nu:${{ matrix.tag }}
- name: Retag and push debian as latest
if: matrix.tag == 'debian'
run: |-
VERSION=${GITHUB_REF##*/}
# ${latest features} ${latest patch} ${exact version}
tags=( ${VERSION%%.*} ${VERSION%.*} ${VERSION} )
for tag in ${tags[@]}; do
docker tag ${DOCKER_REGISTRY}/nu:${VERSION}-${{ matrix.tag }} ${DOCKER_REGISTRY}/nu:${tag}
docker push ${DOCKER_REGISTRY}/nu:${tag}
done
# latest version
docker tag ${DOCKER_REGISTRY}/nu:${{ matrix.tag }} ${DOCKER_REGISTRY}/nu:latest
docker push ${DOCKER_REGISTRY}/nu:latest
#endregion semantics tagging

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

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

View File

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

View File

@ -19,11 +19,10 @@ jobs:
operations-per-run: 520
enable-statistics: true
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is being marked stale because it has been open for 30 days without activity. If you feel that this is in error, please comment below and we will keep it marked as active.'
stale-pr-message: 'This PR is being marked stale because it has been open for 45 days without activity. If this PR is still active, please comment below and we will keep it marked as active.'
close-issue-message: 'This issue has been marked stale for more than 10 days without activity. Closing this issue, but if you find that the issue is still valid, please reopen.'
close-pr-message: 'This PR has been marked stale for more than 10 days without activity. Closing this PR, but if you are still working on it, please reopen.'
days-before-issue-stale: 30
close-issue-message: 'This issue has been marked stale for more than 100000 days without activity. Closing this issue, but if you find that the issue is still valid, please reopen.'
close-pr-message: 'This PR has been marked stale for more than 100 days without activity. Closing this PR, but if you are still working on it, please reopen.'
days-before-issue-stale: 90
days-before-pr-stale: 45
days-before-issue-close: 10
days-before-pr-close: 10
days-before-issue-close: 100000
days-before-pr-close: 100
exempt-issue-labels: 'exempt,keep'

19
.github/workflows/winget-submission.yml vendored Normal file
View File

@ -0,0 +1,19 @@
name: Submit Nushell package to Windows Package Manager Community Repository
on:
workflow_dispatch:
release:
types: [published]
jobs:
winget:
name: Publish winget package
runs-on: windows-latest
steps:
- name: Submit package to Windows Package Manager Community Repository
run: |
iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
$github = Get-Content '${{ github.event_path }}' | ConvertFrom-Json
$installerUrl = $github.release.assets | Where-Object -Property name -match 'windows.msi' | Select -ExpandProperty browser_download_url -First 1
.\wingetcreate.exe update Nushell.Nushell -s -v $github.release.tag_name -u $installerUrl -t ${{ secrets.NUSHELL_PAT }}

9
.gitignore vendored
View File

@ -4,6 +4,7 @@
history.txt
tests/fixtures/nuplayground
crates/*/target
.mailmap
# Debian/Ubuntu
debian/.debhelper/
@ -20,3 +21,11 @@ debian/nu/
# VSCode's IDE items
.vscode/*
# Helix configuration folder
.helix/*
.helix
# Coverage tools
lcov.info
tarpaulin-report.html

18
.gitpod.Dockerfile vendored
View File

@ -1,18 +0,0 @@
FROM gitpod/workspace-full
# Gitpod will not rebuild Nushell's dev image unless *some* change is made to this Dockerfile.
# To force a rebuild, simply increase this counter:
ENV TRIGGER_REBUILD 1
USER gitpod
RUN sudo apt-get update && \
sudo apt-get install -y \
libssl-dev \
libxcb-composite0-dev \
pkg-config \
libpython3.6 \
rust-lldb \
&& sudo rm -rf /var/lib/apt/lists/*
ENV RUST_LLDB=/usr/bin/lldb-11

View File

@ -1,25 +0,0 @@
image:
file: .gitpod.Dockerfile
tasks:
- name: Clippy
init: cargo clippy --all --features=stable -- -D clippy::result_unwrap_used -D clippy::option_unwrap_used
- name: Testing
init: cargo test --all --features=stable
- name: Build
init: cargo build --features=stable
- name: Nu
init: cargo install --path . --features=stable
command: nu
github:
prebuilds:
branches: true
pullRequestsFromForks: true
addLabel: prebuilt-in-gitpod
vscode:
extensions:
- hbenl.vscode-test-explorer@2.15.0:koqDUMWDPJzELp/hdS/lWw==
- Swellaby.vscode-rust-test-adapter@0.11.0:Xg+YeZZQiVpVUsIkH+uiiw==
- serayuzgur.crates@0.4.7:HMkoguLcXp9M3ud7ac3eIw==
- belfz.search-crates-io@1.2.1:kSLnyrOhXtYPjQpKnMr4eQ==
- bungcip.better-toml@0.3.2:3QfgGxxYtGHfJKQU7H0nEw==
- webfreak.debug@0.24.0:1zVcRsAhewYEX3/A9xjMNw==

View File

@ -1,14 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "gdb",
"request": "launch",
"name": "Debug Rust Code",
"preLaunchTask": "cargo",
"target": "${workspaceFolder}/target/debug/nu",
"cwd": "${workspaceFolder}",
"valuesFormatting": "parseText"
}
]
}

View File

@ -1,12 +0,0 @@
{
"tasks": [
{
"command": "cargo",
"args": [
"build"
],
"type": "process",
"label": "cargo",
}
],
}

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 -- --loglevel trace
cargo run --release --features=extra -- --log-level trace
```

5636
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
[package]
authors = ["The Nu Project Contributors"]
authors = ["The Nushell Project Developers"]
default-run = "nu"
description = "A new type of shell"
documentation = "https://www.nushell.sh/book/"
@ -10,250 +10,110 @@ license = "MIT"
name = "nu"
readme = "README.md"
repository = "https://github.com/nushell/nushell"
version = "0.34.0"
[workspace]
members = ["crates/*/"]
rust-version = "1.60"
version = "0.64.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[workspace]
members = [
"crates/nu-cli",
"crates/nu-engine",
"crates/nu-parser",
"crates/nu-system",
"crates/nu-command",
"crates/nu-protocol",
"crates/nu-plugin",
"crates/nu_plugin_inc",
"crates/nu_plugin_gstat",
"crates/nu_plugin_example",
"crates/nu_plugin_query",
"crates/nu-utils",
]
[dependencies]
nu-cli = { version = "0.34.0", path="./crates/nu-cli", default-features=false }
nu-command = { version = "0.34.0", path="./crates/nu-command" }
nu-completion = { version = "0.34.0", path="./crates/nu-completion" }
nu-data = { version = "0.34.0", path="./crates/nu-data" }
nu-engine = { version = "0.34.0", path="./crates/nu-engine" }
nu-errors = { version = "0.34.0", path="./crates/nu-errors" }
nu-parser = { version = "0.34.0", path="./crates/nu-parser" }
nu-path = { version = "0.34.0", path="./crates/nu-path" }
nu-plugin = { version = "0.34.0", path="./crates/nu-plugin" }
nu-protocol = { version = "0.34.0", path="./crates/nu-protocol" }
nu-source = { version = "0.34.0", path="./crates/nu-source" }
nu-value-ext = { version = "0.34.0", path="./crates/nu-value-ext" }
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.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"
is_executable = "1.0.1"
nu_plugin_binaryview = { version = "0.34.0", path="./crates/nu_plugin_binaryview", optional=true }
nu_plugin_chart = { version = "0.34.0", path="./crates/nu_plugin_chart", optional=true }
nu_plugin_fetch = { version = "0.34.0", path="./crates/nu_plugin_fetch", optional=true }
nu_plugin_from_bson = { version = "0.34.0", path="./crates/nu_plugin_from_bson", optional=true }
nu_plugin_from_sqlite = { version = "0.34.0", path="./crates/nu_plugin_from_sqlite", optional=true }
nu_plugin_inc = { version = "0.34.0", path="./crates/nu_plugin_inc", optional=true }
nu_plugin_match = { version = "0.34.0", path="./crates/nu_plugin_match", optional=true }
nu_plugin_post = { version = "0.34.0", path="./crates/nu_plugin_post", optional=true }
nu_plugin_ps = { version = "0.34.0", path="./crates/nu_plugin_ps", optional=true }
nu_plugin_query_json = { version = "0.34.0", path="./crates/nu_plugin_query_json", optional=true }
nu_plugin_s3 = { version = "0.34.0", path="./crates/nu_plugin_s3", optional=true }
nu_plugin_selector = { version = "0.34.0", path="./crates/nu_plugin_selector", optional=true }
nu_plugin_start = { version = "0.34.0", path="./crates/nu_plugin_start", optional=true }
nu_plugin_sys = { version = "0.34.0", path="./crates/nu_plugin_sys", optional=true }
nu_plugin_textview = { version = "0.34.0", path="./crates/nu_plugin_textview", optional=true }
nu_plugin_to_bson = { version = "0.34.0", path="./crates/nu_plugin_to_bson", optional=true }
nu_plugin_to_sqlite = { version = "0.34.0", path="./crates/nu_plugin_to_sqlite", optional=true }
nu_plugin_tree = { version = "0.34.0", path="./crates/nu_plugin_tree", optional=true }
nu_plugin_xpath = { version = "0.34.0", path="./crates/nu_plugin_xpath", optional=true }
# Required to bootstrap the main binary
ctrlc = { version="3.1.7", optional=true }
futures = { version="0.3.12", features=["compat", "io-compat"] }
itertools = "0.10.0"
[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 = { version = "0.34.0", path="./crates/nu-test-support" }
dunce = "1.0.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"
serial_test = "0.5.1"
hamcrest2 = "0.3.0"
rstest = "0.10.0"
rstest = "0.12.0"
itertools = "0.10.3"
[build-dependencies]
[target.'cfg(windows)'.build-dependencies]
winres = "0.1"
[features]
ctrlc-support = ["nu-cli/ctrlc", "nu-command/ctrlc"]
rustyline-support = ["nu-cli/rustyline-support", "nu-command/rustyline-support"]
term-support = ["nu-command/term"]
uuid-support = ["nu-command/uuid_crate"]
which-support = ["nu-command/which", "nu-engine/which"]
default = [
"nu-cli/shadow-rs",
"sys",
"ps",
"ctrlc-support",
"which-support",
"term-support",
"rustyline-support",
"match",
"post",
"fetch",
"zip-support",
"dataframe",
]
plugin = ["nu-plugin", "nu-cli/plugin", "nu-parser/plugin", "nu-command/plugin", "nu-protocol/plugin", "nu-engine/plugin"]
default = ["plugin", "which-support", "trash-support"]
stable = ["default"]
extra = [
"default",
"binaryview",
"inc",
"tree",
"textview",
"clipboard-cli",
"trash-support",
"uuid-support",
"start",
"bson",
"sqlite",
"s3",
"chart",
"xpath",
"selector",
"query-json",
]
wasi = ["inc", "match", "match", "tree", "rustyline-support"]
extra = ["default", "dataframe", "database"]
wasi = []
# Enable to statically link OpenSSL; otherwise the system version will be used. Not enabled by default because it takes a while to build
static-link-openssl = ["dep:openssl"]
# Stable (Default)
fetch = ["nu_plugin_fetch"]
inc = ["nu_plugin_inc"]
match = ["nu_plugin_match"]
post = ["nu_plugin_post"]
ps = ["nu_plugin_ps"]
sys = ["nu_plugin_sys"]
textview = ["nu_plugin_textview"]
which-support = ["nu-command/which-support"]
trash-support = ["nu-command/trash-support"]
# Extra
binaryview = ["nu_plugin_binaryview"]
bson = ["nu_plugin_from_bson", "nu_plugin_to_bson"]
chart = ["nu_plugin_chart"]
clipboard-cli = ["nu-command/clipboard-cli"]
query-json = ["nu_plugin_query_json"]
s3 = ["nu_plugin_s3"]
selector = ["nu_plugin_selector"]
sqlite = ["nu_plugin_from_sqlite", "nu_plugin_to_sqlite"]
start = ["nu_plugin_start"]
trash-support = [
"nu-command/trash-support",
"nu-engine/trash-support",
]
tree = ["nu_plugin_tree"]
xpath = ["nu_plugin_xpath"]
zip-support = ["nu-command/zip"]
#This is disabled in extra for now
table-pager = ["nu-command/table-pager"]
# Dataframe feature for nushell
dataframe = ["nu-command/dataframe"]
#dataframe feature for nushell
dataframe = [
"nu-engine/dataframe",
"nu-protocol/dataframe",
"nu-command/dataframe",
"nu-value-ext/dataframe",
"nu-data/dataframe",
"nu_plugin_post/dataframe",
"nu_plugin_to_bson/dataframe",
]
# Database commands for nushell
database = ["nu-command/database"]
# Core plugins that ship with `cargo install nu` by default
# Currently, Cargo limits us to installing only one binary
# unless we use [[bin]], so we use this as a workaround
[[bin]]
name = "nu_plugin_core_textview"
path = "src/plugins/nu_plugin_core_textview.rs"
required-features = ["textview"]
[profile.release]
opt-level = "s" # Optimize for size
strip = "debuginfo"
lto = "thin"
[[bin]]
name = "nu_plugin_core_inc"
path = "src/plugins/nu_plugin_core_inc.rs"
required-features = ["inc"]
# build with `cargo build --profile profiling`
# to analyze performance with tooling like linux perf
[profile.profiling]
inherits = "release"
strip = false
debug = true
[[bin]]
name = "nu_plugin_core_ps"
path = "src/plugins/nu_plugin_core_ps.rs"
required-features = ["ps"]
[[bin]]
name = "nu_plugin_core_sys"
path = "src/plugins/nu_plugin_core_sys.rs"
required-features = ["sys"]
[[bin]]
name = "nu_plugin_core_fetch"
path = "src/plugins/nu_plugin_core_fetch.rs"
required-features = ["fetch"]
[[bin]]
name = "nu_plugin_core_match"
path = "src/plugins/nu_plugin_core_match.rs"
required-features = ["match"]
[[bin]]
name = "nu_plugin_core_post"
path = "src/plugins/nu_plugin_core_post.rs"
required-features = ["post"]
# Extra plugins
[[bin]]
name = "nu_plugin_extra_binaryview"
path = "src/plugins/nu_plugin_extra_binaryview.rs"
required-features = ["binaryview"]
[[bin]]
name = "nu_plugin_extra_tree"
path = "src/plugins/nu_plugin_extra_tree.rs"
required-features = ["tree"]
[[bin]]
name = "nu_plugin_extra_query_json"
path = "src/plugins/nu_plugin_extra_query_json.rs"
required-features = ["query-json"]
[[bin]]
name = "nu_plugin_extra_start"
path = "src/plugins/nu_plugin_extra_start.rs"
required-features = ["start"]
[[bin]]
name = "nu_plugin_extra_s3"
path = "src/plugins/nu_plugin_extra_s3.rs"
required-features = ["s3"]
[[bin]]
name = "nu_plugin_extra_chart_bar"
path = "src/plugins/nu_plugin_extra_chart_bar.rs"
required-features = ["chart"]
[[bin]]
name = "nu_plugin_extra_chart_line"
path = "src/plugins/nu_plugin_extra_chart_line.rs"
required-features = ["chart"]
[[bin]]
name = "nu_plugin_extra_xpath"
path = "src/plugins/nu_plugin_extra_xpath.rs"
required-features = ["xpath"]
[[bin]]
name = "nu_plugin_extra_selector"
path = "src/plugins/nu_plugin_extra_selector.rs"
required-features = ["selector"]
[[bin]]
name = "nu_plugin_extra_from_bson"
path = "src/plugins/nu_plugin_extra_from_bson.rs"
required-features = ["bson"]
[[bin]]
name = "nu_plugin_extra_to_bson"
path = "src/plugins/nu_plugin_extra_to_bson.rs"
required-features = ["bson"]
[[bin]]
name = "nu_plugin_extra_from_sqlite"
path = "src/plugins/nu_plugin_extra_from_sqlite.rs"
required-features = ["sqlite"]
[[bin]]
name = "nu_plugin_extra_to_sqlite"
path = "src/plugins/nu_plugin_extra_to_sqlite.rs"
required-features = ["sqlite"]
# build with `cargo build --profile ci`
# to analyze performance with tooling like linux perf
[profile.ci]
inherits = "dev"
strip = false
debug = false
# Main nu binary
[[bin]]

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2019 - 2021 Yehuda Katz, Jonathan Turner
Copyright (c) 2019 - 2022 The Nushell Project Developers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,24 +0,0 @@
[tasks.lalrpop]
install_crate = { crate_name = "lalrpop", binary = "lalrpop", test_arg = "--help" }
command = "lalrpop"
args = ["src/parser/parser.lalrpop"]
[tasks.baseline]
command = "cargo"
args = ["build", "--bins"]
[tasks.run]
command = "cargo"
args = ["run"]
dependencies = ["baseline"]
[tasks.test]
command = "cargo"
args = ["test"]
dependencies = ["baseline"]
[tasks.check]
command = "cargo"
args = ["check"]
dependencies = ["baseline"]

View File

@ -1 +0,0 @@
Nu will look for the plugins in your PATH on startup. While nu will have some functionality without them, for full functionality you'll need to copy them into your path so they can be loaded.

330
README.md
View File

@ -1,179 +1,106 @@
# README
# Nushell <!-- omit in toc -->
[![Crates.io](https://img.shields.io/crates/v/nu.svg)](https://crates.io/crates/nu)
[![Build Status](https://dev.azure.com/nushell/nushell/_apis/build/status/nushell.nushell?branchName=main)](https://dev.azure.com/nushell/nushell/_build/latest?definitionId=2&branchName=main)
![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)
[![The Changelog #363](https://img.shields.io/badge/The%20Changelog-%23363-61c192.svg)](https://changelog.com/podcast/363)
[![@nu_shell](https://img.shields.io/badge/twitter-@nu_shell-1DA1F3?style=flat-square)](https://twitter.com/nu_shell)
![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-autocomplete5.gif "Example of nushell")
![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/).
Try it in Gitpod.
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/nushell/nushell)
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.51 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`):
```shell
cargo install nu
```bash
# Linux and macOS
brew install nushell
# Windows
winget install nushell
```
To install Nu via the [Windows Package Manager](https://aka.ms/winget-cli):
To use `Nu` in Github Action, check [setup-nu](https://github.com/marketplace/actions/setup-nu) for more detail.
```shell
winget install nu
```
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
```
### Docker
#### Quickstart
Want to try Nu right away? Execute the following to get started.
```shell
docker run -it quay.io/nushell/nu:latest
```
#### Guide
If you want to pull a pre-built container, you can browse tags for the [nushell organization](https://quay.io/organization/nushell)
on Quay.io. Pulling a container would come down to:
```shell
docker pull quay.io/nushell/nu
docker pull quay.io/nushell/nu-base
```
Both "nu-base" and "nu" provide the nu binary, however, nu-base also includes the source code at `/code`
in the container and all dependencies.
Optionally, you can also build the containers locally using the [dockerfiles provided](docker):
To build the base image:
```shell
docker build -f docker/Dockerfile.nu-base -t nushell/nu-base .
```
And then to build the smaller container (using a Multistage build):
```shell
docker build -f docker/Dockerfile -t nushell/nu .
```
Either way, you can run either container as follows:
```shell
docker run -it nushell/nu-base
docker run -it nushell/nu
/> exit
```
The second container is a bit smaller if the size is important to you.
### 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 │ docker │ Dir │ 288 B │ 3 months ago
4 │ docs │ Dir │ 192 B │ 50 mins ago
5 │ images │ Dir │ 160 B │ 5 months ago
6src Dir 128 B │ 1 day ago
7targetDir │ 160 B │ 5 days ago
8testsDir │ 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 │ docker dir │ 0 B │ 2 weeks ago
4 │ docs dir │ 0 B │ 2 weeks ago
5 │ images dir │ 0 B │ 2 weeks ago
6pkg_mgrs │ dir 0 B │ 2 weeks ago │
7samples dir │ 0 B │ 2 weeks ago
8src 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.
@ -181,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
@ -199,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.
@ -275,53 +177,53 @@ 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 |
| ------------- | :---------: | :-------: | :-: | :-----: | :----: | -------------------------------------------------------------------- |
| Aliases | | | X | | | Aliases allow for shortening large commands, while passing flags |
| Aliases | | | | X | | Aliases allow for shortening large commands, while passing flags |
| Notebook | | X | | | | Initial jupyter support, but it loses state and lacks features |
| File ops | | | X | | | cp, mv, rm, mkdir have some support, but lacking others |
| Environment | | | X | | | Temporary environment and scoped environment variables |
| Shells | | X | | | | Basic value and file shells, but no opt-in/opt-out for commands |
| Protocol | | | X | | | Streaming protocol is serviceable |
| Plugins | | X | | | | Plugins work on one row at a time, lack batching and expression eval |
| Errors | | | X | | | Error reporting works, but could use usability polish |
| File ops | | | | X | | cp, mv, rm, mkdir have some support, but lacking others |
| Environment | | | | X | | Temporary environment and scoped environment variables |
| Shells | | | | X | | Basic value and file shells, but no opt-in/opt-out for commands |
| Protocol | | | | X | | Streaming protocol is serviceable |
| Plugins | | | X | | | Plugins work on one row at a time, lack batching and expression eval |
| Errors | | | | X | | Error reporting works, but could use usability polish |
| Documentation | | | X | | | Book updated to latest release, including usage examples |
| Paging | | X | | | | Textview has paging, but we'd like paging for tables |
| Functions | | | X | | | Functions and aliases are supported |
| Variables | | | X | | | Nu supports variables and environment variables |
| Completions | | | X | | | Completions for filepaths |
| Paging | | | | X | | Textview has paging, but we'd like paging for tables |
| Functions | | | | X | | Functions and aliases are supported |
| Variables | | | | X | | Nu supports variables and environment variables |
| Completions | | | | X | | Completions for filepaths |
| Type-checking | | | X | | | Commands check basic types, but input/output isn't checked |
## Current Roadmap
## Officially Supported By
We've added a `Roadmap Board` to help collaboratively capture the direction we're going for the current release and capture some important issues we'd like to see in Nushell. You can find the Roadmap [here](https://github.com/nushell/nushell/projects/2).
Please submit an issue or PR to be added to this list.
- [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)
## 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" />
<img src="https://contributors-img.web.app/image?repo=nushell/nushell&max=500" />
</a>
## License

3
README.release.txt Normal file
View File

@ -0,0 +1,3 @@
To use Nu plugins, use the register command to tell Nu where to find the plugin. For example:
> register -e json ./nu_plugin_query

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
assets/nu_logo.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

23
build-all-maclin.sh Executable file
View File

@ -0,0 +1,23 @@
#!/bin/sh
echo "---------------------------------------------------------------"
echo "Building nushell (nu) with --features=extra and all the plugins"
echo "---------------------------------------------------------------"
echo ""
NU_PLUGINS=(
'nu_plugin_example'
'nu_plugin_gstat'
'nu_plugin_inc'
'nu_plugin_query'
)
echo "Building nushell"
cargo build --features=extra
for plugin in "${NU_PLUGINS[@]}"
do
echo '' && cd crates/$plugin
echo "Building $plugin..."
echo "-----------------------------"
cargo build && cd ../..
done

32
build-all-windows.cmd Normal file
View File

@ -0,0 +1,32 @@
@echo off
@echo -------------------------------------------------------------------
@echo Building nushell (nu.exe) with --features=extra and all the plugins
@echo -------------------------------------------------------------------
@echo.
echo Building nushell.exe
cargo build --features=extra
@echo.
@cd crates\nu_plugin_example
echo Building nu_plugin_example.exe
cargo build
@echo.
@cd ..\..\crates\nu_plugin_gstat
echo Building nu_plugin_gstat.exe
cargo build
@echo.
@cd ..\..\crates\nu_plugin_inc
echo Building nu_plugin_inc.exe
cargo build
@echo.
@cd ..\..\crates\nu_plugin_query
echo Building nu_plugin_query.exe
cargo build
@echo.
@cd ..\..

22
build-all.nu Normal file
View File

@ -0,0 +1,22 @@
echo '-------------------------------------------------------------------'
echo 'Building nushell (nu) with --features=extra and all the plugins'
echo '-------------------------------------------------------------------'
echo $'(char nl)Building nushell'
echo '----------------------------'
cargo build --features=extra
let plugins = [
nu_plugin_inc,
nu_plugin_gstat,
nu_plugin_query,
nu_plugin_example,
]
for plugin in $plugins {
$'(char nl)Building ($plugin)'
'----------------------------'
cd $'crates/($plugin)'
cargo build
ignore
}

13
build.rs Normal file
View File

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

View File

@ -10,4 +10,4 @@ Foundational libraries are split into two kinds of crates:
Plugins are likewise also split into two types:
* Core plugins - plugins that provide part of the default experience of Nu, including access to the system properties, processes, and web-connectivity features.
* Extra plugins - these plugins run a wide range of differnt capabilities like working with different file types, charting, viewing binary data, and more.
* Extra plugins - these plugins run a wide range of different capabilities like working with different file types, charting, viewing binary data, and more.

View File

@ -1,2 +0,0 @@
target
Cargo.lock

View File

@ -1,40 +0,0 @@
[package]
authors = [
"ogham@bsago.me",
"Ryan Scheel (Havvy) <ryan.havvy@gmail.com>",
"Josh Triplett <josh@joshtriplett.org>",
"The Nu Project Contributors",
]
description = "Library for ANSI terminal colors and styles (bold, underline)"
edition = "2018"
license = "MIT"
name = "nu-ansi-term"
version = "0.34.0"
[lib]
doctest = false
# name = "nu-ansi-term"
[features]
derive_serde_style = ["serde"]
[dependencies]
overload = "0.1.1"
serde = { version="1.0.90", features=["derive"], optional=true }
itertools = "0.10.0"
# [dependencies.serde]
# version = "1.0.90"
# features = ["derive"]
# optional = true
[target.'cfg(target_os="windows")'.dependencies.winapi]
version = "0.3.4"
features = ["consoleapi", "errhandlingapi", "fileapi", "handleapi", "processenv"]
[dev-dependencies]
doc-comment = "0.3"
regex = "1.1.9"
[dev-dependencies.serde_json]
version = "1.0.39"

View File

@ -1,182 +0,0 @@
# nu-ansi-term
> This is a copy of rust-ansi-term but with Color change to Color and light foreground colors added (90-97) as well as light background colors added (100-107).
This is a library for controlling colors and formatting, such as red bold text or blue underlined text, on ANSI terminals.
### [View the Rustdoc](https://docs.rs/nu_ansi_term/)
# Installation
This crate works with [Cargo](http://crates.io). Add the following to your `Cargo.toml` dependencies section:
```toml
[dependencies]
nu_ansi_term = "0.13"
```
## Basic usage
There are three main types in this crate that you need to be concerned with: `ANSIString`, `Style`, and `Color`.
A `Style` holds stylistic information: foreground and background colors, whether the text should be bold, or blinking, or other properties.
The `Color` enum represents the available colors.
And an `ANSIString` is a string paired with a `Style`.
`Color` is also available as an alias to `Color`.
To format a string, call the `paint` method on a `Style` or a `Color`, passing in the string you want to format as the argument.
For example, heres how to get some red text:
```rust
use nu_ansi_term::Color::Red;
println!("This is in red: {}", Red.paint("a red string"));
```
Its important to note that the `paint` method does _not_ actually return a string with the ANSI control characters surrounding it.
Instead, it returns an `ANSIString` value that has a `Display` implementation that, when formatted, returns the characters.
This allows strings to be printed with a minimum of `String` allocations being performed behind the scenes.
If you _do_ want to get at the escape codes, then you can convert the `ANSIString` to a string as you would any other `Display` value:
```rust
use nu_ansi_term::Color::Red;
let red_string = Red.paint("a red string").to_string();
```
**Note for Windows 10 users:** On Windows 10, the application must enable ANSI support first:
```rust,ignore
let enabled = nu_ansi_term::enable_ansi_support();
```
## Bold, underline, background, and other styles
For anything more complex than plain foreground color changes, you need to construct `Style` values themselves, rather than beginning with a `Color`.
You can do this by chaining methods based on a new `Style`, created with `Style::new()`.
Each method creates a new style that has that specific property set.
For example:
```rust
use nu_ansi_term::Style;
println!("How about some {} and {}?",
Style::new().bold().paint("bold"),
Style::new().underline().paint("underline"));
```
For brevity, these methods have also been implemented for `Color` values, so you can give your styles a foreground color without having to begin with an empty `Style` value:
```rust
use nu_ansi_term::Color::{Blue, Yellow};
println!("Demonstrating {} and {}!",
Blue.bold().paint("blue bold"),
Yellow.underline().paint("yellow underline"));
println!("Yellow on blue: {}", Yellow.on(Blue).paint("wow!"));
```
The complete list of styles you can use are:
`bold`, `dimmed`, `italic`, `underline`, `blink`, `reverse`, `hidden`, and `on` for background colors.
In some cases, you may find it easier to change the foreground on an existing `Style` rather than starting from the appropriate `Color`.
You can do this using the `fg` method:
```rust
use nu_ansi_term::Style;
use nu_ansi_term::Color::{Blue, Cyan, Yellow};
println!("Yellow on blue: {}", Style::new().on(Blue).fg(Yellow).paint("yow!"));
println!("Also yellow on blue: {}", Cyan.on(Blue).fg(Yellow).paint("zow!"));
```
You can turn a `Color` into a `Style` with the `normal` method.
This will produce the exact same `ANSIString` as if you just used the `paint` method on the `Color` directly, but its useful in certain cases: for example, you may have a method that returns `Styles`, and need to represent both the “red bold” and “red, but not bold” styles with values of the same type. The `Style` struct also has a `Default` implementation if you want to have a style with _nothing_ set.
```rust
use nu_ansi_term::Style;
use nu_ansi_term::Color::Red;
Red.normal().paint("yet another red string");
Style::default().paint("a completely regular string");
```
## Extended colors
You can access the extended range of 256 colors by using the `Color::Fixed` variant, which takes an argument of the color number to use.
This can be included wherever you would use a `Color`:
```rust
use nu_ansi_term::Color::Fixed;
Fixed(134).paint("A sort of light purple");
Fixed(221).on(Fixed(124)).paint("Mustard in the ketchup");
```
The first sixteen of these values are the same as the normal and bold standard color variants.
Theres nothing stopping you from using these as `Fixed` colors instead, but theres nothing to be gained by doing so either.
You can also access full 24-bit color by using the `Color::RGB` variant, which takes separate `u8` arguments for red, green, and blue:
```rust
use nu_ansi_term::Color::RGB;
RGB(70, 130, 180).paint("Steel blue");
```
## Combining successive coloured strings
The benefit of writing ANSI escape codes to the terminal is that they _stack_: you do not need to end every coloured string with a reset code if the text that follows it is of a similar style.
For example, if you want to have some blue text followed by some blue bold text, its possible to send the ANSI code for blue, followed by the ANSI code for bold, and finishing with a reset code without having to have an extra one between the two strings.
This crate can optimise the ANSI codes that get printed in situations like this, making life easier for your terminal renderer.
The `ANSIStrings` struct takes a slice of several `ANSIString` values, and will iterate over each of them, printing only the codes for the styles that need to be updated as part of its formatting routine.
The following code snippet uses this to enclose a binary number displayed in red bold text inside some red, but not bold, brackets:
```rust
use nu_ansi_term::Color::Red;
use nu_ansi_term::{ANSIString, ANSIStrings};
let some_value = format!("{:b}", 42);
let strings: &[ANSIString<'static>] = &[
Red.paint("["),
Red.bold().paint(some_value),
Red.paint("]"),
];
println!("Value: {}", ANSIStrings(strings));
```
There are several things to note here.
Firstly, the `paint` method can take _either_ an owned `String` or a borrowed `&str`.
Internally, an `ANSIString` holds a copy-on-write (`Cow`) string value to deal with both owned and borrowed strings at the same time.
This is used here to display a `String`, the result of the `format!` call, using the same mechanism as some statically-available `&str` slices.
Secondly, that the `ANSIStrings` value works in the same way as its singular counterpart, with a `Display` implementation that only performs the formatting when required.
## Byte strings
This library also supports formatting `[u8]` byte strings; this supports applications working with text in an unknown encoding.
`Style` and `Color` support painting `[u8]` values, resulting in an `ANSIByteString`.
This type does not implement `Display`, as it may not contain UTF-8, but it does provide a method `write_to` to write the result to any value that implements `Write`:
```rust
use nu_ansi_term::Color::Green;
Green.paint("user data".as_bytes()).write_to(&mut std::io::stdout()).unwrap();
```
Similarly, the type `ANSIByteStrings` supports writing a list of `ANSIByteString` values with minimal escape sequences:
```rust
use nu_ansi_term::Color::Green;
use nu_ansi_term::ANSIByteStrings;
ANSIByteStrings(&[
Green.paint("user data 1\n".as_bytes()),
Green.bold().paint("user data 2\n".as_bytes()),
]).write_to(&mut std::io::stdout()).unwrap();
```

View File

@ -1,72 +0,0 @@
extern crate nu_ansi_term;
use nu_ansi_term::Color;
// This example prints out the 256 colors.
// They're arranged like this:
//
// - 0 to 8 are the eight standard colors.
// - 9 to 15 are the eight bold colors.
// - 16 to 231 are six blocks of six-by-six color squares.
// - 232 to 255 are shades of grey.
fn main() {
// First two lines
for c in 0..8 {
glow(c, c != 0);
print!(" ");
}
println!();
for c in 8..16 {
glow(c, c != 8);
print!(" ");
}
println!("\n");
// Six lines of the first three squares
for row in 0..6 {
for square in 0..3 {
for column in 0..6 {
glow(16 + square * 36 + row * 6 + column, row >= 3);
print!(" ");
}
print!(" ");
}
println!();
}
println!();
// Six more lines of the other three squares
for row in 0..6 {
for square in 0..3 {
for column in 0..6 {
glow(124 + square * 36 + row * 6 + column, row >= 3);
print!(" ");
}
print!(" ");
}
println!();
}
println!();
// The last greyscale lines
for c in 232..=243 {
glow(c, false);
print!(" ");
}
println!();
for c in 244..=255 {
glow(c, true);
print!(" ");
}
println!();
}
fn glow(c: u8, light_bg: bool) {
let base = if light_bg { Color::Black } else { Color::White };
let style = base.on(Color::Fixed(c));
print!("{}", style.paint(&format!(" {:3} ", c)));
}

View File

@ -1,18 +0,0 @@
extern crate nu_ansi_term;
use nu_ansi_term::{Color::*, Style};
// This example prints out the 16 basic colors.
fn main() {
let normal = Style::default();
println!("{} {}", normal.paint("Normal"), normal.bold().paint("bold"));
println!("{} {}", Black.paint("Black"), Black.bold().paint("bold"));
println!("{} {}", Red.paint("Red"), Red.bold().paint("bold"));
println!("{} {}", Green.paint("Green"), Green.bold().paint("bold"));
println!("{} {}", Yellow.paint("Yellow"), Yellow.bold().paint("bold"));
println!("{} {}", Blue.paint("Blue"), Blue.bold().paint("bold"));
println!("{} {}", Purple.paint("Purple"), Purple.bold().paint("bold"));
println!("{} {}", Cyan.paint("Cyan"), Cyan.bold().paint("bold"));
println!("{} {}", White.paint("White"), White.bold().paint("bold"));
}

View File

@ -1,37 +0,0 @@
use nu_ansi_term::{build_all_gradient_text, Color, Gradient, Rgb, TargetGround};
fn main() {
let text = "lorem ipsum quia dolor sit amet, consectetur, adipisci velit";
// a gradient from hex colors
let start = Rgb::from_hex(0x40c9ff);
let end = Rgb::from_hex(0xe81cff);
let grad0 = Gradient::new(start, end);
// a gradient from color::rgb()
let start = Color::Rgb(64, 201, 255);
let end = Color::Rgb(232, 28, 255);
let gradient = Gradient::from_color_rgb(start, end);
// a slightly different gradient
let start2 = Color::Rgb(128, 64, 255);
let end2 = Color::Rgb(0, 28, 255);
let gradient2 = Gradient::from_color_rgb(start2, end2);
// reverse the gradient
let gradient3 = gradient.reverse();
let build_fg = gradient.build(text, TargetGround::Foreground);
println!("{}", build_fg);
let build_bg = gradient.build(text, TargetGround::Background);
println!("{}", build_bg);
let bgt = build_all_gradient_text(text, gradient, gradient2);
println!("{}", bgt);
let bgt2 = build_all_gradient_text(text, gradient, gradient3);
println!("{}", bgt2);
println!(
"{}",
grad0.build("nushell is awesome", TargetGround::Foreground)
);
}

View File

@ -1,23 +0,0 @@
extern crate nu_ansi_term;
use nu_ansi_term::{Color, Style};
// This example prints out a color gradient in a grid by calculating each
// characters red, green, and blue components, and using 24-bit color codes
// to display them.
const WIDTH: i32 = 80;
const HEIGHT: i32 = 24;
fn main() {
for row in 0..HEIGHT {
for col in 0..WIDTH {
let r = (row * 255 / HEIGHT) as u8;
let g = (col * 255 / WIDTH) as u8;
let b = 128;
print!("{}", Style::default().on(Color::Rgb(r, g, b)).paint(" "));
}
println!();
}
}

View File

@ -1,405 +0,0 @@
#![allow(missing_docs)]
use crate::style::{Color, Style};
use crate::write::AnyWrite;
use std::fmt;
impl Style {
/// Write any bytes that go *before* a piece of text to the given writer.
fn write_prefix<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
// If there are actually no styles here, then dont write *any* codes
// as the prefix. An empty ANSI code may not affect the terminal
// output at all, but a user may just want a code-free string.
if self.is_plain() {
return Ok(());
}
// Write the codes prefix, then write numbers, separated by
// semicolons, for each text style we want to apply.
write!(f, "\x1B[")?;
let mut written_anything = false;
{
let mut write_char = |c| {
if written_anything {
write!(f, ";")?;
}
written_anything = true;
write!(f, "{}", c)?;
Ok(())
};
if self.is_bold {
write_char('1')?
}
if self.is_dimmed {
write_char('2')?
}
if self.is_italic {
write_char('3')?
}
if self.is_underline {
write_char('4')?
}
if self.is_blink {
write_char('5')?
}
if self.is_reverse {
write_char('7')?
}
if self.is_hidden {
write_char('8')?
}
if self.is_strikethrough {
write_char('9')?
}
}
// The foreground and background colors, if specified, need to be
// handled specially because the number codes are more complicated.
// (see `write_background_code` and `write_foreground_code`)
if let Some(bg) = self.background {
if written_anything {
write!(f, ";")?;
}
written_anything = true;
bg.write_background_code(f)?;
}
if let Some(fg) = self.foreground {
if written_anything {
write!(f, ";")?;
}
fg.write_foreground_code(f)?;
}
// All the codes end with an `m`, because reasons.
write!(f, "m")?;
Ok(())
}
/// Write any bytes that go *after* a piece of text to the given writer.
fn write_suffix<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
if self.is_plain() {
Ok(())
} else {
write!(f, "{}", RESET)
}
}
}
/// The code to send to reset all styles and return to `Style::default()`.
pub static RESET: &str = "\x1B[0m";
impl Color {
fn write_foreground_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
match *self {
Color::Black => write!(f, "30"),
Color::Red => write!(f, "31"),
Color::Green => write!(f, "32"),
Color::Yellow => write!(f, "33"),
Color::Blue => write!(f, "34"),
Color::Purple => write!(f, "35"),
Color::Magenta => write!(f, "35"),
Color::Cyan => write!(f, "36"),
Color::White => write!(f, "37"),
Color::Fixed(num) => write!(f, "38;5;{}", &num),
Color::Rgb(r, g, b) => write!(f, "38;2;{};{};{}", &r, &g, &b),
Color::DarkGray => write!(f, "90"),
Color::LightRed => write!(f, "91"),
Color::LightGreen => write!(f, "92"),
Color::LightYellow => write!(f, "93"),
Color::LightBlue => write!(f, "94"),
Color::LightPurple => write!(f, "95"),
Color::LightMagenta => write!(f, "95"),
Color::LightCyan => write!(f, "96"),
Color::LightGray => write!(f, "97"),
}
}
fn write_background_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
match *self {
Color::Black => write!(f, "40"),
Color::Red => write!(f, "41"),
Color::Green => write!(f, "42"),
Color::Yellow => write!(f, "43"),
Color::Blue => write!(f, "44"),
Color::Purple => write!(f, "45"),
Color::Magenta => write!(f, "45"),
Color::Cyan => write!(f, "46"),
Color::White => write!(f, "47"),
Color::Fixed(num) => write!(f, "48;5;{}", &num),
Color::Rgb(r, g, b) => write!(f, "48;2;{};{};{}", &r, &g, &b),
Color::DarkGray => write!(f, "100"),
Color::LightRed => write!(f, "101"),
Color::LightGreen => write!(f, "102"),
Color::LightYellow => write!(f, "103"),
Color::LightBlue => write!(f, "104"),
Color::LightPurple => write!(f, "105"),
Color::LightMagenta => write!(f, "105"),
Color::LightCyan => write!(f, "106"),
Color::LightGray => write!(f, "107"),
}
}
}
/// Like `ANSIString`, but only displays the style prefix.
///
/// This type implements the `Display` trait, meaning it can be written to a
/// `std::fmt` formatting without doing any extra allocation, and written to a
/// string with the `.to_string()` method. For examples, see
/// [`Style::prefix`](struct.Style.html#method.prefix).
#[derive(Clone, Copy, Debug)]
pub struct Prefix(Style);
/// Like `ANSIString`, but only displays the difference between two
/// styles.
///
/// This type implements the `Display` trait, meaning it can be written to a
/// `std::fmt` formatting without doing any extra allocation, and written to a
/// string with the `.to_string()` method. For examples, see
/// [`Style::infix`](struct.Style.html#method.infix).
#[derive(Clone, Copy, Debug)]
pub struct Infix(Style, Style);
/// Like `ANSIString`, but only displays the style suffix.
///
/// This type implements the `Display` trait, meaning it can be written to a
/// `std::fmt` formatting without doing any extra allocation, and written to a
/// string with the `.to_string()` method. For examples, see
/// [`Style::suffix`](struct.Style.html#method.suffix).
#[derive(Clone, Copy, Debug)]
pub struct Suffix(Style);
impl Style {
/// The prefix bytes for this style. These are the bytes that tell the
/// terminal to use a different color or font style.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::{Style, Color::Blue};
///
/// let style = Style::default().bold();
/// assert_eq!("\x1b[1m",
/// style.prefix().to_string());
///
/// let style = Blue.bold();
/// assert_eq!("\x1b[1;34m",
/// style.prefix().to_string());
///
/// let style = Style::default();
/// assert_eq!("",
/// style.prefix().to_string());
/// ```
pub fn prefix(self) -> Prefix {
Prefix(self)
}
/// The infix bytes between this style and `next` style. These are the bytes
/// that tell the terminal to change the style to `next`. These may include
/// a reset followed by the next color and style, depending on the two styles.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::{Style, Color::Green};
///
/// let style = Style::default().bold();
/// assert_eq!("\x1b[32m",
/// style.infix(Green.bold()).to_string());
///
/// let style = Green.normal();
/// assert_eq!("\x1b[1m",
/// style.infix(Green.bold()).to_string());
///
/// let style = Style::default();
/// assert_eq!("",
/// style.infix(style).to_string());
/// ```
pub fn infix(self, next: Style) -> Infix {
Infix(self, next)
}
/// The suffix for this style. These are the bytes that tell the terminal
/// to reset back to its normal color and font style.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::{Style, Color::Green};
///
/// let style = Style::default().bold();
/// assert_eq!("\x1b[0m",
/// style.suffix().to_string());
///
/// let style = Green.normal().bold();
/// assert_eq!("\x1b[0m",
/// style.suffix().to_string());
///
/// let style = Style::default();
/// assert_eq!("",
/// style.suffix().to_string());
/// ```
pub fn suffix(self) -> Suffix {
Suffix(self)
}
}
impl Color {
/// The prefix bytes for this color as a `Style`. These are the bytes
/// that tell the terminal to use a different color or font style.
///
/// See also [`Style::prefix`](struct.Style.html#method.prefix).
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color::Green;
///
/// assert_eq!("\x1b[0m",
/// Green.suffix().to_string());
/// ```
pub fn prefix(self) -> Prefix {
Prefix(self.normal())
}
/// The infix bytes between this color and `next` color. These are the bytes
/// that tell the terminal to use the `next` color, or to do nothing if
/// the two colors are equal.
///
/// See also [`Style::infix`](struct.Style.html#method.infix).
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color::{Red, Yellow};
///
/// assert_eq!("\x1b[33m",
/// Red.infix(Yellow).to_string());
/// ```
pub fn infix(self, next: Color) -> Infix {
Infix(self.normal(), next.normal())
}
/// The suffix for this color as a `Style`. These are the bytes that
/// tell the terminal to reset back to its normal color and font style.
///
/// See also [`Style::suffix`](struct.Style.html#method.suffix).
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color::Purple;
///
/// assert_eq!("\x1b[0m",
/// Purple.suffix().to_string());
/// ```
pub fn suffix(self) -> Suffix {
Suffix(self.normal())
}
}
impl fmt::Display for Prefix {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let f: &mut dyn fmt::Write = f;
self.0.write_prefix(f)
}
}
impl fmt::Display for Infix {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use crate::difference::Difference;
match Difference::between(&self.0, &self.1) {
Difference::ExtraStyles(style) => {
let f: &mut dyn fmt::Write = f;
style.write_prefix(f)
}
Difference::Reset => {
let f: &mut dyn fmt::Write = f;
write!(f, "{}{}", RESET, self.1.prefix())
}
Difference::Empty => {
Ok(()) // nothing to write
}
}
}
}
impl fmt::Display for Suffix {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let f: &mut dyn fmt::Write = f;
self.0.write_suffix(f)
}
}
#[cfg(test)]
mod test {
use crate::style::Color::*;
use crate::style::Style;
macro_rules! test {
($name: ident: $style: expr; $input: expr => $result: expr) => {
#[test]
fn $name() {
assert_eq!($style.paint($input).to_string(), $result.to_string());
let mut v = Vec::new();
$style.paint($input.as_bytes()).write_to(&mut v).unwrap();
assert_eq!(v.as_slice(), $result.as_bytes());
}
};
}
test!(plain: Style::default(); "text/plain" => "text/plain");
test!(red: Red; "hi" => "\x1B[31mhi\x1B[0m");
test!(black: Black.normal(); "hi" => "\x1B[30mhi\x1B[0m");
test!(yellow_bold: Yellow.bold(); "hi" => "\x1B[1;33mhi\x1B[0m");
test!(yellow_bold_2: Yellow.normal().bold(); "hi" => "\x1B[1;33mhi\x1B[0m");
test!(blue_underline: Blue.underline(); "hi" => "\x1B[4;34mhi\x1B[0m");
test!(green_bold_ul: Green.bold().underline(); "hi" => "\x1B[1;4;32mhi\x1B[0m");
test!(green_bold_ul_2: Green.underline().bold(); "hi" => "\x1B[1;4;32mhi\x1B[0m");
test!(purple_on_white: Purple.on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
test!(purple_on_white_2: Purple.normal().on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
test!(yellow_on_blue: Style::new().on(Blue).fg(Yellow); "hi" => "\x1B[44;33mhi\x1B[0m");
test!(magenta_on_white: Magenta.on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
test!(magenta_on_white_2: Magenta.normal().on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
test!(yellow_on_blue_2: Cyan.on(Blue).fg(Yellow); "hi" => "\x1B[44;33mhi\x1B[0m");
test!(cyan_bold_on_white: Cyan.bold().on(White); "hi" => "\x1B[1;47;36mhi\x1B[0m");
test!(cyan_ul_on_white: Cyan.underline().on(White); "hi" => "\x1B[4;47;36mhi\x1B[0m");
test!(cyan_bold_ul_on_white: Cyan.bold().underline().on(White); "hi" => "\x1B[1;4;47;36mhi\x1B[0m");
test!(cyan_ul_bold_on_white: Cyan.underline().bold().on(White); "hi" => "\x1B[1;4;47;36mhi\x1B[0m");
test!(fixed: Fixed(100); "hi" => "\x1B[38;5;100mhi\x1B[0m");
test!(fixed_on_purple: Fixed(100).on(Purple); "hi" => "\x1B[45;38;5;100mhi\x1B[0m");
test!(fixed_on_fixed: Fixed(100).on(Fixed(200)); "hi" => "\x1B[48;5;200;38;5;100mhi\x1B[0m");
test!(rgb: Rgb(70,130,180); "hi" => "\x1B[38;2;70;130;180mhi\x1B[0m");
test!(rgb_on_blue: Rgb(70,130,180).on(Blue); "hi" => "\x1B[44;38;2;70;130;180mhi\x1B[0m");
test!(blue_on_rgb: Blue.on(Rgb(70,130,180)); "hi" => "\x1B[48;2;70;130;180;34mhi\x1B[0m");
test!(rgb_on_rgb: Rgb(70,130,180).on(Rgb(5,10,15)); "hi" => "\x1B[48;2;5;10;15;38;2;70;130;180mhi\x1B[0m");
test!(bold: Style::new().bold(); "hi" => "\x1B[1mhi\x1B[0m");
test!(underline: Style::new().underline(); "hi" => "\x1B[4mhi\x1B[0m");
test!(bunderline: Style::new().bold().underline(); "hi" => "\x1B[1;4mhi\x1B[0m");
test!(dimmed: Style::new().dimmed(); "hi" => "\x1B[2mhi\x1B[0m");
test!(italic: Style::new().italic(); "hi" => "\x1B[3mhi\x1B[0m");
test!(blink: Style::new().blink(); "hi" => "\x1B[5mhi\x1B[0m");
test!(reverse: Style::new().reverse(); "hi" => "\x1B[7mhi\x1B[0m");
test!(hidden: Style::new().hidden(); "hi" => "\x1B[8mhi\x1B[0m");
test!(stricken: Style::new().strikethrough(); "hi" => "\x1B[9mhi\x1B[0m");
test!(lr_on_lr: LightRed.on(LightRed); "hi" => "\x1B[101;91mhi\x1B[0m");
#[test]
fn test_infix() {
assert_eq!(
Style::new().dimmed().infix(Style::new()).to_string(),
"\x1B[0m"
);
assert_eq!(
White.dimmed().infix(White.normal()).to_string(),
"\x1B[0m\x1B[37m"
);
assert_eq!(White.normal().infix(White.bold()).to_string(), "\x1B[1m");
assert_eq!(White.normal().infix(Blue.normal()).to_string(), "\x1B[34m");
assert_eq!(Blue.bold().infix(Blue.bold()).to_string(), "");
}
}

View File

@ -1,152 +0,0 @@
use crate::style::Style;
use std::fmt;
/// Styles have a special `Debug` implementation that only shows the fields that
/// are set. Fields that havent been touched arent included in the output.
///
/// This behaviour gets bypassed when using the alternate formatting mode
/// `format!("{:#?}")`.
///
/// use nu_ansi_term::Color::{Red, Blue};
/// assert_eq!("Style { fg(Red), on(Blue), bold, italic }",
/// format!("{:?}", Red.on(Blue).bold().italic()));
impl fmt::Debug for Style {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
if fmt.alternate() {
fmt.debug_struct("Style")
.field("foreground", &self.foreground)
.field("background", &self.background)
.field("blink", &self.is_blink)
.field("bold", &self.is_bold)
.field("dimmed", &self.is_dimmed)
.field("hidden", &self.is_hidden)
.field("italic", &self.is_italic)
.field("reverse", &self.is_reverse)
.field("strikethrough", &self.is_strikethrough)
.field("underline", &self.is_underline)
.finish()
} else if self.is_plain() {
fmt.write_str("Style {}")
} else {
fmt.write_str("Style { ")?;
let mut written_anything = false;
if let Some(fg) = self.foreground {
if written_anything {
fmt.write_str(", ")?
}
written_anything = true;
write!(fmt, "fg({:?})", fg)?
}
if let Some(bg) = self.background {
if written_anything {
fmt.write_str(", ")?
}
written_anything = true;
write!(fmt, "on({:?})", bg)?
}
{
let mut write_flag = |name| {
if written_anything {
fmt.write_str(", ")?
}
written_anything = true;
fmt.write_str(name)
};
if self.is_blink {
write_flag("blink")?
}
if self.is_bold {
write_flag("bold")?
}
if self.is_dimmed {
write_flag("dimmed")?
}
if self.is_hidden {
write_flag("hidden")?
}
if self.is_italic {
write_flag("italic")?
}
if self.is_reverse {
write_flag("reverse")?
}
if self.is_strikethrough {
write_flag("strikethrough")?
}
if self.is_underline {
write_flag("underline")?
}
}
write!(fmt, " }}")
}
}
}
#[cfg(test)]
mod test {
use crate::style::Color::*;
use crate::style::Style;
fn style() -> Style {
Style::new()
}
macro_rules! test {
($name: ident: $obj: expr => $result: expr) => {
#[test]
fn $name() {
assert_eq!($result, format!("{:?}", $obj));
}
};
}
test!(empty: style() => "Style {}");
test!(bold: style().bold() => "Style { bold }");
test!(italic: style().italic() => "Style { italic }");
test!(both: style().bold().italic() => "Style { bold, italic }");
test!(red: Red.normal() => "Style { fg(Red) }");
test!(redblue: Red.normal().on(Rgb(3, 2, 4)) => "Style { fg(Red), on(Rgb(3, 2, 4)) }");
test!(everything:
Red.on(Blue).blink().bold().dimmed().hidden().italic().reverse().strikethrough().underline() =>
"Style { fg(Red), on(Blue), blink, bold, dimmed, hidden, italic, reverse, strikethrough, underline }");
#[test]
fn long_and_detailed() {
extern crate regex;
let expected_debug = "Style { fg(Blue), bold }";
let expected_pretty_repat = r##"(?x)
Style\s+\{\s+
foreground:\s+Some\(\s+
Blue,?\s+
\),\s+
background:\s+None,\s+
blink:\s+false,\s+
bold:\s+true,\s+
dimmed:\s+false,\s+
hidden:\s+false,\s+
italic:\s+false,\s+
reverse:\s+false,\s+
strikethrough:\s+
false,\s+
underline:\s+false,?\s+
\}"##;
let re = regex::Regex::new(expected_pretty_repat).unwrap();
let style = Blue.bold();
let style_fmt_debug = format!("{:?}", style);
let style_fmt_pretty = format!("{:#?}", style);
println!("style_fmt_debug:\n{}", style_fmt_debug);
println!("style_fmt_pretty:\n{}", style_fmt_pretty);
assert_eq!(expected_debug, style_fmt_debug);
assert!(re.is_match(&style_fmt_pretty));
}
}

View File

@ -1,174 +0,0 @@
use super::Style;
/// When printing out one colored string followed by another, use one of
/// these rules to figure out which *extra* control codes need to be sent.
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum Difference {
/// Print out the control codes specified by this style to end up looking
/// like the second string's styles.
ExtraStyles(Style),
/// Converting between these two is impossible, so just send a reset
/// command and then the second string's styles.
Reset,
/// The before style is exactly the same as the after style, so no further
/// control codes need to be printed.
Empty,
}
impl Difference {
/// Compute the 'style difference' required to turn an existing style into
/// the given, second style.
///
/// For example, to turn green text into green bold text, it's redundant
/// to write a reset command then a second green+bold command, instead of
/// just writing one bold command. This method should see that both styles
/// use the foreground color green, and reduce it to a single command.
///
/// This method returns an enum value because it's not actually always
/// possible to turn one style into another: for example, text could be
/// made bold and underlined, but you can't remove the bold property
/// without also removing the underline property. So when this has to
/// happen, this function returns None, meaning that the entire set of
/// styles should be reset and begun again.
pub fn between(first: &Style, next: &Style) -> Difference {
use self::Difference::*;
// XXX(Havvy): This algorithm is kind of hard to replicate without
// having the Plain/Foreground enum variants, so I'm just leaving
// it commented out for now, and defaulting to Reset.
if first == next {
return Empty;
}
// Cannot un-bold, so must Reset.
if first.is_bold && !next.is_bold {
return Reset;
}
if first.is_dimmed && !next.is_dimmed {
return Reset;
}
if first.is_italic && !next.is_italic {
return Reset;
}
// Cannot un-underline, so must Reset.
if first.is_underline && !next.is_underline {
return Reset;
}
if first.is_blink && !next.is_blink {
return Reset;
}
if first.is_reverse && !next.is_reverse {
return Reset;
}
if first.is_hidden && !next.is_hidden {
return Reset;
}
if first.is_strikethrough && !next.is_strikethrough {
return Reset;
}
// Cannot go from foreground to no foreground, so must Reset.
if first.foreground.is_some() && next.foreground.is_none() {
return Reset;
}
// Cannot go from background to no background, so must Reset.
if first.background.is_some() && next.background.is_none() {
return Reset;
}
let mut extra_styles = Style::default();
if first.is_bold != next.is_bold {
extra_styles.is_bold = true;
}
if first.is_dimmed != next.is_dimmed {
extra_styles.is_dimmed = true;
}
if first.is_italic != next.is_italic {
extra_styles.is_italic = true;
}
if first.is_underline != next.is_underline {
extra_styles.is_underline = true;
}
if first.is_blink != next.is_blink {
extra_styles.is_blink = true;
}
if first.is_reverse != next.is_reverse {
extra_styles.is_reverse = true;
}
if first.is_hidden != next.is_hidden {
extra_styles.is_hidden = true;
}
if first.is_strikethrough != next.is_strikethrough {
extra_styles.is_strikethrough = true;
}
if first.foreground != next.foreground {
extra_styles.foreground = next.foreground;
}
if first.background != next.background {
extra_styles.background = next.background;
}
ExtraStyles(extra_styles)
}
}
#[cfg(test)]
mod test {
use super::Difference::*;
use super::*;
use crate::style::Color::*;
use crate::style::Style;
fn style() -> Style {
Style::new()
}
macro_rules! test {
($name: ident: $first: expr; $next: expr => $result: expr) => {
#[test]
fn $name() {
assert_eq!($result, Difference::between(&$first, &$next));
}
};
}
test!(nothing: Green.normal(); Green.normal() => Empty);
test!(uppercase: Green.normal(); Green.bold() => ExtraStyles(style().bold()));
test!(lowercase: Green.bold(); Green.normal() => Reset);
test!(nothing2: Green.bold(); Green.bold() => Empty);
test!(color_change: Red.normal(); Blue.normal() => ExtraStyles(Blue.normal()));
test!(addition_of_blink: style(); style().blink() => ExtraStyles(style().blink()));
test!(addition_of_dimmed: style(); style().dimmed() => ExtraStyles(style().dimmed()));
test!(addition_of_hidden: style(); style().hidden() => ExtraStyles(style().hidden()));
test!(addition_of_reverse: style(); style().reverse() => ExtraStyles(style().reverse()));
test!(addition_of_strikethrough: style(); style().strikethrough() => ExtraStyles(style().strikethrough()));
test!(removal_of_strikethrough: style().strikethrough(); style() => Reset);
test!(removal_of_reverse: style().reverse(); style() => Reset);
test!(removal_of_hidden: style().hidden(); style() => Reset);
test!(removal_of_dimmed: style().dimmed(); style() => Reset);
test!(removal_of_blink: style().blink(); style() => Reset);
}

View File

@ -1,303 +0,0 @@
use crate::ansi::RESET;
use crate::difference::Difference;
use crate::style::{Color, Style};
use crate::write::AnyWrite;
use std::borrow::Cow;
use std::fmt;
use std::io;
use std::ops::Deref;
/// An `ANSIGenericString` includes a generic string type and a `Style` to
/// display that string. `ANSIString` and `ANSIByteString` are aliases for
/// this type on `str` and `\[u8]`, respectively.
#[derive(PartialEq, Debug)]
pub struct AnsiGenericString<'a, S: 'a + ToOwned + ?Sized>
where
<S as ToOwned>::Owned: fmt::Debug,
{
style: Style,
string: Cow<'a, S>,
}
/// Cloning an `ANSIGenericString` will clone its underlying string.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::ANSIString;
///
/// let plain_string = ANSIString::from("a plain string");
/// let clone_string = plain_string.clone();
/// assert_eq!(clone_string, plain_string);
/// ```
impl<'a, S: 'a + ToOwned + ?Sized> Clone for AnsiGenericString<'a, S>
where
<S as ToOwned>::Owned: fmt::Debug,
{
fn clone(&self) -> AnsiGenericString<'a, S> {
AnsiGenericString {
style: self.style,
string: self.string.clone(),
}
}
}
// You might think that the hand-written Clone impl above is the same as the
// one that gets generated with #[derive]. But its not *quite* the same!
//
// `str` is not Clone, and the derived Clone implementation puts a Clone
// constraint on the S type parameter (generated using --pretty=expanded):
//
// ↓_________________↓
// impl <'a, S: ::std::clone::Clone + 'a + ToOwned + ?Sized> ::std::clone::Clone
// for ANSIGenericString<'a, S> where
// <S as ToOwned>::Owned: fmt::Debug { ... }
//
// This resulted in compile errors when you tried to derive Clone on a type
// that used it:
//
// #[derive(PartialEq, Debug, Clone, Default)]
// pub struct TextCellContents(Vec<ANSIString<'static>>);
// ^^^^^^^^^^^^^^^^^^^^^^^^^
// error[E0277]: the trait `std::clone::Clone` is not implemented for `str`
//
// The hand-written impl above can ignore that constraint and still compile.
/// An ANSI String is a string coupled with the `Style` to display it
/// in a terminal.
///
/// Although not technically a string itself, it can be turned into
/// one with the `to_string` method.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::ANSIString;
/// use nu_ansi_term::Color::Red;
///
/// let red_string = Red.paint("a red string");
/// println!("{}", red_string);
/// ```
///
/// ```
/// use nu_ansi_term::ANSIString;
///
/// let plain_string = ANSIString::from("a plain string");
/// assert_eq!(&*plain_string, "a plain string");
/// ```
pub type AnsiString<'a> = AnsiGenericString<'a, str>;
/// An `AnsiByteString` represents a formatted series of bytes. Use
/// `AnsiByteString` when styling text with an unknown encoding.
pub type AnsiByteString<'a> = AnsiGenericString<'a, [u8]>;
impl<'a, I, S: 'a + ToOwned + ?Sized> From<I> for AnsiGenericString<'a, S>
where
I: Into<Cow<'a, S>>,
<S as ToOwned>::Owned: fmt::Debug,
{
fn from(input: I) -> AnsiGenericString<'a, S> {
AnsiGenericString {
string: input.into(),
style: Style::default(),
}
}
}
impl<'a, S: 'a + ToOwned + ?Sized> AnsiGenericString<'a, S>
where
<S as ToOwned>::Owned: fmt::Debug,
{
/// Directly access the style
pub fn style_ref(&self) -> &Style {
&self.style
}
/// Directly access the style mutably
pub fn style_ref_mut(&mut self) -> &mut Style {
&mut self.style
}
}
impl<'a, S: 'a + ToOwned + ?Sized> Deref for AnsiGenericString<'a, S>
where
<S as ToOwned>::Owned: fmt::Debug,
{
type Target = S;
fn deref(&self) -> &S {
self.string.deref()
}
}
/// A set of `AnsiGenericStrings`s collected together, in order to be
/// written with a minimum of control characters.
#[derive(Debug, PartialEq)]
pub struct AnsiGenericStrings<'a, S: 'a + ToOwned + ?Sized>(pub &'a [AnsiGenericString<'a, S>])
where
<S as ToOwned>::Owned: fmt::Debug,
S: PartialEq;
/// A set of `AnsiString`s collected together, in order to be written with a
/// minimum of control characters.
pub type AnsiStrings<'a> = AnsiGenericStrings<'a, str>;
/// A function to construct an `AnsiStrings` instance.
#[allow(non_snake_case)]
pub fn AnsiStrings<'a>(arg: &'a [AnsiString<'a>]) -> AnsiStrings<'a> {
AnsiGenericStrings(arg)
}
/// A set of `AnsiByteString`s collected together, in order to be
/// written with a minimum of control characters.
pub type AnsiByteStrings<'a> = AnsiGenericStrings<'a, [u8]>;
/// A function to construct an `ANSIByteStrings` instance.
#[allow(non_snake_case)]
pub fn ANSIByteStrings<'a>(arg: &'a [AnsiByteString<'a>]) -> AnsiByteStrings<'a> {
AnsiGenericStrings(arg)
}
// ---- paint functions ----
impl Style {
/// Paints the given text with this color, returning an ANSI string.
#[must_use]
pub fn paint<'a, I, S: 'a + ToOwned + ?Sized>(self, input: I) -> AnsiGenericString<'a, S>
where
I: Into<Cow<'a, S>>,
<S as ToOwned>::Owned: fmt::Debug,
{
AnsiGenericString {
string: input.into(),
style: self,
}
}
}
impl Color {
/// Paints the given text with this color, returning an ANSI string.
/// This is a short-cut so you dont have to use `Blue.normal()` just
/// to get blue text.
///
/// ```
/// use nu_ansi_term::Color::Blue;
/// println!("{}", Blue.paint("da ba dee"));
/// ```
#[must_use]
pub fn paint<'a, I, S: 'a + ToOwned + ?Sized>(self, input: I) -> AnsiGenericString<'a, S>
where
I: Into<Cow<'a, S>>,
<S as ToOwned>::Owned: fmt::Debug,
{
AnsiGenericString {
string: input.into(),
style: self.normal(),
}
}
}
// ---- writers for individual ANSI strings ----
impl<'a> fmt::Display for AnsiString<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let w: &mut dyn fmt::Write = f;
self.write_to_any(w)
}
}
impl<'a> AnsiByteString<'a> {
/// Write an `ANSIByteString` to an `io::Write`. This writes the escape
/// sequences for the associated `Style` around the bytes.
pub fn write_to<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
let w: &mut dyn io::Write = w;
self.write_to_any(w)
}
}
impl<'a, S: 'a + ToOwned + ?Sized> AnsiGenericString<'a, S>
where
<S as ToOwned>::Owned: fmt::Debug,
&'a S: AsRef<[u8]>,
{
fn write_to_any<W: AnyWrite<Wstr = S> + ?Sized>(&self, w: &mut W) -> Result<(), W::Error> {
write!(w, "{}", self.style.prefix())?;
w.write_str(self.string.as_ref())?;
write!(w, "{}", self.style.suffix())
}
}
// ---- writers for combined ANSI strings ----
impl<'a> fmt::Display for AnsiStrings<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let f: &mut dyn fmt::Write = f;
self.write_to_any(f)
}
}
impl<'a> AnsiByteStrings<'a> {
/// Write `ANSIByteStrings` to an `io::Write`. This writes the minimal
/// escape sequences for the associated `Style`s around each set of
/// bytes.
pub fn write_to<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
let w: &mut dyn io::Write = w;
self.write_to_any(w)
}
}
impl<'a, S: 'a + ToOwned + ?Sized + PartialEq> AnsiGenericStrings<'a, S>
where
<S as ToOwned>::Owned: fmt::Debug,
&'a S: AsRef<[u8]>,
{
fn write_to_any<W: AnyWrite<Wstr = S> + ?Sized>(&self, w: &mut W) -> Result<(), W::Error> {
use self::Difference::*;
let first = match self.0.first() {
None => return Ok(()),
Some(f) => f,
};
write!(w, "{}", first.style.prefix())?;
w.write_str(first.string.as_ref())?;
for window in self.0.windows(2) {
match Difference::between(&window[0].style, &window[1].style) {
ExtraStyles(style) => write!(w, "{}", style.prefix())?,
Reset => write!(w, "{}{}", RESET, window[1].style.prefix())?,
Empty => { /* Do nothing! */ }
}
w.write_str(&window[1].string)?;
}
// Write the final reset string after all of the ANSIStrings have been
// written, *except* if the last one has no styles, because it would
// have already been written by this point.
if let Some(last) = self.0.last() {
if !last.style.is_plain() {
write!(w, "{}", RESET)?;
}
}
Ok(())
}
}
// ---- tests ----
#[cfg(test)]
mod tests {
pub use super::super::AnsiStrings;
pub use crate::style::Color::*;
pub use crate::style::Style;
#[test]
fn no_control_codes_for_plain() {
let one = Style::default().paint("one");
let two = Style::default().paint("two");
let output = format!("{}", AnsiStrings(&[one, two]));
assert_eq!(&*output, "onetwo");
}
}

View File

@ -1,105 +0,0 @@
use crate::{rgb::Rgb, Color};
/// Linear color gradient between two color stops
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Gradient {
/// Start Color of Gradient
pub start: Rgb,
/// End Color of Gradient
pub end: Rgb,
}
impl Gradient {
/// Creates a new [Gradient] with two [Rgb] colors, `start` and `end`
#[inline]
pub const fn new(start: Rgb, end: Rgb) -> Self {
Self { start, end }
}
pub const fn from_color_rgb(start: Color, end: Color) -> Self {
let start_grad = match start {
Color::Rgb(r, g, b) => Rgb { r, g, b },
_ => Rgb { r: 0, g: 0, b: 0 },
};
let end_grad = match end {
Color::Rgb(r, g, b) => Rgb { r, g, b },
_ => Rgb { r: 0, g: 0, b: 0 },
};
Self {
start: start_grad,
end: end_grad,
}
}
/// Computes the [Rgb] color between `start` and `end` for `t`
pub fn at(&self, t: f32) -> Rgb {
self.start.lerp(self.end, t)
}
/// Returns the reverse of `self`
#[inline]
pub const fn reverse(&self) -> Self {
Self::new(self.end, self.start)
}
#[allow(dead_code)]
pub fn build(&self, text: &str, target: TargetGround) -> String {
let delta = 1.0 / text.len() as f32;
let mut result = text.char_indices().fold(String::new(), |mut acc, (i, c)| {
let temp = format!(
"\x1B[{}m{}",
self.at(i as f32 * delta).ansi_color_code(target),
c
);
acc.push_str(&temp);
acc
});
result.push_str("\x1B[0m");
result
}
}
#[allow(dead_code)]
pub fn build_all_gradient_text(text: &str, foreground: Gradient, background: Gradient) -> String {
let delta = 1.0 / text.len() as f32;
let mut result = text.char_indices().fold(String::new(), |mut acc, (i, c)| {
let step = i as f32 * delta;
let temp = format!(
"\x1B[{};{}m{}",
foreground
.at(step)
.ansi_color_code(TargetGround::Foreground),
background
.at(step)
.ansi_color_code(TargetGround::Background),
c
);
acc.push_str(&temp);
acc
});
result.push_str("\x1B[0m");
result
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TargetGround {
Foreground,
Background,
}
impl TargetGround {
#[inline]
pub const fn code(&self) -> u8 {
match self {
Self::Foreground => 30,
Self::Background => 40,
}
}
}
pub trait ANSIColorCode {
fn ansi_color_code(&self, target: TargetGround) -> String;
}

View File

@ -1,273 +0,0 @@
//! This is a library for controlling colors and formatting, such as
//! red bold text or blue underlined text, on ANSI terminals.
//!
//!
//! ## Basic usage
//!
//! There are three main types in this crate that you need to be
//! concerned with: [`ANSIString`], [`Style`], and [`Color`].
//!
//! A `Style` holds stylistic information: foreground and background colors,
//! whether the text should be bold, or blinking, or other properties. The
//! [`Color`] enum represents the available colors. And an [`ANSIString`] is a
//! string paired with a [`Style`].
//!
//! [`Color`] is also available as an alias to `Color`.
//!
//! To format a string, call the `paint` method on a `Style` or a `Color`,
//! passing in the string you want to format as the argument. For example,
//! heres how to get some red text:
//!
//! ```
//! use nu_ansi_term::Color::Red;
//!
//! println!("This is in red: {}", Red.paint("a red string"));
//! ```
//!
//! Its important to note that the `paint` method does *not* actually return a
//! string with the ANSI control characters surrounding it. Instead, it returns
//! an [`ANSIString`] value that has a [`Display`] implementation that, when
//! formatted, returns the characters. This allows strings to be printed with a
//! minimum of [`String`] allocations being performed behind the scenes.
//!
//! If you *do* want to get at the escape codes, then you can convert the
//! [`ANSIString`] to a string as you would any other `Display` value:
//!
//! ```
//! use nu_ansi_term::Color::Red;
//!
//! let red_string = Red.paint("a red string").to_string();
//! ```
//!
//!
//! ## Bold, underline, background, and other styles
//!
//! For anything more complex than plain foreground color changes, you need to
//! construct `Style` values themselves, rather than beginning with a `Color`.
//! You can do this by chaining methods based on a new `Style`, created with
//! [`Style::new()`]. Each method creates a new style that has that specific
//! property set. For example:
//!
//! ```
//! use nu_ansi_term::Style;
//!
//! println!("How about some {} and {}?",
//! Style::new().bold().paint("bold"),
//! Style::new().underline().paint("underline"));
//! ```
//!
//! For brevity, these methods have also been implemented for `Color` values,
//! so you can give your styles a foreground color without having to begin with
//! an empty `Style` value:
//!
//! ```
//! use nu_ansi_term::Color::{Blue, Yellow};
//!
//! println!("Demonstrating {} and {}!",
//! Blue.bold().paint("blue bold"),
//! Yellow.underline().paint("yellow underline"));
//!
//! println!("Yellow on blue: {}", Yellow.on(Blue).paint("wow!"));
//! ```
//!
//! The complete list of styles you can use are: [`bold`], [`dimmed`], [`italic`],
//! [`underline`], [`blink`], [`reverse`], [`hidden`], [`strikethrough`], and [`on`] for
//! background colors.
//!
//! In some cases, you may find it easier to change the foreground on an
//! existing `Style` rather than starting from the appropriate `Color`.
//! You can do this using the [`fg`] method:
//!
//! ```
//! use nu_ansi_term::Style;
//! use nu_ansi_term::Color::{Blue, Cyan, Yellow};
//!
//! println!("Yellow on blue: {}", Style::new().on(Blue).fg(Yellow).paint("yow!"));
//! println!("Also yellow on blue: {}", Cyan.on(Blue).fg(Yellow).paint("zow!"));
//! ```
//!
//! You can turn a `Color` into a `Style` with the [`normal`] method.
//! This will produce the exact same `ANSIString` as if you just used the
//! `paint` method on the `Color` directly, but its useful in certain cases:
//! for example, you may have a method that returns `Styles`, and need to
//! represent both the “red bold” and “red, but not bold” styles with values of
//! the same type. The `Style` struct also has a [`Default`] implementation if you
//! want to have a style with *nothing* set.
//!
//! ```
//! use nu_ansi_term::Style;
//! use nu_ansi_term::Color::Red;
//!
//! Red.normal().paint("yet another red string");
//! Style::default().paint("a completely regular string");
//! ```
//!
//!
//! ## Extended colors
//!
//! You can access the extended range of 256 colors by using the `Color::Fixed`
//! variant, which takes an argument of the color number to use. This can be
//! included wherever you would use a `Color`:
//!
//! ```
//! use nu_ansi_term::Color::Fixed;
//!
//! Fixed(134).paint("A sort of light purple");
//! Fixed(221).on(Fixed(124)).paint("Mustard in the ketchup");
//! ```
//!
//! The first sixteen of these values are the same as the normal and bold
//! standard color variants. Theres nothing stopping you from using these as
//! `Fixed` colors instead, but theres nothing to be gained by doing so
//! either.
//!
//! You can also access full 24-bit color by using the `Color::Rgb` variant,
//! which takes separate `u8` arguments for red, green, and blue:
//!
//! ```
//! use nu_ansi_term::Color::Rgb;
//!
//! Rgb(70, 130, 180).paint("Steel blue");
//! ```
//!
//! ## Combining successive colored strings
//!
//! The benefit of writing ANSI escape codes to the terminal is that they
//! *stack*: you do not need to end every colored string with a reset code if
//! the text that follows it is of a similar style. For example, if you want to
//! have some blue text followed by some blue bold text, its possible to send
//! the ANSI code for blue, followed by the ANSI code for bold, and finishing
//! with a reset code without having to have an extra one between the two
//! strings.
//!
//! This crate can optimise the ANSI codes that get printed in situations like
//! this, making life easier for your terminal renderer. The [`ANSIStrings`]
//! type takes a slice of several [`ANSIString`] values, and will iterate over
//! each of them, printing only the codes for the styles that need to be updated
//! as part of its formatting routine.
//!
//! The following code snippet uses this to enclose a binary number displayed in
//! red bold text inside some red, but not bold, brackets:
//!
//! ```
//! use nu_ansi_term::Color::Red;
//! use nu_ansi_term::{ANSIString, ANSIStrings};
//!
//! let some_value = format!("{:b}", 42);
//! let strings: &[ANSIString<'static>] = &[
//! Red.paint("["),
//! Red.bold().paint(some_value),
//! Red.paint("]"),
//! ];
//!
//! println!("Value: {}", ANSIStrings(strings));
//! ```
//!
//! There are several things to note here. Firstly, the [`paint`] method can take
//! *either* an owned [`String`] or a borrowed [`&str`]. Internally, an [`ANSIString`]
//! holds a copy-on-write ([`Cow`]) string value to deal with both owned and
//! borrowed strings at the same time. This is used here to display a `String`,
//! the result of the `format!` call, using the same mechanism as some
//! statically-available `&str` slices. Secondly, that the [`ANSIStrings`] value
//! works in the same way as its singular counterpart, with a [`Display`]
//! implementation that only performs the formatting when required.
//!
//! ## Byte strings
//!
//! This library also supports formatting `\[u8]` byte strings; this supports
//! applications working with text in an unknown encoding. [`Style`] and
//! [`Color`] support painting `\[u8]` values, resulting in an [`ANSIByteString`].
//! This type does not implement [`Display`], as it may not contain UTF-8, but
//! it does provide a method [`write_to`] to write the result to any value that
//! implements [`Write`]:
//!
//! ```
//! use nu_ansi_term::Color::Green;
//!
//! Green.paint("user data".as_bytes()).write_to(&mut std::io::stdout()).unwrap();
//! ```
//!
//! Similarly, the type [`ANSIByteStrings`] supports writing a list of
//! [`ANSIByteString`] values with minimal escape sequences:
//!
//! ```
//! use nu_ansi_term::Color::Green;
//! use nu_ansi_term::ANSIByteStrings;
//!
//! ANSIByteStrings(&[
//! Green.paint("user data 1\n".as_bytes()),
//! Green.bold().paint("user data 2\n".as_bytes()),
//! ]).write_to(&mut std::io::stdout()).unwrap();
//! ```
//!
//! [`Cow`]: https://doc.rust-lang.org/std/borrow/enum.Cow.html
//! [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html
//! [`Default`]: https://doc.rust-lang.org/std/default/trait.Default.html
//! [`String`]: https://doc.rust-lang.org/std/string/struct.String.html
//! [`&str`]: https://doc.rust-lang.org/std/primitive.str.html
//! [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
//! [`Style`]: struct.Style.html
//! [`Style::new()`]: struct.Style.html#method.new
//! [`Color`]: enum.Color.html
//! [`Color`]: enum.Color.html
//! [`ANSIString`]: type.ANSIString.html
//! [`ANSIStrings`]: type.ANSIStrings.html
//! [`ANSIByteString`]: type.ANSIByteString.html
//! [`ANSIByteStrings`]: type.ANSIByteStrings.html
//! [`write_to`]: type.ANSIByteString.html#method.write_to
//! [`paint`]: type.ANSIByteString.html#method.write_to
//! [`normal`]: enum.Color.html#method.normal
//!
//! [`bold`]: struct.Style.html#method.bold
//! [`dimmed`]: struct.Style.html#method.dimmed
//! [`italic`]: struct.Style.html#method.italic
//! [`underline`]: struct.Style.html#method.underline
//! [`blink`]: struct.Style.html#method.blink
//! [`reverse`]: struct.Style.html#method.reverse
//! [`hidden`]: struct.Style.html#method.hidden
//! [`strikethrough`]: struct.Style.html#method.strikethrough
//! [`fg`]: struct.Style.html#method.fg
//! [`on`]: struct.Style.html#method.on
#![crate_name = "nu_ansi_term"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![warn(missing_copy_implementations)]
// #![warn(missing_docs)]
#![warn(trivial_casts, trivial_numeric_casts)]
// #![warn(unused_extern_crates, unused_qualifications)]
#[cfg(target_os = "windows")]
extern crate winapi;
#[cfg(test)]
#[macro_use]
extern crate doc_comment;
#[cfg(test)]
doctest!("../README.md");
pub mod ansi;
pub use ansi::{Infix, Prefix, Suffix};
mod style;
pub use style::{Color, Style};
mod difference;
mod display;
pub use display::*;
mod write;
mod windows;
pub use windows::*;
mod util;
pub use util::*;
mod debug;
pub mod gradient;
pub use gradient::*;
mod rgb;
pub use rgb::*;

View File

@ -1,173 +0,0 @@
// Code liberally borrowed from here
// https://github.com/navierr/coloriz
use std::ops;
use std::u32;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Rgb {
/// Red
pub r: u8,
/// Green
pub g: u8,
/// Blue
pub b: u8,
}
impl Rgb {
/// Creates a new [Rgb] color
#[inline]
pub const fn new(r: u8, g: u8, b: u8) -> Self {
Self { r, g, b }
}
/// Creates a new [Rgb] color with a hex code
#[inline]
pub const fn from_hex(hex: u32) -> Self {
Self::new((hex >> 16) as u8, (hex >> 8) as u8, hex as u8)
}
pub fn from_hex_string(hex: String) -> Self {
if hex.chars().count() == 8 && hex.starts_with("0x") {
// eprintln!("hex:{:?}", hex);
let (_, value_string) = hex.split_at(2);
// eprintln!("value_string:{:?}", value_string);
let int_val = u64::from_str_radix(value_string, 16);
match int_val {
Ok(num) => Self::new(
((num & 0xff0000) >> 16) as u8,
((num & 0xff00) >> 8) as u8,
(num & 0xff) as u8,
),
// Don't fail, just make the color black
// Should we fail?
_ => Self::new(0, 0, 0),
}
} else {
// Don't fail, just make the color black.
// Should we fail?
Self::new(0, 0, 0)
}
}
/// Creates a new [Rgb] color with three [f32] values
pub fn from_f32(r: f32, g: f32, b: f32) -> Self {
Self::new(
(r.clamp(0.0, 1.0) * 255.0) as u8,
(g.clamp(0.0, 1.0) * 255.0) as u8,
(b.clamp(0.0, 1.0) * 255.0) as u8,
)
}
/// Creates a grayscale [Rgb] color
#[inline]
pub const fn gray(x: u8) -> Self {
Self::new(x, x, x)
}
/// Creates a grayscale [Rgb] color with a [f32] value
pub fn gray_f32(x: f32) -> Self {
Self::from_f32(x, x, x)
}
/// Creates a new [Rgb] color from a [HSL] color
// pub fn from_hsl(hsl: HSL) -> Self {
// if hsl.s == 0.0 {
// return Self::gray_f32(hsl.l);
// }
// let q = if hsl.l < 0.5 {
// hsl.l * (1.0 + hsl.s)
// } else {
// hsl.l + hsl.s - hsl.l * hsl.s
// };
// let p = 2.0 * hsl.l - q;
// let h2c = |t: f32| {
// let t = t.clamp(0.0, 1.0);
// if 6.0 * t < 1.0 {
// p + 6.0 * (q - p) * t
// } else if t < 0.5 {
// q
// } else if 1.0 < 1.5 * t {
// p + 6.0 * (q - p) * (1.0 / 1.5 - t)
// } else {
// p
// }
// };
// Self::from_f32(h2c(hsl.h + 1.0 / 3.0), h2c(hsl.h), h2c(hsl.h - 1.0 / 3.0))
// }
/// Computes the linear interpolation between `self` and `other` for `t`
pub fn lerp(&self, other: Self, t: f32) -> Self {
let t = t.clamp(0.0, 1.0);
self * (1.0 - t) + other * t
}
}
impl From<(u8, u8, u8)> for Rgb {
fn from((r, g, b): (u8, u8, u8)) -> Self {
Self::new(r, g, b)
}
}
impl From<(f32, f32, f32)> for Rgb {
fn from((r, g, b): (f32, f32, f32)) -> Self {
Self::from_f32(r, g, b)
}
}
use crate::ANSIColorCode;
use crate::TargetGround;
impl ANSIColorCode for Rgb {
fn ansi_color_code(&self, target: TargetGround) -> String {
format!("{};2;{};{};{}", target.code() + 8, self.r, self.g, self.b)
}
}
overload::overload!(
(lhs: ?Rgb) + (rhs: ?Rgb) -> Rgb {
Rgb::new(
lhs.r.saturating_add(rhs.r),
lhs.g.saturating_add(rhs.g),
lhs.b.saturating_add(rhs.b)
)
}
);
overload::overload!(
(lhs: ?Rgb) - (rhs: ?Rgb) -> Rgb {
Rgb::new(
lhs.r.saturating_sub(rhs.r),
lhs.g.saturating_sub(rhs.g),
lhs.b.saturating_sub(rhs.b)
)
}
);
overload::overload!(
(lhs: ?Rgb) * (rhs: ?f32) -> Rgb {
Rgb::new(
(lhs.r as f32 * rhs.clamp(0.0, 1.0)) as u8,
(lhs.g as f32 * rhs.clamp(0.0, 1.0)) as u8,
(lhs.b as f32 * rhs.clamp(0.0, 1.0)) as u8
)
}
);
overload::overload!(
(lhs: ?f32) * (rhs: ?Rgb) -> Rgb {
Rgb::new(
(rhs.r as f32 * lhs.clamp(0.0, 1.0)) as u8,
(rhs.g as f32 * lhs.clamp(0.0, 1.0)) as u8,
(rhs.b as f32 * lhs.clamp(0.0, 1.0)) as u8
)
}
);
overload::overload!(
-(rgb: ?Rgb) -> Rgb {
Rgb::new(
255 - rgb.r,
255 - rgb.g,
255 - rgb.b)
}
);

View File

@ -1,626 +0,0 @@
/// A style is a collection of properties that can format a string
/// using ANSI escape codes.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::{Style, Color};
///
/// let style = Style::new().bold().on(Color::Black);
/// println!("{}", style.paint("Bold on black"));
/// ```
#[derive(PartialEq, Clone, Copy)]
#[cfg_attr(
feature = "derive_serde_style",
derive(serde::Deserialize, serde::Serialize)
)]
pub struct Style {
/// The style's foreground color, if it has one.
pub foreground: Option<Color>,
/// The style's background color, if it has one.
pub background: Option<Color>,
/// Whether this style is bold.
pub is_bold: bool,
/// Whether this style is dimmed.
pub is_dimmed: bool,
/// Whether this style is italic.
pub is_italic: bool,
/// Whether this style is underlined.
pub is_underline: bool,
/// Whether this style is blinking.
pub is_blink: bool,
/// Whether this style has reverse colors.
pub is_reverse: bool,
/// Whether this style is hidden.
pub is_hidden: bool,
/// Whether this style is struckthrough.
pub is_strikethrough: bool,
}
impl Style {
/// Creates a new Style with no properties set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// let style = Style::new();
/// println!("{}", style.paint("hi"));
/// ```
pub fn new() -> Style {
Style::default()
}
/// Returns a `Style` with the bold property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// let style = Style::new().bold();
/// println!("{}", style.paint("hey"));
/// ```
pub fn bold(&self) -> Style {
Style {
is_bold: true,
..*self
}
}
/// Returns a `Style` with the dimmed property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// let style = Style::new().dimmed();
/// println!("{}", style.paint("sup"));
/// ```
pub fn dimmed(&self) -> Style {
Style {
is_dimmed: true,
..*self
}
}
/// Returns a `Style` with the italic property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// let style = Style::new().italic();
/// println!("{}", style.paint("greetings"));
/// ```
pub fn italic(&self) -> Style {
Style {
is_italic: true,
..*self
}
}
/// Returns a `Style` with the underline property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// let style = Style::new().underline();
/// println!("{}", style.paint("salutations"));
/// ```
pub fn underline(&self) -> Style {
Style {
is_underline: true,
..*self
}
}
/// Returns a `Style` with the blink property set.
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// let style = Style::new().blink();
/// println!("{}", style.paint("wazzup"));
/// ```
pub fn blink(&self) -> Style {
Style {
is_blink: true,
..*self
}
}
/// Returns a `Style` with the reverse property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// let style = Style::new().reverse();
/// println!("{}", style.paint("aloha"));
/// ```
pub fn reverse(&self) -> Style {
Style {
is_reverse: true,
..*self
}
}
/// Returns a `Style` with the hidden property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// let style = Style::new().hidden();
/// println!("{}", style.paint("ahoy"));
/// ```
pub fn hidden(&self) -> Style {
Style {
is_hidden: true,
..*self
}
}
/// Returns a `Style` with the strikethrough property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// let style = Style::new().strikethrough();
/// println!("{}", style.paint("yo"));
/// ```
pub fn strikethrough(&self) -> Style {
Style {
is_strikethrough: true,
..*self
}
}
/// Returns a `Style` with the foreground color property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::{Style, Color};
///
/// let style = Style::new().fg(Color::Yellow);
/// println!("{}", style.paint("hi"));
/// ```
pub fn fg(&self, foreground: Color) -> Style {
Style {
foreground: Some(foreground),
..*self
}
}
/// Returns a `Style` with the background color property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::{Style, Color};
///
/// let style = Style::new().on(Color::Blue);
/// println!("{}", style.paint("eyyyy"));
/// ```
pub fn on(&self, background: Color) -> Style {
Style {
background: Some(background),
..*self
}
}
/// Return true if this `Style` has no actual styles, and can be written
/// without any control characters.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// assert_eq!(true, Style::default().is_plain());
/// assert_eq!(false, Style::default().bold().is_plain());
/// ```
pub fn is_plain(self) -> bool {
self == Style::default()
}
}
impl Default for Style {
/// Returns a style with *no* properties set. Formatting text using this
/// style returns the exact same text.
///
/// ```
/// use nu_ansi_term::Style;
/// assert_eq!(None, Style::default().foreground);
/// assert_eq!(None, Style::default().background);
/// assert_eq!(false, Style::default().is_bold);
/// assert_eq!("txt", Style::default().paint("txt").to_string());
/// ```
fn default() -> Style {
Style {
foreground: None,
background: None,
is_bold: false,
is_dimmed: false,
is_italic: false,
is_underline: false,
is_blink: false,
is_reverse: false,
is_hidden: false,
is_strikethrough: false,
}
}
}
// ---- colors ----
/// A color is one specific type of ANSI escape code, and can refer
/// to either the foreground or background color.
///
/// These use the standard numeric sequences.
/// See <http://invisible-island.net/xterm/ctlseqs/ctlseqs.html>
#[derive(PartialEq, Clone, Copy, Debug)]
#[cfg_attr(
feature = "derive_serde_style",
derive(serde::Deserialize, serde::Serialize)
)]
pub enum Color {
/// Color #0 (foreground code `30`, background code `40`).
///
/// This is not necessarily the background color, and using it as one may
/// render the text hard to read on terminals with dark backgrounds.
Black,
/// Color #0 (foreground code `90`, background code `100`).
DarkGray,
/// Color #1 (foreground code `31`, background code `41`).
Red,
/// Color #1 (foreground code `91`, background code `101`).
LightRed,
/// Color #2 (foreground code `32`, background code `42`).
Green,
/// Color #2 (foreground code `92`, background code `102`).
LightGreen,
/// Color #3 (foreground code `33`, background code `43`).
Yellow,
/// Color #3 (foreground code `93`, background code `103`).
LightYellow,
/// Color #4 (foreground code `34`, background code `44`).
Blue,
/// Color #4 (foreground code `94`, background code `104`).
LightBlue,
/// Color #5 (foreground code `35`, background code `45`).
Purple,
/// Color #5 (foreground code `95`, background code `105`).
LightPurple,
/// Color #5 (foreground code `35`, background code `45`).
Magenta,
/// Color #5 (foreground code `95`, background code `105`).
LightMagenta,
/// Color #6 (foreground code `36`, background code `46`).
Cyan,
/// Color #6 (foreground code `96`, background code `106`).
LightCyan,
/// Color #7 (foreground code `37`, background code `47`).
///
/// As above, this is not necessarily the foreground color, and may be
/// hard to read on terminals with light backgrounds.
White,
/// Color #7 (foreground code `97`, background code `107`).
LightGray,
/// A color number from 0 to 255, for use in 256-color terminal
/// environments.
///
/// - colors 0 to 7 are the `Black` to `White` variants respectively.
/// These colors can usually be changed in the terminal emulator.
/// - colors 8 to 15 are brighter versions of the eight colors above.
/// These can also usually be changed in the terminal emulator, or it
/// could be configured to use the original colors and show the text in
/// bold instead. It varies depending on the program.
/// - colors 16 to 231 contain several palettes of bright colors,
/// arranged in six squares measuring six by six each.
/// - colors 232 to 255 are shades of grey from black to white.
///
/// It might make more sense to look at a [color chart][cc].
///
/// [cc]: https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg
Fixed(u8),
/// A 24-bit Rgb color, as specified by ISO-8613-3.
Rgb(u8, u8, u8),
}
impl Default for Color {
fn default() -> Self {
Color::White
}
}
impl Color {
/// Returns a `Style` with the foreground color set to this color.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::Red.normal();
/// println!("{}", style.paint("hi"));
/// ```
pub fn normal(self) -> Style {
Style {
foreground: Some(self),
..Style::default()
}
}
/// Returns a `Style` with the foreground color set to this color and the
/// bold property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::Green.bold();
/// println!("{}", style.paint("hey"));
/// ```
pub fn bold(self) -> Style {
Style {
foreground: Some(self),
is_bold: true,
..Style::default()
}
}
/// Returns a `Style` with the foreground color set to this color and the
/// dimmed property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::Yellow.dimmed();
/// println!("{}", style.paint("sup"));
/// ```
pub fn dimmed(self) -> Style {
Style {
foreground: Some(self),
is_dimmed: true,
..Style::default()
}
}
/// Returns a `Style` with the foreground color set to this color and the
/// italic property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::Blue.italic();
/// println!("{}", style.paint("greetings"));
/// ```
pub fn italic(self) -> Style {
Style {
foreground: Some(self),
is_italic: true,
..Style::default()
}
}
/// Returns a `Style` with the foreground color set to this color and the
/// underline property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::Purple.underline();
/// println!("{}", style.paint("salutations"));
/// ```
pub fn underline(self) -> Style {
Style {
foreground: Some(self),
is_underline: true,
..Style::default()
}
}
/// Returns a `Style` with the foreground color set to this color and the
/// blink property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::Cyan.blink();
/// println!("{}", style.paint("wazzup"));
/// ```
pub fn blink(self) -> Style {
Style {
foreground: Some(self),
is_blink: true,
..Style::default()
}
}
/// Returns a `Style` with the foreground color set to this color and the
/// reverse property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::Black.reverse();
/// println!("{}", style.paint("aloha"));
/// ```
pub fn reverse(self) -> Style {
Style {
foreground: Some(self),
is_reverse: true,
..Style::default()
}
}
/// Returns a `Style` with the foreground color set to this color and the
/// hidden property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::White.hidden();
/// println!("{}", style.paint("ahoy"));
/// ```
pub fn hidden(self) -> Style {
Style {
foreground: Some(self),
is_hidden: true,
..Style::default()
}
}
/// Returns a `Style` with the foreground color set to this color and the
/// strikethrough property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::Fixed(244).strikethrough();
/// println!("{}", style.paint("yo"));
/// ```
pub fn strikethrough(self) -> Style {
Style {
foreground: Some(self),
is_strikethrough: true,
..Style::default()
}
}
/// Returns a `Style` with the foreground color set to this color and the
/// background color property set to the given color.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::Rgb(31, 31, 31).on(Color::White);
/// println!("{}", style.paint("eyyyy"));
/// ```
pub fn on(self, background: Color) -> Style {
Style {
foreground: Some(self),
background: Some(background),
..Style::default()
}
}
}
impl From<Color> for Style {
/// You can turn a `Color` into a `Style` with the foreground color set
/// with the `From` trait.
///
/// ```
/// use nu_ansi_term::{Style, Color};
/// let green_foreground = Style::default().fg(Color::Green);
/// assert_eq!(green_foreground, Color::Green.normal());
/// assert_eq!(green_foreground, Color::Green.into());
/// assert_eq!(green_foreground, Style::from(Color::Green));
/// ```
fn from(color: Color) -> Style {
color.normal()
}
}
#[cfg(test)]
#[cfg(feature = "derive_serde_style")]
mod serde_json_tests {
use super::{Color, Style};
#[test]
fn color_serialization() {
let colors = &[
Color::Red,
Color::Blue,
Color::Rgb(123, 123, 123),
Color::Fixed(255),
];
assert_eq!(
serde_json::to_string(&colors).unwrap(),
String::from("[\"Red\",\"Blue\",{\"Rgb\":[123,123,123]},{\"Fixed\":255}]")
);
}
#[test]
fn color_deserialization() {
let colors = &[
Color::Red,
Color::Blue,
Color::Rgb(123, 123, 123),
Color::Fixed(255),
];
for color in colors.iter() {
let serialized = serde_json::to_string(&color).unwrap();
let deserialized: Color = serde_json::from_str(&serialized).unwrap();
assert_eq!(color, &deserialized);
}
}
#[test]
fn style_serialization() {
let style = Style::default();
assert_eq!(serde_json::to_string(&style).unwrap(), "{\"foreground\":null,\"background\":null,\"is_bold\":false,\"is_dimmed\":false,\"is_italic\":false,\"is_underline\":false,\"is_blink\":false,\"is_reverse\":false,\"is_hidden\":false,\"is_strikethrough\":false}".to_string());
}
}

View File

@ -1,80 +0,0 @@
use crate::display::{AnsiString, AnsiStrings};
use std::ops::Deref;
/// Return a substring of the given ANSIStrings sequence, while keeping the formatting.
pub fn sub_string<'a>(
start: usize,
len: usize,
strs: &AnsiStrings<'a>,
) -> Vec<AnsiString<'static>> {
let mut vec = Vec::new();
let mut pos = start;
let mut len_rem = len;
for i in strs.0.iter() {
let fragment = i.deref();
let frag_len = fragment.len();
if pos >= frag_len {
pos -= frag_len;
continue;
}
if len_rem == 0 {
break;
}
let end = pos + len_rem;
let pos_end = if end >= frag_len { frag_len } else { end };
vec.push(i.style_ref().paint(String::from(&fragment[pos..pos_end])));
if end <= frag_len {
break;
}
len_rem -= pos_end - pos;
pos = 0;
}
vec
}
/// Return a concatenated copy of `strs` without the formatting, as an allocated `String`.
pub fn unstyle(strs: &AnsiStrings) -> String {
let mut s = String::new();
for i in strs.0.iter() {
s += i.deref();
}
s
}
/// Return the unstyled length of ANSIStrings. This is equaivalent to `unstyle(strs).len()`.
pub fn unstyled_len(strs: &AnsiStrings) -> usize {
let mut l = 0;
for i in strs.0.iter() {
l += i.deref().len();
}
l
}
#[cfg(test)]
mod test {
use super::*;
use crate::Color::*;
#[test]
fn test() {
let l = [
Black.paint("first"),
Red.paint("-second"),
White.paint("-third"),
];
let a = AnsiStrings(&l);
assert_eq!(unstyle(&a), "first-second-third");
assert_eq!(unstyled_len(&a), 18);
let l2 = [Black.paint("st"), Red.paint("-second"), White.paint("-t")];
assert_eq!(sub_string(3, 11, &a).as_slice(), &l2);
}
}

View File

@ -1,62 +0,0 @@
/// Enables ANSI code support on Windows 10.
///
/// This uses Windows API calls to alter the properties of the console that
/// the program is running in.
///
/// https://msdn.microsoft.com/en-us/library/windows/desktop/mt638032(v=vs.85).aspx
///
/// Returns a `Result` with the Windows error code if unsuccessful.
#[cfg(windows)]
pub fn enable_ansi_support() -> Result<(), u32> {
// ref: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#EXAMPLE_OF_ENABLING_VIRTUAL_TERMINAL_PROCESSING @@ https://archive.is/L7wRJ#76%
use std::ffi::OsStr;
use std::iter::once;
use std::os::windows::ffi::OsStrExt;
use std::ptr::null_mut;
use winapi::um::consoleapi::{GetConsoleMode, SetConsoleMode};
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING};
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
use winapi::um::winnt::{FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE};
const ENABLE_VIRTUAL_TERMINAL_PROCESSING: u32 = 0x0004;
unsafe {
// ref: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
// Using `CreateFileW("CONOUT$", ...)` to retrieve the console handle works correctly even if STDOUT and/or STDERR are redirected
let console_out_name: Vec<u16> =
OsStr::new("CONOUT$").encode_wide().chain(once(0)).collect();
let console_handle = CreateFileW(
console_out_name.as_ptr(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE,
null_mut(),
OPEN_EXISTING,
0,
null_mut(),
);
if console_handle == INVALID_HANDLE_VALUE {
return Err(GetLastError());
}
// ref: https://docs.microsoft.com/en-us/windows/console/getconsolemode
let mut console_mode: u32 = 0;
if 0 == GetConsoleMode(console_handle, &mut console_mode) {
return Err(GetLastError());
}
// VT processing not already enabled?
if console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0 {
// https://docs.microsoft.com/en-us/windows/console/setconsolemode
if 0 == SetConsoleMode(
console_handle,
console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING,
) {
return Err(GetLastError());
}
}
}
Ok(())
}

View File

@ -1,37 +0,0 @@
use std::fmt;
use std::io;
pub trait AnyWrite {
type Wstr: ?Sized;
type Error;
fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Self::Error>;
fn write_str(&mut self, s: &Self::Wstr) -> Result<(), Self::Error>;
}
impl<'a> AnyWrite for dyn fmt::Write + 'a {
type Wstr = str;
type Error = fmt::Error;
fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Self::Error> {
fmt::Write::write_fmt(self, fmt)
}
fn write_str(&mut self, s: &Self::Wstr) -> Result<(), Self::Error> {
fmt::Write::write_str(self, s)
}
}
impl<'a> AnyWrite for dyn io::Write + 'a {
type Wstr = [u8];
type Error = io::Error;
fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Self::Error> {
io::Write::write_fmt(self, fmt)
}
fn write_str(&mut self, s: &Self::Wstr) -> Result<(), Self::Error> {
io::Write::write_all(self, s)
}
}

View File

@ -1,41 +1,33 @@
[package]
authors = ["The Nu Project Contributors"]
description = "CLI for nushell"
edition = "2018"
authors = ["The Nushell Project Developers"]
description = "CLI-related functionality for Nushell"
edition = "2021"
license = "MIT"
name = "nu-cli"
version = "0.34.0"
build = "build.rs"
version = "0.64.0"
[lib]
doctest = false
[dev-dependencies]
nu-test-support = { path="../nu-test-support", version = "0.64.0" }
nu-command = { path = "../nu-command", version = "0.64.0" }
[dependencies]
nu-completion = { version = "0.34.0", path="../nu-completion" }
nu-command = { version = "0.34.0", path="../nu-command" }
nu-data = { version = "0.34.0", path="../nu-data" }
nu-engine = { version = "0.34.0", path="../nu-engine" }
nu-errors = { version = "0.34.0", path="../nu-errors" }
nu-parser = { version = "0.34.0", path="../nu-parser" }
nu-protocol = { version = "0.34.0", path="../nu-protocol" }
nu-source = { version = "0.34.0", path="../nu-source" }
nu-stream = { version = "0.34.0", path="../nu-stream" }
nu-ansi-term = { version = "0.34.0", path="../nu-ansi-term" }
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"
fuzzy-matcher = "0.3.7"
indexmap ="1.6.1"
log = "0.4.14"
pretty_env_logger = "0.4.0"
strip-ansi-escapes = "0.1.0"
rustyline = { version="8.1.0", optional=true }
ctrlc = { version="3.1.7", optional=true }
shadow-rs = { version="0.6", default-features=false, optional=true }
serde = { version="1.0.123", features=["derive"] }
serde_yaml = "0.8.16"
[build-dependencies]
shadow-rs = "0.6"
log = "0.4"
is_executable = "1.0.1"
chrono = "0.4.19"
sysinfo = "0.24.1"
[features]
default = ["shadow-rs"]
rustyline-support = ["rustyline", "nu-engine/rustyline-support"]
stable = []
plugin = []

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
MIT License
Copyright (c) 2014 Benjamin Sago
Copyright (c) 2019 - 2022 The Nushell Project Developers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,4 +0,0 @@
# nu-cli
This crate provides the fundamental needs when creating the Nushell interactive REPL. In it, you'll find features for interacting with the line editor (the piece which writes the prompt and takes input from the user), keybindings, handlers for the commandline arguments passed to the REPL as it starts up, and more.

View File

@ -1,3 +0,0 @@
fn main() -> shadow_rs::SdResult<()> {
shadow_rs::new()
}

View File

@ -1,525 +0,0 @@
mod logger;
mod options;
mod options_parser;
pub use options::{CliOptions, NuScript, Options};
use options_parser::{NuParser, OptionsParser};
use nu_command::{commands::NuSignature as Nu, utils::test_bins as binaries};
use nu_engine::{get_full_help, EvaluationContext};
use nu_errors::ShellError;
use nu_protocol::hir::{Call, Expression, SpannedExpression, Synthetic};
use nu_protocol::{Primitive, UntaggedValue};
use nu_source::{Span, Tag};
use nu_stream::InputStream;
pub struct App {
parser: Box<dyn OptionsParser>,
pub options: Options,
}
impl App {
pub fn new(parser: Box<dyn OptionsParser>, options: Options) -> Self {
Self { parser, options }
}
pub fn run(args: &[String]) -> Result<(), ShellError> {
let nu = Box::new(NuParser::new());
let options = Options::default();
let ui = App::new(nu, options);
ui.main(args)
}
pub fn main(&self, argv: &[String]) -> Result<(), ShellError> {
let argv = quote_positionals(argv).join(" ");
if let Err(cause) = self.parse(&argv) {
self.parser
.context()
.host()
.lock()
.print_err(cause, &nu_source::Text::from(argv));
std::process::exit(1);
}
if self.help() {
let context = self.parser.context();
let stream = nu_stream::OutputStream::one(
UntaggedValue::string(get_full_help(&Nu, &context.scope))
.into_value(nu_source::Tag::unknown()),
);
consume(context, stream)?;
std::process::exit(0);
}
if self.version() {
let context = self.parser.context();
let stream = nu_command::commands::version(nu_engine::CommandArgs {
context: context.clone(),
call_info: nu_engine::UnevaluatedCallInfo {
args: Call::new(
Box::new(SpannedExpression::new(
Expression::Synthetic(Synthetic::String("version".to_string())),
Span::unknown(),
)),
Span::unknown(),
),
name_tag: Tag::unknown(),
},
input: InputStream::empty(),
})?;
let stream = {
let command = context
.get_command("pivot")
.expect("could not find version command");
context.run_command(
command,
Tag::unknown(),
Call::new(
Box::new(SpannedExpression::new(
Expression::Synthetic(Synthetic::String("pivot".to_string())),
Span::unknown(),
)),
Span::unknown(),
),
stream,
)?
};
consume(context, stream)?;
std::process::exit(0);
}
if let Some(bin) = self.testbin() {
match bin.as_deref() {
Ok("echo_env") => binaries::echo_env(),
Ok("cococo") => binaries::cococo(),
Ok("meow") => binaries::meow(),
Ok("iecho") => binaries::iecho(),
Ok("fail") => binaries::fail(),
Ok("nonu") => binaries::nonu(),
Ok("chop") => binaries::chop(),
Ok("repeater") => binaries::repeater(),
_ => unreachable!(),
}
return Ok(());
}
let mut opts = CliOptions::new();
opts.config = self.config().map(std::ffi::OsString::from);
opts.stdin = self.takes_stdin();
opts.save_history = self.save_history();
use logger::{configure, debug_filters, logger, trace_filters};
logger(|builder| {
configure(&self, builder)?;
trace_filters(&self, builder)?;
debug_filters(&self, builder)?;
Ok(())
})?;
if let Some(commands) = self.commands() {
let commands = commands?;
let script = NuScript::code(&commands)?;
opts.scripts = vec![script];
let context = crate::create_default_context(false)?;
return crate::run_script_file(context, opts);
}
if let Some(scripts) = self.scripts() {
let mut source_files = vec![];
for script in scripts {
let script_name = script?;
let path = std::ffi::OsString::from(&script_name);
match NuScript::source_file(path.as_os_str()) {
Ok(file) => source_files.push(file),
Err(_) => {
eprintln!("File not found: {}", script_name);
return Ok(());
}
}
}
for file in source_files {
let mut opts = opts.clone();
opts.scripts = vec![file];
let context = crate::create_default_context(false)?;
crate::run_script_file(context, opts)?;
}
return Ok(());
}
let context = crate::create_default_context(true)?;
if !self.skip_plugins() {
let _ = crate::register_plugins(&context);
}
#[cfg(feature = "rustyline-support")]
{
crate::cli(context, opts)?;
}
#[cfg(not(feature = "rustyline-support"))]
{
println!("Nushell needs the 'rustyline-support' feature for CLI support");
}
Ok(())
}
pub fn commands(&self) -> Option<Result<String, ShellError>> {
self.options.get("commands").map(|v| match v.value {
UntaggedValue::Error(err) => Err(err),
UntaggedValue::Primitive(Primitive::String(name)) => Ok(name),
_ => Err(ShellError::untagged_runtime_error("Unsupported option")),
})
}
pub fn help(&self) -> bool {
self.options
.get("help")
.map(|v| matches!(v.as_bool(), Ok(true)))
.unwrap_or(false)
}
pub fn version(&self) -> bool {
self.options
.get("version")
.map(|v| matches!(v.as_bool(), Ok(true)))
.unwrap_or(false)
}
pub fn scripts(&self) -> Option<Vec<Result<String, ShellError>>> {
self.options.get("args").map(|v| {
v.table_entries()
.map(|v| match &v.value {
UntaggedValue::Error(err) => Err(err.clone()),
UntaggedValue::Primitive(Primitive::FilePath(path)) => {
Ok(path.display().to_string())
}
UntaggedValue::Primitive(Primitive::String(name)) => Ok(name.clone()),
_ => Err(ShellError::untagged_runtime_error("Unsupported option")),
})
.collect()
})
}
pub fn takes_stdin(&self) -> bool {
self.options
.get("stdin")
.map(|v| matches!(v.as_bool(), Ok(true)))
.unwrap_or(false)
}
pub fn config(&self) -> Option<String> {
self.options
.get("config-file")
.map(|v| v.as_string().expect("not a string"))
}
pub fn develop(&self) -> Option<Vec<Result<String, ShellError>>> {
self.options.get("develop").map(|v| {
let mut values = vec![];
match v.value {
UntaggedValue::Error(err) => values.push(Err(err)),
UntaggedValue::Primitive(Primitive::String(filters)) => {
values.extend(filters.split(',').map(|filter| Ok(filter.to_string())));
}
_ => values.push(Err(ShellError::untagged_runtime_error(
"Unsupported option",
))),
};
values
})
}
pub fn debug(&self) -> Option<Vec<Result<String, ShellError>>> {
self.options.get("debug").map(|v| {
let mut values = vec![];
match v.value {
UntaggedValue::Error(err) => values.push(Err(err)),
UntaggedValue::Primitive(Primitive::String(filters)) => {
values.extend(filters.split(',').map(|filter| Ok(filter.to_string())));
}
_ => values.push(Err(ShellError::untagged_runtime_error(
"Unsupported option",
))),
};
values
})
}
pub fn loglevel(&self) -> Option<Result<String, ShellError>> {
self.options.get("loglevel").map(|v| match v.value {
UntaggedValue::Error(err) => Err(err),
UntaggedValue::Primitive(Primitive::String(name)) => Ok(name),
_ => Err(ShellError::untagged_runtime_error("Unsupported option")),
})
}
pub fn testbin(&self) -> Option<Result<String, ShellError>> {
self.options.get("testbin").map(|v| match v.value {
UntaggedValue::Error(err) => Err(err),
UntaggedValue::Primitive(Primitive::String(name)) => Ok(name),
_ => Err(ShellError::untagged_runtime_error("Unsupported option")),
})
}
pub fn skip_plugins(&self) -> bool {
self.options
.get("skip-plugins")
.map(|v| matches!(v.as_bool(), Ok(true)))
.unwrap_or(false)
}
pub fn save_history(&self) -> bool {
self.options
.get("no-history")
.map(|v| !matches!(v.as_bool(), Ok(true)))
.unwrap_or(true)
}
pub fn parse(&self, args: &str) -> Result<(), ShellError> {
self.parser.parse(&args).map(|options| {
self.options.swap(&options);
})
}
}
fn quote_positionals(parameters: &[String]) -> Vec<String> {
parameters
.iter()
.cloned()
.map(|arg| {
if arg.contains(' ') {
format!("\"{}\"", arg)
} else {
arg
}
})
.collect::<Vec<_>>()
}
fn consume(context: &EvaluationContext, stream: InputStream) -> Result<(), ShellError> {
let autoview_cmd = context
.get_command("autoview")
.expect("could not find autoview command");
let stream = context.run_command(
autoview_cmd,
Tag::unknown(),
Call::new(
Box::new(SpannedExpression::new(
Expression::Synthetic(Synthetic::String("autoview".to_string())),
Span::unknown(),
)),
Span::unknown(),
),
stream,
)?;
for _ in stream {}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
fn cli_app() -> App {
let parser = Box::new(NuParser::new());
let options = Options::default();
App::new(parser, options)
}
#[test]
fn default_options() -> Result<(), ShellError> {
let ui = cli_app();
ui.parse("nu")?;
assert!(!ui.version());
assert!(!ui.help());
assert!(!ui.takes_stdin());
assert!(ui.save_history());
assert!(!ui.skip_plugins());
assert_eq!(ui.config(), None);
assert_eq!(ui.loglevel(), None);
assert_eq!(ui.debug(), None);
assert_eq!(ui.develop(), None);
assert_eq!(ui.testbin(), None);
assert_eq!(ui.commands(), None);
assert_eq!(ui.scripts(), None);
Ok(())
}
#[test]
fn reports_errors_on_unsupported_flags() -> Result<(), ShellError> {
let ui = cli_app();
assert!(ui.parse("nu --coonfig-file /path/to/config.toml").is_err());
assert!(ui.config().is_none());
Ok(())
}
#[test]
fn configures_debug_trace_level_with_filters() -> Result<(), ShellError> {
let ui = cli_app();
ui.parse("nu --develop=cli,parser")?;
assert_eq!(ui.develop().unwrap()[0], Ok("cli".to_string()));
assert_eq!(ui.develop().unwrap()[1], Ok("parser".to_string()));
Ok(())
}
#[test]
fn configures_debug_level_with_filters() -> Result<(), ShellError> {
let ui = cli_app();
ui.parse("nu --debug=cli,run")?;
assert_eq!(ui.debug().unwrap()[0], Ok("cli".to_string()));
assert_eq!(ui.debug().unwrap()[1], Ok("run".to_string()));
Ok(())
}
#[test]
fn can_use_loglevels() -> Result<(), ShellError> {
for level in &["error", "warn", "info", "debug", "trace"] {
let ui = cli_app();
let args = format!("nu --loglevel={}", *level);
ui.parse(&args)?;
assert_eq!(ui.loglevel().unwrap(), Ok(level.to_string()));
let ui = cli_app();
let args = format!("nu -l {}", *level);
ui.parse(&args)?;
assert_eq!(ui.loglevel().unwrap(), Ok(level.to_string()));
}
let ui = cli_app();
ui.parse("nu --loglevel=nada")?;
assert_eq!(
ui.loglevel().unwrap(),
Err(ShellError::untagged_runtime_error("nada is not supported."))
);
Ok(())
}
#[test]
fn can_be_passed_nu_scripts() -> Result<(), ShellError> {
let ui = cli_app();
ui.parse("nu code.nu bootstrap.nu")?;
assert_eq!(ui.scripts().unwrap()[0], Ok("code.nu".into()));
assert_eq!(ui.scripts().unwrap()[1], Ok("bootstrap.nu".into()));
Ok(())
}
#[test]
fn can_use_test_binaries() -> Result<(), ShellError> {
for binarie_name in &[
"echo_env", "cococo", "iecho", "fail", "nonu", "chop", "repeater", "meow",
] {
let ui = cli_app();
let args = format!("nu --testbin={}", *binarie_name);
ui.parse(&args)?;
assert_eq!(ui.testbin().unwrap(), Ok(binarie_name.to_string()));
}
let ui = cli_app();
ui.parse("nu --testbin=andres")?;
assert_eq!(
ui.testbin().unwrap(),
Err(ShellError::untagged_runtime_error(
"andres is not supported."
))
);
Ok(())
}
#[test]
fn has_version() -> Result<(), ShellError> {
let ui = cli_app();
ui.parse("nu --version")?;
assert!(ui.version());
Ok(())
}
#[test]
fn has_help() -> Result<(), ShellError> {
let ui = cli_app();
ui.parse("nu --help")?;
assert!(ui.help());
Ok(())
}
#[test]
fn can_take_stdin() -> Result<(), ShellError> {
let ui = cli_app();
ui.parse("nu --stdin")?;
assert!(ui.takes_stdin());
Ok(())
}
#[test]
fn can_opt_to_avoid_saving_history() -> Result<(), ShellError> {
let ui = cli_app();
ui.parse("nu --no-history")?;
assert!(!ui.save_history());
Ok(())
}
#[test]
fn can_opt_to_skip_plugins() -> Result<(), ShellError> {
let ui = cli_app();
ui.parse("nu --skip-plugins")?;
assert!(ui.skip_plugins());
Ok(())
}
#[test]
fn understands_commands_need_to_be_run() -> Result<(), ShellError> {
let ui = cli_app();
ui.parse("nu -c \"ls | get name\"")?;
assert_eq!(ui.commands().unwrap(), Ok(String::from("ls | get name")));
let ui = cli_app();
ui.parse("nu -c \"echo 'hola'\"")?;
assert_eq!(ui.commands().unwrap(), Ok(String::from("echo 'hola'")));
Ok(())
}
#[test]
fn knows_custom_configurations() -> Result<(), ShellError> {
let ui = cli_app();
ui.parse("nu --config-file /path/to/config.toml")?;
assert_eq!(ui.config().unwrap(), String::from("/path/to/config.toml"));
Ok(())
}
}

View File

@ -1,52 +0,0 @@
use super::App;
use log::LevelFilter;
use nu_errors::ShellError;
use pretty_env_logger::env_logger::Builder;
pub fn logger(f: impl FnOnce(&mut Builder) -> Result<(), ShellError>) -> Result<(), ShellError> {
let mut builder = pretty_env_logger::formatted_builder();
f(&mut builder)?;
let _ = builder.try_init();
Ok(())
}
pub fn configure(app: &App, logger: &mut Builder) -> Result<(), ShellError> {
if let Some(level) = app.loglevel() {
let level = match level.as_deref() {
Ok("error") => LevelFilter::Error,
Ok("warn") => LevelFilter::Warn,
Ok("info") => LevelFilter::Info,
Ok("debug") => LevelFilter::Debug,
Ok("trace") => LevelFilter::Trace,
Ok(_) | Err(_) => LevelFilter::Warn,
};
logger.filter_module("nu", level);
};
if let Ok(s) = std::env::var("RUST_LOG") {
logger.parse_filters(&s);
}
Ok(())
}
pub fn trace_filters(app: &App, logger: &mut Builder) -> Result<(), ShellError> {
if let Some(filters) = app.develop() {
filters.into_iter().filter_map(Result::ok).for_each(|name| {
logger.filter_module(&name, LevelFilter::Trace);
})
}
Ok(())
}
pub fn debug_filters(app: &App, logger: &mut Builder) -> Result<(), ShellError> {
if let Some(filters) = app.debug() {
filters.into_iter().filter_map(Result::ok).for_each(|name| {
logger.filter_module(&name, LevelFilter::Debug);
})
}
Ok(())
}

View File

@ -1,100 +0,0 @@
use indexmap::IndexMap;
use nu_errors::ShellError;
use nu_protocol::{UntaggedValue, Value};
use std::cell::RefCell;
use std::ffi::{OsStr, OsString};
#[derive(Debug, Clone)]
pub struct CliOptions {
pub config: Option<OsString>,
pub stdin: bool,
pub scripts: Vec<NuScript>,
pub save_history: bool,
}
impl Default for CliOptions {
fn default() -> Self {
Self::new()
}
}
impl CliOptions {
pub fn new() -> Self {
Self {
config: None,
stdin: false,
scripts: vec![],
save_history: true,
}
}
}
#[derive(Debug)]
pub struct Options {
inner: RefCell<IndexMap<String, Value>>,
}
impl Options {
pub fn default() -> Self {
Self {
inner: RefCell::new(IndexMap::default()),
}
}
pub fn get(&self, key: &str) -> Option<Value> {
self.inner.borrow().get(key).map(Clone::clone)
}
pub fn put(&self, key: &str, value: Value) {
self.inner.borrow_mut().insert(key.into(), value);
}
pub fn shift(&self) {
if let Some(Value {
value: UntaggedValue::Table(ref mut args),
..
}) = self.inner.borrow_mut().get_mut("args")
{
args.remove(0);
}
}
pub fn swap(&self, other: &Options) {
self.inner.swap(&other.inner);
}
}
#[derive(Debug, Clone)]
pub struct NuScript {
pub filepath: Option<OsString>,
pub contents: String,
}
impl NuScript {
pub fn code(content: &str) -> Result<Self, ShellError> {
Ok(Self {
filepath: None,
contents: content.to_string(),
})
}
pub fn get_code(&self) -> &str {
&self.contents
}
pub fn source_file(path: &OsStr) -> Result<Self, ShellError> {
use std::fs::File;
use std::io::Read;
let path = path.to_os_string();
let mut file = File::open(&path)?;
let mut buffer = String::new();
file.read_to_string(&mut buffer)?;
Ok(Self {
filepath: Some(path),
contents: buffer,
})
}
}

View File

@ -1,143 +0,0 @@
use super::Options;
use nu_command::commands::{loglevels, testbins, NuSignature as Nu};
use nu_command::commands::{Autoview, Pivot, Table, Version as NuVersion};
use nu_engine::{whole_stream_command, EvaluationContext};
use nu_errors::ShellError;
use nu_protocol::hir::{ClassifiedCommand, InternalCommand, NamedValue};
use nu_protocol::UntaggedValue;
use nu_source::Tag;
pub struct NuParser {
context: EvaluationContext,
}
pub trait OptionsParser {
fn parse(&self, input: &str) -> Result<Options, ShellError>;
fn context(&self) -> &EvaluationContext;
}
impl NuParser {
pub fn new() -> Self {
let context = EvaluationContext::basic();
context.add_commands(vec![
whole_stream_command(Nu {}),
whole_stream_command(NuVersion {}),
whole_stream_command(Autoview {}),
whole_stream_command(Pivot {}),
whole_stream_command(Table {}),
]);
Self { context }
}
}
impl OptionsParser for NuParser {
fn context(&self) -> &EvaluationContext {
&self.context
}
fn parse(&self, input: &str) -> Result<Options, ShellError> {
let options = Options::default();
let (lite_result, _err) = nu_parser::lex(input, 0, nu_parser::NewlineMode::Normal);
let (lite_result, _err) = nu_parser::parse_block(lite_result);
let (parsed, err) = nu_parser::classify_block(&lite_result, &self.context.scope);
if let Some(reason) = err {
return Err(reason.into());
}
match parsed.block[0].pipelines[0].list[0] {
ClassifiedCommand::Internal(InternalCommand { ref args, .. }) => {
if let Some(ref params) = args.named {
params.iter().for_each(|(k, v)| {
let value = match v {
NamedValue::AbsentSwitch => {
Some(UntaggedValue::from(false).into_untagged_value())
}
NamedValue::PresentSwitch(span) => {
Some(UntaggedValue::from(true).into_value(Tag::from(span)))
}
NamedValue::AbsentValue => None,
NamedValue::Value(span, exprs) => {
let value = nu_engine::evaluate_baseline_expr(exprs, &self.context)
.expect("value");
Some(value.value.into_value(Tag::from(span)))
}
};
let value =
value
.map(|v| match k.as_ref() {
"testbin" => {
if let Ok(name) = v.as_string() {
if testbins().iter().any(|n| name == *n) {
Some(v)
} else {
Some(
UntaggedValue::Error(
ShellError::untagged_runtime_error(
format!("{} is not supported.", name),
),
)
.into_value(v.tag),
)
}
} else {
Some(v)
}
}
"loglevel" => {
if let Ok(name) = v.as_string() {
if loglevels().iter().any(|n| name == *n) {
Some(v)
} else {
Some(
UntaggedValue::Error(
ShellError::untagged_runtime_error(
format!("{} is not supported.", name),
),
)
.into_value(v.tag),
)
}
} else {
Some(v)
}
}
_ => Some(v),
})
.flatten();
if let Some(value) = value {
options.put(&k, value);
}
});
}
let mut positional_args = vec![];
if let Some(positional) = &args.positional {
for pos in positional {
let result = nu_engine::evaluate_baseline_expr(pos, &self.context)?;
positional_args.push(result);
}
}
if !positional_args.is_empty() {
options.put(
"args",
UntaggedValue::Table(positional_args).into_untagged_value(),
);
}
}
ClassifiedCommand::Error(ref reason) => {
return Err(reason.clone().into());
}
_ => return Err(ShellError::untagged_runtime_error("unrecognized command")),
}
Ok(options)
}
}

View File

@ -1,458 +0,0 @@
use crate::line_editor::configure_ctrl_c;
use nu_ansi_term::Color;
use nu_engine::{maybe_print_errors, run_block, script::run_script_standalone, EvaluationContext};
#[allow(unused_imports)]
pub(crate) use nu_engine::script::{process_script, LineResult};
#[cfg(feature = "rustyline-support")]
use crate::line_editor::{
configure_rustyline_editor, convert_rustyline_result_to_string,
default_rustyline_editor_configuration, nu_line_editor_helper,
};
#[allow(unused_imports)]
use nu_data::config;
use nu_source::{Tag, Text};
use nu_stream::InputStream;
#[allow(unused_imports)]
use std::sync::atomic::Ordering;
#[cfg(feature = "rustyline-support")]
use rustyline::{self, error::ReadlineError};
use nu_errors::ShellError;
use nu_parser::ParserScope;
use nu_protocol::{hir::ExternalRedirection, ConfigPath, UntaggedValue, Value};
use log::trace;
use std::error::Error;
use std::iter::Iterator;
use std::path::PathBuf;
pub fn search_paths() -> Vec<std::path::PathBuf> {
use std::env;
let mut search_paths = Vec::new();
// Automatically add path `nu` is in as a search path
if let Ok(exe_path) = env::current_exe() {
if let Some(exe_dir) = exe_path.parent() {
search_paths.push(exe_dir.to_path_buf());
}
}
if let Ok(config) = nu_data::config::config(Tag::unknown()) {
if let Some(Value {
value: UntaggedValue::Table(pipelines),
..
}) = config.get("plugin_dirs")
{
for pipeline in pipelines {
if let Ok(plugin_dir) = pipeline.as_string() {
search_paths.push(PathBuf::from(plugin_dir));
}
}
}
}
search_paths
}
pub fn run_script_file(
context: EvaluationContext,
options: super::app::CliOptions,
) -> Result<(), ShellError> {
if let Some(cfg) = options.config {
load_cfg_as_global_cfg(&context, PathBuf::from(cfg));
} else {
load_global_cfg(&context);
}
let _ = register_plugins(&context);
let _ = configure_ctrl_c(&context);
let script = options
.scripts
.get(0)
.ok_or_else(|| ShellError::unexpected("Nu source code not available"))?;
run_script_standalone(script.get_code().to_string(), options.stdin, &context, true)?;
Ok(())
}
#[cfg(feature = "rustyline-support")]
pub fn cli(
context: EvaluationContext,
options: super::app::CliOptions,
) -> Result<(), Box<dyn Error>> {
let _ = configure_ctrl_c(&context);
// start time for running startup scripts (this metric includes loading of the cfg, but w/e)
let startup_commands_start_time = std::time::Instant::now();
if let Some(cfg) = options.config {
load_cfg_as_global_cfg(&context, PathBuf::from(cfg));
} else {
load_global_cfg(&context);
}
// Store cmd duration in an env var
context.scope.add_env_var(
"CMD_DURATION_MS",
format!("{}", startup_commands_start_time.elapsed().as_millis()),
);
trace!(
"startup commands took {:?}",
startup_commands_start_time.elapsed()
);
//Configure rustyline
let mut rl = default_rustyline_editor_configuration();
let history_path = if let Some(cfg) = &context.configs().lock().global_config {
let _ = configure_rustyline_editor(&mut rl, cfg);
let helper = Some(nu_line_editor_helper(&context, cfg));
rl.set_helper(helper);
nu_data::config::path::history_path_or_default(cfg)
} else {
nu_data::config::path::default_history_path()
};
// Don't load history if it's not necessary
if options.save_history {
let _ = rl.load_history(&history_path);
}
//set vars from cfg if present
let (skip_welcome_message, prompt) = if let Some(cfg) = &context.configs().lock().global_config
{
(
cfg.var("skip_welcome_message")
.map(|x| x.is_true())
.unwrap_or(false),
cfg.var("prompt"),
)
} else {
(false, None)
};
//Check whether dir we start in contains local cfg file and if so load it.
load_local_cfg_if_present(&context);
// Give ourselves a scope to work in
context.scope.enter_scope();
let mut session_text = String::new();
let mut line_start: usize = 0;
if !skip_welcome_message {
println!(
"Welcome to Nushell {} (type 'help' for more info)",
nu_command::commands::core_version()
);
}
#[cfg(windows)]
{
let _ = nu_ansi_term::enable_ansi_support();
}
let mut ctrlcbreak = false;
loop {
if context.ctrl_c().load(Ordering::SeqCst) {
context.ctrl_c().store(false, Ordering::SeqCst);
continue;
}
let cwd = context.shell_manager().path();
let colored_prompt = {
if let Some(prompt) = &prompt {
let prompt_line = prompt.as_string()?;
context.scope.enter_scope();
let (prompt_block, err) = nu_parser::parse(&prompt_line, 0, &context.scope);
if err.is_some() {
context.scope.exit_scope();
format!(
"{}{}{}{}{}{}> ",
Color::Green.bold().prefix().to_string(),
cwd,
nu_ansi_term::ansi::RESET,
Color::Cyan.bold().prefix().to_string(),
current_branch(),
nu_ansi_term::ansi::RESET
)
} else {
let run_result = run_block(
&prompt_block,
&context,
InputStream::empty(),
ExternalRedirection::Stdout,
);
context.scope.exit_scope();
match run_result {
Ok(result) => match result.collect_string(Tag::unknown()) {
Ok(string_result) => {
let errors = context.get_errors();
maybe_print_errors(&context, Text::from(prompt_line));
context.clear_errors();
if !errors.is_empty() {
"> ".to_string()
} else {
string_result.item
}
}
Err(e) => {
context.host().lock().print_err(e, &Text::from(prompt_line));
context.clear_errors();
"> ".to_string()
}
},
Err(e) => {
context.host().lock().print_err(e, &Text::from(prompt_line));
context.clear_errors();
"> ".to_string()
}
}
}
} else {
format!(
"{}{}{}{}{}{}> ",
Color::Green.bold().prefix().to_string(),
cwd,
nu_ansi_term::ansi::RESET,
Color::Cyan.bold().prefix().to_string(),
current_branch(),
nu_ansi_term::ansi::RESET
)
}
};
let prompt = {
if let Ok(bytes) = strip_ansi_escapes::strip(&colored_prompt) {
String::from_utf8_lossy(&bytes).to_string()
} else {
"> ".to_string()
}
};
if let Some(helper) = rl.helper_mut() {
helper.colored_prompt = colored_prompt;
}
let mut initial_command = Some(String::new());
let mut readline = Err(ReadlineError::Eof);
while let Some(ref cmd) = initial_command {
readline = rl.readline_with_initial(&prompt, (cmd, ""));
initial_command = None;
}
if let Ok(line) = &readline {
line_start = session_text.len();
session_text.push_str(line);
session_text.push('\n');
}
// start time for command duration
let cmd_start_time = std::time::Instant::now();
let line = match convert_rustyline_result_to_string(readline) {
LineResult::Success(_) => process_script(
&session_text[line_start..],
&context,
false,
line_start,
true,
),
x => x,
};
// Store cmd duration in an env var
context.scope.add_env_var(
"CMD_DURATION_MS",
format!("{}", cmd_start_time.elapsed().as_millis()),
);
match line {
LineResult::Success(line) => {
if options.save_history && !line.trim().is_empty() {
rl.add_history_entry(&line);
let _ = rl.append_history(&history_path);
}
maybe_print_errors(&context, Text::from(session_text.clone()));
}
LineResult::ClearHistory => {
if options.save_history {
rl.clear_history();
let _ = rl.append_history(&history_path);
}
}
LineResult::Error(line, err) => {
if options.save_history && !line.trim().is_empty() {
rl.add_history_entry(&line);
let _ = rl.append_history(&history_path);
}
context
.host()
.lock()
.print_err(err, &Text::from(session_text.clone()));
// I am not so sure, we don't need maybe_print_errors here (as we printed an err
// above), because maybe_print_errors also clears the errors.
// TODO Analyze where above err comes from, and whether we need to clear
// context.errors here
// Or just be consistent and return errors always in context.errors...
maybe_print_errors(&context, Text::from(session_text.clone()));
}
LineResult::CtrlC => {
let config_ctrlc_exit = context
.configs()
.lock()
.global_config
.as_ref()
.map(|cfg| cfg.var("ctrlc_exit"))
.flatten()
.map(|ctrl_c| ctrl_c.is_true())
.unwrap_or(false); // default behavior is to allow CTRL-C spamming similar to other shells
if !config_ctrlc_exit {
continue;
}
if ctrlcbreak {
if options.save_history {
let _ = rl.append_history(&history_path);
}
std::process::exit(0);
} else {
context.with_host(|host| host.stdout("CTRL-C pressed (again to quit)"));
ctrlcbreak = true;
continue;
}
}
LineResult::CtrlD => {
context.shell_manager().remove_at_current();
if context.shell_manager().is_empty() {
break;
}
}
LineResult::Break => {
break;
}
}
ctrlcbreak = false;
}
// we are ok if we can not save history
if options.save_history {
let _ = rl.append_history(&history_path);
}
Ok(())
}
pub fn load_local_cfg_if_present(context: &EvaluationContext) {
trace!("Loading local cfg if present");
match config::loadable_cfg_exists_in_dir(PathBuf::from(context.shell_manager().path())) {
Ok(Some(cfg_path)) => {
if let Err(err) = context.load_config(&ConfigPath::Local(cfg_path)) {
context.host().lock().print_err(err, &Text::from(""))
}
}
Err(e) => {
//Report error while checking for local cfg file
context.host().lock().print_err(e, &Text::from(""))
}
Ok(None) => {
//No local cfg file present in start dir
}
}
}
fn load_cfg_as_global_cfg(context: &EvaluationContext, path: PathBuf) {
if let Err(err) = context.load_config(&ConfigPath::Global(path)) {
context.host().lock().print_err(err, &Text::from(""));
}
}
pub fn load_global_cfg(context: &EvaluationContext) {
match config::default_path() {
Ok(path) => {
load_cfg_as_global_cfg(context, path);
}
Err(e) => {
context.host().lock().print_err(e, &Text::from(""));
}
}
}
pub fn register_plugins(context: &EvaluationContext) -> Result<(), ShellError> {
if let Ok(plugins) = nu_engine::plugin::build_plugin::scan(search_paths()) {
context.add_commands(
plugins
.into_iter()
.filter(|p| !context.is_command_registered(p.name()))
.collect(),
);
}
Ok(())
}
pub fn parse_and_eval(line: &str, ctx: &EvaluationContext) -> Result<String, ShellError> {
// FIXME: do we still need this?
let line = if let Some(s) = line.strip_suffix('\n') {
s
} else {
line
};
// TODO ensure the command whose examples we're testing is actually in the pipeline
ctx.scope.enter_scope();
let (classified_block, err) = nu_parser::parse(line, 0, &ctx.scope);
if let Some(err) = err {
ctx.scope.exit_scope();
return Err(err.into());
}
let input_stream = InputStream::empty();
let result = run_block(
&classified_block,
ctx,
input_stream,
ExternalRedirection::Stdout,
);
ctx.scope.exit_scope();
result?.collect_string(Tag::unknown()).map(|x| x.item)
}
#[allow(dead_code)]
fn current_branch() -> String {
#[cfg(feature = "shadow-rs")]
{
Some(shadow_rs::branch())
.map(|x| x.trim().to_string())
.filter(|x| !x.is_empty())
.map(|x| format!("({})", x))
.unwrap_or_default()
}
#[cfg(not(feature = "shadow-rs"))]
{
"".to_string()
}
}

View File

@ -0,0 +1,94 @@
use crate::util::report_error;
use log::info;
use miette::Result;
use nu_engine::{convert_env_values, eval_block};
use nu_parser::parse;
use nu_protocol::engine::Stack;
use nu_protocol::{
engine::{EngineState, StateDelta, StateWorkingSet},
PipelineData, Spanned, Value,
};
use std::path::Path;
pub fn evaluate_commands(
commands: &Spanned<String>,
init_cwd: &Path,
engine_state: &mut EngineState,
stack: &mut Stack,
input: PipelineData,
is_perf_true: bool,
table_mode: Option<Value>,
) -> Result<()> {
// Run a command (or commands) given to us by the user
let (block, delta) = {
if let Some(ref t_mode) = table_mode {
let mut config = engine_state.get_config().clone();
config.table_mode = t_mode.as_string()?;
engine_state.set_config(&config);
}
let mut working_set = StateWorkingSet::new(engine_state);
let (output, err) = parse(&mut working_set, None, commands.item.as_bytes(), false, &[]);
if let Some(err) = err {
report_error(&working_set, &err);
std::process::exit(1);
}
(output, working_set.render())
};
if let Err(err) = engine_state.merge_delta(delta, None, init_cwd) {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &err);
}
let mut config = engine_state.get_config().clone();
if let Some(t_mode) = table_mode {
config.table_mode = t_mode.as_string()?;
}
// Merge the delta in case env vars changed in the config
match nu_engine::env::current_dir(engine_state, stack) {
Ok(cwd) => {
if let Err(e) =
engine_state.merge_delta(StateDelta::new(engine_state), Some(stack), cwd)
{
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &e);
std::process::exit(1);
}
}
Err(e) => {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &e);
std::process::exit(1);
}
}
// Translate environment variables from Strings to Values
if let Some(e) = convert_env_values(engine_state, stack) {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &e);
std::process::exit(1);
}
match eval_block(engine_state, stack, &block, input, false, false) {
Ok(pipeline_data) => {
crate::eval_file::print_table_or_error(engine_state, stack, pipeline_data, &mut config)
}
Err(err) => {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &err);
std::process::exit(1);
}
}
if is_perf_true {
info!("evaluate {}:{}:{}", file!(), line!(), column!());
}
Ok(())
}

View File

@ -0,0 +1,43 @@
use crate::completions::{CompletionOptions, SortBy};
use nu_protocol::{engine::StateWorkingSet, levenshtein_distance, Span};
use reedline::Suggestion;
// Completer trait represents the three stages of the completion
// fetch, filter and sort
pub trait Completer {
fn fetch(
&mut self,
working_set: &StateWorkingSet,
prefix: Vec<u8>,
span: Span,
offset: usize,
pos: usize,
options: &CompletionOptions,
) -> Vec<Suggestion>;
fn get_sort_by(&self) -> SortBy {
SortBy::Ascending
}
fn sort(&self, items: Vec<Suggestion>, prefix: Vec<u8>) -> Vec<Suggestion> {
let prefix_str = String::from_utf8_lossy(&prefix).to_string();
let mut filtered_items = items;
// Sort items
match self.get_sort_by() {
SortBy::LevenshteinDistance => {
filtered_items.sort_by(|a, b| {
let a_distance = levenshtein_distance(&prefix_str, &a.value);
let b_distance = levenshtein_distance(&prefix_str, &b.value);
a_distance.cmp(&b_distance)
});
}
SortBy::Ascending => {
filtered_items.sort_by(|a, b| a.value.cmp(&b.value));
}
SortBy::None => {}
};
filtered_items
}
}

View File

@ -0,0 +1,228 @@
use crate::completions::{Completer, CompletionOptions, MatchAlgorithm, SortBy};
use nu_parser::FlatShape;
use nu_protocol::{
engine::{EngineState, StateWorkingSet},
Span,
};
use reedline::Suggestion;
use std::sync::Arc;
pub struct CommandCompletion {
engine_state: Arc<EngineState>,
flattened: Vec<(Span, FlatShape)>,
flat_shape: FlatShape,
}
impl CommandCompletion {
pub fn new(
engine_state: Arc<EngineState>,
_: &StateWorkingSet,
flattened: Vec<(Span, FlatShape)>,
flat_shape: FlatShape,
) -> Self {
Self {
engine_state,
flattened,
flat_shape,
}
}
fn external_command_completion(
&self,
prefix: &str,
match_algorithm: MatchAlgorithm,
) -> Vec<String> {
let mut executables = vec![];
let paths = self.engine_state.get_env_var("PATH");
if let Some(paths) = paths {
if let Ok(paths) = paths.as_list() {
for path in paths {
let path = path.as_string().unwrap_or_default();
if let Ok(mut contents) = std::fs::read_dir(path) {
while let Some(Ok(item)) = contents.next() {
if !executables.contains(
&item
.path()
.file_name()
.map(|x| x.to_string_lossy().to_string())
.unwrap_or_default(),
) && matches!(
item.path()
.file_name()
.map(|x| match_algorithm
.matches_str(&x.to_string_lossy(), prefix)),
Some(true)
) && is_executable::is_executable(&item.path())
{
if let Ok(name) = item.file_name().into_string() {
executables.push(name);
}
}
}
}
}
}
}
executables
}
fn complete_commands(
&self,
working_set: &StateWorkingSet,
span: Span,
offset: usize,
find_externals: bool,
match_algorithm: MatchAlgorithm,
) -> Vec<Suggestion> {
let partial = working_set.get_span_contents(span);
let filter_predicate = |command: &[u8]| match_algorithm.matches_u8(command, partial);
let results = working_set
.find_commands_by_predicate(filter_predicate)
.into_iter()
.map(move |x| Suggestion {
value: String::from_utf8_lossy(&x.0).to_string(),
description: x.1,
extra: None,
span: reedline::Span {
start: span.start - offset,
end: span.end - offset,
},
append_whitespace: true,
});
let results_aliases = working_set
.find_aliases_by_predicate(filter_predicate)
.into_iter()
.map(move |x| Suggestion {
value: String::from_utf8_lossy(&x).to_string(),
description: None,
extra: None,
span: reedline::Span {
start: span.start - offset,
end: span.end - offset,
},
append_whitespace: true,
});
let mut results = results.chain(results_aliases).collect::<Vec<_>>();
let partial = working_set.get_span_contents(span);
let partial = String::from_utf8_lossy(partial).to_string();
let results = if find_externals {
let results_external = self
.external_command_completion(&partial, match_algorithm)
.into_iter()
.map(move |x| Suggestion {
value: x,
description: None,
extra: None,
span: reedline::Span {
start: span.start - offset,
end: span.end - offset,
},
append_whitespace: true,
});
for external in results_external {
if results.contains(&external) {
results.push(Suggestion {
value: format!("^{}", external.value),
description: None,
extra: None,
span: external.span,
append_whitespace: true,
})
} else {
results.push(external)
}
}
results
} else {
results
};
results
}
}
impl Completer for CommandCompletion {
fn fetch(
&mut self,
working_set: &StateWorkingSet,
_prefix: Vec<u8>,
span: Span,
offset: usize,
pos: usize,
options: &CompletionOptions,
) -> Vec<Suggestion> {
let last = self
.flattened
.iter()
.rev()
.skip_while(|x| x.0.end > pos)
.take_while(|x| {
matches!(
x.1,
FlatShape::InternalCall
| FlatShape::External
| FlatShape::ExternalArg
| FlatShape::Literal
| FlatShape::String
)
})
.last();
// The last item here would be the earliest shape that could possible by part of this subcommand
let subcommands = if let Some(last) = last {
self.complete_commands(
working_set,
Span {
start: last.0.start,
end: pos,
},
offset,
false,
options.match_algorithm,
)
} else {
vec![]
};
if !subcommands.is_empty() {
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,
config.enable_external_completion,
options.match_algorithm,
)
} else {
vec![]
};
subcommands
.into_iter()
.chain(commands.into_iter())
.collect::<Vec<_>>()
}
fn get_sort_by(&self) -> SortBy {
SortBy::LevenshteinDistance
}
}

View File

@ -0,0 +1,354 @@
use crate::completions::{
CommandCompletion, Completer, CompletionOptions, CustomCompletion, DirectoryCompletion,
DotNuCompletion, FileCompletion, FlagCompletion, MatchAlgorithm, VariableCompletion,
};
use nu_parser::{flatten_expression, parse, FlatShape};
use nu_protocol::{
engine::{EngineState, Stack, StateWorkingSet},
Span,
};
use reedline::{Completer as ReedlineCompleter, Suggestion};
use std::str;
use std::sync::Arc;
#[derive(Clone)]
pub struct NuCompleter {
engine_state: Arc<EngineState>,
stack: Stack,
}
impl NuCompleter {
pub fn new(engine_state: Arc<EngineState>, stack: Stack) -> Self {
Self {
engine_state,
stack,
}
}
// Process the completion for a given completer
fn process_completion<T: Completer>(
&self,
completer: &mut T,
working_set: &StateWorkingSet,
prefix: Vec<u8>,
new_span: Span,
offset: usize,
pos: usize,
) -> Vec<Suggestion> {
let config = self.engine_state.get_config();
let mut options = CompletionOptions {
case_sensitive: config.case_sensitive_completions,
..Default::default()
};
if config.completion_algorithm == "fuzzy" {
options.match_algorithm = MatchAlgorithm::Fuzzy;
}
// Fetch
let mut suggestions =
completer.fetch(working_set, prefix.clone(), new_span, offset, pos, &options);
// Sort
suggestions = completer.sort(suggestions, prefix);
suggestions
}
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();
new_line.push(b'a');
let pos = offset + pos;
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() {
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 = 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 - alias));
// Completions that depends on the previous expression (e.g: use, source)
if flat_idx > 0 {
if let Some(previous_expr) = flattened.get(flat_idx - 1) {
// Read the content for the previous expression
let prev_expr_str =
working_set.get_span_contents(previous_expr.0).to_vec();
// Completion for .nu files
if prev_expr_str == b"use" || prev_expr_str == b"source" {
let mut completer =
DotNuCompletion::new(self.engine_state.clone());
return self.process_completion(
&mut completer,
&working_set,
prefix,
new_span,
offset,
pos,
);
}
}
}
// Variables completion
if prefix.starts_with(b"$") || most_left_var.is_some() {
let mut completer = VariableCompletion::new(
self.engine_state.clone(),
self.stack.clone(),
most_left_var.unwrap_or((vec![], vec![])),
);
return self.process_completion(
&mut completer,
&working_set,
prefix,
new_span,
offset,
pos,
);
}
// Flags completion
if prefix.starts_with(b"-") {
let mut completer = FlagCompletion::new(expr);
return self.process_completion(
&mut completer,
&working_set,
prefix,
new_span,
offset,
pos,
);
}
// Match other types
match &flat.1 {
FlatShape::Custom(decl_id) => {
let mut completer = CustomCompletion::new(
self.engine_state.clone(),
self.stack.clone(),
*decl_id,
initial_line,
);
return self.process_completion(
&mut completer,
&working_set,
prefix,
new_span,
offset,
pos,
);
}
FlatShape::Directory => {
let mut completer =
DirectoryCompletion::new(self.engine_state.clone());
return self.process_completion(
&mut completer,
&working_set,
prefix,
new_span,
offset,
pos,
);
}
flat_shape => {
let mut completer = CommandCompletion::new(
self.engine_state.clone(),
&working_set,
flattened.clone(),
// flat_idx,
flat_shape.clone(),
);
let out: Vec<_> = self.process_completion(
&mut completer,
&working_set,
prefix.clone(),
new_span,
offset,
pos,
);
if out.is_empty() {
let mut completer =
FileCompletion::new(self.engine_state.clone());
return self.process_completion(
&mut completer,
&working_set,
prefix,
new_span,
offset,
pos,
);
}
return out;
}
};
}
}
}
}
return vec![];
}
}
impl ReedlineCompleter for NuCompleter {
fn complete(&mut self, line: &str, pos: usize) -> Vec<Suggestion> {
self.completion_helper(line, pos)
}
}
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(
idx: usize,
working_set: &StateWorkingSet<'_>,
flattened: Vec<(Span, FlatShape)>,
) -> Option<(Vec<u8>, Vec<Vec<u8>>)> {
// Reverse items to read the list backwards and truncate
// because the only items that matters are the ones before the current index
let mut rev = flattened;
rev.truncate(idx);
rev = rev.into_iter().rev().collect();
// Store the variables and sub levels found and reverse to correct order
let mut variables_found: Vec<Vec<u8>> = vec![];
let mut found_var = false;
for item in rev.clone() {
let result = working_set.get_span_contents(item.0).to_vec();
match item.1 {
FlatShape::Variable => {
variables_found.push(result);
found_var = true;
break;
}
FlatShape::String => {
variables_found.push(result);
}
_ => {
break;
}
}
}
// If most left var was not found
if !found_var {
return None;
}
// Reverse the order back
variables_found = variables_found.into_iter().rev().collect();
// Extract the variable and the sublevels
let var = variables_found.first().unwrap_or(&vec![]).to_vec();
let sublevels: Vec<Vec<u8>> = variables_found.into_iter().skip(1).collect();
Some((var, sublevels))
}

View File

@ -0,0 +1,137 @@
use std::fmt::Display;
use fuzzy_matcher::{skim::SkimMatcherV2, FuzzyMatcher};
use nu_parser::trim_quotes_str;
#[derive(Copy, Clone)]
pub enum SortBy {
LevenshteinDistance,
Ascending,
None,
}
/// Describes how suggestions should be matched.
#[derive(Copy, Clone, Debug)]
pub enum MatchAlgorithm {
/// Only show suggestions which begin with the given input
///
/// Example:
/// "git switch" is matched by "git sw"
Prefix,
/// Only show suggestions which contain the input chars at any place
///
/// Example:
/// "git checkout" is matched by "gco"
Fuzzy,
}
impl MatchAlgorithm {
/// Returns whether the `needle` search text matches the given `haystack`.
pub fn matches_str(&self, haystack: &str, needle: &str) -> bool {
let haystack = trim_quotes_str(haystack);
let needle = trim_quotes_str(needle);
match *self {
MatchAlgorithm::Prefix => haystack.starts_with(needle),
MatchAlgorithm::Fuzzy => {
let matcher = SkimMatcherV2::default();
matcher.fuzzy_match(haystack, needle).is_some()
}
}
}
/// Returns whether the `needle` search text matches the given `haystack`.
pub fn matches_u8(&self, haystack: &[u8], needle: &[u8]) -> bool {
match *self {
MatchAlgorithm::Prefix => haystack.starts_with(needle),
MatchAlgorithm::Fuzzy => {
let haystack_str = String::from_utf8_lossy(haystack);
let needle_str = String::from_utf8_lossy(needle);
let matcher = SkimMatcherV2::default();
matcher.fuzzy_match(&haystack_str, &needle_str).is_some()
}
}
}
}
impl TryFrom<String> for MatchAlgorithm {
type Error = InvalidMatchAlgorithm;
fn try_from(value: String) -> Result<Self, Self::Error> {
match value.as_str() {
"prefix" => Ok(Self::Prefix),
"fuzzy" => Ok(Self::Fuzzy),
_ => Err(InvalidMatchAlgorithm::Unknown),
}
}
}
#[derive(Debug)]
pub enum InvalidMatchAlgorithm {
Unknown,
}
impl Display for InvalidMatchAlgorithm {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match *self {
InvalidMatchAlgorithm::Unknown => write!(f, "unknown match algorithm"),
}
}
}
impl std::error::Error for InvalidMatchAlgorithm {}
#[derive(Clone)]
pub struct CompletionOptions {
pub case_sensitive: bool,
pub positional: bool,
pub sort_by: SortBy,
pub match_algorithm: MatchAlgorithm,
}
impl Default for CompletionOptions {
fn default() -> Self {
Self {
case_sensitive: true,
positional: true,
sort_by: SortBy::Ascending,
match_algorithm: MatchAlgorithm::Prefix,
}
}
}
#[cfg(test)]
mod test {
use super::MatchAlgorithm;
#[test]
fn match_algorithm_prefix() {
let algorithm = MatchAlgorithm::Prefix;
assert!(algorithm.matches_str("example text", ""));
assert!(algorithm.matches_str("example text", "examp"));
assert!(!algorithm.matches_str("example text", "text"));
assert!(algorithm.matches_u8(&[1, 2, 3], &[]));
assert!(algorithm.matches_u8(&[1, 2, 3], &[1, 2]));
assert!(!algorithm.matches_u8(&[1, 2, 3], &[2, 3]));
}
#[test]
fn match_algorithm_fuzzy() {
let algorithm = MatchAlgorithm::Fuzzy;
assert!(algorithm.matches_str("example text", ""));
assert!(algorithm.matches_str("example text", "examp"));
assert!(algorithm.matches_str("example text", "ext"));
assert!(algorithm.matches_str("example text", "mplxt"));
assert!(!algorithm.matches_str("example text", "mpp"));
assert!(algorithm.matches_u8(&[1, 2, 3], &[]));
assert!(algorithm.matches_u8(&[1, 2, 3], &[1, 2]));
assert!(algorithm.matches_u8(&[1, 2, 3], &[2, 3]));
assert!(algorithm.matches_u8(&[1, 2, 3], &[1, 3]));
assert!(!algorithm.matches_u8(&[1, 2, 3], &[2, 2]));
}
}

View File

@ -0,0 +1,233 @@
use crate::completions::{Completer, CompletionOptions, MatchAlgorithm, SortBy};
use nu_engine::eval_call;
use nu_protocol::{
ast::{Argument, Call, Expr, Expression},
engine::{EngineState, Stack, StateWorkingSet},
PipelineData, Span, Type, Value,
};
use reedline::Suggestion;
use std::sync::Arc;
pub struct CustomCompletion {
engine_state: Arc<EngineState>,
stack: Stack,
decl_id: usize,
line: String,
sort_by: SortBy,
}
impl CustomCompletion {
pub fn new(engine_state: Arc<EngineState>, stack: Stack, decl_id: usize, line: String) -> Self {
Self {
engine_state,
stack,
decl_id,
line,
sort_by: SortBy::None,
}
}
fn map_completions<'a>(
&self,
list: impl Iterator<Item = &'a Value>,
span: Span,
offset: usize,
) -> Vec<Suggestion> {
list.filter_map(move |x| {
// Match for string values
if let Ok(s) = x.as_string() {
return Some(Suggestion {
value: s,
description: None,
extra: None,
span: reedline::Span {
start: span.start - offset,
end: span.end - offset,
},
append_whitespace: false,
});
}
// Match for record values
if let Ok((cols, vals)) = x.as_record() {
let mut suggestion = Suggestion {
value: String::from(""), // Initialize with empty string
description: None,
extra: None,
span: reedline::Span {
start: span.start - offset,
end: span.end - offset,
},
append_whitespace: false,
};
// Iterate the cols looking for `value` and `description`
cols.iter().zip(vals).for_each(|it| {
// Match `value` column
if it.0 == "value" {
// Convert the value to string
if let Ok(val_str) = it.1.as_string() {
// Update the suggestion value
suggestion.value = val_str;
}
}
// Match `description` column
if it.0 == "description" {
// Convert the value to string
if let Ok(desc_str) = it.1.as_string() {
// Update the suggestion value
suggestion.description = Some(desc_str);
}
}
});
return Some(suggestion);
}
None
})
.collect()
}
}
impl Completer for CustomCompletion {
fn fetch(
&mut self,
_: &StateWorkingSet,
prefix: Vec<u8>,
span: Span,
offset: usize,
pos: usize,
completion_options: &CompletionOptions,
) -> Vec<Suggestion> {
// Line position
let line_pos = pos - offset;
// Call custom declaration
let result = eval_call(
&self.engine_state,
&mut self.stack,
&Call {
decl_id: self.decl_id,
head: span,
arguments: vec![
Argument::Positional(Expression {
span: Span { start: 0, end: 0 },
ty: Type::String,
expr: Expr::String(self.line.clone()),
custom_completion: None,
}),
Argument::Positional(Expression {
span: Span { start: 0, end: 0 },
ty: Type::Int,
expr: Expr::Int(line_pos as i64),
custom_completion: None,
}),
],
redirect_stdout: true,
redirect_stderr: true,
},
PipelineData::new(span),
);
let mut custom_completion_options = None;
// Parse result
let suggestions = match result {
Ok(pd) => {
let value = pd.into_value(span);
match &value {
Value::Record { .. } => {
let completions = value
.get_data_by_key("completions")
.and_then(|val| {
val.as_list()
.ok()
.map(|it| self.map_completions(it.iter(), span, offset))
})
.unwrap_or_default();
let options = value.get_data_by_key("options");
if let Some(Value::Record { .. }) = &options {
let options = options.unwrap_or_default();
let should_sort = options
.get_data_by_key("sort")
.and_then(|val| val.as_bool().ok())
.unwrap_or(false);
if should_sort {
self.sort_by = SortBy::Ascending;
}
custom_completion_options = Some(CompletionOptions {
case_sensitive: options
.get_data_by_key("case_sensitive")
.and_then(|val| val.as_bool().ok())
.unwrap_or(true),
positional: options
.get_data_by_key("positional")
.and_then(|val| val.as_bool().ok())
.unwrap_or(true),
sort_by: if should_sort {
SortBy::Ascending
} else {
SortBy::None
},
match_algorithm: match options
.get_data_by_key("completion_algorithm")
{
Some(option) => option
.as_string()
.ok()
.and_then(|option| option.try_into().ok())
.unwrap_or(MatchAlgorithm::Prefix),
None => completion_options.match_algorithm,
},
});
}
completions
}
Value::List { vals, .. } => self.map_completions(vals.iter(), span, offset),
_ => vec![],
}
}
_ => vec![],
};
if let Some(custom_completion_options) = custom_completion_options {
filter(&prefix, suggestions, &custom_completion_options)
} else {
filter(&prefix, suggestions, completion_options)
}
}
fn get_sort_by(&self) -> SortBy {
self.sort_by
}
}
fn filter(prefix: &[u8], items: Vec<Suggestion>, options: &CompletionOptions) -> Vec<Suggestion> {
items
.into_iter()
.filter(|it| match options.match_algorithm {
MatchAlgorithm::Prefix => match (options.case_sensitive, options.positional) {
(true, true) => it.value.as_bytes().starts_with(prefix),
(true, false) => it.value.contains(std::str::from_utf8(prefix).unwrap_or("")),
(false, positional) => {
let value = it.value.to_lowercase();
let prefix = std::str::from_utf8(prefix).unwrap_or("").to_lowercase();
if positional {
value.starts_with(&prefix)
} else {
value.contains(&prefix)
}
}
},
MatchAlgorithm::Fuzzy => options
.match_algorithm
.matches_u8(it.value.as_bytes(), prefix),
})
.collect()
}

View File

@ -0,0 +1,160 @@
use crate::completions::{matches, Completer, CompletionOptions};
use nu_protocol::{
engine::{EngineState, StateWorkingSet},
levenshtein_distance, Span,
};
use reedline::Suggestion;
use std::fs;
use std::path::Path;
use std::sync::Arc;
use super::{partial_from, prepend_base_dir};
const SEP: char = std::path::MAIN_SEPARATOR;
#[derive(Clone)]
pub struct DirectoryCompletion {
engine_state: Arc<EngineState>,
}
impl DirectoryCompletion {
pub fn new(engine_state: Arc<EngineState>) -> Self {
Self { engine_state }
}
}
impl Completer for DirectoryCompletion {
fn fetch(
&mut self,
_: &StateWorkingSet,
prefix: Vec<u8>,
span: Span,
offset: usize,
_: usize,
options: &CompletionOptions,
) -> Vec<Suggestion> {
let cwd = if let Some(d) = self.engine_state.get_env_var("PWD") {
match d.as_string() {
Ok(s) => s,
Err(_) => "".to_string(),
}
} else {
"".to_string()
};
let partial = String::from_utf8_lossy(&prefix).to_string();
// Filter only the folders
let output: Vec<_> = directory_completion(span, &partial, &cwd, options)
.into_iter()
.map(move |x| Suggestion {
value: x.1,
description: None,
extra: None,
span: reedline::Span {
start: x.0.start - offset,
end: x.0.end - offset,
},
append_whitespace: false,
})
.collect();
output
}
// Sort results prioritizing the non hidden folders
fn sort(&self, items: Vec<Suggestion>, prefix: Vec<u8>) -> Vec<Suggestion> {
let prefix_str = String::from_utf8_lossy(&prefix).to_string();
// Sort items
let mut sorted_items = items;
sorted_items.sort_by(|a, b| a.value.cmp(&b.value));
sorted_items.sort_by(|a, b| {
let a_distance = levenshtein_distance(&prefix_str, &a.value);
let b_distance = levenshtein_distance(&prefix_str, &b.value);
a_distance.cmp(&b_distance)
});
// Separate the results between hidden and non hidden
let mut hidden: Vec<Suggestion> = vec![];
let mut non_hidden: Vec<Suggestion> = vec![];
for item in sorted_items.into_iter() {
let item_path = Path::new(&item.value);
if let Some(value) = item_path.file_name() {
if let Some(value) = value.to_str() {
if value.starts_with('.') {
hidden.push(item);
} else {
non_hidden.push(item);
}
}
}
}
// Append the hidden folders to the non hidden vec to avoid creating a new vec
non_hidden.append(&mut hidden);
non_hidden
}
}
pub fn directory_completion(
span: nu_protocol::Span,
partial: &str,
cwd: &str,
options: &CompletionOptions,
) -> Vec<(nu_protocol::Span, String)> {
let original_input = partial;
let (base_dir_name, partial) = partial_from(partial);
let base_dir = nu_path::expand_path_with(&base_dir_name, cwd);
// This check is here as base_dir.read_dir() with base_dir == "" will open the current dir
// which we don't want in this case (if we did, base_dir would already be ".")
if base_dir == Path::new("") {
return Vec::new();
}
if let Ok(result) = base_dir.read_dir() {
return result
.filter_map(|entry| {
entry.ok().and_then(|entry| {
if let Ok(metadata) = fs::metadata(entry.path()) {
if metadata.is_dir() {
let mut file_name = entry.file_name().to_string_lossy().into_owned();
if matches(&partial, &file_name, options) {
let mut path = if prepend_base_dir(original_input, &base_dir_name) {
format!("{}{}", base_dir_name, file_name)
} else {
file_name.to_string()
};
if entry.path().is_dir() {
path.push(SEP);
file_name.push(SEP);
}
// Fix files or folders with quotes
if path.contains('\'') || path.contains('"') || path.contains(' ') {
path = format!("`{}`", path);
}
Some((span, path))
} else {
None
}
} else {
None
}
} else {
None
}
})
})
.collect();
}
Vec::new()
}

View File

@ -0,0 +1,124 @@
use crate::completions::{
file_path_completion, partial_from, Completer, CompletionOptions, SortBy,
};
use nu_protocol::{
engine::{EngineState, StateWorkingSet},
Span,
};
use reedline::Suggestion;
use std::sync::Arc;
const SEP: char = std::path::MAIN_SEPARATOR;
#[derive(Clone)]
pub struct DotNuCompletion {
engine_state: Arc<EngineState>,
}
impl DotNuCompletion {
pub fn new(engine_state: Arc<EngineState>) -> Self {
Self { engine_state }
}
}
impl Completer for DotNuCompletion {
fn fetch(
&mut self,
_: &StateWorkingSet,
prefix: Vec<u8>,
span: Span,
offset: usize,
_: usize,
options: &CompletionOptions,
) -> Vec<Suggestion> {
let prefix_str = String::from_utf8_lossy(&prefix).to_string();
let mut search_dirs: Vec<String> = vec![];
let (base_dir, mut partial) = partial_from(&prefix_str);
let mut is_current_folder = false;
// Fetch the lib dirs
let lib_dirs: Vec<String> =
if let Some(lib_dirs) = self.engine_state.get_env_var("NU_LIB_DIRS") {
lib_dirs
.as_list()
.into_iter()
.flat_map(|it| {
it.iter().map(|x| {
x.as_path()
.expect("internal error: failed to convert lib path")
})
})
.map(|it| {
it.into_os_string()
.into_string()
.expect("internal error: failed to convert OS path")
})
.collect()
} else {
vec![]
};
// Check if the base_dir is a folder
if base_dir != format!(".{}", SEP) {
// Add the base dir into the directories to be searched
search_dirs.push(base_dir.clone());
// Reset the partial adding the basic dir back
// in order to make the span replace work properly
let mut base_dir_partial = base_dir;
base_dir_partial.push_str(&partial);
partial = base_dir_partial;
} else {
// Fetch the current folder
let current_folder = if let Some(d) = self.engine_state.get_env_var("PWD") {
match d.as_string() {
Ok(s) => s,
Err(_) => "".to_string(),
}
} else {
"".to_string()
};
is_current_folder = true;
// Add the current folder and the lib dirs into the
// directories to be searched
search_dirs.push(current_folder);
search_dirs.extend(lib_dirs);
}
// Fetch the files filtering the ones that ends with .nu
// and transform them into suggestions
let output: Vec<Suggestion> = search_dirs
.into_iter()
.flat_map(|it| {
file_path_completion(span, &partial, &it, options)
.into_iter()
.filter(|it| {
// Different base dir, so we list the .nu files or folders
if !is_current_folder {
it.1.ends_with(".nu") || it.1.ends_with(SEP)
} else {
// Lib dirs, so we filter only the .nu files
it.1.ends_with(".nu")
}
})
.map(move |x| Suggestion {
value: x.1,
description: None,
extra: None,
span: reedline::Span {
start: x.0.start - offset,
end: x.0.end - offset,
},
append_whitespace: true,
})
})
.collect();
output
}
fn get_sort_by(&self) -> SortBy {
SortBy::LevenshteinDistance
}
}

View File

@ -0,0 +1,190 @@
use crate::completions::{Completer, CompletionOptions};
use nu_protocol::{
engine::{EngineState, StateWorkingSet},
levenshtein_distance, Span,
};
use reedline::Suggestion;
use std::path::{is_separator, Path};
use std::sync::Arc;
const SEP: char = std::path::MAIN_SEPARATOR;
#[derive(Clone)]
pub struct FileCompletion {
engine_state: Arc<EngineState>,
}
impl FileCompletion {
pub fn new(engine_state: Arc<EngineState>) -> Self {
Self { engine_state }
}
}
impl Completer for FileCompletion {
fn fetch(
&mut self,
_: &StateWorkingSet,
prefix: Vec<u8>,
span: Span,
offset: usize,
_: usize,
options: &CompletionOptions,
) -> Vec<Suggestion> {
let cwd = if let Some(d) = self.engine_state.get_env_var("PWD") {
match d.as_string() {
Ok(s) => s,
Err(_) => "".to_string(),
}
} else {
"".to_string()
};
let prefix = String::from_utf8_lossy(&prefix).to_string();
let output: Vec<_> = file_path_completion(span, &prefix, &cwd, options)
.into_iter()
.map(move |x| Suggestion {
value: x.1,
description: None,
extra: None,
span: reedline::Span {
start: x.0.start - offset,
end: x.0.end - offset,
},
append_whitespace: false,
})
.collect();
output
}
// Sort results prioritizing the non hidden folders
fn sort(&self, items: Vec<Suggestion>, prefix: Vec<u8>) -> Vec<Suggestion> {
let prefix_str = String::from_utf8_lossy(&prefix).to_string();
// Sort items
let mut sorted_items = items;
sorted_items.sort_by(|a, b| a.value.cmp(&b.value));
sorted_items.sort_by(|a, b| {
let a_distance = levenshtein_distance(&prefix_str, &a.value);
let b_distance = levenshtein_distance(&prefix_str, &b.value);
a_distance.cmp(&b_distance)
});
// Separate the results between hidden and non hidden
let mut hidden: Vec<Suggestion> = vec![];
let mut non_hidden: Vec<Suggestion> = vec![];
for item in sorted_items.into_iter() {
let item_path = Path::new(&item.value);
if let Some(value) = item_path.file_name() {
if let Some(value) = value.to_str() {
if value.starts_with('.') {
hidden.push(item);
} else {
non_hidden.push(item);
}
}
}
}
// Append the hidden folders to the non hidden vec to avoid creating a new vec
non_hidden.append(&mut hidden);
non_hidden
}
}
pub fn partial_from(input: &str) -> (String, String) {
let partial = input.replace('`', "");
// If partial is only a word we want to search in the current dir
let (base, rest) = partial.rsplit_once(is_separator).unwrap_or((".", &partial));
// On windows, this standardizes paths to use \
let mut base = base.replace(is_separator, &SEP.to_string());
// rsplit_once removes the separator
base.push(SEP);
(base.to_string(), rest.to_string())
}
pub fn file_path_completion(
span: nu_protocol::Span,
partial: &str,
cwd: &str,
options: &CompletionOptions,
) -> Vec<(nu_protocol::Span, String)> {
let original_input = partial;
let (base_dir_name, partial) = partial_from(partial);
let base_dir = nu_path::expand_path_with(&base_dir_name, cwd);
// This check is here as base_dir.read_dir() with base_dir == "" will open the current dir
// which we don't want in this case (if we did, base_dir would already be ".")
if base_dir == Path::new("") {
return Vec::new();
}
if let Ok(result) = base_dir.read_dir() {
return result
.filter_map(|entry| {
entry.ok().and_then(|entry| {
let mut file_name = entry.file_name().to_string_lossy().into_owned();
if matches(&partial, &file_name, options) {
let mut path = if prepend_base_dir(original_input, &base_dir_name) {
format!("{}{}", base_dir_name, file_name)
} else {
file_name.to_string()
};
if entry.path().is_dir() {
path.push(SEP);
file_name.push(SEP);
}
// Fix files or folders with quotes
if path.contains('\'') || path.contains('"') || path.contains(' ') {
path = format!("`{}`", path);
}
Some((span, path))
} else {
None
}
})
})
.collect();
}
Vec::new()
}
pub fn matches(partial: &str, from: &str, options: &CompletionOptions) -> bool {
// Check for case sensitive
if !options.case_sensitive {
return options
.match_algorithm
.matches_str(&from.to_ascii_lowercase(), &partial.to_ascii_lowercase());
}
options.match_algorithm.matches_str(from, partial)
}
/// Returns whether the base_dir should be prepended to the file path
pub fn prepend_base_dir(input: &str, base_dir: &str) -> bool {
if base_dir == format!(".{}", SEP) {
// if the current base_dir path is the local folder we only add a "./" prefix if the user
// input already includes a local folder prefix.
let manually_entered = {
let mut chars = input.chars();
let first_char = chars.next();
let second_char = chars.next();
first_char == Some('.') && second_char.map(is_separator).unwrap_or(false)
};
manually_entered
} else {
// always prepend the base dir if it is a subfolder
true
}
}

View File

@ -0,0 +1,86 @@
use crate::completions::{Completer, CompletionOptions};
use nu_protocol::{
ast::{Expr, Expression},
engine::StateWorkingSet,
Span,
};
use reedline::Suggestion;
#[derive(Clone)]
pub struct FlagCompletion {
expression: Expression,
}
impl FlagCompletion {
pub fn new(expression: Expression) -> Self {
Self { expression }
}
}
impl Completer for FlagCompletion {
fn fetch(
&mut self,
working_set: &StateWorkingSet,
prefix: Vec<u8>,
span: Span,
offset: usize,
_: usize,
options: &CompletionOptions,
) -> Vec<Suggestion> {
// Check if it's a flag
if let Expr::Call(call) = &self.expression.expr {
let decl = working_set.get_decl(call.decl_id);
let sig = decl.signature();
let mut output = vec![];
for named in &sig.named {
let flag_desc = &named.desc;
if let Some(short) = named.short {
let mut named = vec![0; short.len_utf8()];
short.encode_utf8(&mut named);
named.insert(0, b'-');
if options.match_algorithm.matches_u8(&named, &prefix) {
output.push(Suggestion {
value: String::from_utf8_lossy(&named).to_string(),
description: Some(flag_desc.to_string()),
extra: None,
span: reedline::Span {
start: span.start - offset,
end: span.end - offset,
},
append_whitespace: true,
});
}
}
if named.long.is_empty() {
continue;
}
let mut named = named.long.as_bytes().to_vec();
named.insert(0, b'-');
named.insert(0, b'-');
if options.match_algorithm.matches_u8(&named, &prefix) {
output.push(Suggestion {
value: String::from_utf8_lossy(&named).to_string(),
description: Some(flag_desc.to_string()),
extra: None,
span: reedline::Span {
start: span.start - offset,
end: span.end - offset,
},
append_whitespace: true,
});
}
}
return output;
}
vec![]
}
}

View File

@ -0,0 +1,23 @@
mod base;
mod command_completions;
mod completer;
mod completion_options;
mod custom_completions;
mod directory_completions;
mod dotnu_completions;
mod file_completions;
mod flag_completions;
mod variable_completions;
pub use base::Completer;
pub use command_completions::CommandCompletion;
pub use completer::NuCompleter;
pub use completion_options::{CompletionOptions, MatchAlgorithm, SortBy};
pub use custom_completions::CustomCompletion;
pub use directory_completions::DirectoryCompletion;
pub use dotnu_completions::DotNuCompletion;
pub use file_completions::{
file_path_completion, matches, partial_from, prepend_base_dir, FileCompletion,
};
pub use flag_completions::FlagCompletion;
pub use variable_completions::VariableCompletion;

View File

@ -0,0 +1,292 @@
use crate::completions::{Completer, CompletionOptions};
use nu_engine::eval_variable;
use nu_protocol::{
engine::{EngineState, Stack, StateWorkingSet},
Span, Value,
};
use reedline::Suggestion;
use std::str;
use std::sync::Arc;
#[derive(Clone)]
pub struct VariableCompletion {
engine_state: Arc<EngineState>, // TODO: Is engine state necessary? It's already a part of working set in fetch()
stack: Stack,
var_context: (Vec<u8>, Vec<Vec<u8>>), // tuple with $var and the sublevels (.b.c.d)
}
impl VariableCompletion {
pub fn new(
engine_state: Arc<EngineState>,
stack: Stack,
var_context: (Vec<u8>, Vec<Vec<u8>>),
) -> Self {
Self {
engine_state,
stack,
var_context,
}
}
}
impl Completer for VariableCompletion {
fn fetch(
&mut self,
working_set: &StateWorkingSet,
prefix: Vec<u8>,
span: Span,
offset: usize,
_: usize,
options: &CompletionOptions,
) -> Vec<Suggestion> {
let mut output = vec![];
let builtins = ["$nu", "$in", "$config", "$env", "$nothing"];
let var_str = std::str::from_utf8(&self.var_context.0)
.unwrap_or("")
.to_lowercase();
let var_id = working_set.find_variable(&self.var_context.0);
let current_span = reedline::Span {
start: span.start - offset,
end: span.end - offset,
};
let sublevels_count = self.var_context.1.len();
// Completions for the given variable
if !var_str.is_empty() {
// Completion for $env.<tab>
if var_str.as_str() == "$env" {
let env_vars = self.stack.get_env_vars(&self.engine_state);
// Return nested values
if sublevels_count > 0 {
// Extract the target var ($env.<target-var>)
let target_var = self.var_context.1[0].clone();
let target_var_str =
str::from_utf8(&target_var).unwrap_or_default().to_string();
// Everything after the target var is the nested level ($env.<target-var>.<nested_levels>...)
let nested_levels: Vec<Vec<u8>> =
self.var_context.1.clone().into_iter().skip(1).collect();
if let Some(val) = env_vars.get(&target_var_str) {
for suggestion in
nested_suggestions(val.clone(), nested_levels, current_span)
{
if options
.match_algorithm
.matches_u8(suggestion.value.as_bytes(), &prefix)
{
output.push(suggestion);
}
}
return output;
}
} else {
// No nesting provided, return all env vars
for env_var in env_vars {
if options
.match_algorithm
.matches_u8(env_var.0.as_bytes(), &prefix)
{
output.push(Suggestion {
value: env_var.0,
description: None,
extra: None,
span: current_span,
append_whitespace: false,
});
}
}
return output;
}
}
// Completions for $nu.<tab>
if var_str.as_str() == "$nu" {
// Eval nu var
if let Ok(nuval) = eval_variable(
&self.engine_state,
&self.stack,
nu_protocol::NU_VARIABLE_ID,
nu_protocol::Span {
start: current_span.start,
end: current_span.end,
},
) {
for suggestion in
nested_suggestions(nuval, self.var_context.1.clone(), current_span)
{
if options
.match_algorithm
.matches_u8(suggestion.value.as_bytes(), &prefix)
{
output.push(suggestion);
}
}
return output;
}
}
// Completion other variable types
if let Some(var_id) = var_id {
// Extract the variable value from the stack
let var = self.stack.get_var(
var_id,
Span {
start: span.start,
end: span.end,
},
);
// If the value exists and it's of type Record
if let Ok(value) = var {
for suggestion in
nested_suggestions(value, self.var_context.1.clone(), current_span)
{
if options
.match_algorithm
.matches_u8(suggestion.value.as_bytes(), &prefix)
{
output.push(suggestion);
}
}
return output;
}
}
}
// Variable completion (e.g: $en<tab> to complete $env)
for builtin in builtins {
if options
.match_algorithm
.matches_u8(builtin.as_bytes(), &prefix)
{
output.push(Suggestion {
value: builtin.to_string(),
description: None,
extra: None,
span: current_span,
append_whitespace: false,
});
}
}
// TODO: The following can be refactored (see find_commands_by_predicate() used in
// command_completions).
let mut removed_overlays = vec![];
// Working set scope vars
for scope_frame in working_set.delta.scope.iter().rev() {
for overlay_frame in scope_frame
.active_overlays(&mut removed_overlays)
.iter()
.rev()
{
for v in &overlay_frame.vars {
if options.match_algorithm.matches_u8(v.0, &prefix) {
output.push(Suggestion {
value: String::from_utf8_lossy(v.0).to_string(),
description: None,
extra: None,
span: current_span,
append_whitespace: false,
});
}
}
}
}
// Permanent state vars
// for scope in &self.engine_state.scope {
for overlay_frame in self
.engine_state
.active_overlays(&removed_overlays)
.iter()
.rev()
{
for v in &overlay_frame.vars {
if options.match_algorithm.matches_u8(v.0, &prefix) {
output.push(Suggestion {
value: String::from_utf8_lossy(v.0).to_string(),
description: None,
extra: None,
span: current_span,
append_whitespace: false,
});
}
}
}
output.dedup(); // TODO: Removes only consecutive duplicates, is it intended?
output
}
}
// Find recursively the values for sublevels
// if no sublevels are set it returns the current value
fn nested_suggestions(
val: Value,
sublevels: Vec<Vec<u8>>,
current_span: reedline::Span,
) -> Vec<Suggestion> {
let mut output: Vec<Suggestion> = vec![];
let value = recursive_value(val, sublevels);
match value {
Value::Record {
cols,
vals: _,
span: _,
} => {
// Add all the columns as completion
for item in cols {
output.push(Suggestion {
value: item,
description: None,
extra: None,
span: current_span,
append_whitespace: false,
});
}
output
}
_ => output,
}
}
// Extracts the recursive value (e.g: $var.a.b.c)
fn recursive_value(val: Value, sublevels: Vec<Vec<u8>>) -> Value {
// Go to next sublevel
if let Some(next_sublevel) = sublevels.clone().into_iter().next() {
match val {
Value::Record {
cols,
vals,
span: _,
} => {
for item in cols.into_iter().zip(vals.into_iter()) {
// Check if index matches with sublevel
if item.0.as_bytes().to_vec() == next_sublevel {
// If matches try to fetch recursively the next
return recursive_value(item.1, sublevels.into_iter().skip(1).collect());
}
}
// Current sublevel value not found
return Value::Nothing {
span: Span { start: 0, end: 0 },
};
}
_ => return val,
}
}
val
}

View File

@ -0,0 +1,100 @@
use crate::util::{eval_source, report_error};
#[cfg(feature = "plugin")]
use log::info;
use nu_protocol::engine::{EngineState, Stack, StateDelta, StateWorkingSet};
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,
stack: &mut Stack,
storage_path: &str,
is_perf_true: bool,
) {
// Reading signatures from signature file
// The plugin.nu file stores the parsed signature collected from each registered plugin
add_plugin_file(engine_state, storage_path);
let plugin_path = engine_state.plugin_signatures.clone();
if let Some(plugin_path) = plugin_path {
let plugin_filename = plugin_path.to_string_lossy().to_owned();
if let Ok(contents) = std::fs::read(&plugin_path) {
eval_source(
engine_state,
stack,
&contents,
&plugin_filename,
PipelineData::new(Span::new(0, 0)),
);
}
}
if is_perf_true {
info!("read_plugin_file {}:{}:{}", file!(), line!(), column!());
}
}
#[cfg(feature = "plugin")]
pub fn add_plugin_file(engine_state: &mut EngineState, storage_path: &str) {
if let Some(mut plugin_path) = nu_path::config_dir() {
// Path to store plugins signatures
plugin_path.push(storage_path);
plugin_path.push(PLUGIN_FILE);
engine_state.plugin_signatures = Some(plugin_path.clone());
}
}
pub fn eval_config_contents(
config_path: PathBuf,
engine_state: &mut EngineState,
stack: &mut Stack,
) {
if config_path.exists() & config_path.is_file() {
let config_filename = config_path.to_string_lossy().to_owned();
if let Ok(contents) = std::fs::read(&config_path) {
eval_source(
engine_state,
stack,
&contents,
&config_filename,
PipelineData::new(Span::new(0, 0)),
);
// Merge the delta in case env vars changed in the config
match nu_engine::env::current_dir(engine_state, stack) {
Ok(cwd) => {
if let Err(e) =
engine_state.merge_delta(StateDelta::new(engine_state), Some(stack), cwd)
{
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &e);
}
}
Err(e) => {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &e);
}
}
}
}
}
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

@ -0,0 +1,135 @@
use crate::util::{eval_source, report_error};
use log::info;
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},
Config, PipelineData, Span, Value,
};
use nu_utils::stdout_write_all_and_flush;
/// Main function used when a file path is found as argument for nu
pub fn evaluate_file(
path: String,
args: &[String],
engine_state: &mut EngineState,
stack: &mut Stack,
input: PipelineData,
is_perf_true: bool,
) -> Result<()> {
// Translate environment variables from Strings to Values
if let Some(e) = convert_env_values(engine_state, stack) {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &e);
std::process::exit(1);
}
let file = std::fs::read(&path).into_diagnostic()?;
let mut working_set = StateWorkingSet::new(engine_state);
trace!("parsing file: {}", path);
let _ = parse(&mut working_set, Some(&path), &file, false, &[]);
if working_set.find_decl(b"main", &Type::Any).is_some() {
let args = format!("main {}", args.join(" "));
if !eval_source(
engine_state,
stack,
&file,
&path,
PipelineData::new(Span::new(0, 0)),
) {
std::process::exit(1);
}
if !eval_source(engine_state, stack, args.as_bytes(), "<commandline>", input) {
std::process::exit(1);
}
} else if !eval_source(engine_state, stack, &file, &path, input) {
std::process::exit(1);
}
if is_perf_true {
info!("evaluate {}:{}:{}", file!(), line!(), column!());
}
Ok(())
}
pub fn print_table_or_error(
engine_state: &mut EngineState,
stack: &mut Stack,
mut pipeline_data: PipelineData,
config: &mut Config,
) {
let exit_code = match &mut pipeline_data {
PipelineData::ExternalStream { exit_code, .. } => exit_code.take(),
_ => None,
};
// Change the engine_state config to use the passed in configuration
engine_state.set_config(config);
match engine_state.find_decl("table".as_bytes(), &[]) {
Some(decl_id) => {
let table = engine_state.get_decl(decl_id).run(
engine_state,
stack,
&Call::new(Span::new(0, 0)),
pipeline_data,
);
match table {
Ok(table) => {
for item in table {
if let Value::Error { error } = item {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &error);
std::process::exit(1);
}
let mut out = item.into_string("\n", config);
out.push('\n');
let _ = stdout_write_all_and_flush(out).map_err(|err| eprintln!("{}", err));
}
}
Err(error) => {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &error);
std::process::exit(1);
}
}
}
None => {
for item in pipeline_data {
if let Value::Error { error } = item {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &error);
std::process::exit(1);
}
let mut out = item.into_string("\n", config);
out.push('\n');
let _ = stdout_write_all_and_flush(out).map_err(|err| eprintln!("{}", err));
}
}
};
// Make sure everything has finished
if let Some(exit_code) = exit_code {
let _: Vec<_> = exit_code.into_iter().collect();
}
}

View File

@ -1,473 +0,0 @@
use rustyline::{KeyCode as RustyKeyCode, Modifiers};
use serde::{Deserialize, Serialize};
pub fn convert_keyevent(key_event: KeyCode, modifiers: Option<Modifiers>) -> rustyline::KeyEvent {
match key_event {
KeyCode::UnknownEscSeq => convert_to_rl_keyevent(RustyKeyCode::UnknownEscSeq, modifiers),
KeyCode::Backspace => convert_to_rl_keyevent(RustyKeyCode::Backspace, modifiers),
KeyCode::BackTab => convert_to_rl_keyevent(RustyKeyCode::BackTab, modifiers),
KeyCode::BracketedPasteStart => {
convert_to_rl_keyevent(RustyKeyCode::BracketedPasteStart, modifiers)
}
KeyCode::BracketedPasteEnd => {
convert_to_rl_keyevent(RustyKeyCode::BracketedPasteEnd, modifiers)
}
KeyCode::Char(c) => convert_to_rl_keyevent(RustyKeyCode::Char(c), modifiers),
KeyCode::Delete => convert_to_rl_keyevent(RustyKeyCode::Delete, modifiers),
KeyCode::Down => convert_to_rl_keyevent(RustyKeyCode::Down, modifiers),
KeyCode::End => convert_to_rl_keyevent(RustyKeyCode::End, modifiers),
KeyCode::Enter => convert_to_rl_keyevent(RustyKeyCode::Enter, modifiers),
KeyCode::Esc => convert_to_rl_keyevent(RustyKeyCode::Esc, modifiers),
KeyCode::F(u) => convert_to_rl_keyevent(RustyKeyCode::F(u), modifiers),
KeyCode::Home => convert_to_rl_keyevent(RustyKeyCode::Home, modifiers),
KeyCode::Insert => convert_to_rl_keyevent(RustyKeyCode::Insert, modifiers),
KeyCode::Left => convert_to_rl_keyevent(RustyKeyCode::Left, modifiers),
KeyCode::Null => convert_to_rl_keyevent(RustyKeyCode::Null, modifiers),
KeyCode::PageDown => convert_to_rl_keyevent(RustyKeyCode::PageDown, modifiers),
KeyCode::PageUp => convert_to_rl_keyevent(RustyKeyCode::PageUp, modifiers),
KeyCode::Right => convert_to_rl_keyevent(RustyKeyCode::Right, modifiers),
KeyCode::Tab => convert_to_rl_keyevent(RustyKeyCode::Tab, modifiers),
KeyCode::Up => convert_to_rl_keyevent(RustyKeyCode::Up, modifiers),
}
}
fn convert_to_rl_keyevent(
key_code: RustyKeyCode,
modifier: Option<Modifiers>,
) -> rustyline::KeyEvent {
rustyline::KeyEvent {
0: key_code,
1: modifier.unwrap_or(Modifiers::NONE),
}
}
fn convert_word(word: Word) -> rustyline::Word {
match word {
Word::Big => rustyline::Word::Big,
Word::Emacs => rustyline::Word::Emacs,
Word::Vi => rustyline::Word::Vi,
}
}
fn convert_at(at: At) -> rustyline::At {
match at {
At::AfterEnd => rustyline::At::AfterEnd,
At::BeforeEnd => rustyline::At::BeforeEnd,
At::Start => rustyline::At::Start,
}
}
fn convert_char_search(search: CharSearch) -> rustyline::CharSearch {
match search {
CharSearch::Backward(c) => rustyline::CharSearch::Backward(c),
CharSearch::BackwardAfter(c) => rustyline::CharSearch::BackwardAfter(c),
CharSearch::Forward(c) => rustyline::CharSearch::Forward(c),
CharSearch::ForwardBefore(c) => rustyline::CharSearch::ForwardBefore(c),
}
}
fn convert_movement(movement: Movement) -> rustyline::Movement {
match movement {
Movement::BackwardChar(u) => rustyline::Movement::BackwardChar(u),
Movement::BackwardWord { repeat, word } => {
rustyline::Movement::BackwardWord(repeat, convert_word(word))
}
Movement::BeginningOfBuffer => rustyline::Movement::BeginningOfBuffer,
Movement::BeginningOfLine => rustyline::Movement::BeginningOfLine,
Movement::EndOfBuffer => rustyline::Movement::EndOfBuffer,
Movement::EndOfLine => rustyline::Movement::EndOfLine,
Movement::ForwardChar(u) => rustyline::Movement::ForwardChar(u),
Movement::ForwardWord { repeat, at, word } => {
rustyline::Movement::ForwardWord(repeat, convert_at(at), convert_word(word))
}
Movement::LineDown(u) => rustyline::Movement::LineDown(u),
Movement::LineUp(u) => rustyline::Movement::LineUp(u),
Movement::ViCharSearch { repeat, search } => {
rustyline::Movement::ViCharSearch(repeat, convert_char_search(search))
}
Movement::ViFirstPrint => rustyline::Movement::ViFirstPrint,
Movement::WholeBuffer => rustyline::Movement::WholeBuffer,
Movement::WholeLine => rustyline::Movement::WholeLine,
}
}
fn convert_anchor(anchor: Anchor) -> rustyline::Anchor {
match anchor {
Anchor::After => rustyline::Anchor::After,
Anchor::Before => rustyline::Anchor::Before,
}
}
fn convert_cmd(cmd: Cmd) -> rustyline::Cmd {
match cmd {
Cmd::Abort => rustyline::Cmd::Abort,
Cmd::AcceptLine => rustyline::Cmd::AcceptLine,
Cmd::AcceptOrInsertLine => rustyline::Cmd::AcceptOrInsertLine {
accept_in_the_middle: false,
},
Cmd::BeginningOfHistory => rustyline::Cmd::BeginningOfHistory,
Cmd::CapitalizeWord => rustyline::Cmd::CapitalizeWord,
Cmd::ClearScreen => rustyline::Cmd::ClearScreen,
Cmd::Complete => rustyline::Cmd::Complete,
Cmd::CompleteBackward => rustyline::Cmd::CompleteBackward,
Cmd::CompleteHint => rustyline::Cmd::CompleteHint,
Cmd::Dedent(movement) => rustyline::Cmd::Dedent(convert_movement(movement)),
Cmd::DowncaseWord => rustyline::Cmd::DowncaseWord,
Cmd::EndOfFile => rustyline::Cmd::EndOfFile,
Cmd::EndOfHistory => rustyline::Cmd::EndOfHistory,
Cmd::ForwardSearchHistory => rustyline::Cmd::ForwardSearchHistory,
Cmd::HistorySearchBackward => rustyline::Cmd::HistorySearchBackward,
Cmd::HistorySearchForward => rustyline::Cmd::HistorySearchForward,
Cmd::Indent(movement) => rustyline::Cmd::Indent(convert_movement(movement)),
Cmd::Insert { repeat, string } => rustyline::Cmd::Insert(repeat, string),
Cmd::Interrupt => rustyline::Cmd::Interrupt,
Cmd::Kill(movement) => rustyline::Cmd::Kill(convert_movement(movement)),
Cmd::LineDownOrNextHistory(u) => rustyline::Cmd::LineDownOrNextHistory(u),
Cmd::LineUpOrPreviousHistory(u) => rustyline::Cmd::LineUpOrPreviousHistory(u),
Cmd::Move(movement) => rustyline::Cmd::Move(convert_movement(movement)),
Cmd::NextHistory => rustyline::Cmd::NextHistory,
Cmd::Newline => rustyline::Cmd::Newline,
Cmd::Noop => rustyline::Cmd::Noop,
Cmd::Overwrite(c) => rustyline::Cmd::Overwrite(c),
#[cfg(windows)]
Cmd::PasteFromClipboard => rustyline::Cmd::PasteFromClipboard,
Cmd::PreviousHistory => rustyline::Cmd::PreviousHistory,
Cmd::QuotedInsert => rustyline::Cmd::QuotedInsert,
Cmd::Replace {
movement,
replacement,
} => rustyline::Cmd::Replace(convert_movement(movement), replacement),
Cmd::ReplaceChar { repeat, ch } => rustyline::Cmd::ReplaceChar(repeat, ch),
Cmd::ReverseSearchHistory => rustyline::Cmd::ReverseSearchHistory,
Cmd::SelfInsert { repeat, ch } => rustyline::Cmd::SelfInsert(repeat, ch),
Cmd::Suspend => rustyline::Cmd::Suspend,
Cmd::TransposeChars => rustyline::Cmd::TransposeChars,
Cmd::TransposeWords(u) => rustyline::Cmd::TransposeWords(u),
Cmd::Undo(u) => rustyline::Cmd::Undo(u),
Cmd::Unknown => rustyline::Cmd::Unknown,
Cmd::UpcaseWord => rustyline::Cmd::UpcaseWord,
Cmd::ViYankTo(movement) => rustyline::Cmd::ViYankTo(convert_movement(movement)),
Cmd::Yank { repeat, anchor } => rustyline::Cmd::Yank(repeat, convert_anchor(anchor)),
Cmd::YankPop => rustyline::Cmd::YankPop,
}
}
fn convert_keybinding(keybinding: Keybinding) -> (rustyline::KeyEvent, rustyline::Cmd) {
let rusty_modifiers = match keybinding.modifiers {
Some(mods) => match mods {
NuModifiers::Ctrl => Some(Modifiers::CTRL),
NuModifiers::Alt => Some(Modifiers::ALT),
NuModifiers::Shift => Some(Modifiers::SHIFT),
NuModifiers::None => Some(Modifiers::NONE),
NuModifiers::CtrlShift => Some(Modifiers::CTRL_SHIFT),
NuModifiers::AltShift => Some(Modifiers::ALT_SHIFT),
NuModifiers::CtrlAlt => Some(Modifiers::CTRL_ALT),
NuModifiers::CtrlAltShift => Some(Modifiers::CTRL_ALT_SHIFT),
// _ => None,
},
None => None,
};
(
convert_keyevent(keybinding.key, rusty_modifiers),
convert_cmd(keybinding.binding),
)
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum KeyCode {
/// Unsupported escape sequence (on unix platform)
UnknownEscSeq,
/// ⌫ or `KeyEvent::Ctrl('H')`
Backspace,
/// ⇤ (usually Shift-Tab)
BackTab,
/// Paste (on unix platform)
BracketedPasteStart,
/// Paste (on unix platform)
BracketedPasteEnd,
/// Single char
Char(char),
/// ⌦
Delete,
/// ↓ arrow key
Down,
/// ⇲
End,
/// ↵ or `KeyEvent::Ctrl('M')`
Enter,
/// Escape or `KeyEvent::Ctrl('[')`
Esc,
/// Function key
F(u8),
/// ⇱
Home,
/// Insert key
Insert,
/// ← arrow key
Left,
// /// `KeyEvent::Char('\0')`
Null,
/// ⇟
PageDown,
/// ⇞
PageUp,
/// → arrow key
Right,
/// ⇥ or `KeyEvent::Ctrl('I')`
Tab,
/// ↑ arrow key
Up,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum Cmd {
/// abort
Abort, // Miscellaneous Command
/// accept-line
AcceptLine,
/// beginning-of-history
BeginningOfHistory,
/// capitalize-word
CapitalizeWord,
/// clear-screen
ClearScreen,
/// complete
Complete,
/// complete-backward
CompleteBackward,
/// complete-hint
CompleteHint,
/// Dedent current line
Dedent(Movement),
/// downcase-word
DowncaseWord,
/// vi-eof-maybe
EndOfFile,
/// end-of-history
EndOfHistory,
/// forward-search-history
ForwardSearchHistory,
/// history-search-backward
HistorySearchBackward,
/// history-search-forward
HistorySearchForward,
/// Indent current line
Indent(Movement),
/// Insert text
Insert { repeat: RepeatCount, string: String },
/// Interrupt signal (Ctrl-C)
Interrupt,
/// backward-delete-char, backward-kill-line, backward-kill-word
/// delete-char, kill-line, kill-word, unix-line-discard, unix-word-rubout,
/// vi-delete, vi-delete-to, vi-rubout
Kill(Movement),
/// backward-char, backward-word, beginning-of-line, end-of-line,
/// forward-char, forward-word, vi-char-search, vi-end-word, vi-next-word,
/// vi-prev-word
Move(Movement),
/// Inserts a newline
Newline,
/// next-history
NextHistory,
/// No action
Noop,
/// vi-replace
Overwrite(char),
/// Paste from the clipboard
#[cfg(windows)]
PasteFromClipboard,
/// previous-history
PreviousHistory,
/// quoted-insert
QuotedInsert,
/// vi-change-char
ReplaceChar { repeat: RepeatCount, ch: char },
/// vi-change-to, vi-substitute
Replace {
movement: Movement,
replacement: Option<String>,
},
/// reverse-search-history
ReverseSearchHistory,
/// self-insert
SelfInsert { repeat: RepeatCount, ch: char },
/// Suspend signal (Ctrl-Z on unix platform)
Suspend,
/// transpose-chars
TransposeChars,
/// transpose-words
TransposeWords(RepeatCount),
/// undo
Undo(RepeatCount),
/// Unsupported / unexpected
Unknown,
/// upcase-word
UpcaseWord,
/// vi-yank-to
ViYankTo(Movement),
/// yank, vi-put
Yank { repeat: RepeatCount, anchor: Anchor },
/// yank-pop
YankPop,
/// moves cursor to the line above or switches to prev history entry if
/// the cursor is already on the first line
LineUpOrPreviousHistory(RepeatCount),
/// moves cursor to the line below or switches to next history entry if
/// the cursor is already on the last line
LineDownOrNextHistory(RepeatCount),
/// accepts the line when cursor is at the end of the text (non including
/// trailing whitespace), inserts newline character otherwise
AcceptOrInsertLine,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum Movement {
/// Whole current line (not really a movement but a range)
WholeLine,
/// beginning-of-line
BeginningOfLine,
/// end-of-line
EndOfLine,
/// backward-word, vi-prev-word
BackwardWord { repeat: RepeatCount, word: Word }, // Backward until start of word
/// forward-word, vi-end-word, vi-next-word
ForwardWord {
repeat: RepeatCount,
at: At,
word: Word,
}, // Forward until start/end of word
/// vi-char-search
ViCharSearch {
repeat: RepeatCount,
search: CharSearch,
},
/// vi-first-print
ViFirstPrint,
/// backward-char
BackwardChar(RepeatCount),
/// forward-char
ForwardChar(RepeatCount),
/// move to the same column on the previous line
LineUp(RepeatCount),
/// move to the same column on the next line
LineDown(RepeatCount),
/// Whole user input (not really a movement but a range)
WholeBuffer,
/// beginning-of-buffer
BeginningOfBuffer,
/// end-of-buffer
EndOfBuffer,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
enum InputMode {
/// Vi Command/Alternate
Command,
/// Insert/Input mode
Insert,
/// Overwrite mode
Replace,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum Word {
/// non-blanks characters
Big,
/// alphanumeric characters
Emacs,
/// alphanumeric (and '_') characters
Vi,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum At {
/// Start of word.
Start,
/// Before end of word.
BeforeEnd,
/// After end of word.
AfterEnd,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum Anchor {
/// After cursor
After,
/// Before cursor
Before,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum CharSearch {
/// Forward search
Forward(char),
/// Forward search until
ForwardBefore(char),
/// Backward search
Backward(char),
/// Backward search until
BackwardAfter(char),
}
/// The set of modifier keys that were triggered along with a key press.
#[derive(Debug, Serialize, Deserialize)]
#[allow(non_camel_case_types)]
pub enum NuModifiers {
/// Control modifier
#[serde(alias = "CTRL")]
Ctrl = 8,
/// Escape or Alt modifier
#[serde(alias = "ALT")]
Alt = 4,
/// Shift modifier
#[serde(alias = "SHIFT")]
Shift = 2,
/// No modifier
#[serde(alias = "NONE")]
None = 0,
/// Ctrl + Shift
#[serde(alias = "CTRL_SHIFT")]
CtrlShift = 10,
/// Alt + Shift
#[serde(alias = "ALT_SHIFT")]
AltShift = 6,
/// Ctrl + Alt
#[serde(alias = "CTRL_ALT")]
CtrlAlt = 12,
/// Ctrl + Alt + Shift
#[serde(alias = "CTRL_ALT_SHIFT")]
CtrlAltShift = 14,
}
/// The number of times one command should be repeated.
pub type RepeatCount = usize;
#[derive(Debug, Serialize, Deserialize)]
pub struct Keybinding {
key: KeyCode,
modifiers: Option<NuModifiers>,
binding: Cmd,
}
type Keybindings = Vec<Keybinding>;
pub(crate) fn load_keybindings(
rl: &mut rustyline::Editor<crate::shell::Helper>,
) -> Result<(), nu_errors::ShellError> {
let filename = nu_data::keybinding::keybinding_path()?;
let contents = std::fs::read_to_string(filename);
// Silently fail if there is no file there
if let Ok(contents) = contents {
let keybindings: Keybindings = serde_yaml::from_str(&contents)?;
// eprintln!("{:#?}", keybindings);
for keybinding in keybindings.into_iter() {
let (k, b) = convert_keybinding(keybinding);
// eprintln!("{:?} {:?}", k, b);
rl.bind_sequence(k, b);
}
}
Ok(())
}

View File

@ -1,15 +1,32 @@
pub mod app;
mod cli;
#[cfg(feature = "rustyline-support")]
mod keybinding;
mod line_editor;
#[cfg(feature = "rustyline-support")]
mod shell;
mod commands;
mod completions;
mod config_files;
mod eval_file;
mod menus;
mod nu_highlight;
mod print;
mod prompt;
mod prompt_update;
mod reedline_config;
mod repl;
mod syntax_highlight;
mod util;
mod validation;
#[cfg(feature = "rustyline-support")]
pub use crate::cli::cli;
pub use commands::evaluate_commands;
pub use completions::{FileCompletion, NuCompleter};
pub use config_files::eval_config_contents;
pub use eval_file::evaluate_file;
pub use menus::{DescriptionMenu, NuHelpCompleter};
pub use nu_highlight::NuHighlight;
pub use print::Print;
pub use prompt::NushellPrompt;
pub use repl::evaluate_repl;
pub use syntax_highlight::NuHighlighter;
pub use util::{eval_source, gather_parent_env_vars, get_init_cwd, report_error};
pub use validation::NuValidator;
pub use crate::app::App;
pub use crate::cli::{parse_and_eval, register_plugins, run_script_file};
pub use nu_command::create_default_context;
#[cfg(feature = "plugin")]
pub use config_files::add_plugin_file;
#[cfg(feature = "plugin")]
pub use config_files::read_plugin_file;

View File

@ -1,274 +0,0 @@
use nu_engine::EvaluationContext;
use nu_errors::ShellError;
use std::error::Error;
#[allow(unused_imports)]
use std::sync::atomic::Ordering;
#[allow(unused_imports)]
use nu_engine::script::LineResult;
#[cfg(feature = "rustyline-support")]
use crate::keybinding::{convert_keyevent, KeyCode};
#[cfg(feature = "rustyline-support")]
use crate::shell::Helper;
#[cfg(feature = "rustyline-support")]
use rustyline::{
self,
config::Configurer,
config::{ColorMode, CompletionType, Config},
error::ReadlineError,
line_buffer::LineBuffer,
At, Cmd, ConditionalEventHandler, Editor, EventHandler, Modifiers, Movement, Word,
};
#[cfg(feature = "rustyline-support")]
pub fn convert_rustyline_result_to_string(input: Result<String, ReadlineError>) -> LineResult {
match input {
Ok(s) if s == "history -c" || s == "history --clear" => LineResult::ClearHistory,
Ok(s) => LineResult::Success(s),
Err(ReadlineError::Interrupted) => LineResult::CtrlC,
Err(ReadlineError::Eof) => LineResult::CtrlD,
Err(err) => {
eprintln!("Error: {:?}", err);
LineResult::Break
}
}
}
#[derive(Clone)]
#[cfg(feature = "rustyline-support")]
struct PartialCompleteHintHandler;
#[cfg(feature = "rustyline-support")]
impl ConditionalEventHandler for PartialCompleteHintHandler {
fn handle(
&self,
_evt: &rustyline::Event,
_n: rustyline::RepeatCount,
_positive: bool,
ctx: &rustyline::EventContext,
) -> Option<Cmd> {
Some(match ctx.hint_text() {
Some(hint_text) if ctx.pos() == ctx.line().len() => {
let mut line_buffer = LineBuffer::with_capacity(hint_text.len());
line_buffer.update(hint_text, 0);
line_buffer.move_to_next_word(At::AfterEnd, Word::Vi, 1);
let text = hint_text[0..line_buffer.pos()].to_string();
Cmd::Insert(1, text)
}
_ => Cmd::Move(Movement::ForwardWord(1, At::AfterEnd, Word::Vi)),
})
}
}
#[cfg(feature = "rustyline-support")]
pub fn default_rustyline_editor_configuration() -> Editor<Helper> {
#[cfg(windows)]
const DEFAULT_COMPLETION_MODE: CompletionType = CompletionType::Circular;
#[cfg(not(windows))]
const DEFAULT_COMPLETION_MODE: CompletionType = CompletionType::List;
let config = Config::builder()
.check_cursor_position(true)
.color_mode(ColorMode::Forced)
.build();
let mut rl: Editor<_> = Editor::with_config(config);
// add key bindings to move over a whole word with Ctrl+ArrowLeft and Ctrl+ArrowRight
//M modifier, E KeyEvent, K KeyCode
rl.bind_sequence(
convert_keyevent(KeyCode::Left, Some(Modifiers::CTRL)),
Cmd::Move(Movement::BackwardWord(1, Word::Vi)),
);
rl.bind_sequence(
convert_keyevent(KeyCode::Right, Some(Modifiers::CTRL)),
EventHandler::Conditional(Box::new(PartialCompleteHintHandler)),
);
// workaround for multiline-paste hang in rustyline (see https://github.com/kkawakam/rustyline/issues/202)
rl.bind_sequence(
convert_keyevent(KeyCode::BracketedPasteStart, None),
rustyline::Cmd::Noop,
);
// Let's set the defaults up front and then override them later if the user indicates
// defaults taken from here https://github.com/kkawakam/rustyline/blob/2fe886c9576c1ea13ca0e5808053ad491a6fe049/src/config.rs#L150-L167
rl.set_max_history_size(100);
rl.set_history_ignore_dups(true);
rl.set_history_ignore_space(false);
rl.set_completion_type(DEFAULT_COMPLETION_MODE);
rl.set_completion_prompt_limit(100);
rl.set_keyseq_timeout(-1);
rl.set_edit_mode(rustyline::config::EditMode::Emacs);
rl.set_auto_add_history(false);
rl.set_bell_style(rustyline::config::BellStyle::default());
rl.set_color_mode(rustyline::ColorMode::Enabled);
rl.set_tab_stop(8);
if let Err(e) = crate::keybinding::load_keybindings(&mut rl) {
println!("Error loading keybindings: {:?}", e);
}
rl
}
#[cfg(feature = "rustyline-support")]
pub fn configure_rustyline_editor(
rl: &mut Editor<Helper>,
config: &dyn nu_data::config::Conf,
) -> Result<(), ShellError> {
#[cfg(windows)]
const DEFAULT_COMPLETION_MODE: CompletionType = CompletionType::Circular;
#[cfg(not(windows))]
const DEFAULT_COMPLETION_MODE: CompletionType = CompletionType::List;
if let Some(line_editor_vars) = config.var("line_editor") {
for (idx, value) in line_editor_vars.row_entries() {
match idx.as_ref() {
"max_history_size" => {
if let Ok(max_history_size) = value.as_u64() {
rl.set_max_history_size(max_history_size as usize);
}
}
"history_duplicates" => {
// history_duplicates = match value.as_string() {
// Ok(s) if s.to_lowercase() == "alwaysadd" => {
// rustyline::config::HistoryDuplicates::AlwaysAdd
// }
// Ok(s) if s.to_lowercase() == "ignoreconsecutive" => {
// rustyline::config::HistoryDuplicates::IgnoreConsecutive
// }
// _ => rustyline::config::HistoryDuplicates::AlwaysAdd,
// };
if let Ok(history_duplicates) = value.as_bool() {
rl.set_history_ignore_dups(history_duplicates);
}
}
"history_ignore_space" => {
if let Ok(history_ignore_space) = value.as_bool() {
rl.set_history_ignore_space(history_ignore_space);
}
}
"completion_type" => {
let completion_type = match value.as_string() {
Ok(s) if s.to_lowercase() == "circular" => {
rustyline::config::CompletionType::Circular
}
Ok(s) if s.to_lowercase() == "list" => {
rustyline::config::CompletionType::List
}
#[cfg(all(unix, feature = "with-fuzzy"))]
Ok(s) if s.to_lowercase() == "fuzzy" => {
rustyline::config::CompletionType::Fuzzy
}
_ => DEFAULT_COMPLETION_MODE,
};
rl.set_completion_type(completion_type);
}
"completion_prompt_limit" => {
if let Ok(completion_prompt_limit) = value.as_u64() {
rl.set_completion_prompt_limit(completion_prompt_limit as usize);
}
}
"keyseq_timeout_ms" => {
if let Ok(keyseq_timeout_ms) = value.as_u64() {
rl.set_keyseq_timeout(keyseq_timeout_ms as i32);
}
}
"edit_mode" => {
let edit_mode = match value.as_string() {
Ok(s) if s.to_lowercase() == "vi" => rustyline::config::EditMode::Vi,
Ok(s) if s.to_lowercase() == "emacs" => rustyline::config::EditMode::Emacs,
_ => rustyline::config::EditMode::Emacs,
};
rl.set_edit_mode(edit_mode);
// Note: When edit_mode is Emacs, the keyseq_timeout_ms is set to -1
// no matter what you may have configured. This is so that key chords
// can be applied without having to do them in a given timeout. So,
// it essentially turns off the keyseq timeout.
}
"auto_add_history" => {
if let Ok(auto_add_history) = value.as_bool() {
rl.set_auto_add_history(auto_add_history);
}
}
"bell_style" => {
let bell_style = match value.as_string() {
Ok(s) if s.to_lowercase() == "audible" => {
rustyline::config::BellStyle::Audible
}
Ok(s) if s.to_lowercase() == "none" => rustyline::config::BellStyle::None,
Ok(s) if s.to_lowercase() == "visible" => {
rustyline::config::BellStyle::Visible
}
_ => rustyline::config::BellStyle::default(),
};
rl.set_bell_style(bell_style);
}
"color_mode" => {
let color_mode = match value.as_string() {
Ok(s) if s.to_lowercase() == "enabled" => rustyline::ColorMode::Enabled,
Ok(s) if s.to_lowercase() == "forced" => rustyline::ColorMode::Forced,
Ok(s) if s.to_lowercase() == "disabled" => rustyline::ColorMode::Disabled,
_ => rustyline::ColorMode::Enabled,
};
rl.set_color_mode(color_mode);
}
"tab_stop" => {
if let Ok(tab_stop) = value.as_u64() {
rl.set_tab_stop(tab_stop as usize);
}
}
_ => (),
}
}
}
Ok(())
}
#[cfg(feature = "rustyline-support")]
pub fn nu_line_editor_helper(
context: &EvaluationContext,
config: &dyn nu_data::config::Conf,
) -> crate::shell::Helper {
let hinter = rustyline_hinter(config);
crate::shell::Helper::new(context.clone(), hinter)
}
#[cfg(feature = "rustyline-support")]
pub fn rustyline_hinter(
config: &dyn nu_data::config::Conf,
) -> Option<rustyline::hint::HistoryHinter> {
if let Some(line_editor_vars) = config.var("line_editor") {
for (idx, value) in line_editor_vars.row_entries() {
if idx == "show_hints" && value.expect_string() == "false" {
return None;
}
}
}
Some(rustyline::hint::HistoryHinter {})
}
pub fn configure_ctrl_c(_context: &EvaluationContext) -> Result<(), Box<dyn Error>> {
#[cfg(feature = "ctrlc")]
{
let cc = _context.ctrl_c().clone();
ctrlc::set_handler(move || {
cc.store(true, Ordering::SeqCst);
})?;
if _context.ctrl_c().load(Ordering::SeqCst) {
_context.ctrl_c().store(false, Ordering::SeqCst);
}
}
Ok(())
}

View File

@ -0,0 +1,724 @@
use {
nu_ansi_term::{ansi::RESET, Style},
reedline::{
menu_functions::string_difference, Completer, LineBuffer, Menu, MenuEvent, MenuTextStyle,
Painter, Suggestion,
},
};
/// Default values used as reference for the menu. These values are set during
/// the initial declaration of the menu and are always kept as reference for the
/// changeable [`WorkingDetails`]
struct DefaultMenuDetails {
/// Number of columns that the menu will have
pub columns: u16,
/// Column width
pub col_width: Option<usize>,
/// Column padding
pub col_padding: usize,
/// Number of rows for commands
pub selection_rows: u16,
/// Number of rows allowed to display the description
pub description_rows: usize,
}
impl Default for DefaultMenuDetails {
fn default() -> Self {
Self {
columns: 4,
col_width: None,
col_padding: 2,
selection_rows: 4,
description_rows: 10,
}
}
}
/// Represents the actual column conditions of the menu. These conditions change
/// since they need to accommodate possible different line sizes for the column values
#[derive(Default)]
struct WorkingDetails {
/// Number of columns that the menu will have
pub columns: u16,
/// Column width
pub col_width: usize,
/// Number of rows for description
pub description_rows: usize,
}
/// Completion menu definition
pub struct DescriptionMenu {
/// Menu name
name: String,
/// Menu status
active: bool,
/// Menu coloring
color: MenuTextStyle,
/// Default column details that are set when creating the menu
/// These values are the reference for the working details
default_details: DefaultMenuDetails,
/// Number of minimum rows that are displayed when
/// the required lines is larger than the available lines
min_rows: u16,
/// Working column details keep changing based on the collected values
working_details: WorkingDetails,
/// Menu cached values
values: Vec<Suggestion>,
/// column position of the cursor. Starts from 0
col_pos: u16,
/// row position in the menu. Starts from 0
row_pos: u16,
/// Menu marker when active
marker: String,
/// Event sent to the menu
event: Option<MenuEvent>,
/// String collected after the menu is activated
input: Option<String>,
/// Examples to select
examples: Vec<String>,
/// Example index
example_index: Option<usize>,
/// Examples may not be shown if there is not enough space in the screen
show_examples: bool,
/// Skipped description rows
skipped_rows: usize,
/// Calls the completer using only the line buffer difference difference
/// after the menu was activated
only_buffer_difference: bool,
}
impl Default for DescriptionMenu {
fn default() -> Self {
Self {
name: "description_menu".to_string(),
active: false,
color: MenuTextStyle::default(),
default_details: DefaultMenuDetails::default(),
min_rows: 3,
working_details: WorkingDetails::default(),
values: Vec::new(),
col_pos: 0,
row_pos: 0,
marker: "? ".to_string(),
event: None,
input: None,
examples: Vec::new(),
example_index: None,
show_examples: true,
skipped_rows: 0,
only_buffer_difference: true,
}
}
}
// Menu configuration
impl DescriptionMenu {
/// Menu builder with new name
pub fn with_name(mut self, name: &str) -> Self {
self.name = name.into();
self
}
/// Menu builder with new value for text style
pub fn with_text_style(mut self, text_style: Style) -> Self {
self.color.text_style = text_style;
self
}
/// Menu builder with new value for text style
pub fn with_selected_text_style(mut self, selected_text_style: Style) -> Self {
self.color.selected_text_style = selected_text_style;
self
}
/// Menu builder with new value for text style
pub fn with_description_text_style(mut self, description_text_style: Style) -> Self {
self.color.description_style = description_text_style;
self
}
/// Menu builder with new columns value
pub fn with_columns(mut self, columns: u16) -> Self {
self.default_details.columns = columns;
self
}
/// Menu builder with new column width value
pub fn with_column_width(mut self, col_width: Option<usize>) -> Self {
self.default_details.col_width = col_width;
self
}
/// Menu builder with new column width value
pub fn with_column_padding(mut self, col_padding: usize) -> Self {
self.default_details.col_padding = col_padding;
self
}
/// Menu builder with new selection rows value
pub fn with_selection_rows(mut self, selection_rows: u16) -> Self {
self.default_details.selection_rows = selection_rows;
self
}
/// Menu builder with new description rows value
pub fn with_description_rows(mut self, description_rows: usize) -> Self {
self.default_details.description_rows = description_rows;
self
}
/// Menu builder with marker
pub fn with_marker(mut self, marker: String) -> Self {
self.marker = marker;
self
}
/// Menu builder with new only buffer difference
pub fn with_only_buffer_difference(mut self, only_buffer_difference: bool) -> Self {
self.only_buffer_difference = only_buffer_difference;
self
}
}
// Menu functionality
impl DescriptionMenu {
/// Move menu cursor to the next element
fn move_next(&mut self) {
let mut new_col = self.col_pos + 1;
let mut new_row = self.row_pos;
if new_col >= self.get_cols() {
new_row += 1;
new_col = 0;
}
if new_row >= self.get_rows() {
new_row = 0;
new_col = 0;
}
let position = new_row * self.get_cols() + new_col;
if position >= self.get_values().len() as u16 {
self.reset_position();
} else {
self.col_pos = new_col;
self.row_pos = new_row;
}
}
/// Move menu cursor to the previous element
fn move_previous(&mut self) {
let new_col = self.col_pos.checked_sub(1);
let (new_col, new_row) = match new_col {
Some(col) => (col, self.row_pos),
None => match self.row_pos.checked_sub(1) {
Some(row) => (self.get_cols().saturating_sub(1), row),
None => (
self.get_cols().saturating_sub(1),
self.get_rows().saturating_sub(1),
),
},
};
let position = new_row * self.get_cols() + new_col;
if position >= self.get_values().len() as u16 {
self.col_pos = (self.get_values().len() as u16 % self.get_cols()).saturating_sub(1);
self.row_pos = self.get_rows().saturating_sub(1);
} else {
self.col_pos = new_col;
self.row_pos = new_row;
}
}
/// Menu index based on column and row position
fn index(&self) -> usize {
let index = self.row_pos * self.get_cols() + self.col_pos;
index as usize
}
/// Get selected value from the menu
fn get_value(&self) -> Option<Suggestion> {
self.get_values().get(self.index()).cloned()
}
/// Calculates how many rows the Menu will use
fn get_rows(&self) -> u16 {
let values = self.get_values().len() as u16;
if values == 0 {
// When the values are empty the no_records_msg is shown, taking 1 line
return 1;
}
let rows = values / self.get_cols();
if values % self.get_cols() != 0 {
rows + 1
} else {
rows
}
}
/// Returns working details col width
fn get_width(&self) -> usize {
self.working_details.col_width
}
/// Reset menu position
fn reset_position(&mut self) {
self.col_pos = 0;
self.row_pos = 0;
self.skipped_rows = 0;
}
fn no_records_msg(&self, use_ansi_coloring: bool) -> String {
let msg = "TYPE TO START SEARCH";
if use_ansi_coloring {
format!(
"{}{}{}",
self.color.selected_text_style.prefix(),
msg,
RESET
)
} else {
msg.to_string()
}
}
/// Returns working details columns
fn get_cols(&self) -> u16 {
self.working_details.columns.max(1)
}
/// End of line for menu
fn end_of_line(&self, column: u16, index: usize) -> &str {
let is_last = index == self.values.len().saturating_sub(1);
if column == self.get_cols().saturating_sub(1) || is_last {
"\r\n"
} else {
""
}
}
/// Update list of examples from the actual value
fn update_examples(&mut self) {
self.examples = self
.get_value()
.and_then(|suggestion| suggestion.extra)
.unwrap_or_default();
self.example_index = None;
}
/// Creates default string that represents one suggestion from the menu
fn create_entry_string(
&self,
suggestion: &Suggestion,
index: usize,
column: u16,
empty_space: usize,
use_ansi_coloring: bool,
) -> String {
if use_ansi_coloring {
if index == self.index() {
format!(
"{}{}{}{:>empty$}{}",
self.color.selected_text_style.prefix(),
&suggestion.value,
RESET,
"",
self.end_of_line(column, index),
empty = empty_space,
)
} else {
format!(
"{}{}{}{:>empty$}{}",
self.color.text_style.prefix(),
&suggestion.value,
RESET,
"",
self.end_of_line(column, index),
empty = empty_space,
)
}
} else {
// If no ansi coloring is found, then the selection word is
// the line in uppercase
let (marker, empty_space) = if index == self.index() {
(">", empty_space.saturating_sub(1))
} else {
("", empty_space)
};
let line = format!(
"{}{}{:>empty$}{}",
marker,
&suggestion.value,
"",
self.end_of_line(column, index),
empty = empty_space,
);
if index == self.index() {
line.to_uppercase()
} else {
line
}
}
}
/// Description string with color
fn create_description_string(&self, use_ansi_coloring: bool) -> String {
let description = self
.get_value()
.and_then(|suggestion| suggestion.description)
.unwrap_or_else(|| "".to_string())
.lines()
.skip(self.skipped_rows)
.take(self.working_details.description_rows)
.collect::<Vec<&str>>()
.join("\r\n");
if use_ansi_coloring && !description.is_empty() {
format!(
"{}{}{}",
self.color.description_style.prefix(),
description,
RESET,
)
} else {
description
}
}
/// Selectable list of examples from the actual value
fn create_example_string(&self, use_ansi_coloring: bool) -> String {
if !self.show_examples {
return "".into();
}
let examples: String = self
.examples
.iter()
.enumerate()
.map(|(index, example)| {
if let Some(example_index) = self.example_index {
if index == example_index {
format!(
" {}{}{}\r\n",
self.color.selected_text_style.prefix(),
example,
RESET
)
} else {
format!(" {}\r\n", example)
}
} else {
format!(" {}\r\n", example)
}
})
.collect();
if examples.is_empty() {
"".into()
} else if use_ansi_coloring {
format!(
"{}\r\n\r\nExamples:\r\n{}{}",
self.color.description_style.prefix(),
RESET,
examples,
)
} else {
format!("\r\n\r\nExamples:\r\n{}", examples,)
}
}
}
impl Menu for DescriptionMenu {
/// Menu name
fn name(&self) -> &str {
self.name.as_str()
}
/// Menu indicator
fn indicator(&self) -> &str {
self.marker.as_str()
}
/// Deactivates context menu
fn is_active(&self) -> bool {
self.active
}
/// The menu stays active even with one record
fn can_quick_complete(&self) -> bool {
false
}
/// The menu does not need to partially complete
fn can_partially_complete(
&mut self,
_values_updated: bool,
_line_buffer: &mut LineBuffer,
_completer: &mut dyn Completer,
) -> bool {
false
}
/// Selects what type of event happened with the menu
fn menu_event(&mut self, event: MenuEvent) {
match &event {
MenuEvent::Activate(_) => self.active = true,
MenuEvent::Deactivate => {
self.active = false;
self.input = None;
self.values = Vec::new();
}
_ => {}
};
self.event = Some(event);
}
/// Updates menu values
fn update_values(&mut self, line_buffer: &mut LineBuffer, completer: &mut dyn Completer) {
if self.only_buffer_difference {
if let Some(old_string) = &self.input {
let (start, input) = string_difference(line_buffer.get_buffer(), old_string);
if !input.is_empty() {
self.reset_position();
self.values = completer.complete(input, start);
}
}
} else {
let trimmed_buffer = line_buffer.get_buffer().replace('\n', " ");
self.values =
completer.complete(trimmed_buffer.as_str(), line_buffer.insertion_point());
self.reset_position();
}
}
/// The working details for the menu changes based on the size of the lines
/// collected from the completer
fn update_working_details(
&mut self,
line_buffer: &mut LineBuffer,
completer: &mut dyn Completer,
painter: &Painter,
) {
if let Some(event) = self.event.take() {
// Updating all working parameters from the menu before executing any of the
// possible event
let max_width = self.get_values().iter().fold(0, |acc, suggestion| {
let str_len = suggestion.value.len() + self.default_details.col_padding;
if str_len > acc {
str_len
} else {
acc
}
});
// If no default width is found, then the total screen width is used to estimate
// the column width based on the default number of columns
let default_width = if let Some(col_width) = self.default_details.col_width {
col_width
} else {
let col_width = painter.screen_width() / self.default_details.columns;
col_width as usize
};
// Adjusting the working width of the column based the max line width found
// in the menu values
if max_width > default_width {
self.working_details.col_width = max_width;
} else {
self.working_details.col_width = default_width;
};
// The working columns is adjusted based on possible number of columns
// that could be fitted in the screen with the calculated column width
let possible_cols = painter.screen_width() / self.working_details.col_width as u16;
if possible_cols > self.default_details.columns {
self.working_details.columns = self.default_details.columns.max(1);
} else {
self.working_details.columns = possible_cols;
}
// Updating the working rows to display the description
if self.menu_required_lines(painter.screen_width()) <= painter.remaining_lines() {
self.working_details.description_rows = self.default_details.description_rows;
self.show_examples = true;
} else {
self.working_details.description_rows = painter
.remaining_lines()
.saturating_sub(self.default_details.selection_rows + 1)
as usize;
self.show_examples = false;
}
match event {
MenuEvent::Activate(_) => {
self.reset_position();
self.input = Some(line_buffer.get_buffer().to_string());
self.update_values(line_buffer, completer);
}
MenuEvent::Deactivate => self.active = false,
MenuEvent::Edit(_) => {
self.reset_position();
self.update_values(line_buffer, completer);
self.update_examples()
}
MenuEvent::NextElement => {
self.skipped_rows = 0;
self.move_next();
self.update_examples();
}
MenuEvent::PreviousElement => {
self.skipped_rows = 0;
self.move_previous();
self.update_examples();
}
MenuEvent::MoveUp => {
if let Some(example_index) = self.example_index {
if let Some(index) = example_index.checked_sub(1) {
self.example_index = Some(index);
} else {
self.example_index = Some(self.examples.len().saturating_sub(1));
}
} else if !self.examples.is_empty() {
self.example_index = Some(0);
}
}
MenuEvent::MoveDown => {
if let Some(example_index) = self.example_index {
let index = example_index + 1;
if index < self.examples.len() {
self.example_index = Some(index);
} else {
self.example_index = Some(0);
}
} else if !self.examples.is_empty() {
self.example_index = Some(0);
}
}
MenuEvent::MoveLeft => self.skipped_rows = self.skipped_rows.saturating_sub(1),
MenuEvent::MoveRight => {
let skipped = self.skipped_rows + 1;
let description_rows = self
.get_value()
.and_then(|suggestion| suggestion.description)
.unwrap_or_else(|| "".to_string())
.lines()
.count();
let allowed_skips =
description_rows.saturating_sub(self.working_details.description_rows);
if skipped < allowed_skips {
self.skipped_rows = skipped;
} else {
self.skipped_rows = allowed_skips;
}
}
MenuEvent::PreviousPage | MenuEvent::NextPage => {}
}
}
}
/// The buffer gets replaced in the Span location
fn replace_in_buffer(&self, line_buffer: &mut LineBuffer) {
if let Some(Suggestion { value, span, .. }) = self.get_value() {
let start = span.start.min(line_buffer.len());
let end = span.end.min(line_buffer.len());
let string_len = if let Some(example_index) = self.example_index {
let example = self
.examples
.get(example_index)
.expect("the example index is always checked");
line_buffer.replace(start..end, example);
example.len()
} else {
line_buffer.replace(start..end, &value);
value.len()
};
let mut offset = line_buffer.insertion_point();
offset += string_len.saturating_sub(end.saturating_sub(start));
line_buffer.set_insertion_point(offset);
}
}
/// Minimum rows that should be displayed by the menu
fn min_rows(&self) -> u16 {
self.get_rows().min(self.min_rows)
}
/// Gets values from filler that will be displayed in the menu
fn get_values(&self) -> &[Suggestion] {
&self.values
}
fn menu_required_lines(&self, _terminal_columns: u16) -> u16 {
let example_lines = self
.examples
.iter()
.fold(0, |acc, example| example.lines().count() + acc);
self.default_details.selection_rows
+ self.default_details.description_rows as u16
+ example_lines as u16
+ 3
}
fn menu_string(&self, _available_lines: u16, use_ansi_coloring: bool) -> String {
if self.get_values().is_empty() {
self.no_records_msg(use_ansi_coloring)
} else {
// The skip values represent the number of lines that should be skipped
// while printing the menu
let available_lines = self.default_details.selection_rows;
let skip_values = if self.row_pos >= available_lines {
let skip_lines = self.row_pos.saturating_sub(available_lines) + 1;
(skip_lines * self.get_cols()) as usize
} else {
0
};
// It seems that crossterm prefers to have a complete string ready to be printed
// rather than looping through the values and printing multiple things
// This reduces the flickering when printing the menu
let available_values = (available_lines * self.get_cols()) as usize;
let selection_values: String = self
.get_values()
.iter()
.skip(skip_values)
.take(available_values)
.enumerate()
.map(|(index, suggestion)| {
// Correcting the enumerate index based on the number of skipped values
let index = index + skip_values;
let column = index as u16 % self.get_cols();
let empty_space = self.get_width().saturating_sub(suggestion.value.len());
self.create_entry_string(
suggestion,
index,
column,
empty_space,
use_ansi_coloring,
)
})
.collect();
format!(
"{}{}{}",
selection_values,
self.create_description_string(use_ansi_coloring),
self.create_example_string(use_ansi_coloring)
)
}
}
}

View File

@ -0,0 +1,112 @@
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>);
impl NuHelpCompleter {
pub fn new(engine_state: Arc<EngineState>) -> Self {
Self(engine_state)
}
fn completion_helper(&self, line: &str, pos: usize) -> Vec<Suggestion> {
let full_commands = self.0.get_signatures_with_examples(false);
//Vec<(Signature, Vec<Example>, bool, bool)> {
let mut commands = full_commands
.iter()
.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()
.contains(&line.to_lowercase())
})
.collect::<Vec<_>>();
commands.sort_by(|(a, _, _, _), (b, _, _, _)| {
let a_distance = levenshtein_distance(line, &a.name);
let b_distance = levenshtein_distance(line, &b.name);
a_distance.cmp(&b_distance)
});
commands
.into_iter()
.map(|(sig, examples, _, _)| {
let mut long_desc = String::new();
let usage = &sig.usage;
if !usage.is_empty() {
long_desc.push_str(usage);
long_desc.push_str("\r\n\r\n");
}
let extra_usage = &sig.extra_usage;
if !extra_usage.is_empty() {
long_desc.push_str(extra_usage);
long_desc.push_str("\r\n\r\n");
}
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))
}
if !sig.required_positional.is_empty()
|| !sig.optional_positional.is_empty()
|| sig.rest_positional.is_some()
{
long_desc.push_str("\r\nParameters:\r\n");
for positional in &sig.required_positional {
let _ = write!(long_desc, " {}: {}\r\n", positional.name, positional.desc);
}
for positional in &sig.optional_positional {
let _ = write!(
long_desc,
" (optional) {}: {}\r\n",
positional.name, positional.desc
);
}
if let Some(rest_positional) = &sig.rest_positional {
let _ = write!(
long_desc,
" ...{}: {}\r\n",
rest_positional.name, rest_positional.desc
);
}
}
let extra: Vec<String> = examples
.iter()
.map(|example| example.example.replace('\n', "\r\n"))
.collect();
Suggestion {
value: sig.name.clone(),
description: Some(long_desc),
extra: Some(extra),
span: reedline::Span {
start: pos,
end: pos + line.len(),
},
append_whitespace: false,
}
})
.collect()
}
}
impl Completer for NuHelpCompleter {
fn complete(&mut self, line: &str, pos: usize) -> Vec<Suggestion> {
self.completion_helper(line, pos)
}
}

View File

@ -0,0 +1,176 @@
use nu_engine::eval_block;
use nu_protocol::{
engine::{EngineState, Stack},
IntoPipelineData, Span, Value,
};
use reedline::{menu_functions::parse_selection_char, Completer, Suggestion};
use std::sync::Arc;
const SELECTION_CHAR: char = '!';
pub struct NuMenuCompleter {
block_id: usize,
span: Span,
stack: Stack,
engine_state: Arc<EngineState>,
only_buffer_difference: bool,
}
impl NuMenuCompleter {
pub fn new(
block_id: usize,
span: Span,
stack: Stack,
engine_state: Arc<EngineState>,
only_buffer_difference: bool,
) -> Self {
Self {
block_id,
span,
stack,
engine_state,
only_buffer_difference,
}
}
}
impl Completer for NuMenuCompleter {
fn complete(&mut self, line: &str, pos: usize) -> Vec<Suggestion> {
let parsed = parse_selection_char(line, SELECTION_CHAR);
let block = self.engine_state.get_block(self.block_id);
if let Some(buffer) = block.signature.get_positional(0) {
if let Some(buffer_id) = &buffer.var_id {
let line_buffer = Value::String {
val: parsed.remainder.to_string(),
span: self.span,
};
self.stack.add_var(*buffer_id, line_buffer);
}
}
if let Some(position) = block.signature.get_positional(1) {
if let Some(position_id) = &position.var_id {
let line_buffer = Value::Int {
val: pos as i64,
span: self.span,
};
self.stack.add_var(*position_id, line_buffer);
}
}
let input = Value::nothing(self.span).into_pipeline_data();
let res = eval_block(
&self.engine_state,
&mut self.stack,
block,
input,
false,
false,
);
if let Ok(values) = res {
let values = values.into_value(self.span);
convert_to_suggestions(values, line, pos, self.only_buffer_difference)
} else {
Vec::new()
}
}
}
fn convert_to_suggestions(
value: Value,
line: &str,
pos: usize,
only_buffer_difference: bool,
) -> Vec<Suggestion> {
match value {
Value::Record { .. } => {
let text = match value
.get_data_by_key("value")
.and_then(|val| val.as_string().ok())
{
Some(val) => val,
None => "No value key".to_string(),
};
let description = value
.get_data_by_key("description")
.and_then(|val| val.as_string().ok());
let span = match value.get_data_by_key("span") {
Some(span @ Value::Record { .. }) => {
let start = span
.get_data_by_key("start")
.and_then(|val| val.as_integer().ok());
let end = span
.get_data_by_key("end")
.and_then(|val| val.as_integer().ok());
match (start, end) {
(Some(start), Some(end)) => {
let start = start.min(end);
reedline::Span {
start: start as usize,
end: end as usize,
}
}
_ => reedline::Span {
start: if only_buffer_difference { pos } else { 0 },
end: if only_buffer_difference {
pos + line.len()
} else {
line.len()
},
},
}
}
_ => reedline::Span {
start: if only_buffer_difference { pos } else { 0 },
end: if only_buffer_difference {
pos + line.len()
} else {
line.len()
},
},
};
let extra = match value.get_data_by_key("extra") {
Some(Value::List { vals, .. }) => {
let extra: Vec<String> = vals
.into_iter()
.filter_map(|extra| match extra {
Value::String { val, .. } => Some(val),
_ => None,
})
.collect();
Some(extra)
}
_ => None,
};
vec![Suggestion {
value: text,
description,
extra,
span,
append_whitespace: false,
}]
}
Value::List { vals, .. } => vals
.into_iter()
.flat_map(|val| convert_to_suggestions(val, line, pos, only_buffer_difference))
.collect(),
_ => vec![Suggestion {
value: format!("Not a record: {:?}", value),
description: None,
extra: None,
span: reedline::Span {
start: 0,
end: line.len(),
},
append_whitespace: false,
}],
}
}

View File

@ -0,0 +1,7 @@
mod description_menu;
mod help_completions;
mod menu_completions;
pub use description_menu::DescriptionMenu;
pub use help_completions::NuHelpCompleter;
pub use menu_completions::NuMenuCompleter;

View File

@ -0,0 +1,67 @@
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Value};
use reedline::Highlighter;
#[derive(Clone)]
pub struct NuHighlight;
impl Command for NuHighlight {
fn name(&self) -> &str {
"nu-highlight"
}
fn signature(&self) -> Signature {
Signature::build("nu-highlight").category(Category::Strings)
}
fn usage(&self) -> &str {
"Syntax highlight the input string."
}
fn search_terms(&self) -> Vec<&str> {
vec!["syntax", "color", "convert"]
}
fn run(
&self,
engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let ctrlc = engine_state.ctrlc.clone();
let engine_state = engine_state.clone();
let config = engine_state.get_config().clone();
let highlighter = crate::NuHighlighter {
engine_state,
config,
};
input.map(
move |x| match x.as_string() {
Ok(line) => {
let highlights = highlighter.highlight(&line, line.len());
Value::String {
val: highlights.render_simple(),
span: head,
}
}
Err(err) => Value::Error { error: err },
},
ctrlc,
)
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Describe the type of a string",
example: "'let x = 3' | nu-highlight",
result: None,
}]
}
}

View File

@ -0,0 +1,68 @@
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Value,
};
#[derive(Clone)]
pub struct Print;
impl Command for Print {
fn name(&self) -> &str {
"print"
}
fn signature(&self) -> Signature {
Signature::build("print")
.rest("rest", SyntaxShape::Any, "the values to print")
.switch(
"no-newline",
"print without inserting a newline for the line ending",
Some('n'),
)
.category(Category::Strings)
}
fn usage(&self) -> &str {
"Prints the values given"
}
fn search_terms(&self) -> Vec<&str> {
vec!["display"]
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
_input: PipelineData,
) -> Result<PipelineData, ShellError> {
let args: Vec<Value> = call.rest(engine_state, stack, 0)?;
let no_newline = call.has_flag("no-newline");
let head = call.head;
for arg in args {
arg.into_pipeline_data()
.print(engine_state, stack, no_newline)?;
}
Ok(PipelineData::new(head))
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Print 'hello world'",
example: r#"print "hello world""#,
result: None,
},
Example {
description: "Print the sum of 2 and 3",
example: r#"print (2 + 3)"#,
result: None,
},
]
}
}

159
crates/nu-cli/src/prompt.rs Normal file
View File

@ -0,0 +1,159 @@
use reedline::DefaultPrompt;
use {
reedline::{
Prompt, PromptEditMode, PromptHistorySearch, PromptHistorySearchStatus, PromptViMode,
},
std::borrow::Cow,
};
/// Nushell prompt definition
#[derive(Clone)]
pub struct NushellPrompt {
left_prompt_string: Option<String>,
right_prompt_string: Option<String>,
default_prompt_indicator: Option<String>,
default_vi_insert_prompt_indicator: Option<String>,
default_vi_normal_prompt_indicator: Option<String>,
default_multiline_indicator: Option<String>,
}
impl Default for NushellPrompt {
fn default() -> Self {
NushellPrompt::new()
}
}
impl NushellPrompt {
pub fn new() -> NushellPrompt {
NushellPrompt {
left_prompt_string: None,
right_prompt_string: None,
default_prompt_indicator: None,
default_vi_insert_prompt_indicator: None,
default_vi_normal_prompt_indicator: None,
default_multiline_indicator: None,
}
}
pub fn update_prompt_left(&mut self, prompt_string: Option<String>) {
self.left_prompt_string = prompt_string;
}
pub fn update_prompt_right(&mut self, prompt_string: Option<String>) {
self.right_prompt_string = prompt_string;
}
pub fn update_prompt_indicator(&mut self, prompt_indicator_string: Option<String>) {
self.default_prompt_indicator = prompt_indicator_string;
}
pub fn update_prompt_vi_insert(&mut self, prompt_vi_insert_string: Option<String>) {
self.default_vi_insert_prompt_indicator = prompt_vi_insert_string;
}
pub fn update_prompt_vi_normal(&mut self, prompt_vi_normal_string: Option<String>) {
self.default_vi_normal_prompt_indicator = prompt_vi_normal_string;
}
pub fn update_prompt_multiline(&mut self, prompt_multiline_indicator_string: Option<String>) {
self.default_multiline_indicator = prompt_multiline_indicator_string;
}
pub fn update_all_prompt_strings(
&mut self,
left_prompt_string: Option<String>,
right_prompt_string: Option<String>,
prompt_indicator_string: Option<String>,
prompt_multiline_indicator_string: Option<String>,
prompt_vi: (Option<String>, Option<String>),
) {
let (prompt_vi_insert_string, prompt_vi_normal_string) = prompt_vi;
self.left_prompt_string = left_prompt_string;
self.right_prompt_string = right_prompt_string;
self.default_prompt_indicator = prompt_indicator_string;
self.default_multiline_indicator = prompt_multiline_indicator_string;
self.default_vi_insert_prompt_indicator = prompt_vi_insert_string;
self.default_vi_normal_prompt_indicator = prompt_vi_normal_string;
}
fn default_wrapped_custom_string(&self, str: String) -> String {
format!("({})", str)
}
}
impl Prompt for NushellPrompt {
fn render_prompt_left(&self) -> Cow<str> {
if let Some(prompt_string) = &self.left_prompt_string {
prompt_string.replace('\n', "\r\n").into()
} else {
let default = DefaultPrompt::new();
default
.render_prompt_left()
.to_string()
.replace('\n', "\r\n")
.into()
}
}
fn render_prompt_right(&self) -> Cow<str> {
if let Some(prompt_string) = &self.right_prompt_string {
prompt_string.replace('\n', "\r\n").into()
} else {
let default = DefaultPrompt::new();
default
.render_prompt_right()
.to_string()
.replace('\n', "\r\n")
.into()
}
}
fn render_prompt_indicator(&self, edit_mode: PromptEditMode) -> Cow<str> {
match edit_mode {
PromptEditMode::Default => match &self.default_prompt_indicator {
Some(indicator) => indicator.as_str().into(),
None => "".into(),
},
PromptEditMode::Emacs => match &self.default_prompt_indicator {
Some(indicator) => indicator.as_str().into(),
None => "".into(),
},
PromptEditMode::Vi(vi_mode) => match vi_mode {
PromptViMode::Normal => match &self.default_vi_normal_prompt_indicator {
Some(indicator) => indicator.as_str().into(),
None => ": ".into(),
},
PromptViMode::Insert => match &self.default_vi_insert_prompt_indicator {
Some(indicator) => indicator.as_str().into(),
None => "".into(),
},
},
PromptEditMode::Custom(str) => self.default_wrapped_custom_string(str).into(),
}
}
fn render_prompt_multiline_indicator(&self) -> Cow<str> {
match &self.default_multiline_indicator {
Some(indicator) => indicator.as_str().into(),
None => "::: ".into(),
}
}
fn render_prompt_history_search_indicator(
&self,
history_search: PromptHistorySearch,
) -> Cow<str> {
let prefix = match history_search.status {
PromptHistorySearchStatus::Passing => "",
PromptHistorySearchStatus::Failing => "failing ",
};
Cow::Owned(format!(
"({}reverse-search: {})",
prefix, history_search.term
))
}
}

View File

@ -0,0 +1,156 @@
use crate::util::report_error;
use crate::NushellPrompt;
use log::info;
use nu_engine::eval_subexpression;
use nu_protocol::{
engine::{EngineState, Stack, StateWorkingSet},
Config, PipelineData, Span, Value,
};
use reedline::Prompt;
// Name of environment variable where the prompt could be stored
pub(crate) const PROMPT_COMMAND: &str = "PROMPT_COMMAND";
pub(crate) const PROMPT_COMMAND_RIGHT: &str = "PROMPT_COMMAND_RIGHT";
pub(crate) const PROMPT_INDICATOR: &str = "PROMPT_INDICATOR";
pub(crate) const PROMPT_INDICATOR_VI_INSERT: &str = "PROMPT_INDICATOR_VI_INSERT";
pub(crate) const PROMPT_INDICATOR_VI_NORMAL: &str = "PROMPT_INDICATOR_VI_NORMAL";
pub(crate) const PROMPT_MULTILINE_INDICATOR: &str = "PROMPT_MULTILINE_INDICATOR";
fn get_prompt_string(
prompt: &str,
config: &Config,
engine_state: &EngineState,
stack: &mut Stack,
is_perf_true: bool,
) -> Option<String> {
stack
.get_env_var(engine_state, prompt)
.and_then(|v| match v {
Value::Block {
val: block_id,
captures,
..
} => {
let block = engine_state.get_block(block_id);
let mut stack = stack.captures_to_stack(&captures);
// Use eval_subexpression to force a redirection of output, so we can use everything in prompt
let ret_val = eval_subexpression(
engine_state,
&mut stack,
block,
PipelineData::new(Span::new(0, 0)), // Don't try this at home, 0 span is ignored
);
if is_perf_true {
info!(
"get_prompt_string (block) {}:{}:{}",
file!(),
line!(),
column!()
);
}
match ret_val {
Ok(ret_val) => Some(ret_val),
Err(err) => {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &err);
None
}
}
}
Value::String { .. } => Some(PipelineData::Value(v.clone(), None)),
_ => None,
})
.and_then(|pipeline_data| {
let output = pipeline_data.collect_string("", config).ok();
match output {
Some(mut x) => {
// Just remove the very last newline.
if x.ends_with('\n') {
x.pop();
}
if x.ends_with('\r') {
x.pop();
}
Some(x)
}
None => None,
}
})
}
pub(crate) fn update_prompt<'prompt>(
config: &Config,
engine_state: &EngineState,
stack: &Stack,
nu_prompt: &'prompt mut NushellPrompt,
is_perf_true: bool,
) -> &'prompt dyn Prompt {
let mut stack = stack.clone();
let left_prompt_string = get_prompt_string(
PROMPT_COMMAND,
config,
engine_state,
&mut stack,
is_perf_true,
);
let right_prompt_string = get_prompt_string(
PROMPT_COMMAND_RIGHT,
config,
engine_state,
&mut stack,
is_perf_true,
);
let prompt_indicator_string = get_prompt_string(
PROMPT_INDICATOR,
config,
engine_state,
&mut stack,
is_perf_true,
);
let prompt_multiline_string = get_prompt_string(
PROMPT_MULTILINE_INDICATOR,
config,
engine_state,
&mut stack,
is_perf_true,
);
let prompt_vi_insert_string = get_prompt_string(
PROMPT_INDICATOR_VI_INSERT,
config,
engine_state,
&mut stack,
is_perf_true,
);
let prompt_vi_normal_string = get_prompt_string(
PROMPT_INDICATOR_VI_NORMAL,
config,
engine_state,
&mut stack,
is_perf_true,
);
// apply the other indicators
nu_prompt.update_all_prompt_strings(
left_prompt_string,
right_prompt_string,
prompt_indicator_string,
prompt_multiline_string,
(prompt_vi_insert_string, prompt_vi_normal_string),
);
let ret_val = nu_prompt as &dyn Prompt;
if is_perf_true {
info!("update_prompt {}:{}:{}", file!(), line!(), column!());
}
ret_val
}

File diff suppressed because it is too large Load Diff

576
crates/nu-cli/src/repl.rs Normal file
View File

@ -0,0 +1,576 @@
use crate::{
completions::NuCompleter,
prompt_update,
reedline_config::{add_menus, create_keybindings, KeybindingsMode},
util::{eval_source, report_error},
NuHighlighter, NuValidator, NushellPrompt,
};
use log::{info, trace};
use miette::{IntoDiagnostic, Result};
use nu_color_config::get_color_config;
use nu_engine::{convert_env_values, eval_block};
use nu_parser::lex;
use nu_protocol::{
engine::{EngineState, Stack, StateWorkingSet},
BlockId, HistoryFileFormat, PipelineData, PositionalArg, ShellError, Span, Value,
};
use reedline::{DefaultHinter, Emacs, SqliteBackedHistory, Vi};
use std::io::{self, Write};
use std::{sync::atomic::Ordering, time::Instant};
use sysinfo::SystemExt;
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,
nushell_path: &str,
is_perf_true: bool,
) -> Result<()> {
use reedline::{FileBackedHistory, Reedline, Signal};
let mut entry_num = 0;
let mut nu_prompt = NushellPrompt::new();
if is_perf_true {
info!(
"translate environment vars {}:{}:{}",
file!(),
line!(),
column!()
);
}
// Translate environment variables from Strings to Values
if let Some(e) = convert_env_values(engine_state, stack) {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &e);
}
// seed env vars
stack.add_env_var(
"CMD_DURATION_MS".into(),
Value::String {
val: "0823".to_string(),
span: Span { start: 0, end: 0 },
},
);
stack.add_env_var(
"LAST_EXIT_CODE".into(),
Value::Int {
val: 0,
span: Span { start: 0, end: 0 },
},
);
if is_perf_true {
info!(
"load config initially {}:{}:{}",
file!(),
line!(),
column!()
);
}
// Get the config once for the history `max_history_size`
// Updating that will not be possible in one session
let mut config = engine_state.get_config();
if is_perf_true {
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<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!(
"load config each loop {}:{}:{}",
file!(),
line!(),
column!()
);
}
//Reset the ctrl-c handler
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();
if is_perf_true {
info!("setup colors {}:{}:{}", file!(), line!(), column!());
}
let color_hm = get_color_config(config);
if is_perf_true {
info!("update reedline {}:{}:{}", file!(), line!(), column!());
}
let engine_reference = std::sync::Arc::new(engine_state.clone());
line_editor = line_editor
.with_highlighter(Box::new(NuHighlighter {
engine_state: engine_state.clone(),
config: config.clone(),
}))
.with_animation(config.animate_prompt)
.with_validator(Box::new(NuValidator {
engine_state: engine_state.clone(),
}))
.with_completer(Box::new(NuCompleter::new(
engine_reference.clone(),
stack.clone(),
)))
.with_quick_completions(config.quick_completions)
.with_partial_completions(config.partial_completions)
.with_ansi_colors(config.use_ansi_coloring);
line_editor = if config.use_ansi_coloring {
line_editor.with_hinter(Box::new(
DefaultHinter::default().with_style(color_hm["hints"]),
))
} else {
line_editor.disable_hints()
};
line_editor = match add_menus(line_editor, engine_reference, stack, config) {
Ok(line_editor) => line_editor,
Err(e) => {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &e);
Reedline::create()
}
};
let buffer_editor = if !config.buffer_editor.is_empty() {
Some(config.buffer_editor.clone())
} else {
stack
.get_env_var(engine_state, "EDITOR")
.map(|v| v.as_string().unwrap_or_default())
.filter(|v| !v.is_empty())
.or_else(|| {
stack
.get_env_var(engine_state, "VISUAL")
.map(|v| v.as_string().unwrap_or_default())
.filter(|v| !v.is_empty())
})
};
line_editor = if let Some(buffer_editor) = buffer_editor {
line_editor.with_buffer_editor(buffer_editor, "nu".into())
} else {
line_editor
};
if config.sync_history_on_enter {
if is_perf_true {
info!("sync history {}:{}:{}", file!(), line!(), column!());
}
line_editor.sync_history().into_diagnostic()?;
}
if is_perf_true {
info!("setup keybindings {}:{}:{}", file!(), line!(), column!());
}
// Changing the line editor based on the found keybindings
line_editor = match create_keybindings(config) {
Ok(keybindings) => match keybindings {
KeybindingsMode::Emacs(keybindings) => {
let edit_mode = Box::new(Emacs::new(keybindings));
line_editor.with_edit_mode(edit_mode)
}
KeybindingsMode::Vi {
insert_keybindings,
normal_keybindings,
} => {
let edit_mode = Box::new(Vi::new(insert_keybindings, normal_keybindings));
line_editor.with_edit_mode(edit_mode)
}
},
Err(e) => {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &e);
line_editor
}
};
if is_perf_true {
info!("prompt_update {}:{}:{}", file!(), line!(), column!());
}
// Right before we start our prompt and take input from the user,
// fire the "pre_prompt" hook
if let Some(hook) = &config.hooks.pre_prompt {
if let Err(err) = run_hook(engine_state, stack, vec![], hook) {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &err);
}
}
// Next, check all the environment variables they ask for
// fire the "env_change" hook
if let Some(hook) = config.hooks.env_change.clone() {
match hook {
Value::Record {
cols, vals: blocks, ..
} => {
for (idx, env_var) in cols.iter().enumerate() {
let before = engine_state
.previous_env_vars
.get(env_var)
.cloned()
.unwrap_or_default();
let after = stack.get_env_var(engine_state, env_var).unwrap_or_default();
if before != after {
if let Err(err) = run_hook(
engine_state,
stack,
vec![before, after.clone()],
&blocks[idx],
) {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &err);
}
engine_state
.previous_env_vars
.insert(env_var.to_string(), after);
}
}
}
x => {
let working_set = StateWorkingSet::new(engine_state);
report_error(
&working_set,
&ShellError::TypeMismatch(
"record for 'env_change' hook".to_string(),
x.span().unwrap_or_else(|_| Span::new(0, 0)),
),
)
}
}
}
config = engine_state.get_config();
let shell_integration = config.shell_integration;
if shell_integration {
run_ansi_sequence(PRE_PROMPT_MARKER)?;
}
let prompt =
prompt_update::update_prompt(config, engine_state, stack, &mut nu_prompt, is_perf_true);
entry_num += 1;
if is_perf_true {
info!(
"finished setup, starting repl {}:{}:{}",
file!(),
line!(),
column!()
);
}
let input = line_editor.read_line(prompt);
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 {
if let Err(err) = run_hook(engine_state, stack, vec![], hook) {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &err);
}
}
if shell_integration {
run_ansi_sequence(RESET_APPLICATION_MODE)?;
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
let maybe_abbrev_path = if let Some(p) = nu_path::home_dir() {
path.replace(&p.as_path().display().to_string(), "~")
} else {
path
};
// Set window title too
// https://tldp.org/HOWTO/Xterm-Title-3.html
// ESC]0;stringBEL -- Set icon name and window title to string
// ESC]1;stringBEL -- Set icon name to string
// ESC]2;stringBEL -- Set window title to string
run_ansi_sequence(&format!("\x1b]2;{}\x07", maybe_abbrev_path))?;
}
}
let start_time = Instant::now();
let tokens = lex(s.as_bytes(), 0, &[], &[], false);
// Check if this is a single call to a directory, if so auto-cd
let cwd = nu_engine::env::current_dir_str(engine_state, stack)?;
let path = nu_path::expand_path_with(&s, &cwd);
let orig = s.clone();
if (orig.starts_with('.')
|| orig.starts_with('~')
|| orig.starts_with('/')
|| orig.starts_with('\\'))
&& path.is_dir()
&& tokens.0.len() == 1
{
// We have an auto-cd
let (path, span) = {
if !path.exists() {
let working_set = StateWorkingSet::new(engine_state);
report_error(
&working_set,
&ShellError::DirectoryNotFound(tokens.0[0].span, None),
);
}
let path = nu_path::canonicalize_with(path, &cwd)
.expect("internal error: cannot canonicalize known path");
(path.to_string_lossy().to_string(), tokens.0[0].span)
};
//FIXME: this only changes the current scope, but instead this environment variable
//should probably be a block that loads the information from the state in the overlay
stack.add_env_var(
"PWD".into(),
Value::String {
val: path.clone(),
span: Span { start: 0, end: 0 },
},
);
let cwd = Value::String { val: cwd, span };
let shells = stack.get_env_var(engine_state, "NUSHELL_SHELLS");
let mut shells = if let Some(v) = shells {
v.as_list()
.map(|x| x.to_vec())
.unwrap_or_else(|_| vec![cwd])
} else {
vec![cwd]
};
let current_shell = stack.get_env_var(engine_state, "NUSHELL_CURRENT_SHELL");
let current_shell = if let Some(v) = current_shell {
v.as_integer().unwrap_or_default() as usize
} else {
0
};
shells[current_shell] = Value::String { val: path, span };
stack.add_env_var("NUSHELL_SHELLS".into(), Value::List { vals: shells, span });
} else {
trace!("eval source: {}", s);
eval_source(
engine_state,
stack,
s.as_bytes(),
&format!("entry #{}", entry_num),
PipelineData::new(Span::new(0, 0)),
);
}
let cmd_duration = start_time.elapsed();
stack.add_env_var(
"CMD_DURATION_MS".into(),
Value::String {
val: format!("{}", cmd_duration.as_millis()),
span: Span { start: 0, end: 0 },
},
);
// FIXME: permanent state changes like this hopefully in time can be removed
// and be replaced by just passing the cwd in where needed
if let Some(cwd) = stack.get_env_var(engine_state, "PWD") {
let path = cwd.as_string()?;
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;
}
Err(err) => {
let message = err.to_string();
if !message.contains("duration") {
println!("Error: {:?}", err);
}
if shell_integration {
run_ansi_sequence(CMD_FINISHED_MARKER)?;
}
}
}
}
Ok(())
}
fn run_ansi_sequence(seq: &str) -> Result<(), ShellError> {
match io::stdout().write_all(seq.as_bytes()) {
Ok(it) => it,
Err(err) => {
return Err(ShellError::GenericError(
"Error writing ansi sequence".into(),
err.to_string(),
Some(Span { start: 0, end: 0 }),
None,
Vec::new(),
));
}
};
io::stdout().flush().map_err(|e| {
ShellError::GenericError(
"Error flushing stdio".into(),
e.to_string(),
Some(Span { start: 0, end: 0 }),
None,
Vec::new(),
)
})
}
pub fn run_hook(
engine_state: &EngineState,
stack: &mut Stack,
arguments: Vec<Value>,
value: &Value,
) -> Result<(), ShellError> {
match value {
Value::List { vals, .. } => {
for val in vals {
run_hook(engine_state, stack, arguments.clone(), val)?
}
Ok(())
}
Value::Block {
val: block_id,
span,
..
} => run_hook_block(engine_state, stack, *block_id, arguments, *span),
x => match x.span() {
Ok(span) => Err(ShellError::MissingConfigValue(
"block for hook in config".into(),
span,
)),
_ => Err(ShellError::MissingConfigValue(
"block for hook in config".into(),
Span { start: 0, end: 0 },
)),
},
}
}
pub fn run_hook_block(
engine_state: &EngineState,
stack: &mut Stack,
block_id: BlockId,
arguments: Vec<Value>,
span: Span,
) -> Result<(), ShellError> {
let block = engine_state.get_block(block_id);
let input = PipelineData::new(span);
let mut callee_stack = stack.gather_captures(&block.captures);
for (idx, PositionalArg { var_id, .. }) in
block.signature.required_positional.iter().enumerate()
{
if let Some(var_id) = var_id {
callee_stack.add_var(*var_id, arguments[idx].clone())
}
}
match eval_block(engine_state, &mut callee_stack, block, input, false, false) {
Ok(pipeline_data) => match pipeline_data.into_value(span) {
Value::Error { error } => Err(error),
_ => Ok(()),
},
Err(err) => Err(err),
}
}

View File

@ -1,231 +0,0 @@
use nu_ansi_term::Color;
use nu_completion::NuCompleter;
use nu_engine::{DefaultPalette, EvaluationContext, Painter};
use nu_source::{Tag, Tagged};
use std::borrow::Cow::{self, Owned};
pub struct Helper {
completer: NuCompleter,
hinter: Option<rustyline::hint::HistoryHinter>,
context: EvaluationContext,
pub colored_prompt: String,
validator: NuValidator,
}
impl Helper {
pub(crate) fn new(
context: EvaluationContext,
hinter: Option<rustyline::hint::HistoryHinter>,
) -> Helper {
Helper {
completer: NuCompleter {},
hinter,
context,
colored_prompt: String::new(),
validator: NuValidator {},
}
}
}
use nu_protocol::{SignatureRegistry, VariableRegistry};
struct CompletionContext<'a>(&'a EvaluationContext);
impl<'a> nu_completion::CompletionContext for CompletionContext<'a> {
fn signature_registry(&self) -> &dyn SignatureRegistry {
&self.0.scope
}
fn scope(&self) -> &dyn nu_parser::ParserScope {
&self.0.scope
}
fn source(&self) -> &EvaluationContext {
self.as_ref()
}
fn variable_registry(&self) -> &dyn VariableRegistry {
self.0
}
}
impl<'a> AsRef<EvaluationContext> for CompletionContext<'a> {
fn as_ref(&self) -> &EvaluationContext {
self.0
}
}
pub struct CompletionSuggestion(nu_completion::Suggestion);
impl rustyline::completion::Candidate for CompletionSuggestion {
fn display(&self) -> &str {
&self.0.display
}
fn replacement(&self) -> &str {
&self.0.replacement
}
}
impl rustyline::completion::Completer for Helper {
type Candidate = CompletionSuggestion;
fn complete(
&self,
line: &str,
pos: usize,
_ctx: &rustyline::Context<'_>,
) -> Result<(usize, Vec<Self::Candidate>), rustyline::error::ReadlineError> {
let ctx = CompletionContext(&self.context);
let (position, suggestions) = self.completer.complete(line, pos, &ctx);
let suggestions = suggestions.into_iter().map(CompletionSuggestion).collect();
Ok((position, suggestions))
}
fn update(&self, line: &mut rustyline::line_buffer::LineBuffer, start: usize, elected: &str) {
let end = line.pos();
line.replace(start..end, elected)
}
}
impl rustyline::hint::Hinter for Helper {
type Hint = String;
fn hint(&self, line: &str, pos: usize, ctx: &rustyline::Context<'_>) -> Option<String> {
self.hinter.as_ref().and_then(|h| h.hint(line, pos, ctx))
}
}
impl rustyline::highlight::Highlighter for Helper {
fn highlight_prompt<'b, 's: 'b, 'p: 'b>(
&'s self,
prompt: &'p str,
default: bool,
) -> Cow<'b, str> {
use std::borrow::Cow::Borrowed;
if default {
Borrowed(&self.colored_prompt)
} else {
Borrowed(prompt)
}
}
fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
Owned(Color::DarkGray.prefix().to_string() + hint + nu_ansi_term::ansi::RESET)
}
fn highlight<'l>(&self, line: &'l str, _pos: usize) -> Cow<'l, str> {
let cfg = &self.context.configs().lock();
if let Some(palette) = &cfg.syntax_config {
Painter::paint_string(line, &self.context.scope, palette)
} else {
Painter::paint_string(line, &self.context.scope, &DefaultPalette {})
}
}
fn highlight_char(&self, _line: &str, _pos: usize) -> bool {
true
}
}
impl rustyline::validate::Validator for Helper {
fn validate(
&self,
ctx: &mut rustyline::validate::ValidationContext,
) -> rustyline::Result<rustyline::validate::ValidationResult> {
self.validator.validate(ctx)
}
fn validate_while_typing(&self) -> bool {
self.validator.validate_while_typing()
}
}
struct NuValidator {}
impl rustyline::validate::Validator for NuValidator {
fn validate(
&self,
ctx: &mut rustyline::validate::ValidationContext,
) -> rustyline::Result<rustyline::validate::ValidationResult> {
let src = ctx.input();
let (tokens, err) = nu_parser::lex(src, 0, nu_parser::NewlineMode::Normal);
if let Some(err) = err {
if let nu_errors::ParseErrorReason::Eof { .. } = err.reason() {
return Ok(rustyline::validate::ValidationResult::Incomplete);
}
}
let (_, err) = nu_parser::parse_block(tokens);
if let Some(err) = err {
if let nu_errors::ParseErrorReason::Eof { .. } = err.reason() {
return Ok(rustyline::validate::ValidationResult::Incomplete);
}
}
Ok(rustyline::validate::ValidationResult::Valid(None))
}
}
#[allow(unused)]
fn vec_tag<T>(input: Vec<Tagged<T>>) -> Option<Tag> {
let mut iter = input.iter();
let first = iter.next()?.tag.clone();
let last = iter.last();
Some(match last {
None => first,
Some(last) => first.until(&last.tag),
})
}
impl rustyline::Helper for Helper {}
#[cfg(test)]
mod tests {
use super::*;
use nu_engine::EvaluationContext;
use rustyline::completion::Completer;
use rustyline::line_buffer::LineBuffer;
#[ignore]
#[test]
fn closing_quote_should_replaced() {
let text = "cd \"folder with spaces\\subdirectory\\\"";
let replacement = "\"folder with spaces\\subdirectory\\subsubdirectory\\\"";
let mut buffer = LineBuffer::with_capacity(256);
buffer.insert_str(0, text);
buffer.set_pos(text.len() - 1);
let helper = Helper::new(EvaluationContext::basic(), None);
helper.update(&mut buffer, "cd ".len(), replacement);
assert_eq!(
buffer.as_str(),
"cd \"folder with spaces\\subdirectory\\subsubdirectory\\\""
);
}
#[ignore]
#[test]
fn replacement_with_cursor_in_text() {
let text = "cd \"folder with spaces\\subdirectory\\\"";
let replacement = "\"folder with spaces\\subdirectory\\subsubdirectory\\\"";
let mut buffer = LineBuffer::with_capacity(256);
buffer.insert_str(0, text);
buffer.set_pos(text.len() - 30);
let helper = Helper::new(EvaluationContext::basic(), None);
helper.update(&mut buffer, "cd ".len(), replacement);
assert_eq!(
buffer.as_str(),
"cd \"folder with spaces\\subdirectory\\subsubdirectory\\\""
);
}
}

View File

@ -0,0 +1,218 @@
use log::trace;
use nu_ansi_term::Style;
use nu_color_config::get_shape_color;
use nu_parser::{flatten_block, parse, FlatShape};
use nu_protocol::engine::{EngineState, StateWorkingSet};
use nu_protocol::Config;
use reedline::{Highlighter, StyledText};
pub struct NuHighlighter {
pub engine_state: EngineState,
pub config: Config,
}
impl Highlighter for NuHighlighter {
fn highlight(&self, line: &str, _cursor: usize) -> StyledText {
trace!("highlighting: {}", line);
let (shapes, global_span_offset) = {
let mut working_set = StateWorkingSet::new(&self.engine_state);
let (block, _) = parse(&mut working_set, None, line.as_bytes(), false, &[]);
let shapes = flatten_block(&working_set, &block);
(shapes, self.engine_state.next_span_start())
};
let mut output = StyledText::default();
let mut last_seen_span = global_span_offset;
for shape in &shapes {
if shape.0.end <= last_seen_span
|| last_seen_span < global_span_offset
|| shape.0.start < global_span_offset
{
// We've already output something for this span
// so just skip this one
continue;
}
if shape.0.start > last_seen_span {
let gap = line
[(last_seen_span - global_span_offset)..(shape.0.start - global_span_offset)]
.to_string();
output.push((Style::new(), gap));
}
let next_token = line
[(shape.0.start - global_span_offset)..(shape.0.end - global_span_offset)]
.to_string();
match shape.1 {
FlatShape::Garbage => output.push((
// nushell Garbage
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
FlatShape::Nothing => output.push((
// nushell Nothing
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
FlatShape::Binary => {
// nushell ?
output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::Bool => {
// nushell ?
output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::Int => {
// nushell Int
output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::Float => {
// nushell Decimal
output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::Range => output.push((
// nushell DotDot ?
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
FlatShape::InternalCall => output.push((
// nushell InternalCommand
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
FlatShape::External => {
// nushell ExternalCommand
output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::ExternalArg => {
// nushell ExternalWord
output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::Literal => {
// nushell ?
output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::Operator => output.push((
// nushell Operator
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
FlatShape::Signature => output.push((
// nushell ?
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
FlatShape::String => {
// nushell String
output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::StringInterpolation => {
// nushell ???
output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::DateTime => {
// nushell ???
output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::List => {
// nushell ???
output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::Table => {
// nushell ???
output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::Record => {
// nushell ???
output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::Block => {
// nushell ???
output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::Filepath => output.push((
// nushell Path
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
FlatShape::Directory => output.push((
// nushell Directory
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
FlatShape::GlobPattern => output.push((
// nushell GlobPattern
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
FlatShape::Variable => output.push((
// nushell Variable
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
FlatShape::Flag => {
// nushell Flag
output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::Custom(..) => output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
}
last_seen_span = shape.0.end;
}
let remainder = line[(last_seen_span - global_span_offset)..].to_string();
if !remainder.is_empty() {
output.push((Style::new(), remainder));
}
output
}
}

347
crates/nu-cli/src/util.rs Normal file
View File

@ -0,0 +1,347 @@
use log::trace;
use nu_engine::eval_block;
use nu_parser::{escape_quote_string, lex, parse, unescape_unquote_string, Token, TokenContents};
use nu_protocol::engine::StateWorkingSet;
use nu_protocol::CliError;
use nu_protocol::{
engine::{EngineState, Stack},
PipelineData, ShellError, Span, Value,
};
#[cfg(windows)]
use nu_utils::enable_vt_processing;
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.
//
// 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,
init_cwd: &Path,
) {
fn report_capture_error(engine_state: &EngineState, env_str: &str, msg: &str) {
let working_set = StateWorkingSet::new(engine_state);
report_error(
&working_set,
&ShellError::GenericError(
format!("Environment variable was not captured: {}", env_str),
"".to_string(),
None,
Some(msg.into()),
Vec::new(),
),
);
}
fn put_env_to_fake_file(name: &str, val: &str, fake_env_file: &mut String) {
fake_env_file.push_str(&escape_quote_string(name));
fake_env_file.push('=');
fake_env_file.push_str(&escape_quote_string(val));
fake_env_file.push('\n');
}
let mut fake_env_file = String::new();
// Write all the env vars into a fake file
for (name, val) in vars {
put_env_to_fake_file(&name, &val, &mut fake_env_file);
}
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(),
),
);
}
}
// Lex the fake file, assign spans to all environment variables and add them
// to stack
let span_offset = engine_state.next_span_start();
engine_state.add_file(
"Host Environment Variables".to_string(),
fake_env_file.as_bytes().to_vec(),
);
let (tokens, _) = lex(fake_env_file.as_bytes(), span_offset, &[], &[], true);
for token in tokens {
if let Token {
contents: TokenContents::Item,
span: full_span,
} = token
{
let contents = engine_state.get_span_contents(&full_span);
let (parts, _) = lex(contents, full_span.start, &[], &[b'='], true);
let name = if let Some(Token {
contents: TokenContents::Item,
span,
}) = parts.get(0)
{
let bytes = engine_state.get_span_contents(span);
if bytes.len() < 2 {
report_capture_error(
engine_state,
&String::from_utf8_lossy(contents),
"Got empty name.",
);
continue;
}
let (bytes, parse_error) = unescape_unquote_string(bytes, *span);
if parse_error.is_some() {
report_capture_error(
engine_state,
&String::from_utf8_lossy(contents),
"Got unparsable name.",
);
continue;
}
bytes
} else {
report_capture_error(
engine_state,
&String::from_utf8_lossy(contents),
"Got empty name.",
);
continue;
};
let value = if let Some(Token {
contents: TokenContents::Item,
span,
}) = parts.get(2)
{
let bytes = engine_state.get_span_contents(span);
if bytes.len() < 2 {
report_capture_error(
engine_state,
&String::from_utf8_lossy(contents),
"Got empty value.",
);
continue;
}
let (bytes, parse_error) = unescape_unquote_string(bytes, *span);
if parse_error.is_some() {
report_capture_error(
engine_state,
&String::from_utf8_lossy(contents),
"Got unparsable value.",
);
continue;
}
Value::String {
val: bytes,
span: *span,
}
} else {
report_capture_error(
engine_state,
&String::from_utf8_lossy(contents),
"Got empty value.",
);
continue;
};
// stack.add_env_var(name, value);
engine_state.add_env_var(name, value);
}
}
}
pub fn eval_source(
engine_state: &mut EngineState,
stack: &mut Stack,
source: &[u8],
fname: &str,
input: PipelineData,
) -> bool {
trace!("eval_source");
let (block, delta) = {
let mut working_set = StateWorkingSet::new(engine_state);
let (output, err) = parse(
&mut working_set,
Some(fname), // format!("entry #{}", entry_num)
source,
false,
&[],
);
if let Some(err) = err {
set_last_exit_code(stack, 1);
report_error(&working_set, &err);
return false;
}
(output, working_set.render())
};
let cwd = match nu_engine::env::current_dir(engine_state, stack) {
Ok(p) => p,
Err(e) => {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &e);
get_init_cwd()
}
};
let _ = engine_state.merge_delta(delta, Some(stack), &cwd);
match eval_block(engine_state, stack, &block, input, false, false) {
Ok(mut pipeline_data) => {
if let PipelineData::ExternalStream { exit_code, .. } = &mut pipeline_data {
if let Some(exit_code) = exit_code.take().and_then(|it| it.last()) {
stack.add_env_var("LAST_EXIT_CODE".to_string(), exit_code);
} else {
set_last_exit_code(stack, 0);
}
} else {
set_last_exit_code(stack, 0);
}
if let Err(err) = pipeline_data.print(engine_state, stack, false) {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &err);
return false;
}
// reset vt processing, aka ansi because illbehaved externals can break it
#[cfg(windows)]
{
let _ = enable_vt_processing();
}
}
Err(err) => {
set_last_exit_code(stack, 1);
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &err);
return false;
}
}
true
}
fn set_last_exit_code(stack: &mut Stack, exit_code: i64) {
stack.add_env_var(
"LAST_EXIT_CODE".to_string(),
Value::Int {
val: exit_code,
span: Span { start: 0, end: 0 },
},
);
}
pub fn report_error(
working_set: &StateWorkingSet,
error: &(dyn miette::Diagnostic + Send + Sync + 'static),
) {
eprintln!("Error: {:?}", CliError(error, working_set));
// reset vt processing, aka ansi because illbehaved externals can break it
#[cfg(windows)]
{
let _ = nu_utils::enable_vt_processing();
}
}
pub fn get_init_cwd() -> PathBuf {
match std::env::current_dir() {
Ok(cwd) => cwd,
Err(_) => match std::env::var("PWD") {
Ok(cwd) => PathBuf::from(cwd),
Err(_) => match nu_path::home_dir() {
Some(cwd) => cwd,
None => PathBuf::new(),
},
},
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_gather_env_vars() {
let mut engine_state = EngineState::new();
let symbols = r##" !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"##;
gather_env_vars(
[
("FOO".into(), "foo".into()),
("SYMBOLS".into(), symbols.into()),
(symbols.into(), "symbols".into()),
]
.into_iter(),
&mut engine_state,
Path::new("t"),
);
let env = engine_state.render_env_vars();
assert!(
matches!(env.get(&"FOO".to_string()), Some(&Value::String { val, .. }) if val == "foo")
);
assert!(
matches!(env.get(&"SYMBOLS".to_string()), Some(&Value::String { val, .. }) if val == symbols)
);
assert!(
matches!(env.get(&symbols.to_string()), Some(&Value::String { val, .. }) if val == "symbols")
);
assert!(env.get(&"PWD".to_string()).is_some());
assert_eq!(env.len(), 4);
}
}

View File

@ -0,0 +1,20 @@
use nu_parser::{parse, ParseError};
use nu_protocol::engine::{EngineState, StateWorkingSet};
use reedline::{ValidationResult, Validator};
pub struct NuValidator {
pub engine_state: EngineState,
}
impl Validator for NuValidator {
fn validate(&self, line: &str) -> ValidationResult {
let mut working_set = StateWorkingSet::new(&self.engine_state);
let (_, err) = parse(&mut working_set, None, line.as_bytes(), false, &[]);
if matches!(err, Some(ParseError::UnexpectedEof(..))) {
ValidationResult::Incomplete
} else {
ValidationResult::Complete
}
}
}

View File

@ -0,0 +1,29 @@
pub mod support;
use nu_cli::NuCompleter;
use reedline::Completer;
use support::{match_suggestions, new_engine};
#[test]
fn variables_completions() {
// Create a new engine
let (dir, _, mut engine, mut stack) = new_engine();
// Add record value as example
let record = r#"def animals [] { ["cat", "dog", "eel" ] }
def my-command [animal: string@animals] { print $animal }"#;
assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok());
// Instatiate a new completer
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
// Test completions for $nu
let suggestions = completer.complete("my-command ", 11);
assert_eq!(3, suggestions.len());
let expected: Vec<String> = vec!["cat".into(), "dog".into(), "eel".into()];
// Match results
match_suggestions(expected, suggestions);
}

View File

@ -0,0 +1,28 @@
pub mod support;
use nu_cli::NuCompleter;
use reedline::Completer;
use support::new_engine;
#[test]
fn dotnu_completions() {
// Create a new engine
let (_, _, engine, stack) = new_engine();
// Instatiate a new completer
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
// Test source completion
let completion_str = "source ".to_string();
let suggestions = completer.complete(&completion_str, completion_str.len());
assert_eq!(1, suggestions.len());
assert_eq!("custom_completion.nu", suggestions.get(0).unwrap().value);
// Test use completion
let completion_str = "use ".to_string();
let suggestions = completer.complete(&completion_str, completion_str.len());
assert_eq!(1, suggestions.len());
assert_eq!("custom_completion.nu", suggestions.get(0).unwrap().value);
}

View File

@ -0,0 +1,42 @@
pub mod support;
use nu_cli::NuCompleter;
use reedline::Completer;
use support::{file, folder, match_suggestions, new_engine};
#[test]
fn file_completions() {
// Create a new engine
let (dir, dir_str, engine, stack) = new_engine();
// Instatiate a new completer
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
// Test completions for the current folder
let target_dir = format!("cp {}", dir_str);
let suggestions = completer.complete(&target_dir, target_dir.len());
// Create the expected values
let expected_paths: Vec<String> = vec![
file(dir.join("nushell")),
folder(dir.join("test_a")),
folder(dir.join("test_b")),
folder(dir.join("another")),
file(dir.join("custom_completion.nu")),
file(dir.join(".hidden_file")),
folder(dir.join(".hidden_folder")),
];
// Match the results
match_suggestions(expected_paths, suggestions);
// Test completions for the completions/another folder
let target_dir = format!("cd {}", folder(dir.join("another")));
let suggestions = completer.complete(&target_dir, target_dir.len());
// Create the expected values
let expected_paths: Vec<String> = vec![file(dir.join("another").join("newfile"))];
// Match the results
match_suggestions(expected_paths, suggestions);
}

View File

@ -0,0 +1,36 @@
pub mod support;
use nu_cli::NuCompleter;
use reedline::Completer;
use support::{match_suggestions, new_engine};
#[test]
fn flag_completions() {
// Create a new engine
let (_, _, engine, stack) = new_engine();
// 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 -", 4);
assert_eq!(12, suggestions.len());
let expected: Vec<String> = vec![
"--all".into(),
"--du".into(),
"--full-paths".into(),
"--help".into(),
"--long".into(),
"--short-names".into(),
"-a".into(),
"-d".into(),
"-f".into(),
"-h".into(),
"-l".into(),
"-s".into(),
];
// Match results
match_suggestions(expected, suggestions);
}

View File

@ -0,0 +1,29 @@
pub mod support;
use nu_cli::NuCompleter;
use reedline::Completer;
use support::{folder, match_suggestions, new_engine};
#[test]
fn folder_completions() {
// Create a new engine
let (dir, dir_str, engine, stack) = new_engine();
// Instatiate a new completer
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
// Test completions for the current folder
let target_dir = format!("cd {}", dir_str);
let suggestions = completer.complete(&target_dir, target_dir.len());
// Create the expected values
let expected_paths: Vec<String> = vec![
folder(dir.join("test_a")),
folder(dir.join("test_b")),
folder(dir.join("another")),
folder(dir.join(".hidden_folder")),
];
// Match the results
match_suggestions(expected_paths, suggestions);
}

View File

@ -0,0 +1,117 @@
use std::path::PathBuf;
use nu_command::create_default_context;
use nu_engine::eval_block;
use nu_parser::parse;
use nu_protocol::{
engine::{EngineState, Stack, StateDelta, StateWorkingSet},
PipelineData, ShellError, Span, Value,
};
use nu_test_support::fs;
use reedline::Suggestion;
const SEP: char = std::path::MAIN_SEPARATOR;
// creates a new engine with the current path into the completions fixtures folder
pub fn new_engine() -> (PathBuf, String, EngineState, Stack) {
// Target folder inside assets
let dir = fs::fixtures().join("completions");
let mut dir_str = dir
.clone()
.into_os_string()
.into_string()
.unwrap_or_default();
dir_str.push(SEP);
// Create a new engine with default context
let mut engine_state = create_default_context(&dir);
// New stack
let mut stack = Stack::new();
// New delta state
let delta = StateDelta::new(&engine_state);
// Add pwd as env var
stack.add_env_var(
"PWD".to_string(),
Value::String {
val: dir_str.clone(),
span: nu_protocol::Span {
start: 0,
end: dir_str.len(),
},
},
);
stack.add_env_var(
"TEST".to_string(),
Value::String {
val: "NUSHELL".to_string(),
span: nu_protocol::Span {
start: 0,
end: dir_str.len(),
},
},
);
// Merge delta
let merge_result = engine_state.merge_delta(delta, Some(&mut stack), &dir);
assert!(merge_result.is_ok());
(dir, dir_str, engine_state, stack)
}
// match a list of suggestions with the expected values
pub fn match_suggestions(expected: Vec<String>, suggestions: Vec<Suggestion>) {
expected.iter().zip(suggestions).for_each(|it| {
assert_eq!(it.0, &it.1.value);
});
}
// append the separator to the converted path
pub fn folder(path: PathBuf) -> String {
let mut converted_path = file(path);
converted_path.push(SEP);
converted_path
}
// convert a given path to string
pub fn file(path: PathBuf) -> String {
path.into_os_string().into_string().unwrap_or_default()
}
// merge_input executes the given input into the engine
// and merges the state
pub fn merge_input(
input: &[u8],
engine_state: &mut EngineState,
stack: &mut Stack,
dir: PathBuf,
) -> Result<(), ShellError> {
let (block, delta) = {
let mut working_set = StateWorkingSet::new(engine_state);
let (block, err) = parse(&mut working_set, None, input, false, &[]);
assert!(err.is_none());
(block, working_set.render())
};
assert!(eval_block(
engine_state,
stack,
&block,
PipelineData::Value(
Value::Nothing {
span: Span { start: 0, end: 0 },
},
None
),
false,
false
)
.is_ok());
// Merge delta
engine_state.merge_delta(delta, Some(stack), &dir)
}

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