Compare commits

...

29 Commits

Author SHA1 Message Date
0522023d4c Bump to 0.16.0 (#2084) 2020-07-01 06:25:09 +12:00
9876169f5d Add dice subcommand to random command (#2082)
* Add dice subcommand to random command

* Update random dice test name

* Stream results of random dice

* Thanks Clippy!
2020-06-30 16:12:51 +12:00
ed10aafa6f Bubble errors even if pipeline isn't used (#2080) 2020-06-30 05:39:11 +12:00
bcddeb3c1f WIP (#2077) 2020-06-29 09:06:05 +12:00
3f170c7fb8 Cal improvements (#2074)
* .get() already checks for the argument, don't need to use .has() as well

* Supplying the month-names flag should also cause the months column to show up, it should not require the -m flag first
2020-06-29 05:16:10 +12:00
8d91d151bf added raw to date for string output (#2075) 2020-06-28 09:01:13 -05:00
821d44af54 Docs autoview pwd touch (#2068)
* [ADD] Add draft documentation for autoview

* [ADD] Add draft documentation for pwd

* [ADD] Add draft documentation for touch

* [MOD] Improve description and add examples

Add the use of `textview` and `binaryview`.
Add examples for single value, source file and binary file.
2020-06-28 14:22:26 +12:00
a30901ff7d added ability to request the date in a format (#2073) 2020-06-27 20:36:15 -05:00
94a1968a88 Add command for printing special characters (#2072) 2020-06-28 09:46:30 +12:00
dffc9c9b1c Properly redirect invocations (#2070)
* Properly redirect invocations

* Don't convert with-env yet, as there's a random test failure
2020-06-28 09:04:57 +12:00
8b3964f518 More ansi (#2067)
* added a few more options for ansi colors
not sure italic works, maybe it's font dependent

* fmt
2020-06-27 10:29:09 -05:00
7fed9992c9 Bump deps and touchup (#2066) 2020-06-27 19:54:31 +12:00
4e2a4236f8 Fix it expansion and add collect (#2065) 2020-06-27 17:38:19 +12:00
05781607f4 Configurable built-in prompts (#2064)
* Add ansi, do, and prompt customization

* Fix test

* Cleanups
2020-06-27 10:37:31 +12:00
6daec399e6 added match plugin and readme.txt for msi (#2063) 2020-06-26 08:39:19 -05:00
306dc89ede Add bool subcommand to random (#2061)
* Add bool subcommand to random

* Fix function name copy paste error

* Fix issue 2062: allow deserialization of a decimal

* Add bias flag to `random bool`
2020-06-26 16:51:05 +12:00
80ce8acf57 Add ThemedPalette (#1873)
* add theme module

* reorganize theme palette code

* improve tests

* move to newtype implementation for ThemeColor and fix Palette name.

* add dead code ignore for now

* fix allow dead code macro

* remove redundant import and unnecessary return

* fix ok_or clippy error

Co-authored-by: Kurtis Nusbaum <kcommiter@gmail.com>
2020-06-26 16:40:12 +12:00
8dfc90a322 Update release.yml 2020-06-26 15:55:18 +12:00
ad5e485594 Update release.yml 2020-06-26 15:24:45 +12:00
60ed40f8bd Update release.yml 2020-06-26 14:34:39 +12:00
a6228cab9e Update main.wxs (#2060) 2020-06-26 11:34:39 +12:00
1857ac69d1 updated wxs to have the right exes (#2059) 2020-06-25 17:38:32 -05:00
e33e80ab24 Update release.yml 2020-06-26 09:40:59 +12:00
d18bc78e7c Update release.yml 2020-06-26 09:28:09 +12:00
3b2a87b6d4 Update release.yml 2020-06-26 09:08:20 +12:00
62c76be7ca Update release.yml 2020-06-26 09:06:33 +12:00
733f93e673 update to make closer to volta's (#2058) 2020-06-26 08:08:59 +12:00
2c88b2fae7 Gh actions with wix (#2057)
* Added wix to gh workflow
Followed volta example

* added --nocapture to see more error detail

* move creation of wix to after we download less.exe

* moved create wix down
2020-06-26 07:30:07 +12:00
501da433d4 Gh actions with wix, added --nocapture (#2056)
* Added wix to gh workflow
Followed volta example

* added --nocapture to see more error detail
2020-06-26 06:26:48 +12:00
65 changed files with 2072 additions and 622 deletions

View File

@ -96,42 +96,36 @@ jobs:
with:
command: build
args: --release --all --features=stable
- 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.1/less.exe" -OutFile "target\release\less.exe"
- name: Copy files to output
run: |
cp target\release\nu.exe output\
rm target\release\nu_plugin_core_*.exe
rm target\release\nu_plugin_stable_*.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 --output target\wix\nushell-windows.msi
- name: Create zip of binaries
run: powershell Compress-Archive nushell-windows.zip
working-directory: ./target/release
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
path: target\wix\nushell-windows.msi
- name: Upload zip
uses: actions/upload-artifact@v2
with:
name: windows-zip
path: target/release/nushell-windows.zip
- name: Create output directory
run: mkdir output
- name: Copy files to output
run: |
cp target\release\nu.exe output\
cp target\release\nu_plugin_*.exe output\
cp README.build.txt output\README.txt
rm output\nu_plugin_core_*.exe
rm output\nu_plugin_stable_*.exe
# 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
- name: Download Less Binary
run: Invoke-WebRequest -Uri "https://github.com/jftuga/less-Windows/releases/download/less-v562.1/less.exe" -OutFile "output\less.exe"
- name: Upload artifact
uses: actions/upload-artifact@v2
with:
name: windows
path: output/*
path: output\*
release:
name: Publish Release
@ -211,17 +205,17 @@ jobs:
asset_content_type: application/zip
- name: Create Windows Directory
run: mkdir -p ${{ steps.info.outputs.windowsdir }}/${{ steps.info.outputs.innerdir }}
- name: Download Windows Artifacts
- name: Download Windows zip
uses: actions/download-artifact@v2
with:
name: windows
name: windows-zip
path: ${{ steps.info.outputs.windowsdir }}/${{ steps.info.outputs.innerdir }}
# TODO: Remove Show
- name: Show Windows Artifacts
run: ls -la ${{ steps.info.outputs.windowsdir }}/${{ steps.info.outputs.innerdir }}
- name: Create Windows Archive
- name: Create macOS Archive
run: zip -r ${{ steps.info.outputs.windowsdir }}.zip ${{ steps.info.outputs.windowsdir }}
- name: Upload Windows Artifact
- name: Upload Windows zip
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -230,3 +224,17 @@ jobs:
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

408
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
[package]
name = "nu"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
description = "A new type of shell"
license = "MIT"
@ -18,23 +18,23 @@ members = ["crates/*/"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nu-cli = { version = "0.15.1", path = "./crates/nu-cli" }
nu-source = { version = "0.15.1", path = "./crates/nu-source" }
nu-plugin = { version = "0.15.1", path = "./crates/nu-plugin" }
nu-protocol = { version = "0.15.1", path = "./crates/nu-protocol" }
nu-errors = { version = "0.15.1", path = "./crates/nu-errors" }
nu-parser = { version = "0.15.1", path = "./crates/nu-parser" }
nu-value-ext = { version = "0.15.1", path = "./crates/nu-value-ext" }
nu_plugin_binaryview = { version = "0.15.1", path = "./crates/nu_plugin_binaryview", optional=true }
nu_plugin_fetch = { version = "0.15.1", path = "./crates/nu_plugin_fetch", optional=true }
nu_plugin_inc = { version = "0.15.1", path = "./crates/nu_plugin_inc", optional=true }
nu_plugin_match = { version = "0.15.1", path = "./crates/nu_plugin_match", optional=true }
nu_plugin_post = { version = "0.15.1", path = "./crates/nu_plugin_post", optional=true }
nu_plugin_ps = { version = "0.15.1", path = "./crates/nu_plugin_ps", optional=true }
nu_plugin_start = { version = "0.15.1", path = "./crates/nu_plugin_start", optional=true }
nu_plugin_sys = { version = "0.15.1", path = "./crates/nu_plugin_sys", optional=true }
nu_plugin_textview = { version = "0.15.1", path = "./crates/nu_plugin_textview", optional=true }
nu_plugin_tree = { version = "0.15.1", path = "./crates/nu_plugin_tree", optional=true }
nu-cli = { version = "0.16.0", path = "./crates/nu-cli" }
nu-source = { version = "0.16.0", path = "./crates/nu-source" }
nu-plugin = { version = "0.16.0", path = "./crates/nu-plugin" }
nu-protocol = { version = "0.16.0", path = "./crates/nu-protocol" }
nu-errors = { version = "0.16.0", path = "./crates/nu-errors" }
nu-parser = { version = "0.16.0", path = "./crates/nu-parser" }
nu-value-ext = { version = "0.16.0", path = "./crates/nu-value-ext" }
nu_plugin_binaryview = { version = "0.16.0", path = "./crates/nu_plugin_binaryview", optional=true }
nu_plugin_fetch = { version = "0.16.0", path = "./crates/nu_plugin_fetch", optional=true }
nu_plugin_inc = { version = "0.16.0", path = "./crates/nu_plugin_inc", optional=true }
nu_plugin_match = { version = "0.16.0", path = "./crates/nu_plugin_match", optional=true }
nu_plugin_post = { version = "0.16.0", path = "./crates/nu_plugin_post", optional=true }
nu_plugin_ps = { version = "0.16.0", path = "./crates/nu_plugin_ps", optional=true }
nu_plugin_start = { version = "0.16.0", path = "./crates/nu_plugin_start", optional=true }
nu_plugin_sys = { version = "0.16.0", path = "./crates/nu_plugin_sys", optional=true }
nu_plugin_textview = { version = "0.16.0", path = "./crates/nu_plugin_textview", optional=true }
nu_plugin_tree = { version = "0.16.0", path = "./crates/nu_plugin_tree", optional=true }
crossterm = { version = "0.17.5", optional = true }
semver = { version = "0.10.0", optional = true }
@ -43,19 +43,19 @@ url = { version = "2.1.1", optional = true }
clap = "2.33.1"
ctrlc = "3.1.4"
dunce = "1.0.0"
dunce = "1.0.1"
futures = { version = "0.3", features = ["compat", "io-compat"] }
log = "0.4.8"
pretty_env_logger = "0.4.0"
starship = "0.42.0"
starship = "0.43.0"
[dev-dependencies]
nu-test-support = { version = "0.15.1", path = "./crates/nu-test-support" }
nu-test-support = { version = "0.16.0", path = "./crates/nu-test-support" }
[build-dependencies]
toml = "0.5.6"
serde = { version = "1.0.110", features = ["derive"] }
nu-build = { version = "0.15.1", path = "./crates/nu-build" }
nu-build = { version = "0.16.0", path = "./crates/nu-build" }
[features]
default = ["sys", "ps", "textview", "inc"]

View File

@ -1,6 +1,6 @@
[package]
name = "nu-build"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
edition = "2018"
description = "Core build system for nushell"
@ -10,7 +10,7 @@ license = "MIT"
doctest = false
[dependencies]
serde = { version = "1.0.110", features = ["derive"] }
serde = { version = "1.0.114", features = ["derive"] }
lazy_static = "1.4.0"
serde_json = "1.0.53"
serde_json = "1.0.55"
toml = "0.5.6"

View File

@ -1,6 +1,6 @@
[package]
name = "nu-cli"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
description = "CLI for nushell"
edition = "2018"
@ -10,25 +10,25 @@ license = "MIT"
doctest = false
[dependencies]
nu-source = { version = "0.15.1", path = "../nu-source" }
nu-plugin = { version = "0.15.1", path = "../nu-plugin" }
nu-protocol = { version = "0.15.1", path = "../nu-protocol" }
nu-errors = { version = "0.15.1", path = "../nu-errors" }
nu-parser = { version = "0.15.1", path = "../nu-parser" }
nu-value-ext = { version = "0.15.1", path = "../nu-value-ext" }
nu-test-support = { version = "0.15.1", path = "../nu-test-support" }
nu-table = {version = "0.15.1", path = "../nu-table"}
nu-source = { version = "0.16.0", path = "../nu-source" }
nu-plugin = { version = "0.16.0", path = "../nu-plugin" }
nu-protocol = { version = "0.16.0", path = "../nu-protocol" }
nu-errors = { version = "0.16.0", path = "../nu-errors" }
nu-parser = { version = "0.16.0", path = "../nu-parser" }
nu-value-ext = { version = "0.16.0", path = "../nu-value-ext" }
nu-test-support = { version = "0.16.0", path = "../nu-test-support" }
nu-table = {version = "0.16.0", path = "../nu-table"}
ansi_term = "0.12.1"
app_dirs = "1.2.1"
async-recursion = "0.3.1"
async-trait = "0.1.31"
async-trait = "0.1.36"
directories = "2.0.2"
base64 = "0.12.1"
base64 = "0.12.3"
bigdecimal = { version = "0.1.2", features = ["serde"] }
bson = { version = "0.14.1", features = ["decimal128"] }
byte-unit = "3.1.3"
bytes = "0.5.4"
bytes = "0.5.5"
calamine = "0.16"
cfg-if = "0.1"
chrono = { version = "0.4.11", features = ["serde"] }
@ -37,7 +37,7 @@ csv = "1.1"
ctrlc = "3.1.4"
derive-new = "0.5.8"
dirs = "2.0.2"
dunce = "1.0.0"
dunce = "1.0.1"
eml-parser = "0.1.0"
filesize = "0.2.0"
futures = { version = "0.3", features = ["compat", "io-compat"] }
@ -50,15 +50,15 @@ hex = "0.4"
htmlescape = "0.3.1"
ical = "0.6.*"
ichwh = "0.3.4"
indexmap = { version = "1.3.2", features = ["serde-1"] }
indexmap = { version = "1.4.0", features = ["serde-1"] }
itertools = "0.9.0"
codespan-reporting = "0.9.4"
codespan-reporting = "0.9.5"
log = "0.4.8"
meval = "0.2"
natural = "0.5.0"
num-bigint = { version = "0.2.6", features = ["serde"] }
num-traits = "0.2.11"
parking_lot = "0.10.2"
parking_lot = "0.11.0"
pin-utils = "0.1.0"
pretty-hex = "0.1.1"
pretty_env_logger = "0.4.0"
@ -66,13 +66,13 @@ ptree = {version = "0.2" }
query_interface = "0.3.5"
rand = "0.7"
regex = "1"
roxmltree = "0.11.0"
roxmltree = "0.13.0"
rustyline = "6.2.0"
serde = { version = "1.0.110", features = ["derive"] }
serde = { version = "1.0.114", features = ["derive"] }
serde-hjson = "0.9.1"
serde_bytes = "0.11.4"
serde_bytes = "0.11.5"
serde_ini = "0.2.0"
serde_json = "1.0.53"
serde_json = "1.0.55"
serde_urlencoded = "0.6.1"
serde_yaml = "0.8"
shellexpand = "2.0.0"
@ -80,18 +80,18 @@ strip-ansi-escapes = "0.1.0"
tempfile = "3.1.0"
term = "0.5.2"
termcolor = "1.1.0"
textwrap = {version = "0.11.0", features = ["term_size"]}
term_size = "0.3.2"
toml = "0.5.6"
typetag = "0.1.4"
typetag = "0.1.5"
umask = "1.0.0"
unicode-xid = "0.2.0"
unicode-xid = "0.2.1"
uuid_crate = { package = "uuid", version = "0.8.1", features = ["v4"] }
which = "4.0.1"
trash = { version = "1.0.1", optional = true }
clipboard = { version = "0.5", optional = true }
starship = "0.42.0"
rayon = "1.3.0"
starship = "0.43.0"
rayon = "1.3.1"
encoding_rs = "0.8.23"
[target.'cfg(unix)'.dependencies]
@ -102,7 +102,7 @@ version = "0.23.1"
features = ["bundled", "blob"]
[build-dependencies]
nu-build = { version = "0.15.1", path = "../nu-build" }
nu-build = { version = "0.16.0", path = "../nu-build" }
[dev-dependencies]
quickcheck = "0.9"

View File

@ -9,7 +9,7 @@ use crate::path::canonicalize;
use crate::prelude::*;
use crate::EnvironmentSyncer;
use futures_codec::FramedRead;
use nu_errors::ShellError;
use nu_errors::{ProximateShellError, ShellDiagnostic, ShellError};
use nu_protocol::hir::{ClassifiedCommand, Expression, InternalCommand, Literal, NamedArguments};
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
@ -269,6 +269,7 @@ pub fn create_default_context(
whole_stream_command(Debug),
whole_stream_command(Alias),
whole_stream_command(WithEnv),
whole_stream_command(Do),
// Statistics
whole_stream_command(Size),
whole_stream_command(Count),
@ -302,7 +303,10 @@ pub fn create_default_context(
whole_stream_command(StrSet),
whole_stream_command(StrToDatetime),
whole_stream_command(StrTrim),
whole_stream_command(StrCollect),
whole_stream_command(BuildString),
whole_stream_command(Ansi),
whole_stream_command(Char),
// Column manipulation
whole_stream_command(Reject),
whole_stream_command(Select),
@ -389,6 +393,8 @@ pub fn create_default_context(
whole_stream_command(RunExternalCommand { interactive }),
// Random value generation
whole_stream_command(Random),
whole_stream_command(RandomBool),
whole_stream_command(RandomDice),
whole_stream_command(RandomUUID),
]);
@ -586,7 +592,21 @@ pub async fn cli(
rl.set_helper(Some(crate::shell::Helper::new(context.clone())));
let config = config::config(Tag::unknown())?;
let config = match config::config(Tag::unknown()) {
Ok(config) => config,
Err(e) => {
eprintln!("Config could not be loaded.");
if let ShellError {
error: ProximateShellError::Diagnostic(ShellDiagnostic { diagnostic }),
..
} = e
{
eprintln!("{}", diagnostic.message);
}
IndexMap::new()
}
};
let use_starship = match config.get("use_starship") {
Some(b) => match b.as_bool() {
Ok(b) => b,
@ -595,7 +615,7 @@ pub async fn cli(
_ => false,
};
let edit_mode = config::config(Tag::unknown())?
let edit_mode = config
.get("edit_mode")
.map(|s| match s.value.expect_string() {
"vi" => EditMode::Vi,
@ -606,21 +626,21 @@ pub async fn cli(
rl.set_edit_mode(edit_mode);
let max_history_size = config::config(Tag::unknown())?
let max_history_size = config
.get("history_size")
.map(|i| i.value.expect_int())
.unwrap_or(100_000);
rl.set_max_history_size(max_history_size as usize);
let key_timeout = config::config(Tag::unknown())?
let key_timeout = config
.get("key_timeout")
.map(|s| s.value.expect_int())
.unwrap_or(1);
rl.set_keyseq_timeout(key_timeout as i32);
let completion_mode = config::config(Tag::unknown())?
let completion_mode = config
.get("completion_mode")
.map(|s| match s.value.expect_string() {
"list" => CompletionType::List,
@ -648,6 +668,62 @@ pub async fn cli(
_ => {}
};
starship::print::get_prompt(starship_context)
} else if let Some(prompt) = config.get("prompt") {
let prompt_line = prompt.as_string()?;
match nu_parser::lite_parse(&prompt_line, 0).map_err(ShellError::from) {
Ok(result) => {
let mut prompt_block =
nu_parser::classify_block(&result, context.registry());
let env = context.get_env();
prompt_block.block.expand_it_usage();
match run_block(
&prompt_block.block,
&mut context,
InputStream::empty(),
&Value::nothing(),
&IndexMap::new(),
&env,
)
.await
{
Ok(result) => match result.collect_string(Tag::unknown()).await {
Ok(string_result) => {
let errors = context.get_errors();
context.maybe_print_errors(Text::from(prompt_line));
context.clear_errors();
if !errors.is_empty() {
"> ".to_string()
} else {
string_result.item
}
}
Err(e) => {
crate::cli::print_err(e, &Text::from(prompt_line));
context.clear_errors();
"> ".to_string()
}
},
Err(e) => {
crate::cli::print_err(e, &Text::from(prompt_line));
context.clear_errors();
"> ".to_string()
}
}
}
Err(e) => {
crate::cli::print_err(e, &Text::from(prompt_line));
context.clear_errors();
"> ".to_string()
}
}
} else {
format!(
"\x1b[32m{}{}\x1b[m> ",

View File

@ -5,6 +5,7 @@ mod from_delimited_data;
mod to_delimited_data;
pub(crate) mod alias;
pub(crate) mod ansi;
pub(crate) mod append;
pub(crate) mod args;
pub(crate) mod autoview;
@ -12,6 +13,7 @@ pub(crate) mod build_string;
pub(crate) mod cal;
pub(crate) mod calc;
pub(crate) mod cd;
pub(crate) mod char_;
pub(crate) mod classified;
#[cfg(feature = "clipboard")]
pub(crate) mod clip;
@ -23,6 +25,7 @@ pub(crate) mod cp;
pub(crate) mod date;
pub(crate) mod debug;
pub(crate) mod default;
pub(crate) mod do_;
pub(crate) mod drop;
pub(crate) mod du;
pub(crate) mod each;
@ -135,10 +138,12 @@ pub(crate) use command::{
};
pub(crate) use alias::Alias;
pub(crate) use ansi::Ansi;
pub(crate) use append::Append;
pub(crate) use build_string::BuildString;
pub(crate) use cal::Cal;
pub(crate) use calc::Calc;
pub(crate) use char_::Char;
pub(crate) use compact::Compact;
pub(crate) use config::Config;
pub(crate) use count::Count;
@ -146,6 +151,7 @@ pub(crate) use cp::Cpy;
pub(crate) use date::Date;
pub(crate) use debug::Debug;
pub(crate) use default::Default;
pub(crate) use do_::Do;
pub(crate) use drop::Drop;
pub(crate) use du::Du;
pub(crate) use each::Each;
@ -213,7 +219,7 @@ pub(crate) use pivot::Pivot;
pub(crate) use prepend::Prepend;
pub(crate) use prev::Previous;
pub(crate) use pwd::Pwd;
pub(crate) use random::{Random, RandomUUID};
pub(crate) use random::{Random, RandomBool, RandomDice, RandomUUID};
pub(crate) use range::Range;
#[allow(unused_imports)]
pub(crate) use reduce_by::ReduceBy;
@ -236,8 +242,8 @@ pub(crate) use split::SplitColumn;
pub(crate) use split::SplitRow;
pub(crate) use split_by::SplitBy;
pub(crate) use str_::{
Str, StrCapitalize, StrDowncase, StrFindReplace, StrSet, StrSubstring, StrToDatetime,
StrToDecimal, StrToInteger, StrTrim, StrUpcase,
Str, StrCapitalize, StrCollect, StrDowncase, StrFindReplace, StrSet, StrSubstring,
StrToDatetime, StrToDecimal, StrToInteger, StrTrim, StrUpcase,
};
#[allow(unused_imports)]
pub(crate) use t_sort_by::TSortBy;

View File

@ -0,0 +1,140 @@
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
pub struct Ansi;
#[derive(Deserialize)]
struct AnsiArgs {
color: Value,
}
#[async_trait]
impl WholeStreamCommand for Ansi {
fn name(&self) -> &str {
"ansi"
}
fn signature(&self) -> Signature {
Signature::build("ansi").required(
"color",
SyntaxShape::Any,
"the name of the color to use or 'reset' to reset the color",
)
}
fn usage(&self) -> &str {
"Output ANSI codes to change color"
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Change color to green",
example: r#"ansi green"#,
result: Some(vec![Value::from("\u{1b}[32m")]),
},
Example {
description: "Reset the color",
example: r#"ansi reset"#,
result: Some(vec![Value::from("\u{1b}[0m")]),
},
]
}
async fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let (AnsiArgs { color }, _) = args.process(&registry).await?;
let color_string = color.as_string()?;
let ansi_code = str_to_ansi_color(color_string);
if let Some(output) = ansi_code {
Ok(OutputStream::one(ReturnSuccess::value(
UntaggedValue::string(output).into_value(color.tag()),
)))
} else {
Err(ShellError::labeled_error(
"Unknown color",
"unknown color",
color.tag(),
))
}
}
}
fn str_to_ansi_color(s: String) -> Option<String> {
match s.as_str() {
"g" | "green" => Some(ansi_term::Color::Green.prefix().to_string()),
"gb" | "green_bold" => Some(ansi_term::Color::Green.bold().prefix().to_string()),
"gu" | "green_underline" => Some(ansi_term::Color::Green.underline().prefix().to_string()),
"gi" | "green_italic" => Some(ansi_term::Color::Green.italic().prefix().to_string()),
"gd" | "green_dimmed" => Some(ansi_term::Color::Green.dimmed().prefix().to_string()),
"gr" | "green_reverse" => Some(ansi_term::Color::Green.reverse().prefix().to_string()),
"r" | "red" => Some(ansi_term::Color::Red.prefix().to_string()),
"rb" | "red_bold" => Some(ansi_term::Color::Red.bold().prefix().to_string()),
"ru" | "red_underline" => Some(ansi_term::Color::Red.underline().prefix().to_string()),
"ri" | "red_italic" => Some(ansi_term::Color::Red.italic().prefix().to_string()),
"rd" | "red_dimmed" => Some(ansi_term::Color::Red.dimmed().prefix().to_string()),
"rr" | "red_reverse" => Some(ansi_term::Color::Red.reverse().prefix().to_string()),
"u" | "blue" => Some(ansi_term::Color::Blue.prefix().to_string()),
"ub" | "blue_bold" => Some(ansi_term::Color::Blue.bold().prefix().to_string()),
"uu" | "blue_underline" => Some(ansi_term::Color::Blue.underline().prefix().to_string()),
"ui" | "blue_italic" => Some(ansi_term::Color::Blue.italic().prefix().to_string()),
"ud" | "blue_dimmed" => Some(ansi_term::Color::Blue.dimmed().prefix().to_string()),
"ur" | "blue_reverse" => Some(ansi_term::Color::Blue.reverse().prefix().to_string()),
"b" | "black" => Some(ansi_term::Color::Black.prefix().to_string()),
"bb" | "black_bold" => Some(ansi_term::Color::Black.bold().prefix().to_string()),
"bu" | "black_underline" => Some(ansi_term::Color::Black.underline().prefix().to_string()),
"bi" | "black_italic" => Some(ansi_term::Color::Black.italic().prefix().to_string()),
"bd" | "black_dimmed" => Some(ansi_term::Color::Black.dimmed().prefix().to_string()),
"br" | "black_reverse" => Some(ansi_term::Color::Black.reverse().prefix().to_string()),
"y" | "yellow" => Some(ansi_term::Color::Yellow.prefix().to_string()),
"yb" | "yellow_bold" => Some(ansi_term::Color::Yellow.bold().prefix().to_string()),
"yu" | "yellow_underline" => {
Some(ansi_term::Color::Yellow.underline().prefix().to_string())
}
"yi" | "yellow_italic" => Some(ansi_term::Color::Yellow.italic().prefix().to_string()),
"yd" | "yellow_dimmed" => Some(ansi_term::Color::Yellow.dimmed().prefix().to_string()),
"yr" | "yellow_reverse" => Some(ansi_term::Color::Yellow.reverse().prefix().to_string()),
"p" | "purple" => Some(ansi_term::Color::Purple.prefix().to_string()),
"pb" | "purple_bold" => Some(ansi_term::Color::Purple.bold().prefix().to_string()),
"pu" | "purple_underline" => {
Some(ansi_term::Color::Purple.underline().prefix().to_string())
}
"pi" | "purple_italic" => Some(ansi_term::Color::Purple.italic().prefix().to_string()),
"pd" | "purple_dimmed" => Some(ansi_term::Color::Purple.dimmed().prefix().to_string()),
"pr" | "purple_reverse" => Some(ansi_term::Color::Purple.reverse().prefix().to_string()),
"c" | "cyan" => Some(ansi_term::Color::Cyan.prefix().to_string()),
"cb" | "cyan_bold" => Some(ansi_term::Color::Cyan.bold().prefix().to_string()),
"cu" | "cyan_underline" => Some(ansi_term::Color::Cyan.underline().prefix().to_string()),
"ci" | "cyan_italic" => Some(ansi_term::Color::Cyan.italic().prefix().to_string()),
"cd" | "cyan_dimmed" => Some(ansi_term::Color::Cyan.dimmed().prefix().to_string()),
"cr" | "cyan_reverse" => Some(ansi_term::Color::Cyan.reverse().prefix().to_string()),
"w" | "white" => Some(ansi_term::Color::White.prefix().to_string()),
"wb" | "white_bold" => Some(ansi_term::Color::White.bold().prefix().to_string()),
"wu" | "white_underline" => Some(ansi_term::Color::White.underline().prefix().to_string()),
"wi" | "white_italic" => Some(ansi_term::Color::White.italic().prefix().to_string()),
"wd" | "white_dimmed" => Some(ansi_term::Color::White.dimmed().prefix().to_string()),
"wr" | "white_reverse" => Some(ansi_term::Color::White.reverse().prefix().to_string()),
"reset" => Some("\x1b[0m".to_owned()),
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::Ansi;
#[test]
fn examples_work_as_expected() {
use crate::examples::test as test_examples;
test_examples(Ansi {})
}
}

View File

@ -106,6 +106,7 @@ pub async fn autoview(context: RunnableContext) -> Result<OutputStream, ShellErr
};
let (mut input_stream, context) = RunnableContextWithoutInput::convert(context);
let term_width = context.host.lock().width();
if let Some(x) = input_stream.next().await {
match input_stream.next().await {
@ -120,7 +121,7 @@ pub async fn autoview(context: RunnableContext) -> Result<OutputStream, ShellErr
if let Some(table) = table {
let command_args = create_default_command_args(&context).with_input(stream);
let result = table.run(command_args, &context.registry).await;
let result = table.run(command_args, &context.registry).await?;
result.collect::<Vec<_>>().await;
}
}
@ -137,7 +138,7 @@ pub async fn autoview(context: RunnableContext) -> Result<OutputStream, ShellErr
);
let command_args =
create_default_command_args(&context).with_input(stream);
let result = text.run(command_args, &context.registry).await;
let result = text.run(command_args, &context.registry).await?;
result.collect::<Vec<_>>().await;
} else {
out!("{}", s);
@ -160,7 +161,7 @@ pub async fn autoview(context: RunnableContext) -> Result<OutputStream, ShellErr
);
let command_args =
create_default_command_args(&context).with_input(stream);
let result = text.run(command_args, &context.registry).await;
let result = text.run(command_args, &context.registry).await?;
result.collect::<Vec<_>>().await;
} else {
out!("{}\n", s);
@ -235,7 +236,7 @@ pub async fn autoview(context: RunnableContext) -> Result<OutputStream, ShellErr
stream.push_back(x);
let command_args =
create_default_command_args(&context).with_input(stream);
let result = binary.run(command_args, &context.registry).await;
let result = binary.run(command_args, &context.registry).await?;
result.collect::<Vec<_>>().await;
} else {
use pretty_hex::*;
@ -263,7 +264,7 @@ pub async fn autoview(context: RunnableContext) -> Result<OutputStream, ShellErr
.iter()
.fold(0usize, |acc, len| acc + len.len())
+ row.entries.iter().count() * 2)
> textwrap::termwidth()) =>
> term_width) =>
{
let mut entries = vec![];
for (key, value) in row.entries.iter() {
@ -286,7 +287,7 @@ pub async fn autoview(context: RunnableContext) -> Result<OutputStream, ShellErr
let table =
nu_table::Table::new(vec![], entries, nu_table::Theme::compact());
nu_table::draw_table(&table, textwrap::termwidth());
nu_table::draw_table(&table, term_width);
}
Value {
@ -297,7 +298,7 @@ pub async fn autoview(context: RunnableContext) -> Result<OutputStream, ShellErr
stream.push_back(x);
let command_args =
create_default_command_args(&context).with_input(stream);
let result = table.run(command_args, &context.registry).await;
let result = table.run(command_args, &context.registry).await?;
result.collect::<Vec<_>>().await;
} else {
out!("{:?}", item);

View File

@ -84,17 +84,15 @@ pub async fn cal(
let mut selected_year: i32 = current_year;
let mut current_day_option: Option<u32> = Some(current_day);
let month_range = if args.has("full-year") {
if let Some(full_year_value) = args.get("full-year") {
if let Ok(year_u64) = full_year_value.as_u64() {
selected_year = year_u64 as i32;
let month_range = if let Some(full_year_value) = args.get("full-year") {
if let Ok(year_u64) = full_year_value.as_u64() {
selected_year = year_u64 as i32;
if selected_year != current_year {
current_day_option = None
}
} else {
return Err(get_invalid_year_shell_error(&full_year_value.tag()));
if selected_year != current_year {
current_day_option = None
}
} else {
return Err(get_invalid_year_shell_error(&full_year_value.tag()));
}
(1, 12)
@ -300,7 +298,7 @@ fn add_month_to_table(
);
}
if should_show_month_column {
if should_show_month_column || should_show_month_names {
let month_value = if should_show_month_names {
UntaggedValue::string(month_helper.month_name.clone()).into_value(tag)
} else {

View File

@ -0,0 +1,81 @@
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
use nu_source::Tagged;
pub struct Char;
#[derive(Deserialize)]
struct CharArgs {
name: Tagged<String>,
}
#[async_trait]
impl WholeStreamCommand for Char {
fn name(&self) -> &str {
"char"
}
fn signature(&self) -> Signature {
Signature::build("ansi").required(
"character",
SyntaxShape::Any,
"the name of the character to output",
)
}
fn usage(&self) -> &str {
"Output special characters (eg. 'newline')"
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Output newline",
example: r#"char newline"#,
result: Some(vec![Value::from("\n")]),
}]
}
async fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let (CharArgs { name }, _) = args.process(&registry).await?;
let special_character = str_to_character(&name.item);
if let Some(output) = special_character {
Ok(OutputStream::one(ReturnSuccess::value(
UntaggedValue::string(output).into_value(name.tag()),
)))
} else {
Err(ShellError::labeled_error(
"Unknown character",
"unknown character",
name.tag(),
))
}
}
}
fn str_to_character(s: &str) -> Option<String> {
match s {
"newline" | "enter" | "nl" => Some("\n".into()),
"tab" => Some("\t".into()),
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::Char;
#[test]
fn examples_work_as_expected() {
use crate::examples::test as test_examples;
test_examples(Char {})
}
}

View File

@ -214,6 +214,9 @@ fn spawn(
if !is_last {
process.stdout(Stdio::piped());
trace!(target: "nu::run::external", "set up stdout pipe");
process.stderr(Stdio::piped());
trace!(target: "nu::run::external", "set up stderr pipe");
}
// open since we have some contents for stdin
@ -312,6 +315,20 @@ fn spawn(
return Err(());
};
let stderr = if let Some(stderr) = child.stderr.take() {
stderr
} else {
let _ = stdout_read_tx.send(Ok(Value {
value: UntaggedValue::Error(ShellError::labeled_error(
"Can't redirect the stderr for external command",
"can't redirect stderr",
&stdout_name_tag,
)),
tag: stdout_name_tag,
}));
return Err(());
};
let file = futures::io::AllowStdIo::new(stdout);
let stream = FramedRead::new(file, MaybeTextCodec);
@ -365,6 +382,64 @@ fn spawn(
}
}
}
let file = futures::io::AllowStdIo::new(stderr);
let err_stream = FramedRead::new(file, MaybeTextCodec);
for err_line in block_on_stream(err_stream) {
match err_line {
Ok(line) => match line {
StringOrBinary::String(s) => {
let result = stdout_read_tx.send(Ok(Value {
value: UntaggedValue::Error(
ShellError::untagged_runtime_error(s.clone()),
),
tag: stdout_name_tag.clone(),
}));
if result.is_err() {
break;
}
}
StringOrBinary::Binary(_) => {
let result = stdout_read_tx.send(Ok(Value {
value: UntaggedValue::Error(
ShellError::untagged_runtime_error(
"Binary in stderr output",
),
),
tag: stdout_name_tag.clone(),
}));
if result.is_err() {
break;
}
}
},
Err(e) => {
// If there's an exit status, it makes sense that we may error when
// trying to read from its stdout pipe (likely been closed). In that
// case, don't emit an error.
let should_error = match child.wait() {
Ok(exit_status) => !exit_status.success(),
Err(_) => true,
};
if should_error {
let _ = stdout_read_tx.send(Ok(Value {
value: UntaggedValue::Error(ShellError::labeled_error(
format!("Unable to read from stderr ({})", e),
"unable to read from stderr",
&stdout_name_tag,
)),
tag: stdout_name_tag.clone(),
}));
}
return Ok(());
}
}
}
}
// We can give an error when we see a non-zero exit code, but this is different

View File

@ -37,7 +37,7 @@ pub(crate) async fn run_internal_command(
&scope,
objects,
)
.await
.await?
};
let head = Arc::new(command.args.head.clone());
@ -89,37 +89,49 @@ pub(crate) async fn run_internal_command(
scope: (&*scope).clone(),
},
};
let mut result = converter
let result = converter
.run(
new_args.with_input(vec![tagged_contents]),
&context.registry,
)
.await;
let result_vec: Vec<Result<ReturnSuccess, ShellError>> =
result.drain_vec().await;
let mut output = vec![];
for res in result_vec {
match res {
Ok(ReturnSuccess::Value(Value {
value: UntaggedValue::Table(list),
..
})) => {
for l in list {
output.push(Ok(l));
match result {
Ok(mut result) => {
let result_vec: Vec<Result<ReturnSuccess, ShellError>> =
result.drain_vec().await;
let mut output = vec![];
for res in result_vec {
match res {
Ok(ReturnSuccess::Value(Value {
value: UntaggedValue::Table(list),
..
})) => {
for l in list {
output.push(Ok(l));
}
}
Ok(ReturnSuccess::Value(Value {
value,
..
})) => {
output
.push(Ok(value
.into_value(contents_tag.clone())));
}
Err(e) => output.push(Err(e)),
_ => {}
}
}
Ok(ReturnSuccess::Value(Value { value, .. })) => {
output.push(Ok(
value.into_value(contents_tag.clone())
));
}
Err(e) => output.push(Err(e)),
_ => {}
futures::stream::iter(output).to_input_stream()
}
Err(e) => {
context.add_error(e);
InputStream::empty()
}
}
futures::stream::iter(output).to_input_stream()
} else {
InputStream::one(tagged_contents)
}

View File

@ -343,18 +343,19 @@ impl Command {
self.0.usage()
}
pub async fn run(&self, args: CommandArgs, registry: &CommandRegistry) -> OutputStream {
pub async fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
if args.call_info.switch_present("help") {
let cl = self.0.clone();
let registry = registry.clone();
OutputStream::one(Ok(ReturnSuccess::Value(
Ok(OutputStream::one(Ok(ReturnSuccess::Value(
UntaggedValue::string(get_help(&*cl, &registry)).into_value(Tag::unknown()),
)))
))))
} else {
match self.0.run(args, registry).await {
Ok(stream) => stream,
Err(err) => OutputStream::one(Err(err)),
}
self.0.run(args, registry).await
}
}

View File

@ -7,7 +7,7 @@ use crate::commands::WholeStreamCommand;
use chrono::{Datelike, TimeZone, Timelike};
use core::fmt::Display;
use indexmap::IndexMap;
use nu_protocol::{Signature, UntaggedValue};
use nu_protocol::{Signature, SyntaxShape, UntaggedValue};
pub struct Date;
@ -21,6 +21,13 @@ impl WholeStreamCommand for Date {
Signature::build("date")
.switch("utc", "use universal time (UTC)", Some('u'))
.switch("local", "use the local time", Some('l'))
.named(
"format",
SyntaxShape::String,
"report datetime in supplied strftime format",
Some('f'),
)
.switch("raw", "print date without tables", Some('r'))
}
fn usage(&self) -> &str {
@ -47,46 +54,72 @@ impl WholeStreamCommand for Date {
example: "date --utc",
result: None,
},
Example {
description: "Get the current time and date and report it based on format",
example: "date --format '%Y-%m-%d %H:%M:%S.%f %z'",
result: None,
},
Example {
description: "Get the current time and date and report it without a table",
example: "date --format '%Y-%m-%d %H:%M:%S.%f %z' --raw",
result: None,
},
]
}
}
pub fn date_to_value<T: TimeZone>(dt: DateTime<T>, tag: Tag) -> Value
pub fn date_to_value_raw<T: TimeZone>(dt: DateTime<T>, dt_format: String) -> String
where
T::Offset: Display,
{
let result = dt.format(&dt_format);
format!("{}", result)
}
pub fn date_to_value<T: TimeZone>(dt: DateTime<T>, tag: Tag, dt_format: String) -> Value
where
T::Offset: Display,
{
let mut indexmap = IndexMap::new();
indexmap.insert(
"year".to_string(),
UntaggedValue::int(dt.year()).into_value(&tag),
);
indexmap.insert(
"month".to_string(),
UntaggedValue::int(dt.month()).into_value(&tag),
);
indexmap.insert(
"day".to_string(),
UntaggedValue::int(dt.day()).into_value(&tag),
);
indexmap.insert(
"hour".to_string(),
UntaggedValue::int(dt.hour()).into_value(&tag),
);
indexmap.insert(
"minute".to_string(),
UntaggedValue::int(dt.minute()).into_value(&tag),
);
indexmap.insert(
"second".to_string(),
UntaggedValue::int(dt.second()).into_value(&tag),
);
if dt_format.is_empty() {
indexmap.insert(
"year".to_string(),
UntaggedValue::int(dt.year()).into_value(&tag),
);
indexmap.insert(
"month".to_string(),
UntaggedValue::int(dt.month()).into_value(&tag),
);
indexmap.insert(
"day".to_string(),
UntaggedValue::int(dt.day()).into_value(&tag),
);
indexmap.insert(
"hour".to_string(),
UntaggedValue::int(dt.hour()).into_value(&tag),
);
indexmap.insert(
"minute".to_string(),
UntaggedValue::int(dt.minute()).into_value(&tag),
);
indexmap.insert(
"second".to_string(),
UntaggedValue::int(dt.second()).into_value(&tag),
);
let tz = dt.offset();
indexmap.insert(
"timezone".to_string(),
UntaggedValue::string(format!("{}", tz)).into_value(&tag),
);
let tz = dt.offset();
indexmap.insert(
"timezone".to_string(),
UntaggedValue::string(format!("{}", tz)).into_value(&tag),
);
} else {
let result = dt.format(&dt_format);
indexmap.insert(
"formatted".to_string(),
UntaggedValue::string(format!("{}", result)).into_value(&tag),
);
}
UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag)
}
@ -97,15 +130,33 @@ pub async fn date(
) -> Result<OutputStream, ShellError> {
let registry = registry.clone();
let args = args.evaluate_once(&registry).await?;
let tag = args.call_info.name_tag.clone();
let raw = args.has("raw");
let dt_fmt = if args.has("format") {
if let Some(dt_fmt) = args.get("format") {
dt_fmt.convert_to_string()
} else {
"".to_string()
}
} else {
"".to_string()
};
let value = if args.has("utc") {
let utc: DateTime<Utc> = Utc::now();
date_to_value(utc, tag)
if raw {
UntaggedValue::string(date_to_value_raw(utc, dt_fmt)).into_untagged_value()
} else {
date_to_value(utc, tag, dt_fmt)
}
} else {
let local: DateTime<Local> = Local::now();
date_to_value(local, tag)
if raw {
UntaggedValue::string(date_to_value_raw(local, dt_fmt)).into_untagged_value()
} else {
date_to_value(local, tag, dt_fmt)
}
};
Ok(OutputStream::one(value))

View File

@ -0,0 +1,111 @@
use crate::commands::classified::block::run_block;
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{hir::Block, ReturnSuccess, Signature, SyntaxShape, Value};
pub struct Do;
#[derive(Deserialize, Debug)]
struct DoArgs {
block: Block,
ignore_errors: bool,
}
#[async_trait]
impl WholeStreamCommand for Do {
fn name(&self) -> &str {
"do"
}
fn signature(&self) -> Signature {
Signature::build("with-env")
.required("block", SyntaxShape::Block, "the block to run ")
.switch(
"ignore_errors",
"ignore errors as the block runs",
Some('i'),
)
}
fn usage(&self) -> &str {
"Runs a block, optionally ignoring errors"
}
async fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
do_(args, registry).await
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Run the block",
example: r#"do { echo hello }"#,
result: Some(vec![Value::from("hello")]),
},
Example {
description: "Run the block and ignore errors",
example: r#"do -i { thisisnotarealcommand }"#,
result: Some(vec![Value::nothing()]),
},
]
}
}
async fn do_(
raw_args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let registry = registry.clone();
let is_last = raw_args.call_info.args.is_last;
let mut context = Context::from_raw(&raw_args, &registry);
let scope = raw_args.call_info.scope.clone();
let (
DoArgs {
ignore_errors,
mut block,
},
input,
) = raw_args.process(&registry).await?;
block.set_is_last(is_last);
let result = run_block(
&block,
&mut context,
input,
&scope.it,
&scope.vars,
&scope.env,
)
.await;
if ignore_errors {
match result {
Ok(mut stream) => {
let output = stream.drain_vec().await;
context.clear_errors();
Ok(futures::stream::iter(output).to_output_stream())
}
Err(_) => Ok(OutputStream::one(ReturnSuccess::value(Value::nothing()))),
}
} else {
result.map(|x| x.to_output_stream())
}
}
#[cfg(test)]
mod tests {
use super::Do;
#[test]
fn examples_work_as_expected() {
use crate::examples::test as test_examples;
test_examples(Do {})
}
}

View File

@ -158,7 +158,7 @@ async fn enter(
};
let mut result = converter
.run(new_args.with_input(vec![tagged_contents]), &registry)
.await;
.await?;
let result_vec: Vec<Result<ReturnSuccess, ShellError>> =
result.drain_vec().await;

View File

@ -74,7 +74,7 @@ mod tests {
Ok(int(10)),
Ok(int(10)),
Ok(int(10)),
Ok(table(&vec![int(10)])),
Ok(table(&[int(10)])),
Ok(int(10)),
],
},
@ -87,7 +87,7 @@ mod tests {
Ok(int(10)),
Ok(int(30)),
Ok(int(20)),
Ok(table(&vec![int(10), int(20), int(30)])),
Ok(table(&[int(10), int(20), int(30)])),
Ok(int(60)),
],
},
@ -100,7 +100,7 @@ mod tests {
Ok(int(10)),
Ok(decimal(26.5)),
Ok(decimal(26.5)),
Ok(table(&vec![decimal(26.5)])),
Ok(table(&[decimal(26.5)])),
Ok(decimal(63)),
],
},
@ -113,7 +113,7 @@ mod tests {
Ok(int(-14)),
Ok(int(10)),
Ok(int(-11)),
Ok(table(&vec![int(-14), int(-11), int(10)])),
Ok(table(&[int(-14), int(-11), int(10)])),
Ok(int(-15)),
],
},
@ -126,7 +126,7 @@ mod tests {
Ok(decimal(-13.5)),
Ok(int(10)),
Ok(decimal(-11.5)),
Ok(table(&vec![decimal(-13.5), decimal(-11.5), int(10)])),
Ok(table(&[decimal(-13.5), decimal(-11.5), int(10)])),
Ok(decimal(-15)),
],
},
@ -145,8 +145,8 @@ mod tests {
Ok(row!["col1".to_owned() => int(4), "col2".to_owned() => int(8)]),
Ok(row!["col1".to_owned() => decimal(2.5), "col2".to_owned() => decimal(6.5)]),
Ok(row![
"col1".to_owned() => table(&vec![int(1), int(2), int(3), int(4)]),
"col2".to_owned() => table(&vec![int(5), int(6), int(7), int(8)])
"col1".to_owned() => table(&[int(1), int(2), int(3), int(4)]),
"col2".to_owned() => table(&[int(5), int(6), int(7), int(8)])
]),
Ok(row!["col1".to_owned() => int(10), "col2".to_owned() => int(26)]),
],

View File

@ -0,0 +1,97 @@
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
use nu_source::Tagged;
use rand::prelude::{thread_rng, Rng};
pub struct SubCommand;
#[derive(Deserialize)]
pub struct BoolArgs {
bias: Option<Tagged<f64>>,
}
#[async_trait]
impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str {
"random bool"
}
fn signature(&self) -> Signature {
Signature::build("random bool").named(
"bias",
SyntaxShape::Number,
"Adjusts the probability of a \"true\" outcome",
Some('b'),
)
}
fn usage(&self) -> &str {
"Generate a random boolean value"
}
async fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
bool_command(args, registry).await
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Generate a random boolean value",
example: "random bool",
result: None,
},
Example {
description: "Generate a random boolean value with a 75% chance of \"true\"",
example: "random bool --bias 0.75",
result: None,
},
]
}
}
pub async fn bool_command(
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let (BoolArgs { bias }, _) = args.process(&registry).await?;
let mut probability = 0.5;
if let Some(prob) = bias {
probability = *prob as f64;
let probability_is_valid = 0.0 <= probability && probability <= 1.0;
if !probability_is_valid {
return Err(ShellError::labeled_error(
"The probability is invalid",
"invalid probability",
prob.span(),
));
}
}
let mut rng = thread_rng();
let bool_result: bool = rng.gen_bool(probability);
let bool_untagged_value = UntaggedValue::boolean(bool_result);
Ok(OutputStream::one(ReturnSuccess::value(bool_untagged_value)))
}
#[cfg(test)]
mod tests {
use super::SubCommand;
#[test]
fn examples_work_as_expected() {
use crate::examples::test as test_examples;
test_examples(SubCommand {})
}
}

View File

@ -0,0 +1,103 @@
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{Signature, SyntaxShape, UntaggedValue};
use nu_source::Tagged;
use rand::prelude::{thread_rng, Rng};
pub struct SubCommand;
#[derive(Deserialize)]
pub struct DiceArgs {
dice: Option<Tagged<u32>>,
sides: Option<Tagged<u32>>,
}
#[async_trait]
impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str {
"random dice"
}
fn signature(&self) -> Signature {
Signature::build("random dice")
.named(
"dice",
SyntaxShape::Int,
"The amount of dice being rolled",
Some('d'),
)
.named(
"sides",
SyntaxShape::Int,
"The amount of sides a die has",
Some('s'),
)
}
fn usage(&self) -> &str {
"Generate a random dice roll"
}
async fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
dice(args, registry).await
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Roll 1 dice with 6 sides each",
example: "random dice",
result: None,
},
Example {
description: "Roll 10 dice with 12 sides each",
example: "random dice -d 10 -s 12",
result: None,
},
]
}
}
pub async fn dice(
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone();
let (DiceArgs { dice, sides }, _) = args.process(&registry).await?;
let dice = if let Some(dice_tagged) = dice {
*dice_tagged
} else {
1
};
let sides = if let Some(sides_tagged) = sides {
*sides_tagged
} else {
6
};
let iter = (0..dice).map(move |_| {
let mut thread_rng = thread_rng();
UntaggedValue::int(thread_rng.gen_range(1, sides + 1)).into_value(tag.clone())
});
Ok(futures::stream::iter(iter).to_output_stream())
}
#[cfg(test)]
mod tests {
use super::SubCommand;
#[test]
fn examples_work_as_expected() {
use crate::examples::test as test_examples;
test_examples(SubCommand {})
}
}

View File

@ -1,5 +1,11 @@
pub mod command;
pub mod bool;
pub mod dice;
pub mod uuid;
pub use command::Command as Random;
pub use self::bool::SubCommand as RandomBool;
pub use dice::SubCommand as RandomDice;
pub use uuid::SubCommand as RandomUUID;

View File

@ -40,7 +40,9 @@ impl WholeStreamCommand for AliasCommand {
) -> Result<OutputStream, ShellError> {
let call_info = args.call_info.clone();
let registry = registry.clone();
let block = self.block.clone();
let mut block = self.block.clone();
block.set_is_last(call_info.args.is_last);
let alias_command = self.clone();
let mut context = Context::from_args(&args, &registry);
let input = args.input;

View File

@ -232,7 +232,7 @@ async fn save(
scope,
},
};
let mut result = converter.run(new_args.with_input(input), &registry).await;
let mut result = converter.run(new_args.with_input(input), &registry).await?;
let result_vec: Vec<Result<ReturnSuccess, ShellError>> =
result.drain_vec().await;
if converter.is_binary() {

View File

@ -0,0 +1,56 @@
use crate::commands::WholeStreamCommand;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue, Value};
pub struct SubCommand;
#[async_trait]
impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str {
"str collect"
}
fn signature(&self) -> Signature {
Signature::build("str collect")
}
fn usage(&self) -> &str {
"collects a list of strings into a string"
}
async fn run(
&self,
args: CommandArgs,
_registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let output = args
.input
.collect_string(args.call_info.name_tag.clone())
.await?;
Ok(OutputStream::one(ReturnSuccess::value(
UntaggedValue::string(output.item).into_value(output.tag),
)))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Collect a list of string",
example: "echo ['a' 'b' 'c'] | str collect",
result: Some(vec![Value::from("abc")]),
}]
}
}
#[cfg(test)]
mod tests {
use super::SubCommand;
#[test]
fn examples_work_as_expected() {
use crate::examples::test as test_examples;
test_examples(SubCommand {})
}
}

View File

@ -1,4 +1,5 @@
mod capitalize;
mod collect;
mod command;
mod downcase;
mod find_replace;
@ -11,6 +12,7 @@ mod trim;
mod upcase;
pub use capitalize::SubCommand as StrCapitalize;
pub use collect::SubCommand as StrCollect;
pub use command::Command as Str;
pub use downcase::SubCommand as StrDowncase;
pub use find_replace::SubCommand as StrFindReplace;

View File

@ -241,7 +241,7 @@ async fn table(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputSt
let mut delay_slot = None;
let termwidth = std::cmp::max(textwrap::termwidth(), 20);
let term_width = args.host.lock().width();
while !finished {
let mut new_input: VecDeque<Value> = VecDeque::new();
@ -294,7 +294,7 @@ async fn table(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputSt
if !input.is_empty() {
let t = from_list(&input, start_number);
draw_table(&t, termwidth);
draw_table(&t, term_width);
}
start_number += input.len();

View File

@ -184,6 +184,10 @@ impl Context {
self.current_errors.lock().clone()
}
pub(crate) fn add_error(&self, err: ShellError) {
self.current_errors.lock().push(err);
}
pub(crate) fn maybe_print_errors(&mut self, source: Text) -> bool {
let errors = self.current_errors.clone();
let mut errors = errors.lock();
@ -232,7 +236,7 @@ impl Context {
args: hir::Call,
scope: &Scope,
input: InputStream,
) -> OutputStream {
) -> Result<OutputStream, ShellError> {
let command_args = self.command_args(args, input, name_tag, scope);
command.run(command_args, self.registry()).await
}

View File

@ -412,6 +412,15 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut ConfigDeserializer<'de> {
let i: i64 = int.tagged(value.val.tag).coerce_into("converting to i64")?;
visit::<Tagged<i64>, _>(i.tagged(tag), name, fields, visitor)
}
Value {
value: UntaggedValue::Primitive(Primitive::Decimal(decimal)),
..
} => {
let i: f64 = decimal
.tagged(value.val.tag)
.coerce_into("converting to f64")?;
visit::<Tagged<f64>, _>(i.tagged(tag), name, fields, visitor)
}
Value {
value: UntaggedValue::Primitive(Primitive::String(string)),
..

View File

@ -120,7 +120,9 @@ impl Host for BasicHost {
}
fn width(&self) -> usize {
std::cmp::max(textwrap::termwidth(), 20)
let (mut term_width, _) = term_size::dimensions().unwrap_or_else(|| (20, 20));
term_width -= 1;
std::cmp::max(term_width, 20)
}
}

View File

@ -196,6 +196,9 @@ async fn evaluate_invocation(
let input = InputStream::empty();
let mut block = block.clone();
block.set_is_last(true);
let result = run_block(&block, &mut context, input, it, vars, env).await?;
let output = result.into_vec().await;

View File

@ -1,6 +1,11 @@
use ansi_term::{Color, Style};
use nu_protocol::hir::FlatShape;
use nu_source::{Span, Spanned};
use serde::{self, Deserialize, Deserializer, Serialize, Serializer};
use std::error::Error;
use std::ops::Deref;
use std::str::Bytes;
use std::{fmt, io};
pub trait Palette {
fn styles_for_shape(&self, shape: &Spanned<FlatShape>) -> Vec<Spanned<Style>>;
@ -58,6 +63,268 @@ impl Palette for DefaultPalette {
}
}
pub struct ThemedPalette {
theme: Theme,
}
impl ThemedPalette {
// remove this once we start actually loading themes.
#[allow(dead_code)]
pub fn new<R: io::Read>(reader: &mut R) -> Result<ThemedPalette, ThemeError> {
let theme = serde_json::from_reader(reader)?;
Ok(ThemedPalette { theme })
}
}
impl Palette for ThemedPalette {
fn styles_for_shape(&self, shape: &Spanned<FlatShape>) -> Vec<Spanned<Style>> {
match &shape.item {
FlatShape::OpenDelimiter(_) => {
single_style_span(self.theme.open_delimiter.normal(), shape.span)
}
FlatShape::CloseDelimiter(_) => {
single_style_span(self.theme.close_delimiter.normal(), shape.span)
}
FlatShape::ItVariable => single_style_span(self.theme.it_variable.bold(), shape.span),
FlatShape::Keyword => single_style_span(self.theme.keyword.bold(), shape.span),
FlatShape::Variable => single_style_span(self.theme.variable.normal(), shape.span),
FlatShape::Identifier => single_style_span(self.theme.identifier.normal(), shape.span),
FlatShape::Type => single_style_span(self.theme.r#type.bold(), shape.span),
FlatShape::Operator => single_style_span(self.theme.operator.normal(), shape.span),
FlatShape::DotDot => single_style_span(self.theme.dot_dot.bold(), shape.span),
FlatShape::Dot => single_style_span(Style::new().fg(*self.theme.dot), shape.span),
FlatShape::InternalCommand => {
single_style_span(self.theme.internal_command.bold(), shape.span)
}
FlatShape::ExternalCommand => {
single_style_span(self.theme.external_command.normal(), shape.span)
}
FlatShape::ExternalWord => {
single_style_span(self.theme.external_word.bold(), shape.span)
}
FlatShape::BareMember => single_style_span(self.theme.bare_member.bold(), shape.span),
FlatShape::StringMember => {
single_style_span(self.theme.string_member.bold(), shape.span)
}
FlatShape::String => single_style_span(self.theme.string.normal(), shape.span),
FlatShape::Path => single_style_span(self.theme.path.normal(), shape.span),
FlatShape::GlobPattern => single_style_span(self.theme.glob_pattern.bold(), shape.span),
FlatShape::Word => single_style_span(self.theme.word.normal(), shape.span),
FlatShape::Pipe => single_style_span(self.theme.pipe.bold(), shape.span),
FlatShape::Flag => single_style_span(self.theme.flag.bold(), shape.span),
FlatShape::ShorthandFlag => {
single_style_span(self.theme.shorthand_flag.bold(), shape.span)
}
FlatShape::Int => single_style_span(self.theme.int.bold(), shape.span),
FlatShape::Decimal => single_style_span(self.theme.decimal.bold(), shape.span),
FlatShape::Whitespace => single_style_span(self.theme.whitespace.normal(), shape.span),
FlatShape::Separator => single_style_span(self.theme.separator.normal(), shape.span),
FlatShape::Comment => single_style_span(self.theme.comment.bold(), shape.span),
FlatShape::Garbage => single_style_span(
Style::new().fg(*self.theme.garbage).on(Color::Red),
shape.span,
),
FlatShape::Size { number, unit } => vec![
Spanned::<Style> {
span: *number,
item: self.theme.size_number.bold(),
},
Spanned::<Style> {
span: *unit,
item: self.theme.size_unit.bold(),
},
],
}
}
}
#[derive(Debug)]
pub struct ThemeError {
serde_err: serde_json::error::Error,
}
impl fmt::Display for ThemeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "failure to load theme")
}
}
impl Error for ThemeError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
Some(&self.serde_err)
}
}
impl From<serde_json::error::Error> for ThemeError {
fn from(serde_err: serde_json::error::Error) -> Self {
ThemeError { serde_err }
}
}
#[derive(Serialize, Deserialize, Debug)]
struct Theme {
open_delimiter: ThemeColor,
close_delimiter: ThemeColor,
r#type: ThemeColor,
identifier: ThemeColor,
it_variable: ThemeColor,
variable: ThemeColor,
operator: ThemeColor,
dot: ThemeColor,
dot_dot: ThemeColor,
internal_command: ThemeColor,
external_command: ThemeColor,
external_word: ThemeColor,
bare_member: ThemeColor,
string_member: ThemeColor,
string: ThemeColor,
path: ThemeColor,
word: ThemeColor,
keyword: ThemeColor,
pipe: ThemeColor,
glob_pattern: ThemeColor,
flag: ThemeColor,
shorthand_flag: ThemeColor,
int: ThemeColor,
decimal: ThemeColor,
garbage: ThemeColor,
whitespace: ThemeColor,
separator: ThemeColor,
comment: ThemeColor,
size_number: ThemeColor,
size_unit: ThemeColor,
}
#[derive(Debug)]
struct ThemeColor(Color);
impl Deref for ThemeColor {
type Target = Color;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Serialize for ThemeColor {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str("TODO: IMPLEMENT SERIALIZATION")
}
}
impl<'de> Deserialize<'de> for ThemeColor {
fn deserialize<D>(deserializer: D) -> Result<ThemeColor, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
ThemeColor::from_str(&s)
}
}
impl ThemeColor {
fn from_str<E>(s: &str) -> Result<ThemeColor, E>
where
E: serde::de::Error,
{
let mut bytes = s.bytes();
let r = ThemeColor::xtoi(&mut bytes)?;
let g = ThemeColor::xtoi(&mut bytes)?;
let b = ThemeColor::xtoi(&mut bytes)?;
Ok(ThemeColor(Color::RGB(r, g, b)))
}
fn xtoi<E>(b: &mut Bytes) -> Result<u8, E>
where
E: serde::de::Error,
{
let upper = b
.next()
.ok_or_else(|| E::custom("color string too short"))?;
let lower = b
.next()
.ok_or_else(|| E::custom("color string too short"))?;
let mut val = ThemeColor::numerical_value(upper)?;
val = (val << 4) | ThemeColor::numerical_value(lower)?;
Ok(val)
}
fn numerical_value<E>(character: u8) -> Result<u8, E>
where
E: serde::de::Error,
{
match character {
b'0'..=b'9' => Ok(character - b'0'),
b'a'..=b'z' => Ok(character - (b'a' - 10)),
_ => Err(E::custom(format!("invalid charater {}", character))),
}
}
}
fn single_style_span(style: Style, span: Span) -> Vec<Spanned<Style>> {
vec![Spanned::<Style> { span, item: style }]
}
#[cfg(test)]
mod tests {
use super::{Palette, ThemedPalette};
use ansi_term::Color;
use nu_protocol::hir::FlatShape;
use nu_source::{Span, Spanned};
use std::io::Cursor;
#[test]
fn create_themed_palette() {
let json = r#"
{
"open_delimiter": "a359cc",
"close_delimiter": "a359cc",
"type": "a359cc",
"identifier": "a359cc",
"it_variable": "a359cc",
"variable": "a359cc",
"operator": "a359cc",
"dot": "a359cc",
"dot_dot": "a359cc",
"internal_command": "a359cc",
"external_command": "a359cc",
"external_word": "a359cc",
"bare_member": "a359cc",
"string_member": "a359cc",
"string": "a359cc",
"path": "a359cc",
"word": "a359cc",
"keyword": "a359cc",
"pipe": "a359cc",
"glob_pattern": "a359cc",
"flag": "a359cc",
"shorthand_flag": "a359cc",
"int": "a359cc",
"decimal": "a359cc",
"garbage": "a359cc",
"whitespace": "a359cc",
"separator": "a359cc",
"comment": "a359cc",
"size_number": "a359cc",
"size_unit": "a359cc"
}"#;
let mut json_reader = Cursor::new(json);
let themed_palette = ThemedPalette::new(&mut json_reader).unwrap();
let test_shape = Spanned {
item: FlatShape::Type,
span: Span::new(4, 9),
};
let styled = themed_palette.styles_for_shape(&test_shape);
assert_eq!(styled.len(), 1);
assert_eq!(
styled[0],
Spanned {
item: Color::RGB(163, 89, 204).bold(),
span: Span::new(4, 9),
},
);
}
}

View File

@ -1,7 +1,7 @@
use crate::prelude::*;
use futures::stream::{iter, once};
use nu_errors::ShellError;
use nu_protocol::{Primitive, UntaggedValue, Value};
use nu_protocol::{Primitive, Type, UntaggedValue, Value};
use nu_source::{Tagged, TaggedItem};
pub struct InputStream {
@ -74,12 +74,24 @@ impl InputStream {
value_tag = value_t;
bytes.extend_from_slice(&b);
}
Some(Value { tag: value_tag, .. }) => {
Some(Value {
value: UntaggedValue::Primitive(Primitive::Nothing),
tag: value_t,
}) => {
value_tag = value_t;
}
Some(Value {
tag: value_tag,
value,
}) => {
return Err(ShellError::labeled_error_with_secondary(
"Expected a string from pipeline",
"requires string input",
tag,
"value originates from here",
format!(
"{} originates from here",
Type::from_value(&value).plain_string(100000)
),
value_tag,
))
}

View File

@ -0,0 +1,16 @@
use nu_test_support::{nu, pipeline};
#[test]
fn generates_a_bool() {
let actual = nu!(
cwd: ".", pipeline(
r#"
random bool
"#
));
let output = actual.out;
let is_boolean_output = output == "true" || output == "false";
assert!(is_boolean_output);
}

View File

@ -0,0 +1,13 @@
use nu_test_support::{nu, pipeline};
#[test]
fn rolls_4_roll() {
let actual = nu!(
cwd: ".", pipeline(
r#"
random dice -d 4 -s 10 | count
"#
));
assert_eq!(actual.out, "4");
}

View File

@ -1 +1,3 @@
mod bool;
mod dice;
mod uuid;

View File

@ -2,7 +2,7 @@ use nu_test_support::{nu, pipeline};
use uuid_crate::Uuid;
#[test]
fn makes_valid_uuid4() {
fn generates_valid_uuid4() {
let actual = nu!(
cwd: ".", pipeline(
r#"

View File

@ -1,6 +1,6 @@
[package]
name = "nu-errors"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
edition = "2018"
description = "Core error subsystem for Nushell"
@ -10,22 +10,22 @@ license = "MIT"
doctest = false
[dependencies]
nu-source = { path = "../nu-source", version = "0.15.1" }
nu-source = { path = "../nu-source", version = "0.16.0" }
ansi_term = "0.12.1"
bigdecimal = { version = "0.1.2", features = ["serde"] }
derive-new = "0.5.8"
codespan-reporting = { version = "0.9.4", features = ["serialization"]}
codespan-reporting = { version = "0.9.5", features = ["serialization"]}
num-bigint = { version = "0.2.6", features = ["serde"] }
num-traits = "0.2.11"
serde = { version = "1.0.110", features = ["derive"] }
num-traits = "0.2.12"
serde = { version = "1.0.114", features = ["derive"] }
getset = "0.1.1"
# implement conversions
serde_yaml = "0.8"
toml = "0.5.6"
serde_json = "1.0.53"
serde_json = "1.0.55"
glob = "0.3.0"
[build-dependencies]
nu-build = { version = "0.15.1", path = "../nu-build" }
nu-build = { version = "0.16.0", path = "../nu-build" }

View File

@ -177,8 +177,8 @@ impl PrettyDebug for ArgumentError {
/// creating a cause chain.
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Serialize, Deserialize, Hash)]
pub struct ShellError {
error: ProximateShellError,
cause: Option<Box<ShellError>>,
pub error: ProximateShellError,
pub cause: Option<Box<ShellError>>,
}
/// `PrettyDebug` is for internal debugging. For user-facing debugging, [into_diagnostic](ShellError::into_diagnostic)
@ -773,7 +773,7 @@ impl HasFallibleSpan for ProximateShellError {
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ShellDiagnostic {
pub(crate) diagnostic: Diagnostic<usize>,
pub diagnostic: Diagnostic<usize>,
}
impl std::hash::Hash for ShellDiagnostic {

View File

@ -1,6 +1,6 @@
[package]
name = "nu-parser"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
edition = "2018"
description = "Nushell parser"
@ -11,18 +11,18 @@ license = "MIT"
[dependencies]
num-bigint = { version = "0.2.6", features = ["serde"] }
bigdecimal = { version = "0.1.2", features = ["serde"] }
indexmap = { version = "1.3.2", features = ["serde-1"] }
parking_lot = "0.10.2"
num-traits = "0.2.11"
indexmap = { version = "1.4.0", features = ["serde-1"] }
parking_lot = "0.11.0"
num-traits = "0.2.12"
derive-new = "0.5.8"
serde = "1.0.110"
codespan-reporting = "0.9.4"
serde = "1.0.114"
codespan-reporting = "0.9.5"
log = "0.4.8"
shellexpand = "2.0.0"
nu-source = { version = "0.15.1", path = "../nu-source" }
nu-protocol = { version = "0.15.1", path = "../nu-protocol" }
nu-errors = { version = "0.15.1", path = "../nu-errors" }
nu-source = { version = "0.16.0", path = "../nu-source" }
nu-protocol = { version = "0.16.0", path = "../nu-protocol" }
nu-errors = { version = "0.16.0", path = "../nu-errors" }
[features]
stable = []

View File

@ -1,6 +1,6 @@
[package]
name = "nu-plugin"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
edition = "2018"
description = "Nushell Plugin"
@ -10,16 +10,16 @@ license = "MIT"
doctest = false
[dependencies]
nu-protocol = { path = "../nu-protocol", version = "0.15.1" }
nu-source = { path = "../nu-source", version = "0.15.1" }
nu-errors = { path = "../nu-errors", version = "0.15.1" }
nu-value-ext = { path = "../nu-value-ext", version = "0.15.1" }
nu-protocol = { path = "../nu-protocol", version = "0.16.0" }
nu-source = { path = "../nu-source", version = "0.16.0" }
nu-errors = { path = "../nu-errors", version = "0.16.0" }
nu-value-ext = { path = "../nu-value-ext", version = "0.16.0" }
indexmap = { version = "1.3.2", features = ["serde-1"] }
serde = { version = "1.0.110", features = ["derive"] }
indexmap = { version = "1.4.0", features = ["serde-1"] }
serde = { version = "1.0.114", features = ["derive"] }
num-bigint = { version = "0.2.6", features = ["serde"] }
serde_json = "1.0.53"
serde_json = "1.0.55"
bigdecimal = { version = "0.1.2", features = ["serde"] }
[build-dependencies]
nu-build = { version = "0.15.1", path = "../nu-build" }
nu-build = { version = "0.16.0", path = "../nu-build" }

View File

@ -1,6 +1,6 @@
[package]
name = "nu-protocol"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
edition = "2018"
description = "Core values and protocols for Nushell"
@ -10,21 +10,21 @@ license = "MIT"
doctest = false
[dependencies]
nu-source = { path = "../nu-source", version = "0.15.1" }
nu-errors = { path = "../nu-errors", version = "0.15.1" }
nu-source = { path = "../nu-source", version = "0.16.0" }
nu-errors = { path = "../nu-errors", version = "0.16.0" }
serde = { version = "1.0.110", features = ["derive"] }
indexmap = { version = "1.3.2", features = ["serde-1"] }
serde = { version = "1.0.114", features = ["derive"] }
indexmap = { version = "1.4.0", features = ["serde-1"] }
num-bigint = { version = "0.2.6", features = ["serde"] }
bigdecimal = { version = "0.1.2", features = ["serde"] }
chrono = { version = "0.4.11", features = ["serde"] }
num-traits = "0.2.11"
serde_bytes = "0.11.4"
num-traits = "0.2.12"
serde_bytes = "0.11.5"
getset = "0.1.1"
derive-new = "0.5.8"
ansi_term = "0.12.1"
codespan-reporting = "0.9.4"
typetag = "0.1.4"
codespan-reporting = "0.9.5"
typetag = "0.1.5"
query_interface = "0.3.5"
byte-unit = "3.1.3"
natural = "0.5.0"
@ -34,7 +34,7 @@ itertools = "0.9.0"
# implement conversions
serde_yaml = "0.8"
toml = "0.5.6"
serde_json = "1.0.53"
serde_json = "1.0.55"
[build-dependencies]
nu-build = { version = "0.15.1", path = "../nu-build" }
nu-build = { version = "0.16.0", path = "../nu-build" }

View File

@ -44,6 +44,14 @@ impl InternalCommand {
),
}
}
pub fn expand_it_usage(&mut self) {
if let Some(positionals) = &mut self.args.positional {
for arg in positionals {
arg.expand_it_usage();
}
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
@ -109,34 +117,8 @@ impl ClassifiedCommand {
pub fn expand_it_usage(&mut self) {
match self {
ClassifiedCommand::Internal(command) => {
if let Some(positionals) = &mut command.args.positional {
for arg in positionals {
if let SpannedExpression {
expr: Expression::Block(block),
..
} = arg
{
block.expand_it_usage();
}
}
}
}
ClassifiedCommand::Expr(expr) => {
if let SpannedExpression {
expr: Expression::Block(ref block),
span,
} = **expr
{
let mut block = block.clone();
block.expand_it_usage();
*expr = Box::new(SpannedExpression {
expr: Expression::Block(block),
span,
});
}
}
ClassifiedCommand::Internal(command) => command.expand_it_usage(),
ClassifiedCommand::Expr(expr) => expr.expand_it_usage(),
_ => {}
}
}
@ -218,6 +200,28 @@ impl Block {
commands.expand_it_usage();
}
}
pub fn set_is_last(&mut self, is_last: bool) {
if let Some(pipeline) = self.block.last_mut() {
if let Some(command) = pipeline.list.last_mut() {
if let ClassifiedCommand::Internal(internal) = command {
internal.args.is_last = is_last;
}
}
}
}
pub fn get_is_last(&mut self) -> Option<bool> {
if let Some(pipeline) = self.block.last_mut() {
if let Some(command) = pipeline.list.last_mut() {
if let ClassifiedCommand::Internal(internal) = command {
return Some(internal.args.is_last);
}
}
}
None
}
}
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, Hash, Deserialize, Serialize)]
@ -588,6 +592,44 @@ impl SpannedExpression {
_ => false,
}
}
pub fn expand_it_usage(&mut self) {
match self {
SpannedExpression {
expr: Expression::Block(block),
..
} => {
block.expand_it_usage();
}
SpannedExpression {
expr: Expression::Invocation(block),
..
} => {
block.expand_it_usage();
}
SpannedExpression {
expr: Expression::List(list),
..
} => {
for item in list.iter_mut() {
item.expand_it_usage();
}
}
SpannedExpression {
expr: Expression::Path(path),
..
} => {
if let SpannedExpression {
expr: Expression::Invocation(block),
..
} = &mut path.head
{
block.expand_it_usage();
}
}
_ => {}
}
}
}
impl std::ops::Deref for SpannedExpression {

View File

@ -1,6 +1,6 @@
[package]
name = "nu-source"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
edition = "2018"
description = "A source string characterizer for Nushell"
@ -10,12 +10,12 @@ license = "MIT"
doctest = false
[dependencies]
serde = { version = "1.0.110", features = ["derive"] }
serde = { version = "1.0.114", features = ["derive"] }
derive-new = "0.5.8"
getset = "0.1.1"
codespan-reporting = "0.9.4"
codespan-reporting = "0.9.5"
termcolor = "1.1.0"
pretty = "0.5.2"
[build-dependencies]
nu-build = { version = "0.15.1", path = "../nu-build" }
nu-build = { version = "0.16.0", path = "../nu-build" }

View File

@ -1,6 +1,6 @@
[package]
name = "nu-table"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
edition = "2018"
description = "Nushell table printing"

View File

@ -1,6 +1,6 @@
[package]
name = "nu-test-support"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
edition = "2018"
description = "A source string characterizer for Nushell"
@ -10,16 +10,16 @@ license = "MIT"
doctest = false
[dependencies]
nu-parser = { path = "../nu-parser", version = "0.15.1" }
nu-source = { path = "../nu-source", version = "0.15.1" }
nu-protocol = { path = "../nu-protocol", version = "0.15.1" }
nu-parser = { path = "../nu-parser", version = "0.16.0" }
nu-source = { path = "../nu-source", version = "0.16.0" }
nu-protocol = { path = "../nu-protocol", version = "0.16.0" }
directories = "2.0.2"
dunce = "1.0.0"
dunce = "1.0.1"
getset = "0.1.1"
glob = "0.3.0"
tempfile = "3.1.0"
indexmap = { version = "1.3.2", features = ["serde-1"] }
indexmap = { version = "1.4.0", features = ["serde-1"] }
[build-dependencies]
nu-build = { version = "0.15.1", path = "../nu-build" }
nu-build = { version = "0.16.0", path = "../nu-build" }

View File

@ -1,6 +1,6 @@
[package]
name = "nu-value-ext"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
edition = "2018"
description = "Extension traits for values in Nushell"
@ -10,14 +10,14 @@ license = "MIT"
doctest = false
[dependencies]
nu-source = { path = "../nu-source", version = "0.15.1" }
nu-errors = { path = "../nu-errors", version = "0.15.1" }
nu-parser = { path = "../nu-parser", version = "0.15.1" }
nu-protocol = { path = "../nu-protocol", version = "0.15.1" }
nu-source = { path = "../nu-source", version = "0.16.0" }
nu-errors = { path = "../nu-errors", version = "0.16.0" }
nu-parser = { path = "../nu-parser", version = "0.16.0" }
nu-protocol = { path = "../nu-protocol", version = "0.16.0" }
num-traits = "0.2.11"
num-traits = "0.2.12"
itertools = "0.9.0"
indexmap = { version = "1.3.2", features = ["serde-1"] }
indexmap = { version = "1.4.0", features = ["serde-1"] }
[build-dependencies]
nu-build = { version = "0.15.1", path = "../nu-build" }
nu-build = { version = "0.16.0", path = "../nu-build" }

View File

@ -1,6 +1,6 @@
[package]
name = "nu_plugin_binaryview"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
edition = "2018"
description = "A binary viewer plugin for Nushell"
@ -12,14 +12,14 @@ doctest = false
[dependencies]
ansi_term = "0.12.1"
crossterm = { version = "0.17.5" }
nu-plugin = { path = "../nu-plugin", version = "0.15.1" }
nu-protocol = { path = "../nu-protocol", version = "0.15.1" }
nu-source = { path = "../nu-source", version = "0.15.1" }
nu-errors = { path = "../nu-errors", version = "0.15.1" }
nu-plugin = { path = "../nu-plugin", version = "0.16.0" }
nu-protocol = { path = "../nu-protocol", version = "0.16.0" }
nu-source = { path = "../nu-source", version = "0.16.0" }
nu-errors = { path = "../nu-errors", version = "0.16.0" }
pretty-hex = "0.1.1"
image = { version = "0.22.4", default_features = false, features = ["png_codec", "jpeg"] }
rawkey = "0.1.2"
neso = "0.5.0"
[build-dependencies]
nu-build = { version = "0.15.1", path = "../nu-build" }
nu-build = { version = "0.16.0", path = "../nu-build" }

View File

@ -1,6 +1,6 @@
[package]
name = "nu_plugin_fetch"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
edition = "2018"
description = "A URL fetch plugin for Nushell"
@ -10,14 +10,14 @@ license = "MIT"
doctest = false
[dependencies]
nu-plugin = { path = "../nu-plugin", version = "0.15.1" }
nu-protocol = { path = "../nu-protocol", version = "0.15.1" }
nu-source = { path = "../nu-source", version = "0.15.1" }
nu-errors = { path = "../nu-errors", version = "0.15.1" }
nu-plugin = { path = "../nu-plugin", version = "0.16.0" }
nu-protocol = { path = "../nu-protocol", version = "0.16.0" }
nu-source = { path = "../nu-source", version = "0.16.0" }
nu-errors = { path = "../nu-errors", version = "0.16.0" }
futures = { version = "0.3", features = ["compat", "io-compat"] }
surf = "1.0.3"
url = "2.1.1"
base64 = "0.12.1"
base64 = "0.12.3"
[build-dependencies]
nu-build = { version = "0.15.1", path = "../nu-build" }
nu-build = { version = "0.16.0", path = "../nu-build" }

View File

@ -1,6 +1,6 @@
[package]
name = "nu_plugin_inc"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
edition = "2018"
description = "A version incrementer plugin for Nushell"
@ -10,13 +10,13 @@ license = "MIT"
doctest = false
[dependencies]
nu-plugin = { path = "../nu-plugin", version = "0.15.1" }
nu-protocol = { path = "../nu-protocol", version = "0.15.1" }
nu-source = { path = "../nu-source", version = "0.15.1" }
nu-errors = { path = "../nu-errors", version = "0.15.1" }
nu-value-ext = { path = "../nu-value-ext", version = "0.15.1" }
nu-plugin = { path = "../nu-plugin", version = "0.16.0" }
nu-protocol = { path = "../nu-protocol", version = "0.16.0" }
nu-source = { path = "../nu-source", version = "0.16.0" }
nu-errors = { path = "../nu-errors", version = "0.16.0" }
nu-value-ext = { path = "../nu-value-ext", version = "0.16.0" }
semver = "0.10.0"
[build-dependencies]
nu-build = { version = "0.15.1", path = "../nu-build" }
nu-build = { version = "0.16.0", path = "../nu-build" }

View File

@ -1,6 +1,6 @@
[package]
name = "nu_plugin_match"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
edition = "2018"
description = "A regex match plugin for Nushell"
@ -10,12 +10,12 @@ license = "MIT"
doctest = false
[dependencies]
nu-plugin = { path = "../nu-plugin", version = "0.15.1" }
nu-protocol = { path = "../nu-protocol", version = "0.15.1" }
nu-source = { path = "../nu-source", version = "0.15.1" }
nu-errors = { path = "../nu-errors", version = "0.15.1" }
nu-plugin = { path = "../nu-plugin", version = "0.16.0" }
nu-protocol = { path = "../nu-protocol", version = "0.16.0" }
nu-source = { path = "../nu-source", version = "0.16.0" }
nu-errors = { path = "../nu-errors", version = "0.16.0" }
futures = { version = "0.3", features = ["compat", "io-compat"] }
regex = "1"
[build-dependencies]
nu-build = { version = "0.15.1", path = "../nu-build" }
nu-build = { version = "0.16.0", path = "../nu-build" }

View File

@ -1,6 +1,6 @@
[package]
name = "nu_plugin_post"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
edition = "2018"
description = "An HTTP post plugin for Nushell"
@ -10,16 +10,16 @@ license = "MIT"
doctest = false
[dependencies]
nu-plugin = { path = "../nu-plugin", version = "0.15.1" }
nu-protocol = { path = "../nu-protocol", version = "0.15.1" }
nu-source = { path = "../nu-source", version = "0.15.1" }
nu-errors = { path = "../nu-errors", version = "0.15.1" }
nu-plugin = { path = "../nu-plugin", version = "0.16.0" }
nu-protocol = { path = "../nu-protocol", version = "0.16.0" }
nu-source = { path = "../nu-source", version = "0.16.0" }
nu-errors = { path = "../nu-errors", version = "0.16.0" }
futures = { version = "0.3", features = ["compat", "io-compat"] }
surf = "1.0.3"
url = "2.1.1"
serde_json = "1.0.53"
base64 = "0.12.1"
num-traits = "0.2.11"
serde_json = "1.0.55"
base64 = "0.12.3"
num-traits = "0.2.12"
[build-dependencies]
nu-build = { version = "0.15.1", path = "../nu-build" }
nu-build = { version = "0.16.0", path = "../nu-build" }

View File

@ -1,6 +1,6 @@
[package]
name = "nu_plugin_ps"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
edition = "2018"
description = "A process list plugin for Nushell"
@ -10,10 +10,10 @@ license = "MIT"
doctest = false
[dependencies]
nu-plugin = { path = "../nu-plugin", version = "0.15.1" }
nu-protocol = { path = "../nu-protocol", version = "0.15.1" }
nu-source = { path = "../nu-source", version = "0.15.1" }
nu-errors = { path = "../nu-errors", version = "0.15.1" }
nu-plugin = { path = "../nu-plugin", version = "0.16.0" }
nu-protocol = { path = "../nu-protocol", version = "0.16.0" }
nu-source = { path = "../nu-source", version = "0.16.0" }
nu-errors = { path = "../nu-errors", version = "0.16.0" }
futures = { version = "0.3", features = ["compat", "io-compat"] }
futures-timer = "3.0.2"
@ -24,4 +24,4 @@ default-features = false
features = ["process"]
[build-dependencies]
nu-build = { version = "0.15.1", path = "../nu-build" }
nu-build = { version = "0.16.0", path = "../nu-build" }

View File

@ -1,6 +1,6 @@
[package]
name = "nu_plugin_start"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
edition = "2018"
description = "A plugin to open files/URLs directly from Nushell"
@ -10,15 +10,15 @@ license = "MIT"
doctest = false
[dependencies]
nu-plugin = { path = "../nu-plugin", version = "0.15.1" }
nu-protocol = { path = "../nu-protocol", version = "0.15.1" }
nu-source = { path = "../nu-source", version = "0.15.1" }
nu-errors = { path = "../nu-errors", version = "0.15.1" }
nu-plugin = { path = "../nu-plugin", version = "0.16.0" }
nu-protocol = { path = "../nu-protocol", version = "0.16.0" }
nu-source = { path = "../nu-source", version = "0.16.0" }
nu-errors = { path = "../nu-errors", version = "0.16.0" }
url = "2.1.1"
open = "1.4.0"
glob = "0.3.0"
[build-dependencies]
nu-build = { version = "0.15.1", path = "../nu-build" }
nu-errors = { version = "0.15.1", path = "../nu-errors" }
nu-source = { version = "0.15.1", path = "../nu-source" }
nu-build = { version = "0.16.0", path = "../nu-build" }
nu-errors = { version = "0.16.0", path = "../nu-errors" }
nu-source = { version = "0.16.0", path = "../nu-source" }

View File

@ -1,6 +1,6 @@
[package]
name = "nu_plugin_sys"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
edition = "2018"
description = "A system info plugin for Nushell"
@ -10,10 +10,10 @@ license = "MIT"
doctest = false
[dependencies]
nu-plugin = { path = "../nu-plugin", version = "0.15.1" }
nu-protocol = { path = "../nu-protocol", version = "0.15.1" }
nu-source = { path = "../nu-source", version = "0.15.1" }
nu-errors = { path = "../nu-errors", version = "0.15.1" }
nu-plugin = { path = "../nu-plugin", version = "0.16.0" }
nu-protocol = { path = "../nu-protocol", version = "0.16.0" }
nu-source = { path = "../nu-source", version = "0.16.0" }
nu-errors = { path = "../nu-errors", version = "0.16.0" }
futures = { version = "0.3", features = ["compat", "io-compat"] }
battery = "0.7.5"
@ -26,4 +26,4 @@ default-features = false
features = ["host", "cpu", "memory", "disk", "net", "sensors"]
[build-dependencies]
nu-build = { version = "0.15.1", path = "../nu-build" }
nu-build = { version = "0.16.0", path = "../nu-build" }

View File

@ -1,6 +1,6 @@
[package]
name = "nu_plugin_textview"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
edition = "2018"
description = "Text viewer plugin for Nushell"
@ -10,18 +10,18 @@ license = "MIT"
doctest = false
[dependencies]
nu-plugin = { path = "../nu-plugin", version = "0.15.1" }
nu-protocol = { path = "../nu-protocol", version = "0.15.1" }
nu-source = { path = "../nu-source", version = "0.15.1" }
nu-errors = { path = "../nu-errors", version = "0.15.1" }
nu-cli = { path = "../nu-cli", version = "0.15.1" }
nu-plugin = { path = "../nu-plugin", version = "0.16.0" }
nu-protocol = { path = "../nu-protocol", version = "0.16.0" }
nu-source = { path = "../nu-source", version = "0.16.0" }
nu-errors = { path = "../nu-errors", version = "0.16.0" }
nu-cli = { path = "../nu-cli", version = "0.16.0" }
crossterm = "0.17.5"
syntect = { version = "4.2", default-features = false, features = ["default-fancy"]}
ansi_term = "0.12.1"
url = "2.1.1"
bat = "0.15.4"
textwrap = {version = "0.11.0", features = ["term_size"]}
term_size = "0.3.2"
[build-dependencies]
nu-build = { version = "0.15.1", path = "../nu-build" }
nu-build = { version = "0.16.0", path = "../nu-build" }

View File

@ -13,7 +13,7 @@ impl TextView {
#[allow(clippy::cognitive_complexity)]
pub fn view_text_value(value: &Value) {
let mut term_width: u64 = textwrap::termwidth() as u64;
let (mut term_width, _) = term_size::dimensions().unwrap_or_else(|| (20, 20));
let mut tab_width: u64 = 4;
let mut colored_output = true;
let mut true_color = true;
@ -38,8 +38,8 @@ pub fn view_text_value(value: &Value) {
match idx.as_ref() {
"term_width" => {
term_width = match value.as_u64() {
Ok(n) => n,
_ => textwrap::termwidth() as u64,
Ok(n) => n as usize,
_ => term_width as usize,
}
}
"tab_width" => {

View File

@ -1,6 +1,6 @@
[package]
name = "nu_plugin_tree"
version = "0.15.1"
version = "0.16.0"
authors = ["The Nu Project Contributors"]
edition = "2018"
description = "Tree viewer plugin for Nushell"
@ -10,12 +10,12 @@ license = "MIT"
doctest = false
[dependencies]
nu-plugin = { path = "../nu-plugin", version = "0.15.1" }
nu-protocol = { path = "../nu-protocol", version = "0.15.1" }
nu-source = { path = "../nu-source", version = "0.15.1" }
nu-errors = { path = "../nu-errors", version = "0.15.1" }
nu-plugin = { path = "../nu-plugin", version = "0.16.0" }
nu-protocol = { path = "../nu-protocol", version = "0.16.0" }
nu-source = { path = "../nu-source", version = "0.16.0" }
nu-errors = { path = "../nu-errors", version = "0.16.0" }
ptree = {version = "0.2" }
derive-new = "0.5.8"
[build-dependencies]
nu-build = { version = "0.15.1", path = "../nu-build" }
nu-build = { version = "0.16.0", path = "../nu-build" }

59
docs/commands/autoview.md Normal file
View File

@ -0,0 +1,59 @@
# autoview
Print the content of the pipeline as a table or list.
It is the implied or default viewer when none is provided.
When reading a single value, a table or a list, `autoview` will attempt to view it.
When reading a string that originally comes from a source file it will attempt
to use `textview`.
When reading a binary file it will attempt to display its content as hexadecimal
numbers and the corresponding characters.
`-h`, `--help`
Display help message.
## Examples
In all following examples `autoview` can be removed with no change in the output.
The use of `autoview` at the end of the pipeline is implied when no viewer is
explicitly used.
```shell
> which nu | get path | autoview
/home/me/.cargo/bin/nu
```
```shell
> ls | autoview
────┬────────────────────┬──────┬─────────┬──────────────
# │ name │ type │ size │ modified
────┼────────────────────┼──────┼─────────┼──────────────
0 │ README.md │ File │ 932 B │ 19 hours ago
1 │ alias.md │ File │ 2.0 KB │ 19 hours ago
2 │ append.md │ File │ 1.4 KB │ 19 hours ago
...
82 │ wrap.md │ File │ 1.8 KB │ 19 hours ago
────┴────────────────────┴──────┴─────────┴──────────────
```
```shell
> echo "# Hi" "## Section" "Some text" | save file.md
> open file.md | autoview
# Hi
## Section
Some text
```
`autoview` will use `textview` to colorize the text based on the file format.
The style used by `textview` can be configured in `config.toml`.
```shell
> open --raw $(which nu | get path) | autoview
...
126d1c0: 64 31 66 37 62 30 31 63 36 2e 31 31 38 2e 6c 6c d1f7b01c6.118.ll
126d1d0: 76 6d 2e 34 34 38 37 35 37 31 32 34 39 35 33 39 vm.4487571249539
126d1e0: 34 34 30 34 30 39 00 61 6e 6f 6e 2e 30 30 61 63 440409.anon.00ac
126d1f0: 37 32 65 36 37 66 32 31 39 34 62 32 32 61 61 63 72e67f2194b22aac
126d200: 62 35 39 37 33 36 30 62 64 31 39 38 2e 31 36 2e b597360bd198.16.
...
```

27
docs/commands/pwd.md Normal file
View File

@ -0,0 +1,27 @@
# pwd
Print the current working directory.
`-h`, `--help`
Display help message.
## Examples
```shell
> pwd
/home/me/nushell/docs/commands
```
```shell
> pwd | split column "/" | reject Column1 | pivot | reject Column0
───┬──────────
# │ Column1
───┼──────────
0 │ home
1 │ me
2 │ projects
3 │ nushell
4 │ docs
5 │ commands
───┴──────────
```

View File

@ -2,9 +2,63 @@
Use `random` to generate random values
## bool
* `random bool`: Generate a random boolean value
### bool Flags
* `-b`, `--bias` \<number>: Adjusts the probability of a "true" outcome
### bool Examples
```shell
> random bool
false
```
```shell
> random bool --bias 0.75
true
```
## dice
* `random dice`: Generate a random dice roll
### dice Flags
* `d`, `--dice` \<integer>: The amount of dice being rolled
* `s`, `--sides` \<integer>: The amount of sides a die has
### dice Examples
```shell
> random dice
4
```
```shell
> random dice -d 10 -s 12
───┬────
011
111
211
311
45
53
610
77
83
91
───┴────
```
## uuid
* `random uuid`: Generate a random uuid4 string
## Examples
### uuid Examples
```shell
> random uuid

View File

@ -88,7 +88,7 @@ version = "0.4.6"
[dependencies.cursive]
default-features = false
features = ["pancurses-backend"]
version = "0.15.1"
version = "0.16.0"
[dependencies.futures-preview]
features = ["compat", "io-compat"]

43
docs/commands/touch.md Normal file
View File

@ -0,0 +1,43 @@
# touch
Create a file in the current or an already existent directory.
It has no effect on existing files.
Unlike GNU touch, the access time and the modified time are not updated.
`-h`, `--help`
Display help message.
## Examples
Create a file in an empty folder. Then touch the file and list files again to observe that the modified time has not been updated.
```shell
> ls
> touch file.ext; ls
──────────┬─────────────
name │ file.ext
type │ File
size │ 0 B
modified │ 0 secs ago
──────────┴─────────────
> touch file.ext; ls
──────────┬───────────
name │ file.ext
type │ File
size │ 0 B
modified │ 10 secs ago
──────────┴───────────
```
Create a file within an already existent folder.
```shell
> mkdir dir
> touch dir/file.ext; ls dir
──────────┬───────────
name │ dir/file.ext
type │ File
size │ 0 B
modified │ 0 secs ago
──────────┴───────────
```

View File

@ -10,6 +10,16 @@ fn shows_error_for_command_not_found() {
assert!(actual.err.contains("Command not found"));
}
#[test]
fn shows_error_for_command_not_found_in_pipeline() {
let actual = nu!(
cwd: ".",
"ferris_is_not_here.exe | echo done"
);
assert!(actual.err.contains("Command not found"));
}
#[test]
fn automatically_change_directory() {
use nu_test_support::playground::Playground;

View File

@ -72,13 +72,37 @@ fn it_expansion_of_list() {
assert_eq!(actual.out, "[\"bar\",\"foo\"]");
}
#[test]
fn it_expansion_of_invocation() {
let actual = nu!(
cwd: ".",
r#"
echo $(echo "4" | echo $it | str to-int )
"#
);
assert_eq!(actual.out, "4");
}
#[test]
fn invocation_properly_redirects() {
let actual = nu!(
cwd: ".",
r#"
echo $(nu --testbin cococo "hello") | str collect
"#
);
assert_eq!(actual.out, "hello");
}
#[test]
fn argument_invocation() {
let actual = nu!(
cwd: ".",
r#"
echo "foo" | echo $(echo $it)
"#
echo "foo" | echo $(echo $it)
"#
);
assert_eq!(actual.out, "foo");

View File

@ -90,100 +90,108 @@
<Component Id='binary0' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe0'
Name='nu_plugin_core_textview.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_core_textview.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary1' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe1'
Name='nu_plugin_core_inc.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_core_inc.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary2' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe2'
Name='nu_plugin_core_ps.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_core_ps.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary3' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe3'
Name='nu_plugin_core_sys.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_core_sys.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary4' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe4'
Name='nu_plugin_stable_fetch.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_stable_fetch.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary5' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe5'
Name='nu_plugin_stable_binaryview.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_stable_binaryview.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary6' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe6'
Name='nu_plugin_stable_match.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_stable_match.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary7' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe7'
Name='nu_plugin_stable_post.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_stable_post.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary8' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe8'
Name='nu_plugin_stable_tree.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_stable_tree.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary9' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe9'
Name='nu_plugin_stable_start.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_stable_start.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary10' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe10'
Name='nu.exe'
DiskId='1'
Source='target\$(var.Profile)\nu.exe'
KeyPath='yes'/>
</Component>
<!-- Downloaded from here https://github.com/jftuga/less-Windows/releases/download/less-v562.0/less.exe -->
<Component Id='binary11' Guid='*' Win64='$(var.Win64)'>
<Component Id='binary1' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe11'
Id='exe1'
Name='nu_plugin_binaryview.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_binaryview.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary2' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe2'
Name='nu_plugin_fetch.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_fetch.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary3' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe3'
Name='nu_plugin_inc.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_inc.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary4' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe4'
Name='nu_plugin_post.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_post.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary5' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe5'
Name='nu_plugin_ps.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_ps.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary6' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe6'
Name='nu_plugin_start.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_start.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary7' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe7'
Name='nu_plugin_sys.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_sys.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary8' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe8'
Name='nu_plugin_textview.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_textview.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary9' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe9'
Name='nu_plugin_tree.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_tree.exe'
KeyPath='yes'/>
</Component>
<!-- Downloaded from here https://github.com/jftuga/less-Windows/releases/download/less-v562.0/less.exe -->
<Component Id='binary10' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe10'
Name='less.exe'
DiskId='1'
Source='output\less.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary11' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe11'
Name='nu_plugin_match.exe'
DiskId='1'
Source='target\$(var.Profile)\nu_plugin_match.exe'
KeyPath='yes'/>
</Component>
<Component Id='binary12' Guid='*' Win64='$(var.Win64)'>
<File
Id='exe12'
Name='README.txt'
DiskId='1'
Source='output\README.txt'
KeyPath='yes'/>
</Component>
</Directory>
</Directory>
</Directory>
@ -216,6 +224,7 @@
<ComponentRef Id='binary9'/>
<ComponentRef Id='binary10'/>
<ComponentRef Id='binary11'/>
<ComponentRef Id='binary12'/>
<Feature
Id='Environment'