mirror of
https://github.com/nushell/nushell.git
synced 2025-07-02 23:51:49 +02:00
Compare commits
29 Commits
Author | SHA1 | Date | |
---|---|---|---|
0522023d4c | |||
9876169f5d | |||
ed10aafa6f | |||
bcddeb3c1f | |||
3f170c7fb8 | |||
8d91d151bf | |||
821d44af54 | |||
a30901ff7d | |||
94a1968a88 | |||
dffc9c9b1c | |||
8b3964f518 | |||
7fed9992c9 | |||
4e2a4236f8 | |||
05781607f4 | |||
6daec399e6 | |||
306dc89ede | |||
80ce8acf57 | |||
8dfc90a322 | |||
ad5e485594 | |||
60ed40f8bd | |||
a6228cab9e | |||
1857ac69d1 | |||
e33e80ab24 | |||
d18bc78e7c | |||
3b2a87b6d4 | |||
62c76be7ca | |||
733f93e673 | |||
2c88b2fae7 | |||
501da433d4 |
64
.github/workflows/release.yml
vendored
64
.github/workflows/release.yml
vendored
@ -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
408
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
44
Cargo.toml
44
Cargo.toml
@ -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"]
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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> ",
|
||||
|
@ -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;
|
||||
|
140
crates/nu-cli/src/commands/ansi.rs
Normal file
140
crates/nu-cli/src/commands/ansi.rs
Normal 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(®istry).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 {})
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
81
crates/nu-cli/src/commands/char_.rs
Normal file
81
crates/nu-cli/src/commands/char_.rs
Normal 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(®istry).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 {})
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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, ®istry)).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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(®istry).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))
|
||||
|
111
crates/nu-cli/src/commands/do_.rs
Normal file
111
crates/nu-cli/src/commands/do_.rs
Normal 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, ®istry);
|
||||
let scope = raw_args.call_info.scope.clone();
|
||||
let (
|
||||
DoArgs {
|
||||
ignore_errors,
|
||||
mut block,
|
||||
},
|
||||
input,
|
||||
) = raw_args.process(®istry).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 {})
|
||||
}
|
||||
}
|
@ -158,7 +158,7 @@ async fn enter(
|
||||
};
|
||||
let mut result = converter
|
||||
.run(new_args.with_input(vec![tagged_contents]), ®istry)
|
||||
.await;
|
||||
.await?;
|
||||
let result_vec: Vec<Result<ReturnSuccess, ShellError>> =
|
||||
result.drain_vec().await;
|
||||
|
||||
|
@ -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)]),
|
||||
],
|
||||
|
97
crates/nu-cli/src/commands/random/bool.rs
Normal file
97
crates/nu-cli/src/commands/random/bool.rs
Normal 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(®istry).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 {})
|
||||
}
|
||||
}
|
103
crates/nu-cli/src/commands/random/dice.rs
Normal file
103
crates/nu-cli/src/commands/random/dice.rs
Normal 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(®istry).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 {})
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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, ®istry);
|
||||
let input = args.input;
|
||||
|
@ -232,7 +232,7 @@ async fn save(
|
||||
scope,
|
||||
},
|
||||
};
|
||||
let mut result = converter.run(new_args.with_input(input), ®istry).await;
|
||||
let mut result = converter.run(new_args.with_input(input), ®istry).await?;
|
||||
let result_vec: Vec<Result<ReturnSuccess, ShellError>> =
|
||||
result.drain_vec().await;
|
||||
if converter.is_binary() {
|
||||
|
56
crates/nu-cli/src/commands/str_/collect.rs
Normal file
56
crates/nu-cli/src/commands/str_/collect.rs
Normal 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 {})
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)),
|
||||
..
|
||||
|
4
crates/nu-cli/src/env/host.rs
vendored
4
crates/nu-cli/src/env/host.rs
vendored
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
))
|
||||
}
|
||||
|
16
crates/nu-cli/tests/commands/random/bool.rs
Normal file
16
crates/nu-cli/tests/commands/random/bool.rs
Normal 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);
|
||||
}
|
13
crates/nu-cli/tests/commands/random/dice.rs
Normal file
13
crates/nu-cli/tests/commands/random/dice.rs
Normal 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");
|
||||
}
|
@ -1 +1,3 @@
|
||||
mod bool;
|
||||
mod dice;
|
||||
mod uuid;
|
||||
|
@ -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#"
|
||||
|
@ -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" }
|
||||
|
@ -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 {
|
||||
|
@ -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 = []
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -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 {
|
||||
|
@ -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" }
|
||||
|
@ -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"
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -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" => {
|
||||
|
@ -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
59
docs/commands/autoview.md
Normal 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
27
docs/commands/pwd.md
Normal 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
|
||||
───┴──────────
|
||||
```
|
@ -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
|
||||
───┬────
|
||||
0 │ 11
|
||||
1 │ 11
|
||||
2 │ 11
|
||||
3 │ 11
|
||||
4 │ 5
|
||||
5 │ 3
|
||||
6 │ 10
|
||||
7 │ 7
|
||||
8 │ 3
|
||||
9 │ 1
|
||||
───┴────
|
||||
```
|
||||
|
||||
## uuid
|
||||
|
||||
* `random uuid`: Generate a random uuid4 string
|
||||
|
||||
## Examples
|
||||
### uuid Examples
|
||||
|
||||
```shell
|
||||
> random uuid
|
||||
|
@ -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
43
docs/commands/touch.md
Normal 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
|
||||
──────────┴───────────
|
||||
```
|
@ -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;
|
||||
|
@ -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");
|
||||
|
175
wix/main.wxs
175
wix/main.wxs
@ -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'
|
||||
|
Reference in New Issue
Block a user