mirror of
https://github.com/nushell/nushell.git
synced 2025-08-19 17:25:42 +02:00
Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
f9ae882012 | ||
|
1d80a68f4c | ||
|
fda69354db | ||
|
cc5c4d38bb | ||
|
0fa0c25fb3 | ||
|
55eafadf02 | ||
|
51c74eebd0 | ||
|
ae9f4135c0 | ||
|
4e2d3ceaaf | ||
|
c9c6bd4836 | ||
|
d90420ac4c | ||
|
260ff99710 | ||
|
08014c6a98 | ||
|
66cedf0b3a | ||
|
707a4ebc15 | ||
|
d95375d494 | ||
|
1c1c58e802 | ||
|
7fe05b8296 | ||
|
17ef531905 | ||
|
b8e2bdd6b1 | ||
|
88817a8f10 | ||
|
3e8ce43dcb | ||
|
9d8845d7ad | ||
|
52578ba483 |
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -38,7 +38,7 @@ body:
|
|||||||
id: config
|
id: config
|
||||||
attributes:
|
attributes:
|
||||||
label: Configuration
|
label: Configuration
|
||||||
description: "Please run `> version | pivot` and paste the output to show OS, features, etc"
|
description: "Please run `> version | pivot key value | to md` and paste the output to show OS, features, etc"
|
||||||
placeholder: |
|
placeholder: |
|
||||||
> version | pivot key value | to md
|
> version | pivot key value | to md
|
||||||
╭───┬────────────────────┬───────────────────────────────────────────────────────────────────────╮
|
╭───┬────────────────────┬───────────────────────────────────────────────────────────────────────╮
|
||||||
|
2345
Cargo.lock
generated
2345
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
96
Cargo.toml
96
Cargo.toml
@@ -10,7 +10,7 @@ license = "MIT"
|
|||||||
name = "nu"
|
name = "nu"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
repository = "https://github.com/nushell/nushell"
|
repository = "https://github.com/nushell/nushell"
|
||||||
version = "0.36.0"
|
version = "0.37.0"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["crates/*/"]
|
members = ["crates/*/"]
|
||||||
@@ -18,38 +18,34 @@ members = ["crates/*/"]
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-cli = { version = "0.36.0", path="./crates/nu-cli", default-features=false }
|
nu-cli = { version = "0.37.0", path="./crates/nu-cli", default-features=false }
|
||||||
nu-command = { version = "0.36.0", path="./crates/nu-command" }
|
nu-command = { version = "0.37.0", path="./crates/nu-command" }
|
||||||
nu-completion = { version = "0.36.0", path="./crates/nu-completion" }
|
nu-completion = { version = "0.37.0", path="./crates/nu-completion" }
|
||||||
nu-data = { version = "0.36.0", path="./crates/nu-data" }
|
nu-data = { version = "0.37.0", path="./crates/nu-data" }
|
||||||
nu-engine = { version = "0.36.0", path="./crates/nu-engine" }
|
nu-engine = { version = "0.37.0", path="./crates/nu-engine" }
|
||||||
nu-errors = { version = "0.36.0", path="./crates/nu-errors" }
|
nu-errors = { version = "0.37.0", path="./crates/nu-errors" }
|
||||||
nu-parser = { version = "0.36.0", path="./crates/nu-parser" }
|
nu-parser = { version = "0.37.0", path="./crates/nu-parser" }
|
||||||
nu-path = { version = "0.36.0", path="./crates/nu-path" }
|
nu-path = { version = "0.37.0", path="./crates/nu-path" }
|
||||||
nu-plugin = { version = "0.36.0", path="./crates/nu-plugin" }
|
nu-plugin = { version = "0.37.0", path="./crates/nu-plugin" }
|
||||||
nu-protocol = { version = "0.36.0", path="./crates/nu-protocol" }
|
nu-protocol = { version = "0.37.0", path="./crates/nu-protocol" }
|
||||||
nu-source = { version = "0.36.0", path="./crates/nu-source" }
|
nu-source = { version = "0.37.0", path="./crates/nu-source" }
|
||||||
nu-value-ext = { version = "0.36.0", path="./crates/nu-value-ext" }
|
nu-value-ext = { version = "0.37.0", path="./crates/nu-value-ext" }
|
||||||
|
|
||||||
nu_plugin_binaryview = { version = "0.36.0", path="./crates/nu_plugin_binaryview", optional=true }
|
nu_plugin_binaryview = { version = "0.37.0", path="./crates/nu_plugin_binaryview", optional=true }
|
||||||
nu_plugin_chart = { version = "0.36.0", path="./crates/nu_plugin_chart", optional=true }
|
nu_plugin_chart = { version = "0.37.0", path="./crates/nu_plugin_chart", optional=true }
|
||||||
nu_plugin_fetch = { version = "0.36.0", path="./crates/nu_plugin_fetch", optional=true }
|
nu_plugin_from_bson = { version = "0.37.0", path="./crates/nu_plugin_from_bson", optional=true }
|
||||||
nu_plugin_from_bson = { version = "0.36.0", path="./crates/nu_plugin_from_bson", optional=true }
|
nu_plugin_from_sqlite = { version = "0.37.0", path="./crates/nu_plugin_from_sqlite", optional=true }
|
||||||
nu_plugin_from_sqlite = { version = "0.36.0", path="./crates/nu_plugin_from_sqlite", optional=true }
|
nu_plugin_inc = { version = "0.37.0", path="./crates/nu_plugin_inc", optional=true }
|
||||||
nu_plugin_inc = { version = "0.36.0", path="./crates/nu_plugin_inc", optional=true }
|
nu_plugin_match = { version = "0.37.0", path="./crates/nu_plugin_match", optional=true }
|
||||||
nu_plugin_match = { version = "0.36.0", path="./crates/nu_plugin_match", optional=true }
|
nu_plugin_query_json = { version = "0.37.0", path="./crates/nu_plugin_query_json", optional=true }
|
||||||
nu_plugin_post = { version = "0.36.0", path="./crates/nu_plugin_post", optional=true }
|
nu_plugin_s3 = { version = "0.37.0", path="./crates/nu_plugin_s3", optional=true }
|
||||||
nu_plugin_ps = { version = "0.36.0", path="./crates/nu_plugin_ps", optional=true }
|
nu_plugin_selector = { version = "0.37.0", path="./crates/nu_plugin_selector", optional=true }
|
||||||
nu_plugin_query_json = { version = "0.36.0", path="./crates/nu_plugin_query_json", optional=true }
|
nu_plugin_start = { version = "0.37.0", path="./crates/nu_plugin_start", optional=true }
|
||||||
nu_plugin_s3 = { version = "0.36.0", path="./crates/nu_plugin_s3", optional=true }
|
nu_plugin_textview = { version = "0.37.0", path="./crates/nu_plugin_textview", optional=true }
|
||||||
nu_plugin_selector = { version = "0.36.0", path="./crates/nu_plugin_selector", optional=true }
|
nu_plugin_to_bson = { version = "0.37.0", path="./crates/nu_plugin_to_bson", optional=true }
|
||||||
nu_plugin_start = { version = "0.36.0", path="./crates/nu_plugin_start", optional=true }
|
nu_plugin_to_sqlite = { version = "0.37.0", path="./crates/nu_plugin_to_sqlite", optional=true }
|
||||||
nu_plugin_sys = { version = "0.36.0", path="./crates/nu_plugin_sys", optional=true }
|
nu_plugin_tree = { version = "0.37.0", path="./crates/nu_plugin_tree", optional=true }
|
||||||
nu_plugin_textview = { version = "0.36.0", path="./crates/nu_plugin_textview", optional=true }
|
nu_plugin_xpath = { version = "0.37.0", path="./crates/nu_plugin_xpath", optional=true }
|
||||||
nu_plugin_to_bson = { version = "0.36.0", path="./crates/nu_plugin_to_bson", optional=true }
|
|
||||||
nu_plugin_to_sqlite = { version = "0.36.0", path="./crates/nu_plugin_to_sqlite", optional=true }
|
|
||||||
nu_plugin_tree = { version = "0.36.0", path="./crates/nu_plugin_tree", optional=true }
|
|
||||||
nu_plugin_xpath = { version = "0.36.0", path="./crates/nu_plugin_xpath", optional=true }
|
|
||||||
|
|
||||||
# Required to bootstrap the main binary
|
# Required to bootstrap the main binary
|
||||||
ctrlc = { version="3.1.7", optional=true }
|
ctrlc = { version="3.1.7", optional=true }
|
||||||
@@ -57,8 +53,7 @@ futures = { version="0.3.12", features=["compat", "io-compat"] }
|
|||||||
itertools = "0.10.0"
|
itertools = "0.10.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
nu-test-support = { version = "0.36.0", path="./crates/nu-test-support" }
|
nu-test-support = { version = "0.37.0", path="./crates/nu-test-support" }
|
||||||
dunce = "1.0.1"
|
|
||||||
serial_test = "0.5.1"
|
serial_test = "0.5.1"
|
||||||
hamcrest2 = "0.3.0"
|
hamcrest2 = "0.3.0"
|
||||||
rstest = "0.10.0"
|
rstest = "0.10.0"
|
||||||
@@ -66,6 +61,8 @@ rstest = "0.10.0"
|
|||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
fetch-support = ["nu-command/fetch", "nu-command/post"]
|
||||||
|
sys-support = ["nu-command/sys", "nu-command/ps"]
|
||||||
ctrlc-support = ["nu-cli/ctrlc", "nu-command/ctrlc"]
|
ctrlc-support = ["nu-cli/ctrlc", "nu-command/ctrlc"]
|
||||||
rustyline-support = ["nu-cli/rustyline-support", "nu-command/rustyline-support"]
|
rustyline-support = ["nu-cli/rustyline-support", "nu-command/rustyline-support"]
|
||||||
term-support = ["nu-command/term"]
|
term-support = ["nu-command/term"]
|
||||||
@@ -74,15 +71,13 @@ which-support = ["nu-command/which", "nu-engine/which"]
|
|||||||
|
|
||||||
default = [
|
default = [
|
||||||
"nu-cli/shadow-rs",
|
"nu-cli/shadow-rs",
|
||||||
"sys",
|
"sys-support",
|
||||||
"ps",
|
|
||||||
"ctrlc-support",
|
"ctrlc-support",
|
||||||
"which-support",
|
"which-support",
|
||||||
"term-support",
|
"term-support",
|
||||||
"rustyline-support",
|
"rustyline-support",
|
||||||
"match",
|
"match",
|
||||||
"post",
|
"fetch-support",
|
||||||
"fetch",
|
|
||||||
"zip-support",
|
"zip-support",
|
||||||
"dataframe",
|
"dataframe",
|
||||||
]
|
]
|
||||||
@@ -110,12 +105,8 @@ extra = [
|
|||||||
wasi = ["inc", "match", "match", "tree", "rustyline-support"]
|
wasi = ["inc", "match", "match", "tree", "rustyline-support"]
|
||||||
|
|
||||||
# Stable (Default)
|
# Stable (Default)
|
||||||
fetch = ["nu_plugin_fetch"]
|
|
||||||
inc = ["nu_plugin_inc"]
|
inc = ["nu_plugin_inc"]
|
||||||
match = ["nu_plugin_match"]
|
match = ["nu_plugin_match"]
|
||||||
post = ["nu_plugin_post"]
|
|
||||||
ps = ["nu_plugin_ps"]
|
|
||||||
sys = ["nu_plugin_sys"]
|
|
||||||
textview = ["nu_plugin_textview"]
|
textview = ["nu_plugin_textview"]
|
||||||
|
|
||||||
# Extra
|
# Extra
|
||||||
@@ -146,7 +137,6 @@ dataframe = [
|
|||||||
"nu-command/dataframe",
|
"nu-command/dataframe",
|
||||||
"nu-value-ext/dataframe",
|
"nu-value-ext/dataframe",
|
||||||
"nu-data/dataframe",
|
"nu-data/dataframe",
|
||||||
"nu_plugin_post/dataframe",
|
|
||||||
"nu_plugin_to_bson/dataframe",
|
"nu_plugin_to_bson/dataframe",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -166,31 +156,11 @@ name = "nu_plugin_core_inc"
|
|||||||
path = "src/plugins/nu_plugin_core_inc.rs"
|
path = "src/plugins/nu_plugin_core_inc.rs"
|
||||||
required-features = ["inc"]
|
required-features = ["inc"]
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "nu_plugin_core_ps"
|
|
||||||
path = "src/plugins/nu_plugin_core_ps.rs"
|
|
||||||
required-features = ["ps"]
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "nu_plugin_core_sys"
|
|
||||||
path = "src/plugins/nu_plugin_core_sys.rs"
|
|
||||||
required-features = ["sys"]
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "nu_plugin_core_fetch"
|
|
||||||
path = "src/plugins/nu_plugin_core_fetch.rs"
|
|
||||||
required-features = ["fetch"]
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "nu_plugin_core_match"
|
name = "nu_plugin_core_match"
|
||||||
path = "src/plugins/nu_plugin_core_match.rs"
|
path = "src/plugins/nu_plugin_core_match.rs"
|
||||||
required-features = ["match"]
|
required-features = ["match"]
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "nu_plugin_core_post"
|
|
||||||
path = "src/plugins/nu_plugin_core_post.rs"
|
|
||||||
required-features = ["post"]
|
|
||||||
|
|
||||||
# Extra plugins
|
# Extra plugins
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
@@ -9,7 +9,7 @@ description = "Library for ANSI terminal colors and styles (bold, underline)"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "nu-ansi-term"
|
name = "nu-ansi-term"
|
||||||
version = "0.36.0"
|
version = "0.37.0"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
doctest = false
|
doctest = false
|
||||||
|
@@ -93,7 +93,7 @@ pub static RESET: &str = "\x1B[0m";
|
|||||||
|
|
||||||
impl Color {
|
impl Color {
|
||||||
fn write_foreground_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
|
fn write_foreground_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
|
||||||
match *self {
|
match self {
|
||||||
Color::Black => write!(f, "30"),
|
Color::Black => write!(f, "30"),
|
||||||
Color::Red => write!(f, "31"),
|
Color::Red => write!(f, "31"),
|
||||||
Color::Green => write!(f, "32"),
|
Color::Green => write!(f, "32"),
|
||||||
@@ -103,8 +103,8 @@ impl Color {
|
|||||||
Color::Magenta => write!(f, "35"),
|
Color::Magenta => write!(f, "35"),
|
||||||
Color::Cyan => write!(f, "36"),
|
Color::Cyan => write!(f, "36"),
|
||||||
Color::White => write!(f, "37"),
|
Color::White => write!(f, "37"),
|
||||||
Color::Fixed(num) => write!(f, "38;5;{}", &num),
|
Color::Fixed(num) => write!(f, "38;5;{}", num),
|
||||||
Color::Rgb(r, g, b) => write!(f, "38;2;{};{};{}", &r, &g, &b),
|
Color::Rgb(r, g, b) => write!(f, "38;2;{};{};{}", r, g, b),
|
||||||
Color::DarkGray => write!(f, "90"),
|
Color::DarkGray => write!(f, "90"),
|
||||||
Color::LightRed => write!(f, "91"),
|
Color::LightRed => write!(f, "91"),
|
||||||
Color::LightGreen => write!(f, "92"),
|
Color::LightGreen => write!(f, "92"),
|
||||||
@@ -118,7 +118,7 @@ impl Color {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn write_background_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
|
fn write_background_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
|
||||||
match *self {
|
match self {
|
||||||
Color::Black => write!(f, "40"),
|
Color::Black => write!(f, "40"),
|
||||||
Color::Red => write!(f, "41"),
|
Color::Red => write!(f, "41"),
|
||||||
Color::Green => write!(f, "42"),
|
Color::Green => write!(f, "42"),
|
||||||
@@ -128,8 +128,8 @@ impl Color {
|
|||||||
Color::Magenta => write!(f, "45"),
|
Color::Magenta => write!(f, "45"),
|
||||||
Color::Cyan => write!(f, "46"),
|
Color::Cyan => write!(f, "46"),
|
||||||
Color::White => write!(f, "47"),
|
Color::White => write!(f, "47"),
|
||||||
Color::Fixed(num) => write!(f, "48;5;{}", &num),
|
Color::Fixed(num) => write!(f, "48;5;{}", num),
|
||||||
Color::Rgb(r, g, b) => write!(f, "48;2;{};{};{}", &r, &g, &b),
|
Color::Rgb(r, g, b) => write!(f, "48;2;{};{};{}", r, g, b),
|
||||||
Color::DarkGray => write!(f, "100"),
|
Color::DarkGray => write!(f, "100"),
|
||||||
Color::LightRed => write!(f, "101"),
|
Color::LightRed => write!(f, "101"),
|
||||||
Color::LightGreen => write!(f, "102"),
|
Color::LightGreen => write!(f, "102"),
|
||||||
|
@@ -297,7 +297,7 @@ mod tests {
|
|||||||
fn no_control_codes_for_plain() {
|
fn no_control_codes_for_plain() {
|
||||||
let one = Style::default().paint("one");
|
let one = Style::default().paint("one");
|
||||||
let two = Style::default().paint("two");
|
let two = Style::default().paint("two");
|
||||||
let output = format!("{}", AnsiStrings(&[one, two]));
|
let output = AnsiStrings(&[one, two]).to_string();
|
||||||
assert_eq!(&*output, "onetwo");
|
assert_eq!(output, "onetwo");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -602,14 +602,14 @@ mod serde_json_tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn color_deserialization() {
|
fn color_deserialization() {
|
||||||
let colors = &[
|
let colors = [
|
||||||
Color::Red,
|
Color::Red,
|
||||||
Color::Blue,
|
Color::Blue,
|
||||||
Color::Rgb(123, 123, 123),
|
Color::Rgb(123, 123, 123),
|
||||||
Color::Fixed(255),
|
Color::Fixed(255),
|
||||||
];
|
];
|
||||||
|
|
||||||
for color in colors.iter() {
|
for color in colors {
|
||||||
let serialized = serde_json::to_string(&color).unwrap();
|
let serialized = serde_json::to_string(&color).unwrap();
|
||||||
let deserialized: Color = serde_json::from_str(&serialized).unwrap();
|
let deserialized: Color = serde_json::from_str(&serialized).unwrap();
|
||||||
|
|
||||||
|
@@ -75,6 +75,6 @@ mod test {
|
|||||||
assert_eq!(unstyled_len(&a), 18);
|
assert_eq!(unstyled_len(&a), 18);
|
||||||
|
|
||||||
let l2 = [Black.paint("st"), Red.paint("-second"), White.paint("-t")];
|
let l2 = [Black.paint("st"), Red.paint("-second"), White.paint("-t")];
|
||||||
assert_eq!(sub_string(3, 11, &a).as_slice(), &l2);
|
assert_eq!(sub_string(3, 11, &a), l2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,23 +4,23 @@ description = "CLI for nushell"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "nu-cli"
|
name = "nu-cli"
|
||||||
version = "0.36.0"
|
version = "0.37.0"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
doctest = false
|
doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-completion = { version = "0.36.0", path="../nu-completion" }
|
nu-completion = { version = "0.37.0", path="../nu-completion" }
|
||||||
nu-command = { version = "0.36.0", path="../nu-command" }
|
nu-command = { version = "0.37.0", path="../nu-command" }
|
||||||
nu-data = { version = "0.36.0", path="../nu-data" }
|
nu-data = { version = "0.37.0", path="../nu-data" }
|
||||||
nu-engine = { version = "0.36.0", path="../nu-engine" }
|
nu-engine = { version = "0.37.0", path="../nu-engine" }
|
||||||
nu-errors = { version = "0.36.0", path="../nu-errors" }
|
nu-errors = { version = "0.37.0", path="../nu-errors" }
|
||||||
nu-parser = { version = "0.36.0", path="../nu-parser" }
|
nu-parser = { version = "0.37.0", path="../nu-parser" }
|
||||||
nu-protocol = { version = "0.36.0", path="../nu-protocol" }
|
nu-protocol = { version = "0.37.0", path="../nu-protocol" }
|
||||||
nu-source = { version = "0.36.0", path="../nu-source" }
|
nu-source = { version = "0.37.0", path="../nu-source" }
|
||||||
nu-stream = { version = "0.36.0", path="../nu-stream" }
|
nu-stream = { version = "0.37.0", path="../nu-stream" }
|
||||||
nu-ansi-term = { version = "0.36.0", path="../nu-ansi-term" }
|
nu-ansi-term = { version = "0.37.0", path="../nu-ansi-term" }
|
||||||
|
|
||||||
indexmap ="1.6.1"
|
indexmap ="1.6.1"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
|
@@ -508,14 +508,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_use_loglevels() -> Result<(), ShellError> {
|
fn can_use_loglevels() -> Result<(), ShellError> {
|
||||||
for level in &["error", "warn", "info", "debug", "trace"] {
|
for level in ["error", "warn", "info", "debug", "trace"] {
|
||||||
let ui = cli_app();
|
let ui = cli_app();
|
||||||
let args = format!("nu --loglevel={}", *level);
|
let args = format!("nu --loglevel={}", level);
|
||||||
ui.parse(&args)?;
|
ui.parse(&args)?;
|
||||||
assert_eq!(ui.loglevel().unwrap(), Ok(level.to_string()));
|
assert_eq!(ui.loglevel().unwrap(), Ok(level.to_string()));
|
||||||
|
|
||||||
let ui = cli_app();
|
let ui = cli_app();
|
||||||
let args = format!("nu -l {}", *level);
|
let args = format!("nu -l {}", level);
|
||||||
ui.parse(&args)?;
|
ui.parse(&args)?;
|
||||||
assert_eq!(ui.loglevel().unwrap(), Ok(level.to_string()));
|
assert_eq!(ui.loglevel().unwrap(), Ok(level.to_string()));
|
||||||
}
|
}
|
||||||
@@ -541,11 +541,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_use_test_binaries() -> Result<(), ShellError> {
|
fn can_use_test_binaries() -> Result<(), ShellError> {
|
||||||
for binarie_name in &[
|
for binarie_name in [
|
||||||
"echo_env", "cococo", "iecho", "fail", "nonu", "chop", "repeater", "meow",
|
"echo_env", "cococo", "iecho", "fail", "nonu", "chop", "repeater", "meow",
|
||||||
] {
|
] {
|
||||||
let ui = cli_app();
|
let ui = cli_app();
|
||||||
let args = format!("nu --testbin={}", *binarie_name);
|
let args = format!("nu --testbin={}", binarie_name);
|
||||||
ui.parse(&args)?;
|
ui.parse(&args)?;
|
||||||
assert_eq!(ui.testbin().unwrap(), Ok(binarie_name.to_string()));
|
assert_eq!(ui.testbin().unwrap(), Ok(binarie_name.to_string()));
|
||||||
}
|
}
|
||||||
|
@@ -44,7 +44,7 @@ impl Options {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, key: &str) -> Option<Value> {
|
pub fn get(&self, key: &str) -> Option<Value> {
|
||||||
self.inner.borrow().get(key).map(Clone::clone)
|
self.inner.borrow().get(key).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn put(&self, key: &str, value: Value) {
|
pub fn put(&self, key: &str, value: Value) {
|
||||||
|
@@ -67,48 +67,37 @@ impl OptionsParser for NuParser {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let value =
|
let value = value.map(|v| match k.as_ref() {
|
||||||
value
|
|
||||||
.map(|v| match k.as_ref() {
|
|
||||||
"testbin" => {
|
"testbin" => {
|
||||||
if let Ok(name) = v.as_string() {
|
if let Ok(name) = v.as_string() {
|
||||||
if testbins().iter().any(|n| name == *n) {
|
if testbins().iter().any(|n| name == *n) {
|
||||||
Some(v)
|
v
|
||||||
} else {
|
} else {
|
||||||
Some(
|
UntaggedValue::Error(ShellError::untagged_runtime_error(
|
||||||
UntaggedValue::Error(
|
|
||||||
ShellError::untagged_runtime_error(
|
|
||||||
format!("{} is not supported.", name),
|
format!("{} is not supported.", name),
|
||||||
),
|
))
|
||||||
)
|
.into_value(v.tag)
|
||||||
.into_value(v.tag),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Some(v)
|
v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"loglevel" => {
|
"loglevel" => {
|
||||||
if let Ok(name) = v.as_string() {
|
if let Ok(name) = v.as_string() {
|
||||||
if loglevels().iter().any(|n| name == *n) {
|
if loglevels().iter().any(|n| name == *n) {
|
||||||
Some(v)
|
v
|
||||||
} else {
|
} else {
|
||||||
Some(
|
UntaggedValue::Error(ShellError::untagged_runtime_error(
|
||||||
UntaggedValue::Error(
|
|
||||||
ShellError::untagged_runtime_error(
|
|
||||||
format!("{} is not supported.", name),
|
format!("{} is not supported.", name),
|
||||||
),
|
))
|
||||||
)
|
.into_value(v.tag)
|
||||||
.into_value(v.tag),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Some(v)
|
v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Some(v),
|
_ => v,
|
||||||
})
|
});
|
||||||
.flatten();
|
|
||||||
|
|
||||||
if let Some(value) = value {
|
if let Some(value) = value {
|
||||||
options.put(k, value);
|
options.put(k, value);
|
||||||
|
@@ -33,7 +33,7 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
// Name of environment variable where the prompt could be stored
|
// Name of environment variable where the prompt could be stored
|
||||||
#[cfg(feature = "rustyline-support")]
|
#[cfg(feature = "rustyline-support")]
|
||||||
const PROMPT_STRING: &str = "PROMPT_STRING";
|
const PROMPT_COMMAND: &str = "PROMPT_COMMAND";
|
||||||
|
|
||||||
pub fn search_paths() -> Vec<std::path::PathBuf> {
|
pub fn search_paths() -> Vec<std::path::PathBuf> {
|
||||||
use std::env;
|
use std::env;
|
||||||
@@ -165,7 +165,10 @@ pub fn cli(
|
|||||||
// Store cmd duration in an env var
|
// Store cmd duration in an env var
|
||||||
context.scope.add_env_var(
|
context.scope.add_env_var(
|
||||||
"CMD_DURATION_MS",
|
"CMD_DURATION_MS",
|
||||||
format!("{}", startup_commands_start_time.elapsed().as_millis()),
|
startup_commands_start_time
|
||||||
|
.elapsed()
|
||||||
|
.as_millis()
|
||||||
|
.to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if options.perf {
|
if options.perf {
|
||||||
@@ -298,9 +301,9 @@ pub fn cli(
|
|||||||
|
|
||||||
let cwd = context.shell_manager().path();
|
let cwd = context.shell_manager().path();
|
||||||
|
|
||||||
// Check if the PROMPT_STRING env variable is set. This env variable
|
// Check if the PROMPT_COMMAND env variable is set. This env variable
|
||||||
// contains nu code that is used to overwrite the prompt
|
// contains nu code that is used to overwrite the prompt
|
||||||
let colored_prompt = match context.scope.get_env(PROMPT_STRING) {
|
let colored_prompt = match context.scope.get_env(PROMPT_COMMAND) {
|
||||||
Some(env_prompt) => evaluate_prompt_string(&env_prompt, &context, &cwd),
|
Some(env_prompt) => evaluate_prompt_string(&env_prompt, &context, &cwd),
|
||||||
None => {
|
None => {
|
||||||
if let Some(prompt) = &prompt {
|
if let Some(prompt) = &prompt {
|
||||||
@@ -353,7 +356,7 @@ pub fn cli(
|
|||||||
// Store cmd duration in an env var
|
// Store cmd duration in an env var
|
||||||
context.scope.add_env_var(
|
context.scope.add_env_var(
|
||||||
"CMD_DURATION_MS",
|
"CMD_DURATION_MS",
|
||||||
format!("{}", cmd_start_time.elapsed().as_millis()),
|
cmd_start_time.elapsed().as_millis().to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
match line {
|
match line {
|
||||||
@@ -397,8 +400,7 @@ pub fn cli(
|
|||||||
.lock()
|
.lock()
|
||||||
.global_config
|
.global_config
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|cfg| cfg.var("ctrlc_exit"))
|
.and_then(|cfg| cfg.var("ctrlc_exit"))
|
||||||
.flatten()
|
|
||||||
.map(|ctrl_c| ctrl_c.is_true())
|
.map(|ctrl_c| ctrl_c.is_true())
|
||||||
.unwrap_or(false); // default behavior is to allow CTRL-C spamming similar to other shells
|
.unwrap_or(false); // default behavior is to allow CTRL-C spamming similar to other shells
|
||||||
|
|
||||||
|
@@ -461,7 +461,7 @@ pub(crate) fn load_keybindings(
|
|||||||
if let Ok(contents) = contents {
|
if let Ok(contents) = contents {
|
||||||
let keybindings: Keybindings = serde_yaml::from_str(&contents)?;
|
let keybindings: Keybindings = serde_yaml::from_str(&contents)?;
|
||||||
// eprintln!("{:#?}", keybindings);
|
// eprintln!("{:#?}", keybindings);
|
||||||
for keybinding in keybindings.into_iter() {
|
for keybinding in keybindings {
|
||||||
let (k, b) = convert_keybinding(keybinding);
|
let (k, b) = convert_keybinding(keybinding);
|
||||||
// eprintln!("{:?} {:?}", k, b);
|
// eprintln!("{:?} {:?}", k, b);
|
||||||
|
|
||||||
|
@@ -5,29 +5,31 @@ description = "CLI for nushell"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "nu-command"
|
name = "nu-command"
|
||||||
version = "0.36.0"
|
version = "0.37.0"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
doctest = false
|
doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-data = { version = "0.36.0", path="../nu-data" }
|
nu-data = { version = "0.37.0", path="../nu-data" }
|
||||||
nu-engine = { version = "0.36.0", path="../nu-engine" }
|
nu-engine = { version = "0.37.0", path="../nu-engine" }
|
||||||
nu-errors = { version = "0.36.0", path="../nu-errors" }
|
nu-errors = { version = "0.37.0", path="../nu-errors" }
|
||||||
nu-json = { version = "0.36.0", path="../nu-json" }
|
nu-json = { version = "0.37.0", path="../nu-json" }
|
||||||
nu-path = { version = "0.36.0", path="../nu-path" }
|
nu-path = { version = "0.37.0", path="../nu-path" }
|
||||||
nu-parser = { version = "0.36.0", path="../nu-parser" }
|
nu-parser = { version = "0.37.0", path="../nu-parser" }
|
||||||
nu-plugin = { version = "0.36.0", path="../nu-plugin" }
|
nu-plugin = { version = "0.37.0", path="../nu-plugin" }
|
||||||
nu-protocol = { version = "0.36.0", path="../nu-protocol" }
|
nu-protocol = { version = "0.37.0", path="../nu-protocol" }
|
||||||
nu-serde = { version = "0.36.0", path="../nu-serde" }
|
nu-serde = { version = "0.37.0", path="../nu-serde" }
|
||||||
nu-source = { version = "0.36.0", path="../nu-source" }
|
nu-source = { version = "0.37.0", path="../nu-source" }
|
||||||
nu-stream = { version = "0.36.0", path="../nu-stream" }
|
nu-stream = { version = "0.37.0", path="../nu-stream" }
|
||||||
nu-table = { version = "0.36.0", path="../nu-table" }
|
nu-table = { version = "0.37.0", path="../nu-table" }
|
||||||
nu-test-support = { version = "0.36.0", path="../nu-test-support" }
|
nu-test-support = { version = "0.37.0", path="../nu-test-support" }
|
||||||
nu-value-ext = { version = "0.36.0", path="../nu-value-ext" }
|
nu-value-ext = { version = "0.37.0", path="../nu-value-ext" }
|
||||||
nu-ansi-term = { version = "0.36.0", path="../nu-ansi-term" }
|
nu-ansi-term = { version = "0.37.0", path="../nu-ansi-term" }
|
||||||
nu-pretty-hex = { version = "0.36.0", path="../nu-pretty-hex" }
|
nu-pretty-hex = { version = "0.37.0", path="../nu-pretty-hex" }
|
||||||
|
|
||||||
|
url = "2.2.1"
|
||||||
|
mime = "0.3.16"
|
||||||
Inflector = "0.11"
|
Inflector = "0.11"
|
||||||
arboard = { version="1.1.0", optional=true }
|
arboard = { version="1.1.0", optional=true }
|
||||||
base64 = "0.13.0"
|
base64 = "0.13.0"
|
||||||
@@ -45,7 +47,6 @@ derive-new = "0.5.8"
|
|||||||
directories-next = "2.0.0"
|
directories-next = "2.0.0"
|
||||||
dirs-next = "2.0.0"
|
dirs-next = "2.0.0"
|
||||||
dtparse = "1.2.0"
|
dtparse = "1.2.0"
|
||||||
dunce = "1.0.1"
|
|
||||||
eml-parser = "0.1.0"
|
eml-parser = "0.1.0"
|
||||||
encoding_rs = "0.8.28"
|
encoding_rs = "0.8.28"
|
||||||
filesize = "0.2.0"
|
filesize = "0.2.0"
|
||||||
@@ -72,6 +73,7 @@ quick-xml = "0.22"
|
|||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
rayon = "1.5.0"
|
rayon = "1.5.0"
|
||||||
regex = "1.4.3"
|
regex = "1.4.3"
|
||||||
|
reqwest = {version = "0.11", optional = true }
|
||||||
roxmltree = "0.14.0"
|
roxmltree = "0.14.0"
|
||||||
rust-embed = "5.9.0"
|
rust-embed = "5.9.0"
|
||||||
rustyline = { version="9.0.0", optional=true }
|
rustyline = { version="9.0.0", optional=true }
|
||||||
@@ -85,16 +87,17 @@ sha2 = "0.9.3"
|
|||||||
strip-ansi-escapes = "0.1.0"
|
strip-ansi-escapes = "0.1.0"
|
||||||
sxd-document = "0.3.2"
|
sxd-document = "0.3.2"
|
||||||
sxd-xpath = "0.4.2"
|
sxd-xpath = "0.4.2"
|
||||||
|
sysinfo = { version = "0.20.2", optional = true }
|
||||||
thiserror = "1.0.26"
|
thiserror = "1.0.26"
|
||||||
tempfile = "3.2.0"
|
tempfile = "3.2.0"
|
||||||
term = { version="0.7.0", optional=true }
|
term = { version="0.7.0", optional=true }
|
||||||
term_size = "0.3.2"
|
term_size = "0.3.2"
|
||||||
termcolor = "1.1.2"
|
termcolor = "1.1.2"
|
||||||
titlecase = "1.1.0"
|
titlecase = "1.1.0"
|
||||||
|
tokio = { version = "1", features = ["rt-multi-thread"], optional = true }
|
||||||
toml = "0.5.8"
|
toml = "0.5.8"
|
||||||
trash = { version="1.3.0", optional=true }
|
trash = { version="1.3.0", optional=true }
|
||||||
unicode-segmentation = "1.8"
|
unicode-segmentation = "1.8"
|
||||||
url = "2.2.0"
|
|
||||||
uuid_crate = { package="uuid", version="0.8.2", features=["v4"], optional=true }
|
uuid_crate = { package="uuid", version="0.8.2", features=["v4"], optional=true }
|
||||||
which = { version="4.1.0", optional=true }
|
which = { version="4.1.0", optional=true }
|
||||||
zip = { version="0.5.9", optional=true }
|
zip = { version="0.5.9", optional=true }
|
||||||
@@ -135,3 +138,7 @@ stable = []
|
|||||||
trash-support = ["trash"]
|
trash-support = ["trash"]
|
||||||
table-pager = ["minus", "crossterm"]
|
table-pager = ["minus", "crossterm"]
|
||||||
dataframe = ["nu-protocol/dataframe", "polars"]
|
dataframe = ["nu-protocol/dataframe", "polars"]
|
||||||
|
fetch = ["reqwest", "tokio"]
|
||||||
|
post = ["reqwest", "tokio"]
|
||||||
|
sys = ["sysinfo"]
|
||||||
|
ps = ["sysinfo"]
|
@@ -4,7 +4,10 @@ use nu_engine::{MaybeTextCodec, StringOrBinary};
|
|||||||
use nu_test_support::NATIVE_PATH_ENV_VAR;
|
use nu_test_support::NATIVE_PATH_ENV_VAR;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
use std::env;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::{borrow::Cow, io::BufReader};
|
use std::{borrow::Cow, io::BufReader};
|
||||||
@@ -17,6 +20,9 @@ use nu_protocol::hir::{ExternalCommand, ExternalRedirection};
|
|||||||
use nu_protocol::{Primitive, ShellTypeName, UntaggedValue, Value};
|
use nu_protocol::{Primitive, ShellTypeName, UntaggedValue, Value};
|
||||||
use nu_source::Tag;
|
use nu_source::Tag;
|
||||||
|
|
||||||
|
#[cfg(feature = "which")]
|
||||||
|
use which::which_in;
|
||||||
|
|
||||||
pub(crate) fn run_external_command(
|
pub(crate) fn run_external_command(
|
||||||
command: ExternalCommand,
|
command: ExternalCommand,
|
||||||
context: &mut EvaluationContext,
|
context: &mut EvaluationContext,
|
||||||
@@ -104,7 +110,7 @@ fn run_with_stdin(
|
|||||||
let process_args = command_args
|
let process_args = command_args
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(arg, _is_literal)| {
|
.map(|(arg, _is_literal)| {
|
||||||
let arg = nu_path::expand_tilde_string(Cow::Borrowed(arg));
|
let arg = nu_path::expand_tilde(arg).to_string_lossy().to_string();
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
{
|
{
|
||||||
@@ -141,19 +147,18 @@ fn run_with_stdin(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn(
|
/// Spawn a direct exe
|
||||||
command: &ExternalCommand,
|
#[allow(unused)]
|
||||||
path: &str,
|
fn spawn_exe(full_path: PathBuf, args: &[String]) -> Command {
|
||||||
args: &[String],
|
let mut process = Command::new(full_path);
|
||||||
input: InputStream,
|
for arg in args {
|
||||||
external_redirection: ExternalRedirection,
|
process.arg(&arg);
|
||||||
scope: &Scope,
|
}
|
||||||
) -> Result<InputStream, ShellError> {
|
process
|
||||||
let command = command.clone();
|
}
|
||||||
|
|
||||||
let mut process = {
|
/// Spawn a cmd command with `cmd /c args...`
|
||||||
#[cfg(windows)]
|
fn spawn_cmd_command(command: &ExternalCommand, args: &[String]) -> Command {
|
||||||
{
|
|
||||||
let mut process = Command::new("cmd");
|
let mut process = Command::new("cmd");
|
||||||
process.arg("/c");
|
process.arg("/c");
|
||||||
process.arg(&command.name);
|
process.arg(&command.name);
|
||||||
@@ -167,15 +172,65 @@ fn spawn(
|
|||||||
process
|
process
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
/// Spawn a sh command with `sh -c args...`
|
||||||
{
|
fn spawn_sh_command(command: &ExternalCommand, args: &[String]) -> Command {
|
||||||
let cmd_with_args = vec![command.name.clone(), args.join(" ")].join(" ");
|
let cmd_with_args = vec![command.name.clone(), args.join(" ")].join(" ");
|
||||||
let mut process = Command::new("sh");
|
let mut process = Command::new("sh");
|
||||||
process.arg("-c").arg(cmd_with_args);
|
process.arg("-c").arg(cmd_with_args);
|
||||||
process
|
process
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
/// a function to spawn any external command
|
||||||
|
#[allow(unused)] // for minimal builds cwd is unused
|
||||||
|
fn spawn_any(command: &ExternalCommand, args: &[String], cwd: &str) -> Command {
|
||||||
|
// resolve the executable name if it is spawnable directly
|
||||||
|
#[cfg(feature = "which")]
|
||||||
|
// TODO add more available paths to `env::var_os("PATH")`?
|
||||||
|
if let Result::Ok(full_path) = which_in(&command.name, env::var_os("PATH"), cwd) {
|
||||||
|
if let Some(extension) = full_path.extension() {
|
||||||
|
#[cfg(windows)]
|
||||||
|
if extension.eq_ignore_ascii_case("exe") {
|
||||||
|
// if exe spawn it directly
|
||||||
|
return spawn_exe(full_path, args);
|
||||||
|
} else {
|
||||||
|
// TODO implement special care for various executable types such as .bat, .ps1, .cmd, etc
|
||||||
|
// https://github.com/mklement0/Native/blob/e0e0b8785cad39a73053e35084d1f60d87fbac58/Native.psm1#L749
|
||||||
|
// otherwise shell out to cmd
|
||||||
|
return spawn_cmd_command(command, args);
|
||||||
|
}
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
if !["sh", "bash"]
|
||||||
|
.iter()
|
||||||
|
.any(|ext| extension.eq_ignore_ascii_case(ext))
|
||||||
|
{
|
||||||
|
// if exe spawn it directly
|
||||||
|
return spawn_exe(full_path, args);
|
||||||
|
} else {
|
||||||
|
// otherwise shell out to sh
|
||||||
|
return spawn_sh_command(command, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// in all the other cases shell out
|
||||||
|
if cfg!(windows) {
|
||||||
|
spawn_cmd_command(command, args)
|
||||||
|
} else {
|
||||||
|
// TODO what happens if that os doesn't support spawning sh?
|
||||||
|
spawn_sh_command(command, args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spawn(
|
||||||
|
command: &ExternalCommand,
|
||||||
|
path: &str,
|
||||||
|
args: &[String],
|
||||||
|
input: InputStream,
|
||||||
|
external_redirection: ExternalRedirection,
|
||||||
|
scope: &Scope,
|
||||||
|
) -> Result<InputStream, ShellError> {
|
||||||
|
let command = command.clone();
|
||||||
|
|
||||||
|
let mut process = spawn_any(&command, args, path);
|
||||||
process.current_dir(path);
|
process.current_dir(path);
|
||||||
trace!(target: "nu::run::external", "cwd = {:?}", &path);
|
trace!(target: "nu::run::external", "cwd = {:?}", &path);
|
||||||
|
|
||||||
@@ -454,7 +509,7 @@ fn spawn(
|
|||||||
Ok(stream.into_input_stream())
|
Ok(stream.into_input_stream())
|
||||||
}
|
}
|
||||||
Err(e) => Err(ShellError::labeled_error(
|
Err(e) => Err(ShellError::labeled_error(
|
||||||
format!("{}", e),
|
e.to_string(),
|
||||||
"failed to spawn",
|
"failed to spawn",
|
||||||
&command.name_tag,
|
&command.name_tag,
|
||||||
)),
|
)),
|
||||||
|
@@ -22,6 +22,7 @@ impl WholeStreamCommand for Histogram {
|
|||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.rest(
|
.rest(
|
||||||
|
"rest",
|
||||||
SyntaxShape::ColumnPath,
|
SyntaxShape::ColumnPath,
|
||||||
"column name to give the histogram's frequency column",
|
"column name to give the histogram's frequency column",
|
||||||
)
|
)
|
||||||
|
@@ -13,6 +13,7 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("into binary").rest(
|
Signature::build("into binary").rest(
|
||||||
|
"rest",
|
||||||
SyntaxShape::ColumnPath,
|
SyntaxShape::ColumnPath,
|
||||||
"column paths to convert to binary (for table input)",
|
"column paths to convert to binary (for table input)",
|
||||||
)
|
)
|
||||||
|
@@ -14,6 +14,7 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("into path").rest(
|
Signature::build("into path").rest(
|
||||||
|
"rest",
|
||||||
SyntaxShape::ColumnPath,
|
SyntaxShape::ColumnPath,
|
||||||
"column paths to convert to filepath (for table input)",
|
"column paths to convert to filepath (for table input)",
|
||||||
)
|
)
|
||||||
|
182
crates/nu-command/src/commands/conversions/into/filesize.rs
Normal file
182
crates/nu-command/src/commands/conversions/into/filesize.rs
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
use nu_engine::WholeStreamCommand;
|
||||||
|
use nu_errors::ShellError;
|
||||||
|
use nu_protocol::{ColumnPath, Primitive, Signature, SyntaxShape, UntaggedValue, Value};
|
||||||
|
use num_bigint::ToBigInt;
|
||||||
|
|
||||||
|
pub struct SubCommand;
|
||||||
|
|
||||||
|
impl WholeStreamCommand for SubCommand {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"into filesize"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build("into filesize").rest(
|
||||||
|
"rest",
|
||||||
|
SyntaxShape::ColumnPath,
|
||||||
|
"column paths to convert to filesize (for table input)",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(&self) -> &str {
|
||||||
|
"Convert value to filesize"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
into_filesize(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
vec![
|
||||||
|
Example {
|
||||||
|
description: "Convert string to filesize in table",
|
||||||
|
example: "echo [[bytes]; ['5'] [3.2] [4] [2kb]] | into filesize bytes",
|
||||||
|
result: Some(vec![
|
||||||
|
UntaggedValue::row(indexmap! {
|
||||||
|
"bytes".to_string() => UntaggedValue::filesize(5).into(),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
UntaggedValue::row(indexmap! {
|
||||||
|
"bytes".to_string() => UntaggedValue::filesize(3).into(),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
UntaggedValue::row(indexmap! {
|
||||||
|
"bytes".to_string() => UntaggedValue::filesize(4).into(),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
UntaggedValue::row(indexmap! {
|
||||||
|
"bytes".to_string() => UntaggedValue::filesize(2000).into(),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Convert string to filesize",
|
||||||
|
example: "echo '2' | into filesize",
|
||||||
|
result: Some(vec![UntaggedValue::filesize(2).into()]),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Convert decimal to filesize",
|
||||||
|
example: "echo 8.3 | into filesize",
|
||||||
|
result: Some(vec![UntaggedValue::filesize(8).into()]),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Convert int to filesize",
|
||||||
|
example: "echo 5 | into filesize",
|
||||||
|
result: Some(vec![UntaggedValue::filesize(5).into()]),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Convert file size to filesize",
|
||||||
|
example: "echo 4KB | into filesize",
|
||||||
|
result: Some(vec![UntaggedValue::filesize(4000).into()]),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_filesize(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
let column_paths: Vec<ColumnPath> = args.rest(0)?;
|
||||||
|
|
||||||
|
Ok(args
|
||||||
|
.input
|
||||||
|
.map(move |v| {
|
||||||
|
if column_paths.is_empty() {
|
||||||
|
action(&v, v.tag())
|
||||||
|
} else {
|
||||||
|
let mut ret = v;
|
||||||
|
for path in &column_paths {
|
||||||
|
ret = ret.swap_data_by_column_path(
|
||||||
|
path,
|
||||||
|
Box::new(move |old| action(old, old.tag())),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ret)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.into_input_stream())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn action(input: &Value, tag: impl Into<Tag>) -> Result<Value, ShellError> {
|
||||||
|
let tag = tag.into();
|
||||||
|
match &input.value {
|
||||||
|
UntaggedValue::Primitive(prim) => Ok(UntaggedValue::filesize(match prim {
|
||||||
|
Primitive::String(a_string) => match int_from_string(a_string.trim(), &tag) {
|
||||||
|
Ok(n) => n,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Primitive::Decimal(dec) => match dec.to_bigint() {
|
||||||
|
Some(n) => match n.to_u64() {
|
||||||
|
Some(i) => i,
|
||||||
|
None => {
|
||||||
|
return Err(ShellError::unimplemented(
|
||||||
|
"failed to convert decimal to filesize",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
return Err(ShellError::unimplemented(
|
||||||
|
"failed to convert decimal to filesize",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Primitive::Int(n_ref) => (*n_ref).try_into().map_err(|_| {
|
||||||
|
ShellError::unimplemented("cannot convert negative integer to filesize")
|
||||||
|
})?,
|
||||||
|
Primitive::Filesize(a_filesize) => *a_filesize,
|
||||||
|
_ => {
|
||||||
|
return Err(ShellError::unimplemented(
|
||||||
|
"'into filesize' for non-numeric primitives",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.into_value(&tag)),
|
||||||
|
UntaggedValue::Row(_) => Err(ShellError::labeled_error(
|
||||||
|
"specify column name to use, with 'into filesize COLUMN'",
|
||||||
|
"found table",
|
||||||
|
tag,
|
||||||
|
)),
|
||||||
|
_ => Err(ShellError::unimplemented(
|
||||||
|
"'into filesize' for unsupported type",
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn int_from_string(a_string: &str, tag: &Tag) -> Result<u64, ShellError> {
|
||||||
|
match a_string.parse::<u64>() {
|
||||||
|
Ok(n) => Ok(n),
|
||||||
|
Err(_) => match a_string.parse::<f64>() {
|
||||||
|
Ok(f) => match f.to_u64() {
|
||||||
|
Some(i) => Ok(i),
|
||||||
|
None => Err(ShellError::labeled_error(
|
||||||
|
"Could not convert string value to filesize",
|
||||||
|
"original value",
|
||||||
|
tag.clone(),
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
Err(_) => Err(ShellError::labeled_error(
|
||||||
|
"Could not convert string value to filesize",
|
||||||
|
"original value",
|
||||||
|
tag.clone(),
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::ShellError;
|
||||||
|
use super::SubCommand;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn examples_work_as_expected() -> Result<(), ShellError> {
|
||||||
|
use crate::examples::test as test_examples;
|
||||||
|
|
||||||
|
test_examples(SubCommand {})
|
||||||
|
}
|
||||||
|
}
|
@@ -13,6 +13,7 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("into int").rest(
|
Signature::build("into int").rest(
|
||||||
|
"rest",
|
||||||
SyntaxShape::ColumnPath,
|
SyntaxShape::ColumnPath,
|
||||||
"column paths to convert to int (for table input)",
|
"column paths to convert to int (for table input)",
|
||||||
)
|
)
|
||||||
|
@@ -1,9 +1,11 @@
|
|||||||
mod binary;
|
mod binary;
|
||||||
mod command;
|
mod command;
|
||||||
mod filepath;
|
mod filepath;
|
||||||
|
mod filesize;
|
||||||
mod int;
|
mod int;
|
||||||
pub mod string;
|
pub mod string;
|
||||||
|
|
||||||
|
pub use self::filesize::SubCommand as IntoFilesize;
|
||||||
pub use binary::SubCommand as IntoBinary;
|
pub use binary::SubCommand as IntoBinary;
|
||||||
pub use command::Command as Into;
|
pub use command::Command as Into;
|
||||||
pub use filepath::SubCommand as IntoFilepath;
|
pub use filepath::SubCommand as IntoFilepath;
|
||||||
|
@@ -20,6 +20,7 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("into string")
|
Signature::build("into string")
|
||||||
.rest(
|
.rest(
|
||||||
|
"rest",
|
||||||
SyntaxShape::ColumnPath,
|
SyntaxShape::ColumnPath,
|
||||||
"column paths to convert to string (for table input)",
|
"column paths to convert to string (for table input)",
|
||||||
)
|
)
|
||||||
@@ -158,7 +159,7 @@ pub fn action(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn format_int(int: i64) -> String {
|
fn format_int(int: i64) -> String {
|
||||||
format!("{}", int)
|
int.to_string()
|
||||||
|
|
||||||
// TODO once platform-specific dependencies are stable (see Cargo.toml)
|
// TODO once platform-specific dependencies are stable (see Cargo.toml)
|
||||||
// #[cfg(windows)]
|
// #[cfg(windows)]
|
||||||
@@ -175,7 +176,7 @@ fn format_int(int: i64) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn format_bigint(int: &BigInt) -> String {
|
fn format_bigint(int: &BigInt) -> String {
|
||||||
format!("{}", int)
|
int.to_string()
|
||||||
|
|
||||||
// TODO once platform-specific dependencies are stable (see Cargo.toml)
|
// TODO once platform-specific dependencies are stable (see Cargo.toml)
|
||||||
// #[cfg(windows)]
|
// #[cfg(windows)]
|
||||||
@@ -229,7 +230,7 @@ fn format_decimal(mut decimal: BigDecimal, digits: Option<u64>, group_digits: bo
|
|||||||
let format_default_loc = |int_part: BigInt| {
|
let format_default_loc = |int_part: BigInt| {
|
||||||
let loc = Locale::en;
|
let loc = Locale::en;
|
||||||
//TODO: when num_format is available for recent bigint, replace this with the locale-based format
|
//TODO: when num_format is available for recent bigint, replace this with the locale-based format
|
||||||
let (int_str, sep) = (format!("{}", int_part), String::from(loc.decimal()));
|
let (int_str, sep) = (int_part.to_string(), String::from(loc.decimal()));
|
||||||
|
|
||||||
format!("{}{}{}", int_str, sep, dec_str)
|
format!("{}{}{}", int_str, sep, dec_str)
|
||||||
};
|
};
|
||||||
|
@@ -15,7 +15,7 @@ impl WholeStreamCommand for Alias {
|
|||||||
Signature::build("alias")
|
Signature::build("alias")
|
||||||
.required("name", SyntaxShape::String, "the name of the alias")
|
.required("name", SyntaxShape::String, "the name of the alias")
|
||||||
.required("equals", SyntaxShape::String, "the equals sign")
|
.required("equals", SyntaxShape::String, "the equals sign")
|
||||||
.rest(SyntaxShape::Any, "the expansion for the alias")
|
.rest("rest", SyntaxShape::Any, "the expansion for the alias")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@@ -27,7 +27,7 @@ impl WholeStreamCommand for Do {
|
|||||||
"ignore errors as the block runs",
|
"ignore errors as the block runs",
|
||||||
Some('i'),
|
Some('i'),
|
||||||
)
|
)
|
||||||
.rest(SyntaxShape::Any, "the parameter(s) for the block")
|
.rest("rest", SyntaxShape::Any, "the parameter(s) for the block")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@@ -12,7 +12,7 @@ impl WholeStreamCommand for Echo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("echo").rest(SyntaxShape::Any, "the values to echo")
|
Signature::build("echo").rest("rest", SyntaxShape::Any, "the values to echo")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
109
crates/nu-command/src/commands/core_commands/error/make.rs
Normal file
109
crates/nu-command/src/commands/core_commands/error/make.rs
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
|
use nu_engine::WholeStreamCommand;
|
||||||
|
use nu_errors::ShellError;
|
||||||
|
use nu_protocol::{Primitive, Signature, UntaggedValue, Value};
|
||||||
|
|
||||||
|
pub struct SubCommand;
|
||||||
|
|
||||||
|
impl WholeStreamCommand for SubCommand {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"error make"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build("error make")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(&self) -> &str {
|
||||||
|
"Create an error."
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
let input = args.input;
|
||||||
|
|
||||||
|
Ok(input
|
||||||
|
.map(|value| {
|
||||||
|
make_error(&value)
|
||||||
|
.map(|err| UntaggedValue::Error(err).into_value(value.tag()))
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
UntaggedValue::Error(ShellError::untagged_runtime_error(
|
||||||
|
"Creating error value not supported.",
|
||||||
|
))
|
||||||
|
.into_value(value.tag())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.into_output_stream())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
vec![Example {
|
||||||
|
description: "Creates a labeled error",
|
||||||
|
example: r#"[
|
||||||
|
[ msg, labels, span];
|
||||||
|
["The message", "Helpful message here", ([[start, end]; [0, 141]])]
|
||||||
|
] | error make"#,
|
||||||
|
result: None,
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_error(value: &Value) -> Option<ShellError> {
|
||||||
|
if let Value {
|
||||||
|
value: UntaggedValue::Row(dict),
|
||||||
|
..
|
||||||
|
} = value
|
||||||
|
{
|
||||||
|
let msg = dict.get_data_by_key("msg".spanned_unknown());
|
||||||
|
|
||||||
|
let labels =
|
||||||
|
dict.get_data_by_key("labels".spanned_unknown())
|
||||||
|
.and_then(|table| match &table.value {
|
||||||
|
UntaggedValue::Table(_) => table
|
||||||
|
.table_entries()
|
||||||
|
.map(|value| value.as_string().ok())
|
||||||
|
.collect(),
|
||||||
|
UntaggedValue::Primitive(Primitive::String(label)) => {
|
||||||
|
Some(vec![label.to_string()])
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
|
||||||
|
let _anchor = dict.get_data_by_key("tag".spanned_unknown());
|
||||||
|
let span = dict.get_data_by_key("span".spanned_unknown());
|
||||||
|
|
||||||
|
if msg.is_none() || labels.is_none() || span.is_none() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let msg = msg.and_then(|msg| msg.as_string().ok());
|
||||||
|
|
||||||
|
if let Some(labels) = labels {
|
||||||
|
if labels.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(ShellError::labeled_error(
|
||||||
|
msg.expect("Message will always be present."),
|
||||||
|
&labels[0],
|
||||||
|
span.map(|data| match data {
|
||||||
|
Value {
|
||||||
|
value: UntaggedValue::Row(vals),
|
||||||
|
..
|
||||||
|
} => match (vals.entries.get("start"), vals.entries.get("end")) {
|
||||||
|
(Some(start), Some(end)) => {
|
||||||
|
let start = start.as_usize().ok().unwrap_or(0);
|
||||||
|
let end = end.as_usize().ok().unwrap_or(0);
|
||||||
|
|
||||||
|
Span::new(start, end)
|
||||||
|
}
|
||||||
|
(_, _) => Span::unknown(),
|
||||||
|
},
|
||||||
|
_ => Span::unknown(),
|
||||||
|
})
|
||||||
|
.unwrap_or_else(Span::unknown),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
@@ -0,0 +1,3 @@
|
|||||||
|
mod make;
|
||||||
|
|
||||||
|
pub use make::SubCommand as ErrorMake;
|
110
crates/nu-command/src/commands/core_commands/find.rs
Normal file
110
crates/nu-command/src/commands/core_commands/find.rs
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
|
use nu_engine::WholeStreamCommand;
|
||||||
|
use nu_errors::ShellError;
|
||||||
|
use nu_protocol::{Dictionary, Signature, SyntaxShape, UntaggedValue, Value};
|
||||||
|
|
||||||
|
pub struct Find;
|
||||||
|
|
||||||
|
impl WholeStreamCommand for Find {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"find"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build("find").rest("rest", SyntaxShape::String, "search term")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(&self) -> &str {
|
||||||
|
"Find text in the output of a previous command"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
find(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
vec![
|
||||||
|
Example {
|
||||||
|
description: "Search pipeline output for multiple terms",
|
||||||
|
example: r#"ls | find toml md sh"#,
|
||||||
|
result: None,
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Search strings for term(s)",
|
||||||
|
example: r#"echo Cargo.toml | find toml"#,
|
||||||
|
result: Some(vec![Value::from("Cargo.toml")]),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Search a number list for term(s)",
|
||||||
|
example: r#"[1 2 3 4 5] | find 5"#,
|
||||||
|
result: Some(vec![UntaggedValue::int(5).into()]),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Search string list for term(s)",
|
||||||
|
example: r#"[moe larry curly] | find l"#,
|
||||||
|
result: Some(vec![Value::from("larry"), Value::from("curly")]),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn row_contains(row: &Dictionary, search_terms: Vec<String>) -> bool {
|
||||||
|
for term in search_terms {
|
||||||
|
for (k, v) in &row.entries {
|
||||||
|
let key = k.to_string().trim().to_lowercase();
|
||||||
|
let value = v.convert_to_string().trim().to_lowercase();
|
||||||
|
if key.contains(&term) || value.contains(&term) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
let rest: Vec<Value> = args.rest(0)?;
|
||||||
|
|
||||||
|
Ok(args
|
||||||
|
.input
|
||||||
|
.filter(move |row| match &row.value {
|
||||||
|
UntaggedValue::Row(row) => {
|
||||||
|
let sterms: Vec<String> = rest
|
||||||
|
.iter()
|
||||||
|
.map(|t| t.convert_to_string().trim().to_lowercase())
|
||||||
|
.collect();
|
||||||
|
row_contains(row, sterms)
|
||||||
|
}
|
||||||
|
UntaggedValue::Primitive(_p) => {
|
||||||
|
// eprint!("prim {}", p.type_name());
|
||||||
|
let sterms: Vec<String> = rest
|
||||||
|
.iter()
|
||||||
|
.map(|t| t.convert_to_string().trim().to_lowercase())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let prim_string = &row.convert_to_string().trim().to_lowercase();
|
||||||
|
for term in sterms {
|
||||||
|
if prim_string.contains(&term) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
.into_output_stream())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::Find;
|
||||||
|
use super::ShellError;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn examples_work_as_expected() -> Result<(), ShellError> {
|
||||||
|
use crate::examples::test as test_examples;
|
||||||
|
|
||||||
|
test_examples(Find {})
|
||||||
|
}
|
||||||
|
}
|
@@ -18,7 +18,11 @@ impl WholeStreamCommand for Help {
|
|||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("help")
|
Signature::build("help")
|
||||||
.rest(SyntaxShape::String, "the name of command to get help on")
|
.rest(
|
||||||
|
"rest",
|
||||||
|
SyntaxShape::String,
|
||||||
|
"the name of command to get help on",
|
||||||
|
)
|
||||||
.named(
|
.named(
|
||||||
"find",
|
"find",
|
||||||
SyntaxShape::String,
|
SyntaxShape::String,
|
||||||
@@ -298,7 +302,7 @@ pub fn signature_dict(signature: Signature, tag: impl Into<Tag>) -> Value {
|
|||||||
let tag = tag.into();
|
let tag = tag.into();
|
||||||
let mut sig = TaggedListBuilder::new(&tag);
|
let mut sig = TaggedListBuilder::new(&tag);
|
||||||
|
|
||||||
for arg in signature.positional.iter() {
|
for arg in &signature.positional {
|
||||||
let is_required = matches!(arg.0, PositionalType::Mandatory(_, _));
|
let is_required = matches!(arg.0, PositionalType::Mandatory(_, _));
|
||||||
|
|
||||||
sig.push_value(for_spec(arg.0.name(), "argument", is_required, &tag));
|
sig.push_value(for_spec(arg.0.name(), "argument", is_required, &tag));
|
||||||
@@ -309,7 +313,7 @@ pub fn signature_dict(signature: Signature, tag: impl Into<Tag>) -> Value {
|
|||||||
sig.push_value(for_spec("rest", "argument", is_required, &tag));
|
sig.push_value(for_spec("rest", "argument", is_required, &tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (name, ty) in signature.named.iter() {
|
for (name, ty) in &signature.named {
|
||||||
match ty.0 {
|
match ty.0 {
|
||||||
NamedType::Mandatory(_, _) => sig.push_value(for_spec(name, "flag", true, &tag)),
|
NamedType::Mandatory(_, _) => sig.push_value(for_spec(name, "flag", true, &tag)),
|
||||||
NamedType::Optional(_, _) => sig.push_value(for_spec(name, "flag", false, &tag)),
|
NamedType::Optional(_, _) => sig.push_value(for_spec(name, "flag", false, &tag)),
|
||||||
|
@@ -100,14 +100,14 @@ fn if_command(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
context.scope.add_vars(&condition.captured.entries);
|
context.scope.add_vars(&condition.captured.entries);
|
||||||
|
|
||||||
//FIXME: should we use the scope that's brought in as well?
|
//FIXME: should we use the scope that's brought in as well?
|
||||||
let condition = evaluate_baseline_expr(cond, &*context);
|
let condition = evaluate_baseline_expr(cond, &context);
|
||||||
match condition {
|
match condition {
|
||||||
Ok(condition) => match condition.as_bool() {
|
Ok(condition) => match condition.as_bool() {
|
||||||
Ok(b) => {
|
Ok(b) => {
|
||||||
let result = if b {
|
let result = if b {
|
||||||
run_block(&then_case.block, &*context, input, external_redirection)
|
run_block(&then_case.block, &context, input, external_redirection)
|
||||||
} else {
|
} else {
|
||||||
run_block(&else_case.block, &*context, input, external_redirection)
|
run_block(&else_case.block, &context, input, external_redirection)
|
||||||
};
|
};
|
||||||
context.scope.exit_scope();
|
context.scope.exit_scope();
|
||||||
|
|
||||||
|
@@ -4,6 +4,8 @@ mod def;
|
|||||||
mod describe;
|
mod describe;
|
||||||
mod do_;
|
mod do_;
|
||||||
pub(crate) mod echo;
|
pub(crate) mod echo;
|
||||||
|
mod error;
|
||||||
|
mod find;
|
||||||
mod help;
|
mod help;
|
||||||
mod history;
|
mod history;
|
||||||
mod if_;
|
mod if_;
|
||||||
@@ -27,6 +29,8 @@ pub use def::Def;
|
|||||||
pub use describe::Describe;
|
pub use describe::Describe;
|
||||||
pub use do_::Do;
|
pub use do_::Do;
|
||||||
pub use echo::Echo;
|
pub use echo::Echo;
|
||||||
|
pub use error::*;
|
||||||
|
pub use find::Find;
|
||||||
pub use help::Help;
|
pub use help::Help;
|
||||||
pub use history::History;
|
pub use history::History;
|
||||||
pub use if_::If;
|
pub use if_::If;
|
||||||
|
@@ -4,7 +4,7 @@ use crate::prelude::*;
|
|||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::WholeStreamCommand;
|
||||||
|
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_path::canonicalize;
|
use nu_path::canonicalize_with;
|
||||||
use nu_protocol::{CommandAction, ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
|
use nu_protocol::{CommandAction, ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
tag,
|
tag,
|
||||||
}) = load_path
|
}) = load_path
|
||||||
{
|
{
|
||||||
let path = canonicalize(shell_manager.path(), load_path).map_err(|_| {
|
let path = canonicalize_with(load_path, shell_manager.path()).map_err(|_| {
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error(
|
||||||
"Cannot load plugins from directory",
|
"Cannot load plugins from directory",
|
||||||
"directory not found",
|
"directory not found",
|
||||||
|
@@ -41,7 +41,7 @@ impl WholeStreamCommand for Command {
|
|||||||
"custom configuration source file",
|
"custom configuration source file",
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.rest(SyntaxShape::String, "source file(s) to run")
|
.rest("rest", SyntaxShape::String, "source file(s) to run")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@@ -2,11 +2,11 @@ use crate::prelude::*;
|
|||||||
use nu_engine::{script, WholeStreamCommand};
|
use nu_engine::{script, WholeStreamCommand};
|
||||||
|
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_path::expand_path;
|
use nu_path::{canonicalize, canonicalize_with};
|
||||||
use nu_protocol::{Signature, SyntaxShape};
|
use nu_protocol::{Signature, SyntaxShape};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
|
|
||||||
use std::{borrow::Cow, path::Path};
|
use std::path::Path;
|
||||||
|
|
||||||
pub struct Source;
|
pub struct Source;
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ impl WholeStreamCommand for Source {
|
|||||||
"Runs a script file in the current context."
|
"Runs a script file in the current context."
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
source(args)
|
source(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,14 +41,68 @@ impl WholeStreamCommand for Source {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn source(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
pub fn source(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let ctx = &args.context;
|
let ctx = &args.context;
|
||||||
let filename: Tagged<String> = args.req(0)?;
|
let filename: Tagged<String> = args.req(0)?;
|
||||||
|
|
||||||
|
let source_file = Path::new(&filename.item);
|
||||||
|
|
||||||
// Note: this is a special case for setting the context from a command
|
// Note: this is a special case for setting the context from a command
|
||||||
// In this case, if we don't set it now, we'll lose the scope that this
|
// In this case, if we don't set it now, we'll lose the scope that this
|
||||||
// variable should be set into.
|
// variable should be set into.
|
||||||
let contents = std::fs::read_to_string(&expand_path(Cow::Borrowed(Path::new(&filename.item))));
|
|
||||||
|
let lib_dirs = &ctx
|
||||||
|
.configs()
|
||||||
|
.lock()
|
||||||
|
.global_config
|
||||||
|
.as_ref()
|
||||||
|
.map(|configuration| match configuration.var("lib_dirs") {
|
||||||
|
Some(paths) => paths
|
||||||
|
.table_entries()
|
||||||
|
.cloned()
|
||||||
|
.map(|path| path.as_string())
|
||||||
|
.collect(),
|
||||||
|
None => vec![],
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(dir) = lib_dirs {
|
||||||
|
for lib_path in dir {
|
||||||
|
match lib_path {
|
||||||
|
Ok(name) => {
|
||||||
|
let path = canonicalize_with(&source_file, name).map_err(|e| {
|
||||||
|
ShellError::labeled_error(
|
||||||
|
format!("Can't load source file. Reason: {}", e.to_string()),
|
||||||
|
"Can't load this file",
|
||||||
|
filename.span(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if let Ok(contents) = std::fs::read_to_string(path) {
|
||||||
|
let result = script::run_script_standalone(contents, true, ctx, false);
|
||||||
|
|
||||||
|
if let Err(err) = result {
|
||||||
|
ctx.error(err);
|
||||||
|
}
|
||||||
|
return Ok(OutputStream::empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(reason) => {
|
||||||
|
ctx.error(reason.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let path = canonicalize(source_file).map_err(|e| {
|
||||||
|
ShellError::labeled_error(
|
||||||
|
format!("Can't load source file. Reason: {}", e.to_string()),
|
||||||
|
"Can't load this file",
|
||||||
|
filename.span(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let contents = std::fs::read_to_string(path);
|
||||||
|
|
||||||
match contents {
|
match contents {
|
||||||
Ok(contents) => {
|
Ok(contents) => {
|
||||||
let result = script::run_script_standalone(contents, true, ctx, false);
|
let result = script::run_script_standalone(contents, true, ctx, false);
|
||||||
@@ -56,16 +110,16 @@ pub fn source(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||||||
if let Err(err) = result {
|
if let Err(err) = result {
|
||||||
ctx.error(err);
|
ctx.error(err);
|
||||||
}
|
}
|
||||||
Ok(ActionStream::empty())
|
Ok(OutputStream::empty())
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(e) => {
|
||||||
ctx.error(ShellError::labeled_error(
|
ctx.error(ShellError::labeled_error(
|
||||||
"Can't load file to source",
|
format!("Can't load source file. Reason: {}", e.to_string()),
|
||||||
"can't load file",
|
"Can't load this file",
|
||||||
filename.span(),
|
filename.span(),
|
||||||
));
|
));
|
||||||
|
|
||||||
Ok(ActionStream::empty())
|
Ok(OutputStream::empty())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::WholeStreamCommand;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Signature, TaggedDictBuilder, UntaggedValue};
|
use nu_protocol::{Primitive, Signature, TaggedDictBuilder, UntaggedValue, Value};
|
||||||
|
|
||||||
pub struct Tags;
|
pub struct Tags;
|
||||||
|
|
||||||
@@ -18,37 +18,64 @@ impl WholeStreamCommand for Tags {
|
|||||||
"Read the tags (metadata) for values."
|
"Read the tags (metadata) for values."
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
Ok(tags(args))
|
Ok(tags(args))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tags(args: CommandArgs) -> ActionStream {
|
fn build_tag_table(tag: impl Into<Tag>) -> Value {
|
||||||
args.input
|
let tag = tag.into();
|
||||||
.map(move |v| {
|
let span = tag.span;
|
||||||
let mut tags = TaggedDictBuilder::new(v.tag());
|
|
||||||
{
|
|
||||||
let anchor = v.anchor();
|
|
||||||
let span = v.tag.span;
|
|
||||||
let mut dict = TaggedDictBuilder::new(v.tag());
|
|
||||||
dict.insert_untagged("start", UntaggedValue::int(span.start() as i64));
|
|
||||||
dict.insert_untagged("end", UntaggedValue::int(span.end() as i64));
|
|
||||||
tags.insert_value("span", dict.into_value());
|
|
||||||
|
|
||||||
match anchor {
|
TaggedDictBuilder::build(tag.clone(), |tags| {
|
||||||
Some(AnchorLocation::File(source)) => {
|
if let Some(anchor) = anchor_as_value(&tag) {
|
||||||
tags.insert_untagged("anchor", UntaggedValue::string(source));
|
tags.insert_value("anchor", anchor);
|
||||||
}
|
|
||||||
Some(AnchorLocation::Url(source)) => {
|
|
||||||
tags.insert_untagged("anchor", UntaggedValue::string(source));
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tags.into_value()
|
tags.insert_value(
|
||||||
|
"span",
|
||||||
|
TaggedDictBuilder::build(tag.clone(), |span_dict| {
|
||||||
|
span_dict.insert_untagged("start", UntaggedValue::int(span.start() as i64));
|
||||||
|
span_dict.insert_untagged("end", UntaggedValue::int(span.end() as i64));
|
||||||
|
}),
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.into_action_stream()
|
}
|
||||||
|
|
||||||
|
fn tags(args: CommandArgs) -> OutputStream {
|
||||||
|
if args.input.is_empty() {
|
||||||
|
OutputStream::one(build_tag_table(&args.name_tag()))
|
||||||
|
} else {
|
||||||
|
args.input
|
||||||
|
.map(move |v| build_tag_table(v.tag()))
|
||||||
|
.into_output_stream()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn anchor_as_value(tag: &Tag) -> Option<Value> {
|
||||||
|
let anchor = tag.anchor.as_ref();
|
||||||
|
|
||||||
|
anchor.as_ref()?;
|
||||||
|
|
||||||
|
Some(TaggedDictBuilder::build(tag, |table| {
|
||||||
|
let value = match anchor {
|
||||||
|
Some(AnchorLocation::File(path)) => {
|
||||||
|
Some(("file", UntaggedValue::from(path.to_string())))
|
||||||
|
}
|
||||||
|
Some(AnchorLocation::Url(destination)) => {
|
||||||
|
Some(("url", UntaggedValue::from(destination.to_string())))
|
||||||
|
}
|
||||||
|
Some(AnchorLocation::Source(text)) => Some((
|
||||||
|
"source",
|
||||||
|
UntaggedValue::Primitive(Primitive::String(text.to_string())),
|
||||||
|
)),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some((key, value)) = value {
|
||||||
|
table.insert_untagged(key, value);
|
||||||
|
}
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@@ -56,7 +56,7 @@ fn tutor(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
let search: Option<String> = args.opt(0).unwrap_or(None);
|
let search: Option<String> = args.opt(0).unwrap_or(None);
|
||||||
let find: Option<String> = args.get_flag("find")?;
|
let find: Option<String> = args.get_flag("find")?;
|
||||||
|
|
||||||
let search_space = vec![
|
let search_space = [
|
||||||
(vec!["begin"], begin_tutor()),
|
(vec!["begin"], begin_tutor()),
|
||||||
(
|
(
|
||||||
vec!["table", "tables", "row", "rows", "column", "columns"],
|
vec!["table", "tables", "row", "rows", "column", "columns"],
|
||||||
@@ -88,7 +88,7 @@ fn tutor(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
if let Some(find) = find {
|
if let Some(find) = find {
|
||||||
let mut results = vec![];
|
let mut results = vec![];
|
||||||
for search_group in search_space {
|
for search_group in search_space {
|
||||||
if search_group.1.contains(&find.as_str()) {
|
if search_group.1.contains(&find) {
|
||||||
results.push(search_group.0[0].to_string())
|
results.push(search_group.0[0].to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -383,7 +383,7 @@ fn display(tag: Tag, scope: &Scope, help: &str) -> OutputStream {
|
|||||||
|
|
||||||
//TODO: support no-color mode
|
//TODO: support no-color mode
|
||||||
let colored_example = nu_engine::Painter::paint_string(item, scope, &palette);
|
let colored_example = nu_engine::Painter::paint_string(item, scope, &palette);
|
||||||
build.push_str(&format!("{}", colored_example));
|
build.push_str(&colored_example);
|
||||||
} else {
|
} else {
|
||||||
code_mode = true;
|
code_mode = true;
|
||||||
build.push_str(item);
|
build.push_str(item);
|
||||||
|
@@ -245,7 +245,7 @@ fn perform_groupby_aggregation(
|
|||||||
None => &col[..],
|
None => &col[..],
|
||||||
};
|
};
|
||||||
|
|
||||||
res.rename(col.as_str(), new_col)
|
res.rename(&col, new_col)
|
||||||
.expect("Column is always there. Looping with known names");
|
.expect("Column is always there. Looping with known names");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -107,7 +107,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
let other: Value = args.req_named("other")?;
|
let other: Value = args.req_named("other")?;
|
||||||
let axis: Tagged<String> = args.req_named("axis")?;
|
let axis: Tagged<String> = args.req_named("axis")?;
|
||||||
|
|
||||||
let axis = Axis::try_from_str(axis.item.as_str(), &axis.tag.span)?;
|
let axis = Axis::try_from_str(&axis.item, &axis.tag.span)?;
|
||||||
|
|
||||||
let df_other = match other.value {
|
let df_other = match other.value {
|
||||||
UntaggedValue::DataFrame(df) => Ok(df),
|
UntaggedValue::DataFrame(df) => Ok(df),
|
||||||
|
@@ -53,7 +53,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
|
|
||||||
let res = df
|
let res = df
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.column(column.item.as_ref())
|
.column(&column.item)
|
||||||
.map_err(|e| parse_polars_error::<&str>(&e, &column.tag.span, None))?;
|
.map_err(|e| parse_polars_error::<&str>(&e, &column.tag.span, None))?;
|
||||||
|
|
||||||
let df = NuDataFrame::try_from_series(vec![res.clone()], &tag.span)?;
|
let df = NuDataFrame::try_from_series(vec![res.clone()], &tag.span)?;
|
||||||
|
@@ -195,7 +195,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
|
|
||||||
let name = format!("{} ({})", col.name(), col.dtype());
|
let name = format!("{} ({})", col.name(), col.dtype());
|
||||||
ChunkedArray::<Float64Type>::new_from_opt_slice(
|
ChunkedArray::<Float64Type>::new_from_opt_slice(
|
||||||
name.as_str(),
|
&name,
|
||||||
&[
|
&[
|
||||||
Some(count),
|
Some(count),
|
||||||
sum,
|
sum,
|
||||||
|
@@ -20,7 +20,11 @@ impl WholeStreamCommand for DataFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("dataframe drop").rest(SyntaxShape::Any, "column names to be dropped")
|
Signature::build("dataframe drop").rest(
|
||||||
|
"rest",
|
||||||
|
SyntaxShape::Any,
|
||||||
|
"column names to be dropped",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
@@ -72,7 +72,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
.expect("using name from list of names from dataframe")
|
.expect("using name from list of names from dataframe")
|
||||||
.dtype();
|
.dtype();
|
||||||
|
|
||||||
let dtype_str = format!("{}", dtype);
|
let dtype_str = dtype.to_string();
|
||||||
dtypes.push(Value {
|
dtypes.push(Value {
|
||||||
value: dtype_str.into(),
|
value: dtype_str.into(),
|
||||||
tag: Tag::default(),
|
tag: Tag::default(),
|
||||||
|
@@ -19,7 +19,11 @@ impl WholeStreamCommand for DataFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("dataframe get").rest(SyntaxShape::Any, "column names to sort dataframe")
|
Signature::build("dataframe get").rest(
|
||||||
|
"rest",
|
||||||
|
SyntaxShape::Any,
|
||||||
|
"column names to sort dataframe",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
@@ -20,7 +20,7 @@ impl WholeStreamCommand for DataFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("dataframe group-by").rest(SyntaxShape::Any, "groupby columns")
|
Signature::build("dataframe group-by").rest("rest", SyntaxShape::Any, "groupby columns")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
@@ -177,7 +177,7 @@ fn check_column_datatypes<T: AsRef<str>>(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (l, r) in l_cols.iter().zip(r_cols.iter()) {
|
for (l, r) in l_cols.iter().zip(r_cols) {
|
||||||
let l_series = df_l
|
let l_series = df_l
|
||||||
.column(l.as_ref())
|
.column(l.as_ref())
|
||||||
.map_err(|e| parse_polars_error::<&str>(&e, l_col_span, None))?;
|
.map_err(|e| parse_polars_error::<&str>(&e, l_col_span, None))?;
|
||||||
|
@@ -5,6 +5,7 @@ use nu_protocol::{
|
|||||||
dataframe::{Column, NuDataFrame},
|
dataframe::{Column, NuDataFrame},
|
||||||
Signature, SyntaxShape, UntaggedValue, Value,
|
Signature, SyntaxShape, UntaggedValue, Value,
|
||||||
};
|
};
|
||||||
|
use nu_source::Tagged;
|
||||||
|
|
||||||
use super::utils::convert_columns;
|
use super::utils::convert_columns;
|
||||||
|
|
||||||
@@ -33,6 +34,18 @@ impl WholeStreamCommand for DataFrame {
|
|||||||
"column names used as value columns",
|
"column names used as value columns",
|
||||||
Some('v'),
|
Some('v'),
|
||||||
)
|
)
|
||||||
|
.named(
|
||||||
|
"variable_name",
|
||||||
|
SyntaxShape::String,
|
||||||
|
"optional name for variable column",
|
||||||
|
Some('r'),
|
||||||
|
)
|
||||||
|
.named(
|
||||||
|
"value_name",
|
||||||
|
SyntaxShape::String,
|
||||||
|
"optional name for value column",
|
||||||
|
Some('l'),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
@@ -105,6 +118,9 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
let id_col: Vec<Value> = args.req_named("columns")?;
|
let id_col: Vec<Value> = args.req_named("columns")?;
|
||||||
let val_col: Vec<Value> = args.req_named("values")?;
|
let val_col: Vec<Value> = args.req_named("values")?;
|
||||||
|
|
||||||
|
let value_name: Option<Tagged<String>> = args.get_flag("value_name")?;
|
||||||
|
let variable_name: Option<Tagged<String>> = args.get_flag("variable_name")?;
|
||||||
|
|
||||||
let (id_col_string, id_col_span) = convert_columns(&id_col, &tag)?;
|
let (id_col_string, id_col_span) = convert_columns(&id_col, &tag)?;
|
||||||
let (val_col_string, val_col_span) = convert_columns(&val_col, &tag)?;
|
let (val_col_string, val_col_span) = convert_columns(&val_col, &tag)?;
|
||||||
|
|
||||||
@@ -113,11 +129,21 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
check_column_datatypes(df.as_ref(), &id_col_string, &id_col_span)?;
|
check_column_datatypes(df.as_ref(), &id_col_string, &id_col_span)?;
|
||||||
check_column_datatypes(df.as_ref(), &val_col_string, &val_col_span)?;
|
check_column_datatypes(df.as_ref(), &val_col_string, &val_col_span)?;
|
||||||
|
|
||||||
let res = df
|
let mut res = df
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.melt(&id_col_string, &val_col_string)
|
.melt(&id_col_string, &val_col_string)
|
||||||
.map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?;
|
.map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?;
|
||||||
|
|
||||||
|
if let Some(name) = &variable_name {
|
||||||
|
res.rename("variable", &name.item)
|
||||||
|
.map_err(|e| parse_polars_error::<&str>(&e, &name.tag.span, None))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(name) = &value_name {
|
||||||
|
res.rename("value", &name.item)
|
||||||
|
.map_err(|e| parse_polars_error::<&str>(&e, &name.tag.span, None))?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag)))
|
Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,6 +18,7 @@ pub mod list;
|
|||||||
pub mod melt;
|
pub mod melt;
|
||||||
pub mod open;
|
pub mod open;
|
||||||
pub mod pivot;
|
pub mod pivot;
|
||||||
|
pub mod rename;
|
||||||
pub mod sample;
|
pub mod sample;
|
||||||
pub mod select;
|
pub mod select;
|
||||||
pub mod shape;
|
pub mod shape;
|
||||||
@@ -52,6 +53,7 @@ pub use list::DataFrame as DataFrameList;
|
|||||||
pub use melt::DataFrame as DataFrameMelt;
|
pub use melt::DataFrame as DataFrameMelt;
|
||||||
pub use open::DataFrame as DataFrameOpen;
|
pub use open::DataFrame as DataFrameOpen;
|
||||||
pub use pivot::DataFrame as DataFramePivot;
|
pub use pivot::DataFrame as DataFramePivot;
|
||||||
|
pub use rename::DataFrame as DataFrameRename;
|
||||||
pub use sample::DataFrame as DataFrameSample;
|
pub use sample::DataFrame as DataFrameSample;
|
||||||
pub use select::DataFrame as DataFrameSelect;
|
pub use select::DataFrame as DataFrameSelect;
|
||||||
pub use shape::DataFrame as DataFrameShape;
|
pub use shape::DataFrame as DataFrameShape;
|
||||||
|
@@ -100,7 +100,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
|
|
||||||
let mut groupby = nu_groupby.to_groupby()?;
|
let mut groupby = nu_groupby.to_groupby()?;
|
||||||
|
|
||||||
let pivot = groupby.pivot(pivot_col.item.as_ref(), value_col.item.as_ref());
|
let pivot = groupby.pivot(&pivot_col.item, &value_col.item);
|
||||||
|
|
||||||
let res = match op {
|
let res = match op {
|
||||||
Operation::Mean => pivot.mean(),
|
Operation::Mean => pivot.mean(),
|
||||||
@@ -120,7 +120,7 @@ fn check_pivot_column(
|
|||||||
col: &Tagged<String>,
|
col: &Tagged<String>,
|
||||||
) -> Result<(), ShellError> {
|
) -> Result<(), ShellError> {
|
||||||
let series = df
|
let series = df
|
||||||
.column(col.item.as_ref())
|
.column(&col.item)
|
||||||
.map_err(|e| parse_polars_error::<&str>(&e, &col.tag.span, None))?;
|
.map_err(|e| parse_polars_error::<&str>(&e, &col.tag.span, None))?;
|
||||||
|
|
||||||
match series.dtype() {
|
match series.dtype() {
|
||||||
@@ -146,7 +146,7 @@ fn check_value_column(
|
|||||||
col: &Tagged<String>,
|
col: &Tagged<String>,
|
||||||
) -> Result<(), ShellError> {
|
) -> Result<(), ShellError> {
|
||||||
let series = df
|
let series = df
|
||||||
.column(col.item.as_ref())
|
.column(&col.item)
|
||||||
.map_err(|e| parse_polars_error::<&str>(&e, &col.tag.span, None))?;
|
.map_err(|e| parse_polars_error::<&str>(&e, &col.tag.span, None))?;
|
||||||
|
|
||||||
match series.dtype() {
|
match series.dtype() {
|
||||||
|
81
crates/nu-command/src/commands/dataframe/rename.rs
Normal file
81
crates/nu-command/src/commands/dataframe/rename.rs
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
|
use nu_engine::WholeStreamCommand;
|
||||||
|
use nu_errors::ShellError;
|
||||||
|
use nu_protocol::{
|
||||||
|
dataframe::{Column, NuDataFrame},
|
||||||
|
Signature, SyntaxShape, UntaggedValue,
|
||||||
|
};
|
||||||
|
|
||||||
|
use nu_source::Tagged;
|
||||||
|
|
||||||
|
use super::utils::parse_polars_error;
|
||||||
|
pub struct DataFrame;
|
||||||
|
|
||||||
|
impl WholeStreamCommand for DataFrame {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"dataframe rename-col"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(&self) -> &str {
|
||||||
|
"[DataFrame] rename a dataframe column"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build("dataframe rename-col")
|
||||||
|
.required("from", SyntaxShape::String, "column name to be renamed")
|
||||||
|
.required("to", SyntaxShape::String, "new column name")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
command(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
vec![Example {
|
||||||
|
description: "Renames a dataframe column",
|
||||||
|
example: "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe rename-col a ab",
|
||||||
|
result: Some(vec![NuDataFrame::try_from_columns(
|
||||||
|
vec![
|
||||||
|
Column::new(
|
||||||
|
"ab".to_string(),
|
||||||
|
vec![UntaggedValue::int(1).into(), UntaggedValue::int(3).into()],
|
||||||
|
),
|
||||||
|
Column::new(
|
||||||
|
"b".to_string(),
|
||||||
|
vec![UntaggedValue::int(2).into(), UntaggedValue::int(4).into()],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
&Span::default(),
|
||||||
|
)
|
||||||
|
.expect("simple df for test should not fail")
|
||||||
|
.into_value(Tag::default())]),
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
let tag = args.call_info.name_tag.clone();
|
||||||
|
let from: Tagged<String> = args.req(0)?;
|
||||||
|
let to: Tagged<String> = args.req(1)?;
|
||||||
|
|
||||||
|
let (mut df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?;
|
||||||
|
|
||||||
|
df.as_mut()
|
||||||
|
.rename(&from.item, &to.item)
|
||||||
|
.map_err(|e| parse_polars_error::<&str>(&e, &df_tag.span, None))?;
|
||||||
|
|
||||||
|
Ok(OutputStream::one(df.into_value(tag)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::DataFrame;
|
||||||
|
use super::ShellError;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn examples_work_as_expected() -> Result<(), ShellError> {
|
||||||
|
use crate::examples::test_dataframe as test_examples;
|
||||||
|
|
||||||
|
test_examples(DataFrame {})
|
||||||
|
}
|
||||||
|
}
|
@@ -20,7 +20,7 @@ impl WholeStreamCommand for DataFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("dataframe select").rest(SyntaxShape::Any, "selected column names")
|
Signature::build("dataframe select").rest("rest", SyntaxShape::Any, "selected column names")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
@@ -68,7 +68,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let res = chunked
|
let res = chunked
|
||||||
.contains(pattern.as_str())
|
.contains(&pattern.item)
|
||||||
.map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?;
|
.map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?;
|
||||||
|
|
||||||
let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?;
|
let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?;
|
||||||
|
@@ -99,7 +99,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let cum_type = CumType::from_str(cum_type.item.as_str(), &cum_type.tag.span)?;
|
let cum_type = CumType::from_str(&cum_type.item, &cum_type.tag.span)?;
|
||||||
let mut res = match cum_type {
|
let mut res = match cum_type {
|
||||||
CumType::Max => series.cum_max(reverse),
|
CumType::Max => series.cum_max(reverse),
|
||||||
CumType::Min => series.cum_min(reverse),
|
CumType::Min => series.cum_min(reverse),
|
||||||
|
@@ -60,7 +60,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
|
|
||||||
let mut series = df.as_series(&df_tag.span)?;
|
let mut series = df.as_series(&df_tag.span)?;
|
||||||
|
|
||||||
series.rename(name.item.as_ref());
|
series.rename(&name.item);
|
||||||
|
|
||||||
let df = NuDataFrame::try_from_series(vec![series], &tag.span)?;
|
let df = NuDataFrame::try_from_series(vec![series], &tag.span)?;
|
||||||
Ok(OutputStream::one(df.into_value(df_tag)))
|
Ok(OutputStream::one(df.into_value(df_tag)))
|
||||||
|
@@ -77,7 +77,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let mut res = chunked
|
let mut res = chunked
|
||||||
.replace(pattern.as_str(), replace.as_str())
|
.replace(&pattern.item, &replace.item)
|
||||||
.map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?;
|
.map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?;
|
||||||
|
|
||||||
res.rename(series.name());
|
res.rename(series.name());
|
||||||
|
@@ -77,7 +77,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let mut res = chunked
|
let mut res = chunked
|
||||||
.replace_all(pattern.as_str(), replace.as_str())
|
.replace_all(&pattern.item, &replace.item)
|
||||||
.map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?;
|
.map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?;
|
||||||
|
|
||||||
res.rename(series.name());
|
res.rename(series.name());
|
||||||
|
@@ -125,7 +125,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let roll_type = RollType::from_str(roll_type.item.as_str(), &roll_type.tag.span)?;
|
let roll_type = RollType::from_str(&roll_type.item, &roll_type.tag.span)?;
|
||||||
let res = match roll_type {
|
let res = match roll_type {
|
||||||
RollType::Max => series.rolling_max(
|
RollType::Max => series.rolling_max(
|
||||||
window_size.item as u32,
|
window_size.item as u32,
|
||||||
|
@@ -61,7 +61,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
.date64()
|
.date64()
|
||||||
.map_err(|e| parse_polars_error::<&str>(&e, &df_tag.span, None))?;
|
.map_err(|e| parse_polars_error::<&str>(&e, &df_tag.span, None))?;
|
||||||
|
|
||||||
let res = casted.strftime(fmt.item.as_str()).into_series();
|
let res = casted.strftime(&fmt.item).into_series();
|
||||||
let df = NuDataFrame::try_from_series(vec![res], &tag.span)?;
|
let df = NuDataFrame::try_from_series(vec![res], &tag.span)?;
|
||||||
Ok(OutputStream::one(df.into_value(df_tag)))
|
Ok(OutputStream::one(df.into_value(df_tag)))
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,7 @@ impl WholeStreamCommand for DataFrame {
|
|||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("dataframe sort")
|
Signature::build("dataframe sort")
|
||||||
.switch("reverse", "invert sort", Some('r'))
|
.switch("reverse", "invert sort", Some('r'))
|
||||||
.rest(SyntaxShape::Any, "column names to sort dataframe")
|
.rest("rest", SyntaxShape::Any, "column names to sort dataframe")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
@@ -64,14 +64,10 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
let delimiter: Option<Tagged<String>> = args.get_flag("delimiter")?;
|
let delimiter: Option<Tagged<String>> = args.get_flag("delimiter")?;
|
||||||
let no_header: bool = args.has_flag("no_header");
|
let no_header: bool = args.has_flag("no_header");
|
||||||
|
|
||||||
let (mut df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?;
|
let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?;
|
||||||
|
|
||||||
let mut file = File::create(&file_name.item).map_err(|e| {
|
let mut file = File::create(&file_name.item).map_err(|e| {
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error("Error with file name", e.to_string(), &file_name.tag.span)
|
||||||
"Error with file name",
|
|
||||||
format!("{}", e),
|
|
||||||
&file_name.tag.span,
|
|
||||||
)
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let writer = CsvWriter::new(&mut file);
|
let writer = CsvWriter::new(&mut file);
|
||||||
@@ -103,7 +99,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
writer
|
writer
|
||||||
.finish(df.as_mut())
|
.finish(df.as_ref())
|
||||||
.map_err(|e| parse_polars_error::<&str>(&e, &file_name.tag.span, None))?;
|
.map_err(|e| parse_polars_error::<&str>(&e, &file_name.tag.span, None))?;
|
||||||
|
|
||||||
let tagged_value = Value {
|
let tagged_value = Value {
|
||||||
|
@@ -48,18 +48,14 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
let tag = args.call_info.name_tag.clone();
|
let tag = args.call_info.name_tag.clone();
|
||||||
let file_name: Tagged<PathBuf> = args.req(0)?;
|
let file_name: Tagged<PathBuf> = args.req(0)?;
|
||||||
|
|
||||||
let (mut df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?;
|
let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?;
|
||||||
|
|
||||||
let file = File::create(&file_name.item).map_err(|e| {
|
let file = File::create(&file_name.item).map_err(|e| {
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error("Error with file name", e.to_string(), &file_name.tag.span)
|
||||||
"Error with file name",
|
|
||||||
format!("{}", e),
|
|
||||||
&file_name.tag.span,
|
|
||||||
)
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
ParquetWriter::new(file)
|
ParquetWriter::new(file)
|
||||||
.finish(df.as_mut())
|
.finish(df.as_ref())
|
||||||
.map_err(|e| parse_polars_error::<&str>(&e, &file_name.tag.span, None))?;
|
.map_err(|e| parse_polars_error::<&str>(&e, &file_name.tag.span, None))?;
|
||||||
|
|
||||||
let tagged_value = Value {
|
let tagged_value = Value {
|
||||||
|
@@ -46,30 +46,32 @@ pub(crate) fn parse_polars_error<T: AsRef<str>>(
|
|||||||
span: &Span,
|
span: &Span,
|
||||||
secondary: Option<T>,
|
secondary: Option<T>,
|
||||||
) -> ShellError {
|
) -> ShellError {
|
||||||
let (msg, label) = match e {
|
let msg = match e {
|
||||||
PolarsError::PolarsArrowError(_) => ("PolarsArrow Error", format!("{}", e)),
|
PolarsError::PolarsArrowError(_) => "PolarsArrow Error",
|
||||||
PolarsError::ArrowError(_) => ("Arrow Error", format!("{}", e)),
|
PolarsError::ArrowError(_) => "Arrow Error",
|
||||||
PolarsError::InvalidOperation(_) => ("Invalid Operation", format!("{}", e)),
|
PolarsError::InvalidOperation(_) => "Invalid Operation",
|
||||||
PolarsError::DataTypeMisMatch(_) => ("Data Type Mismatch", format!("{}", e)),
|
PolarsError::DataTypeMisMatch(_) => "Data Type Mismatch",
|
||||||
PolarsError::NotFound(_) => ("Not Found", format!("{}", e)),
|
PolarsError::NotFound(_) => "Not Found",
|
||||||
PolarsError::ShapeMisMatch(_) => ("Shape Mismatch", format!("{}", e)),
|
PolarsError::ShapeMisMatch(_) => "Shape Mismatch",
|
||||||
PolarsError::Other(_) => ("Other", format!("{}", e)),
|
PolarsError::Other(_) => "Other",
|
||||||
PolarsError::OutOfBounds(_) => ("Out Of Bounds", format!("{}", e)),
|
PolarsError::OutOfBounds(_) => "Out Of Bounds",
|
||||||
PolarsError::NoSlice => ("No Slice", format!("{}", e)),
|
PolarsError::NoSlice => "No Slice",
|
||||||
PolarsError::NoData(_) => ("No Data", format!("{}", e)),
|
PolarsError::NoData(_) => "No Data",
|
||||||
PolarsError::ValueError(_) => ("Value Error", format!("{}", e)),
|
PolarsError::ValueError(_) => "Value Error",
|
||||||
PolarsError::MemoryNotAligned => ("Memory Not Aligned", format!("{}", e)),
|
PolarsError::MemoryNotAligned => "Memory Not Aligned",
|
||||||
PolarsError::ParquetError(_) => ("Parquet Error", format!("{}", e)),
|
PolarsError::ParquetError(_) => "Parquet Error",
|
||||||
PolarsError::RandError(_) => ("Rand Error", format!("{}", e)),
|
PolarsError::RandError(_) => "Rand Error",
|
||||||
PolarsError::HasNullValues(_) => ("Has Null Values", format!("{}", e)),
|
PolarsError::HasNullValues(_) => "Has Null Values",
|
||||||
PolarsError::UnknownSchema(_) => ("Unknown Schema", format!("{}", e)),
|
PolarsError::UnknownSchema(_) => "Unknown Schema",
|
||||||
PolarsError::Various(_) => ("Various", format!("{}", e)),
|
PolarsError::Various(_) => "Various",
|
||||||
PolarsError::Io(_) => ("Io Error", format!("{}", e)),
|
PolarsError::Io(_) => "Io Error",
|
||||||
PolarsError::Regex(_) => ("Regex Error", format!("{}", e)),
|
PolarsError::Regex(_) => "Regex Error",
|
||||||
PolarsError::Duplicate(_) => ("Duplicate Error", format!("{}", e)),
|
PolarsError::Duplicate(_) => "Duplicate Error",
|
||||||
PolarsError::ImplementationError => ("Implementation Error", format!("{}", e)),
|
PolarsError::ImplementationError => "Implementation Error",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let label = e.to_string();
|
||||||
|
|
||||||
match secondary {
|
match secondary {
|
||||||
None => ShellError::labeled_error(msg, label, span),
|
None => ShellError::labeled_error(msg, label, span),
|
||||||
Some(s) => ShellError::labeled_error_with_secondary(msg, label, span, s.as_ref(), span),
|
Some(s) => ShellError::labeled_error_with_secondary(msg, label, span, s.as_ref(), span),
|
||||||
|
@@ -82,7 +82,7 @@ fn command(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
|
|
||||||
let mut series = df.as_series(&value.tag.span)?;
|
let mut series = df.as_series(&value.tag.span)?;
|
||||||
|
|
||||||
let series = series.rename(name.item.as_ref()).clone();
|
let series = series.rename(&name.item).clone();
|
||||||
|
|
||||||
let (mut df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?;
|
let (mut df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?;
|
||||||
|
|
||||||
|
@@ -31,12 +31,12 @@ impl WholeStreamCommand for AutoenvTrust {
|
|||||||
value: UntaggedValue::Primitive(Primitive::String(ref path)),
|
value: UntaggedValue::Primitive(Primitive::String(ref path)),
|
||||||
tag: _,
|
tag: _,
|
||||||
}) => {
|
}) => {
|
||||||
let mut dir = fs::canonicalize(path)?;
|
let mut dir = nu_path::canonicalize(path)?;
|
||||||
dir.push(".nu-env");
|
dir.push(".nu-env");
|
||||||
dir
|
dir
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let mut dir = fs::canonicalize(std::env::current_dir()?)?;
|
let mut dir = nu_path::canonicalize(std::env::current_dir()?)?;
|
||||||
dir.push(".nu-env");
|
dir.push(".nu-env");
|
||||||
dir
|
dir
|
||||||
}
|
}
|
||||||
|
@@ -30,7 +30,7 @@ impl WholeStreamCommand for AutoenvUntrust {
|
|||||||
value: UntaggedValue::Primitive(Primitive::String(ref path)),
|
value: UntaggedValue::Primitive(Primitive::String(ref path)),
|
||||||
tag: _,
|
tag: _,
|
||||||
}) => {
|
}) => {
|
||||||
let mut dir = fs::canonicalize(path)?;
|
let mut dir = nu_path::canonicalize(path)?;
|
||||||
dir.push(".nu-env");
|
dir.push(".nu-env");
|
||||||
dir
|
dir
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ impl WholeStreamCommand for AutoenvUntrust {
|
|||||||
let mut doc = String::new();
|
let mut doc = String::new();
|
||||||
file.read_to_string(&mut doc)?;
|
file.read_to_string(&mut doc)?;
|
||||||
|
|
||||||
let mut allowed: Trusted = toml::from_str(doc.as_str()).unwrap_or_else(|_| Trusted::new());
|
let mut allowed: Trusted = toml::from_str(&doc).unwrap_or_else(|_| Trusted::new());
|
||||||
|
|
||||||
let file_to_untrust = file_to_untrust.to_string_lossy().to_string();
|
let file_to_untrust = file_to_untrust.to_string_lossy().to_string();
|
||||||
|
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_engine::{evaluate_baseline_expr, WholeStreamCommand};
|
use nu_engine::{evaluate_baseline_expr, EnvVar, WholeStreamCommand};
|
||||||
|
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{hir::CapturedBlock, hir::ClassifiedCommand, Signature, SyntaxShape};
|
use nu_protocol::{hir::CapturedBlock, hir::ClassifiedCommand, Signature, SyntaxShape};
|
||||||
@@ -90,9 +92,7 @@ pub fn set_env(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||||||
|
|
||||||
ctx.scope.exit_scope();
|
ctx.scope.exit_scope();
|
||||||
|
|
||||||
let value = value?;
|
let value: EnvVar = value?.try_into()?;
|
||||||
let value = value.as_string()?;
|
|
||||||
|
|
||||||
let name = name.item;
|
let name = name.item;
|
||||||
|
|
||||||
// Note: this is a special case for setting the context from a command
|
// Note: this is a special case for setting the context from a command
|
||||||
|
13
crates/nu-command/src/commands/env/load_env.rs
vendored
13
crates/nu-command/src/commands/env/load_env.rs
vendored
@@ -1,5 +1,7 @@
|
|||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::{EnvVar, WholeStreamCommand};
|
||||||
|
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
use nu_protocol::{Signature, SyntaxShape, Value};
|
||||||
@@ -60,14 +62,17 @@ fn load_env_from_table(
|
|||||||
|
|
||||||
for (key, value) in value.row_entries() {
|
for (key, value) in value.row_entries() {
|
||||||
if key == "name" {
|
if key == "name" {
|
||||||
var_name = Some(value.as_string()?);
|
var_name = Some(value);
|
||||||
} else if key == "value" {
|
} else if key == "value" {
|
||||||
var_value = Some(value.as_string()?);
|
var_value = Some(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match (var_name, var_value) {
|
match (var_name, var_value) {
|
||||||
(Some(name), Some(value)) => ctx.scope.add_env_var(name, value),
|
(Some(name), Some(value)) => {
|
||||||
|
let env_var: EnvVar = value.try_into()?;
|
||||||
|
ctx.scope.add_env_var(name.as_string()?, env_var);
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
r#"Expected each row in the table to have a "name" and "value" field."#,
|
r#"Expected each row in the table to have a "name" and "value" field."#,
|
||||||
|
11
crates/nu-command/src/commands/env/with_env.rs
vendored
11
crates/nu-command/src/commands/env/with_env.rs
vendored
@@ -1,5 +1,8 @@
|
|||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_engine::run_block;
|
use nu_engine::run_block;
|
||||||
|
use nu_engine::EnvVar;
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::WholeStreamCommand;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
@@ -73,20 +76,20 @@ fn with_env(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||||||
let variable: Value = args.req(0)?;
|
let variable: Value = args.req(0)?;
|
||||||
let block: CapturedBlock = args.req(1)?;
|
let block: CapturedBlock = args.req(1)?;
|
||||||
|
|
||||||
let mut env = IndexMap::new();
|
let mut env: IndexMap<String, EnvVar> = IndexMap::new();
|
||||||
|
|
||||||
match &variable.value {
|
match &variable.value {
|
||||||
UntaggedValue::Table(table) => {
|
UntaggedValue::Table(table) => {
|
||||||
if table.len() == 1 {
|
if table.len() == 1 {
|
||||||
// single row([[X W]; [Y Z]])
|
// single row([[X W]; [Y Z]])
|
||||||
for (k, v) in table[0].row_entries() {
|
for (k, v) in table[0].row_entries() {
|
||||||
env.insert(k.clone(), v.convert_to_string());
|
env.insert(k.clone(), v.try_into()?);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// primitive values([X Y W Z])
|
// primitive values([X Y W Z])
|
||||||
for row in table.chunks(2) {
|
for row in table.chunks(2) {
|
||||||
if row.len() == 2 && row[0].is_primitive() && row[1].is_primitive() {
|
if row.len() == 2 && row[0].is_primitive() && row[1].is_primitive() {
|
||||||
env.insert(row[0].convert_to_string(), row[1].convert_to_string());
|
env.insert(row[0].convert_to_string(), (&row[1]).try_into()?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,7 +97,7 @@ fn with_env(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||||||
// when get object by `open x.json` or `from json`
|
// when get object by `open x.json` or `from json`
|
||||||
UntaggedValue::Row(row) => {
|
UntaggedValue::Row(row) => {
|
||||||
for (k, v) in &row.entries {
|
for (k, v) in &row.entries {
|
||||||
env.insert(k.clone(), v.convert_to_string());
|
env.insert(k.clone(), v.try_into()?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@@ -12,6 +12,7 @@ impl WholeStreamCommand for Mkdir {
|
|||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("mkdir")
|
Signature::build("mkdir")
|
||||||
.rest(
|
.rest(
|
||||||
|
"rest",
|
||||||
SyntaxShape::FilePath,
|
SyntaxShape::FilePath,
|
||||||
"the name(s) of the path(s) to create",
|
"the name(s) of the path(s) to create",
|
||||||
)
|
)
|
||||||
|
@@ -6,6 +6,7 @@ use log::debug;
|
|||||||
use nu_engine::StringOrBinary;
|
use nu_engine::StringOrBinary;
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::WholeStreamCommand;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
|
use nu_path::canonicalize;
|
||||||
use nu_protocol::{CommandAction, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{CommandAction, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||||
use nu_source::{AnchorLocation, Span, Tagged};
|
use nu_source::{AnchorLocation, Span, Tagged};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
@@ -172,9 +173,9 @@ fn open(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||||||
Ok(StringOrBinary::String(s)) => {
|
Ok(StringOrBinary::String(s)) => {
|
||||||
ReturnSuccess::value(UntaggedValue::string(s).into_value(file_tag))
|
ReturnSuccess::value(UntaggedValue::string(s).into_value(file_tag))
|
||||||
}
|
}
|
||||||
Ok(StringOrBinary::Binary(b)) => ReturnSuccess::value(
|
Ok(StringOrBinary::Binary(b)) => {
|
||||||
UntaggedValue::binary(b.into_iter().collect()).into_value(file_tag),
|
ReturnSuccess::value(UntaggedValue::binary(b).into_value(file_tag))
|
||||||
),
|
}
|
||||||
Err(se) => Err(se),
|
Err(se) => Err(se),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -193,7 +194,7 @@ pub fn fetch(
|
|||||||
// TODO: I don't understand the point of this? Maybe for better error reporting
|
// TODO: I don't understand the point of this? Maybe for better error reporting
|
||||||
let mut cwd = PathBuf::from(cwd);
|
let mut cwd = PathBuf::from(cwd);
|
||||||
cwd.push(location);
|
cwd.push(location);
|
||||||
let nice_location = dunce::canonicalize(&cwd).map_err(|e| match e.kind() {
|
let nice_location = canonicalize(&cwd).map_err(|e| match e.kind() {
|
||||||
std::io::ErrorKind::NotFound => ShellError::labeled_error(
|
std::io::ErrorKind::NotFound => ShellError::labeled_error(
|
||||||
format!("Cannot find file {:?}", cwd),
|
format!("Cannot find file {:?}", cwd),
|
||||||
"cannot find file",
|
"cannot find file",
|
||||||
|
@@ -26,7 +26,11 @@ impl WholeStreamCommand for Remove {
|
|||||||
)
|
)
|
||||||
.switch("recursive", "delete subdirectories recursively", Some('r'))
|
.switch("recursive", "delete subdirectories recursively", Some('r'))
|
||||||
.switch("force", "suppress error when no file", Some('f'))
|
.switch("force", "suppress error when no file", Some('f'))
|
||||||
.rest(SyntaxShape::GlobPattern, "the file path(s) to remove")
|
.rest(
|
||||||
|
"rest",
|
||||||
|
SyntaxShape::GlobPattern,
|
||||||
|
"the file path(s) to remove",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@@ -142,6 +142,7 @@ impl WholeStreamCommand for Save {
|
|||||||
"treat values as-is rather than auto-converting based on file extension",
|
"treat values as-is rather than auto-converting based on file extension",
|
||||||
Some('r'),
|
Some('r'),
|
||||||
)
|
)
|
||||||
|
.switch("append", "append values rather than overriding", Some('a'))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
@@ -165,6 +166,7 @@ fn save(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
|
|
||||||
let path: Option<Tagged<PathBuf>> = args.opt(0)?;
|
let path: Option<Tagged<PathBuf>> = args.opt(0)?;
|
||||||
let save_raw = args.has_flag("raw");
|
let save_raw = args.has_flag("raw");
|
||||||
|
let append = args.has_flag("append");
|
||||||
|
|
||||||
let input: Vec<Value> = args.input.collect();
|
let input: Vec<Value> = args.input.collect();
|
||||||
if path.is_none() {
|
if path.is_none() {
|
||||||
@@ -231,7 +233,7 @@ fn save(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
shell_manager.save(&full_path, &content?, name.span)
|
shell_manager.save(&full_path, &content?, name.span, append)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string_from(input: &[Value]) -> String {
|
fn string_from(input: &[Value]) -> String {
|
||||||
@@ -239,7 +241,7 @@ fn string_from(input: &[Value]) -> String {
|
|||||||
|
|
||||||
if !input.is_empty() {
|
if !input.is_empty() {
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for i in input.iter() {
|
for i in input {
|
||||||
if !first {
|
if !first {
|
||||||
save_data.push('\n');
|
save_data.push('\n');
|
||||||
} else {
|
} else {
|
||||||
|
@@ -19,7 +19,7 @@ impl WholeStreamCommand for Touch {
|
|||||||
SyntaxShape::FilePath,
|
SyntaxShape::FilePath,
|
||||||
"the path of the file you want to create",
|
"the path of the file you want to create",
|
||||||
)
|
)
|
||||||
.rest(SyntaxShape::FilePath, "additional files to create")
|
.rest("rest", SyntaxShape::FilePath, "additional files to create")
|
||||||
}
|
}
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
"Creates one or more files."
|
"Creates one or more files."
|
||||||
@@ -48,7 +48,7 @@ fn touch(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||||||
let target: Tagged<PathBuf> = args.req(0)?;
|
let target: Tagged<PathBuf> = args.req(0)?;
|
||||||
let rest: Vec<Tagged<PathBuf>> = args.rest(1)?;
|
let rest: Vec<Tagged<PathBuf>> = args.rest(1)?;
|
||||||
|
|
||||||
for item in vec![target].into_iter().chain(rest.into_iter()) {
|
for item in vec![target].into_iter().chain(rest) {
|
||||||
match OpenOptions::new().write(true).create(true).open(&item) {
|
match OpenOptions::new().write(true).create(true).open(&item) {
|
||||||
Ok(_) => continue,
|
Ok(_) => continue,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@@ -45,7 +45,7 @@ impl WholeStreamCommand for Command {
|
|||||||
|
|
||||||
Ok(prepend
|
Ok(prepend
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(args.input.into_iter().chain(vec![value]))
|
.chain(args.input.into_iter().chain([value]))
|
||||||
.into_output_stream())
|
.into_output_stream())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -17,7 +17,11 @@ impl WholeStreamCommand for Compact {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("compact").rest(SyntaxShape::Any, "the columns to compact from the table")
|
Signature::build("compact").rest(
|
||||||
|
"rest",
|
||||||
|
SyntaxShape::Any,
|
||||||
|
"the columns to compact from the table",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@@ -18,7 +18,7 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
SyntaxShape::Int,
|
SyntaxShape::Int,
|
||||||
"the number of the row to drop",
|
"the number of the row to drop",
|
||||||
)
|
)
|
||||||
.rest(SyntaxShape::Any, "Optionally drop more rows")
|
.rest("rest", SyntaxShape::Any, "Optionally drop more rows")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@@ -69,7 +69,7 @@ impl WholeStreamCommand for Each {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_row(
|
pub fn process_row(
|
||||||
captured_block: Arc<Box<CapturedBlock>>,
|
captured_block: Arc<CapturedBlock>,
|
||||||
context: Arc<EvaluationContext>,
|
context: Arc<EvaluationContext>,
|
||||||
input: Value,
|
input: Value,
|
||||||
external_redirection: ExternalRedirection,
|
external_redirection: ExternalRedirection,
|
||||||
@@ -96,7 +96,7 @@ pub fn process_row(
|
|||||||
|
|
||||||
let result = run_block(
|
let result = run_block(
|
||||||
&captured_block.block,
|
&captured_block.block,
|
||||||
&*context,
|
&context,
|
||||||
input_stream,
|
input_stream,
|
||||||
external_redirection,
|
external_redirection,
|
||||||
);
|
);
|
||||||
@@ -121,13 +121,13 @@ fn each(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
let block: CapturedBlock = args.req(0)?;
|
let block: CapturedBlock = args.req(0)?;
|
||||||
let numbered: bool = args.has_flag("numbered");
|
let numbered: bool = args.has_flag("numbered");
|
||||||
|
|
||||||
let block = Arc::new(Box::new(block));
|
let block = Arc::new(block);
|
||||||
|
|
||||||
if numbered {
|
if numbered {
|
||||||
Ok(args
|
Ok(args
|
||||||
.input
|
.input
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(move |input| {
|
.flat_map(move |input| {
|
||||||
let block = block.clone();
|
let block = block.clone();
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
let row = make_indexed_item(input.0, input.1);
|
let row = make_indexed_item(input.0, input.1);
|
||||||
@@ -137,12 +137,11 @@ fn each(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
Err(e) => OutputStream::one(Value::error(e)),
|
Err(e) => OutputStream::one(Value::error(e)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.flatten()
|
|
||||||
.into_output_stream())
|
.into_output_stream())
|
||||||
} else {
|
} else {
|
||||||
Ok(args
|
Ok(args
|
||||||
.input
|
.input
|
||||||
.map(move |input| {
|
.flat_map(move |input| {
|
||||||
let block = block.clone();
|
let block = block.clone();
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
|
|
||||||
@@ -151,7 +150,6 @@ fn each(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
Err(e) => OutputStream::one(Value::error(e)),
|
Err(e) => OutputStream::one(Value::error(e)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.flatten()
|
|
||||||
.into_output_stream())
|
.into_output_stream())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -43,7 +43,7 @@ impl WholeStreamCommand for EachGroup {
|
|||||||
|
|
||||||
let group_size: Tagged<usize> = args.req(0)?;
|
let group_size: Tagged<usize> = args.req(0)?;
|
||||||
let block: CapturedBlock = args.req(1)?;
|
let block: CapturedBlock = args.req(1)?;
|
||||||
let block = Arc::new(Box::new(block));
|
let block = Arc::new(block);
|
||||||
|
|
||||||
let each_group_iterator = EachGroupIterator {
|
let each_group_iterator = EachGroupIterator {
|
||||||
block,
|
block,
|
||||||
@@ -58,7 +58,7 @@ impl WholeStreamCommand for EachGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct EachGroupIterator {
|
struct EachGroupIterator {
|
||||||
block: Arc<Box<CapturedBlock>>,
|
block: Arc<CapturedBlock>,
|
||||||
context: Arc<EvaluationContext>,
|
context: Arc<EvaluationContext>,
|
||||||
group_size: usize,
|
group_size: usize,
|
||||||
input: InputStream,
|
input: InputStream,
|
||||||
@@ -96,7 +96,7 @@ impl Iterator for EachGroupIterator {
|
|||||||
|
|
||||||
pub(crate) fn run_block_on_vec(
|
pub(crate) fn run_block_on_vec(
|
||||||
input: Vec<Value>,
|
input: Vec<Value>,
|
||||||
block: Arc<Box<CapturedBlock>>,
|
block: Arc<CapturedBlock>,
|
||||||
context: Arc<EvaluationContext>,
|
context: Arc<EvaluationContext>,
|
||||||
external_redirection: ExternalRedirection,
|
external_redirection: ExternalRedirection,
|
||||||
) -> OutputStream {
|
) -> OutputStream {
|
||||||
|
@@ -49,7 +49,7 @@ impl WholeStreamCommand for EachWindow {
|
|||||||
let block: CapturedBlock = args.req(1)?;
|
let block: CapturedBlock = args.req(1)?;
|
||||||
let stride: Option<Tagged<usize>> = args.get_flag("stride")?;
|
let stride: Option<Tagged<usize>> = args.get_flag("stride")?;
|
||||||
|
|
||||||
let block = Arc::new(Box::new(block));
|
let block = Arc::new(block);
|
||||||
|
|
||||||
let mut window: Vec<_> = args
|
let mut window: Vec<_> = args
|
||||||
.input
|
.input
|
||||||
@@ -64,7 +64,7 @@ impl WholeStreamCommand for EachWindow {
|
|||||||
Ok(args
|
Ok(args
|
||||||
.input
|
.input
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(move |(i, input)| {
|
.flat_map(move |(i, input)| {
|
||||||
// This would probably be more efficient if `last` was a VecDeque
|
// This would probably be more efficient if `last` was a VecDeque
|
||||||
// But we can't have that because it needs to be put into a Table
|
// But we can't have that because it needs to be put into a Table
|
||||||
window.remove(0);
|
window.remove(0);
|
||||||
@@ -86,7 +86,6 @@ impl WholeStreamCommand for EachWindow {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.flatten()
|
.flatten()
|
||||||
.flatten()
|
|
||||||
.map(Ok)
|
.map(Ok)
|
||||||
.into_input_stream())
|
.into_input_stream())
|
||||||
}
|
}
|
||||||
|
@@ -19,6 +19,7 @@ impl WholeStreamCommand for Command {
|
|||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("empty?")
|
Signature::build("empty?")
|
||||||
.rest(
|
.rest(
|
||||||
|
"rest",
|
||||||
SyntaxShape::ColumnPath,
|
SyntaxShape::ColumnPath,
|
||||||
"the names of the columns to check emptiness",
|
"the names of the columns to check emptiness",
|
||||||
)
|
)
|
||||||
@@ -139,7 +140,7 @@ fn process_row(
|
|||||||
|
|
||||||
let stream = run_block(
|
let stream = run_block(
|
||||||
&default_block.block,
|
&default_block.block,
|
||||||
&*context,
|
context,
|
||||||
input_stream,
|
input_stream,
|
||||||
ExternalRedirection::Stdout,
|
ExternalRedirection::Stdout,
|
||||||
);
|
);
|
||||||
|
@@ -14,7 +14,11 @@ impl WholeStreamCommand for Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("flatten").rest(SyntaxShape::String, "optionally flatten data by column")
|
Signature::build("flatten").rest(
|
||||||
|
"rest",
|
||||||
|
SyntaxShape::String,
|
||||||
|
"optionally flatten data by column",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
@@ -52,8 +56,7 @@ fn flatten(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||||||
let input = args.input;
|
let input = args.input;
|
||||||
|
|
||||||
Ok(input
|
Ok(input
|
||||||
.map(move |item| flat_value(&columns, &item, &tag).into_iter())
|
.flat_map(move |item| flat_value(&columns, &item, &tag))
|
||||||
.flatten()
|
|
||||||
.into_action_stream())
|
.into_action_stream())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +95,7 @@ fn flat_value(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (k, v) in mapa.into_iter() {
|
for (k, v) in mapa {
|
||||||
if out.contains_key(k) {
|
if out.contains_key(k) {
|
||||||
out.insert_value(format!("{}_{}", column, k), v.clone());
|
out.insert_value(format!("{}_{}", column, k), v.clone());
|
||||||
} else {
|
} else {
|
||||||
@@ -155,7 +158,7 @@ fn flat_value(
|
|||||||
let mut expanded = vec![];
|
let mut expanded = vec![];
|
||||||
|
|
||||||
if let Some(TableInside::Entries(column, _, entries)) = a_table {
|
if let Some(TableInside::Entries(column, _, entries)) = a_table {
|
||||||
for entry in entries.into_iter() {
|
for entry in entries {
|
||||||
let mut base = out.clone();
|
let mut base = out.clone();
|
||||||
base.insert_value(column, entry.clone());
|
base.insert_value(column, entry.clone());
|
||||||
expanded.push(base.into_value());
|
expanded.push(base.into_value());
|
||||||
@@ -166,7 +169,7 @@ fn flat_value(
|
|||||||
|
|
||||||
expanded
|
expanded
|
||||||
} else if item.is_table() {
|
} else if item.is_table() {
|
||||||
item.table_entries().map(Clone::clone).collect()
|
item.table_entries().cloned().collect()
|
||||||
} else {
|
} else {
|
||||||
vec![item.clone()]
|
vec![item.clone()]
|
||||||
}
|
}
|
||||||
|
@@ -19,6 +19,7 @@ impl WholeStreamCommand for Command {
|
|||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("get").rest(
|
Signature::build("get").rest(
|
||||||
|
"rest",
|
||||||
SyntaxShape::ColumnPath,
|
SyntaxShape::ColumnPath,
|
||||||
"optionally return additional data by path",
|
"optionally return additional data by path",
|
||||||
)
|
)
|
||||||
@@ -64,14 +65,12 @@ pub fn get(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||||||
} else {
|
} else {
|
||||||
trace!("get {:?}", column_paths);
|
trace!("get {:?}", column_paths);
|
||||||
let output_stream = input
|
let output_stream = input
|
||||||
.map(move |item| {
|
.flat_map(move |item| {
|
||||||
column_paths
|
column_paths
|
||||||
.iter()
|
.iter()
|
||||||
.map(move |path| get_output(&item, path))
|
.flat_map(move |path| get_output(&item, path))
|
||||||
.flatten()
|
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
})
|
})
|
||||||
.flatten()
|
|
||||||
.into_action_stream();
|
.into_action_stream();
|
||||||
Ok(output_stream)
|
Ok(output_stream)
|
||||||
}
|
}
|
||||||
|
@@ -137,10 +137,10 @@ pub fn group_by(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
value: UntaggedValue::Block(block_given),
|
value: UntaggedValue::Block(block_given),
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
let block = Arc::new(block_given);
|
let block = Arc::new(*block_given);
|
||||||
let error_key = "error";
|
let error_key = "error";
|
||||||
|
|
||||||
for value in values.iter() {
|
for value in &values {
|
||||||
let run = block.clone();
|
let run = block.clone();
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
|
|
||||||
|
@@ -80,7 +80,7 @@ fn process_row(
|
|||||||
|
|
||||||
let result = run_block(
|
let result = run_block(
|
||||||
&block.block,
|
&block.block,
|
||||||
&*context,
|
&context,
|
||||||
input_stream,
|
input_stream,
|
||||||
ExternalRedirection::Stdout,
|
ExternalRedirection::Stdout,
|
||||||
);
|
);
|
||||||
@@ -162,7 +162,7 @@ fn insert(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||||||
let column = Arc::new(column);
|
let column = Arc::new(column);
|
||||||
|
|
||||||
Ok(input
|
Ok(input
|
||||||
.map(move |input| {
|
.flat_map(move |input| {
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
let value = value.clone();
|
let value = value.clone();
|
||||||
let column = column.clone();
|
let column = column.clone();
|
||||||
@@ -172,6 +172,5 @@ fn insert(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||||||
Err(e) => ActionStream::one(Err(e)),
|
Err(e) => ActionStream::one(Err(e)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.flatten()
|
|
||||||
.into_action_stream())
|
.into_action_stream())
|
||||||
}
|
}
|
||||||
|
@@ -74,7 +74,7 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
ctx.scope.add_var(arg.name(), item.clone());
|
ctx.scope.add_var(arg.name(), item.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = evaluate_baseline_expr(&*condition, &*ctx);
|
let result = evaluate_baseline_expr(&condition, &ctx);
|
||||||
ctx.scope.exit_scope();
|
ctx.scope.exit_scope();
|
||||||
|
|
||||||
!matches!(result, Ok(ref v) if v.is_true())
|
!matches!(result, Ok(ref v) if v.is_true())
|
||||||
|
@@ -76,7 +76,7 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
}
|
}
|
||||||
trace!("ITEM = {:?}", item);
|
trace!("ITEM = {:?}", item);
|
||||||
|
|
||||||
let result = evaluate_baseline_expr(&*condition, &*ctx);
|
let result = evaluate_baseline_expr(&condition, &ctx);
|
||||||
ctx.scope.exit_scope();
|
ctx.scope.exit_scope();
|
||||||
trace!("RESULT = {:?}", result);
|
trace!("RESULT = {:?}", result);
|
||||||
|
|
||||||
|
@@ -14,7 +14,7 @@ impl WholeStreamCommand for Command {
|
|||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("move")
|
Signature::build("move")
|
||||||
.rest(SyntaxShape::ColumnPath, "the columns to move")
|
.rest("rest", SyntaxShape::ColumnPath, "the columns to move")
|
||||||
.named(
|
.named(
|
||||||
"after",
|
"after",
|
||||||
SyntaxShape::ColumnPath,
|
SyntaxShape::ColumnPath,
|
||||||
@@ -242,7 +242,7 @@ fn move_after(table: &Value, columns: &[String], from: &ColumnPath) -> Result<Va
|
|||||||
let mut insert = false;
|
let mut insert = false;
|
||||||
let mut inserted = false;
|
let mut inserted = false;
|
||||||
|
|
||||||
for name in columns_moved.into_iter() {
|
for name in columns_moved {
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
reordered_columns.push(Some(name.clone()));
|
reordered_columns.push(Some(name.clone()));
|
||||||
|
|
||||||
@@ -291,7 +291,7 @@ fn move_before(table: &Value, columns: &[String], from: &ColumnPath) -> Result<V
|
|||||||
let mut reordered_columns = vec![];
|
let mut reordered_columns = vec![];
|
||||||
let mut inserted = false;
|
let mut inserted = false;
|
||||||
|
|
||||||
for name in columns_moved.into_iter() {
|
for name in columns_moved {
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
if !inserted && name == from {
|
if !inserted && name == from {
|
||||||
for column in columns {
|
for column in columns {
|
||||||
|
@@ -18,7 +18,7 @@ impl WholeStreamCommand for Nth {
|
|||||||
SyntaxShape::Int,
|
SyntaxShape::Int,
|
||||||
"the number of the row to return",
|
"the number of the row to return",
|
||||||
)
|
)
|
||||||
.rest(SyntaxShape::Any, "Optionally return more rows")
|
.rest("rest", SyntaxShape::Any, "Optionally return more rows")
|
||||||
.switch("skip", "Skip the rows instead of selecting them", Some('s'))
|
.switch("skip", "Skip the rows instead of selecting them", Some('s'))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -36,6 +36,7 @@ impl WholeStreamCommand for Pivot {
|
|||||||
Some('i'),
|
Some('i'),
|
||||||
)
|
)
|
||||||
.rest(
|
.rest(
|
||||||
|
"rest",
|
||||||
SyntaxShape::String,
|
SyntaxShape::String,
|
||||||
"the names to give columns once pivoted",
|
"the names to give columns once pivoted",
|
||||||
)
|
)
|
||||||
|
@@ -163,7 +163,7 @@ fn reduce(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||||||
|
|
||||||
context.scope.enter_scope();
|
context.scope.enter_scope();
|
||||||
context.scope.add_var("$acc", f);
|
context.scope.add_var("$acc", f);
|
||||||
let result = process_row(block, &*context, row);
|
let result = process_row(block, &context, row);
|
||||||
context.scope.exit_scope();
|
context.scope.exit_scope();
|
||||||
|
|
||||||
// we make sure that result is an indexed item
|
// we make sure that result is an indexed item
|
||||||
@@ -201,7 +201,7 @@ fn reduce(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||||||
|
|
||||||
context.scope.enter_scope();
|
context.scope.enter_scope();
|
||||||
context.scope.add_var("$acc", f);
|
context.scope.add_var("$acc", f);
|
||||||
let result = process_row(block, &*context, row);
|
let result = process_row(block, &context, row);
|
||||||
context.scope.exit_scope();
|
context.scope.exit_scope();
|
||||||
result
|
result
|
||||||
})?
|
})?
|
||||||
|
@@ -13,7 +13,11 @@ impl WholeStreamCommand for Reject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("reject").rest(SyntaxShape::String, "the names of columns to remove")
|
Signature::build("reject").rest(
|
||||||
|
"rest",
|
||||||
|
SyntaxShape::String,
|
||||||
|
"the names of columns to remove",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@@ -19,7 +19,11 @@ impl WholeStreamCommand for Rename {
|
|||||||
SyntaxShape::String,
|
SyntaxShape::String,
|
||||||
"the new name for the first column",
|
"the new name for the first column",
|
||||||
)
|
)
|
||||||
.rest(SyntaxShape::String, "the new name for additional columns")
|
.rest(
|
||||||
|
"rest",
|
||||||
|
SyntaxShape::String,
|
||||||
|
"the new name for additional columns",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
|
@@ -59,14 +59,12 @@ pub fn roll(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
|
|
||||||
Ok(args
|
Ok(args
|
||||||
.input
|
.input
|
||||||
.map(move |value| {
|
.flat_map(move |value| {
|
||||||
let tag = value.tag();
|
let tag = value.tag();
|
||||||
|
|
||||||
roll_by(value, &options)
|
roll_by(value, &options)
|
||||||
.unwrap_or_else(|| vec![UntaggedValue::nothing().into_value(tag)])
|
.unwrap_or_else(|| vec![UntaggedValue::nothing().into_value(tag)])
|
||||||
.into_iter()
|
|
||||||
})
|
})
|
||||||
.flatten()
|
|
||||||
.into_output_stream())
|
.into_output_stream())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,8 +82,7 @@ fn roll_by(value: Value, options: &Arguments) -> Option<Vec<Value>> {
|
|||||||
let values_rotated = rotate(
|
let values_rotated = rotate(
|
||||||
value
|
value
|
||||||
.row_entries()
|
.row_entries()
|
||||||
.map(|(_, value)| value)
|
.map(|(_, value)| value.clone())
|
||||||
.map(Clone::clone)
|
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
&options.by,
|
&options.by,
|
||||||
direction,
|
direction,
|
||||||
@@ -94,7 +91,7 @@ fn roll_by(value: Value, options: &Arguments) -> Option<Vec<Value>> {
|
|||||||
if let Some(ref values) = values_rotated {
|
if let Some(ref values) = values_rotated {
|
||||||
let mut out = TaggedDictBuilder::new(&tag);
|
let mut out = TaggedDictBuilder::new(&tag);
|
||||||
|
|
||||||
for (k, v) in columns.iter().zip(values.iter()) {
|
for (k, v) in columns.iter().zip(values) {
|
||||||
out.insert_value(k, v.clone());
|
out.insert_value(k, v.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +101,7 @@ fn roll_by(value: Value, options: &Arguments) -> Option<Vec<Value>> {
|
|||||||
None
|
None
|
||||||
} else if value.is_table() {
|
} else if value.is_table() {
|
||||||
rotate(
|
rotate(
|
||||||
value.table_entries().map(Clone::clone).collect(),
|
value.table_entries().cloned().collect(),
|
||||||
&options.by,
|
&options.by,
|
||||||
direction,
|
direction,
|
||||||
)
|
)
|
||||||
|
@@ -17,6 +17,7 @@ impl WholeStreamCommand for Command {
|
|||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("rotate").rest(
|
Signature::build("rotate").rest(
|
||||||
|
"rest",
|
||||||
SyntaxShape::String,
|
SyntaxShape::String,
|
||||||
"the names to give columns once rotated",
|
"the names to give columns once rotated",
|
||||||
)
|
)
|
||||||
|
@@ -17,6 +17,7 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("rotate counter-clockwise").rest(
|
Signature::build("rotate counter-clockwise").rest(
|
||||||
|
"rest",
|
||||||
SyntaxShape::String,
|
SyntaxShape::String,
|
||||||
"the names to give columns once rotated",
|
"the names to give columns once rotated",
|
||||||
)
|
)
|
||||||
|
@@ -16,6 +16,7 @@ impl WholeStreamCommand for Command {
|
|||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("select").rest(
|
Signature::build("select").rest(
|
||||||
|
"rest",
|
||||||
SyntaxShape::ColumnPath,
|
SyntaxShape::ColumnPath,
|
||||||
"the columns to select from the table",
|
"the columns to select from the table",
|
||||||
)
|
)
|
||||||
|
@@ -76,7 +76,7 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
}
|
}
|
||||||
trace!("ITEM = {:?}", item);
|
trace!("ITEM = {:?}", item);
|
||||||
|
|
||||||
let result = evaluate_baseline_expr(&*condition, &*ctx);
|
let result = evaluate_baseline_expr(&condition, &ctx);
|
||||||
ctx.scope.exit_scope();
|
ctx.scope.exit_scope();
|
||||||
trace!("RESULT = {:?}", result);
|
trace!("RESULT = {:?}", result);
|
||||||
|
|
||||||
|
@@ -77,7 +77,7 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
}
|
}
|
||||||
trace!("ITEM = {:?}", item);
|
trace!("ITEM = {:?}", item);
|
||||||
|
|
||||||
let result = evaluate_baseline_expr(&*condition, &*ctx);
|
let result = evaluate_baseline_expr(&condition, &ctx);
|
||||||
ctx.scope.exit_scope();
|
ctx.scope.exit_scope();
|
||||||
trace!("RESULT = {:?}", result);
|
trace!("RESULT = {:?}", result);
|
||||||
|
|
||||||
|
@@ -21,7 +21,7 @@ impl WholeStreamCommand for SortBy {
|
|||||||
Some('i'),
|
Some('i'),
|
||||||
)
|
)
|
||||||
.switch("reverse", "Sort in reverse order", Some('r'))
|
.switch("reverse", "Sort in reverse order", Some('r'))
|
||||||
.rest(SyntaxShape::String, "the column(s) to sort by")
|
.rest("rest", SyntaxShape::String, "the column(s) to sort by")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
@@ -118,7 +118,7 @@ fn sort_by(mut args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
vec.reverse()
|
vec.reverse()
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((vec.into_iter()).into_output_stream())
|
Ok(vec.into_iter().into_output_stream())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sort(
|
pub fn sort(
|
||||||
@@ -137,7 +137,7 @@ pub fn sort(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
for sort_arg in keys.iter() {
|
for sort_arg in keys {
|
||||||
let match_test = &vec[0].get_data_by_key(sort_arg.borrow_spanned());
|
let match_test = &vec[0].get_data_by_key(sort_arg.borrow_spanned());
|
||||||
if match_test.is_none() {
|
if match_test.is_none() {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
|
@@ -66,7 +66,6 @@ fn process_row(
|
|||||||
field: Arc<ColumnPath>,
|
field: Arc<ColumnPath>,
|
||||||
tag: Arc<Tag>,
|
tag: Arc<Tag>,
|
||||||
) -> Result<ActionStream, ShellError> {
|
) -> Result<ActionStream, ShellError> {
|
||||||
let tag = &*tag;
|
|
||||||
let replacement = Arc::make_mut(&mut replacement);
|
let replacement = Arc::make_mut(&mut replacement);
|
||||||
|
|
||||||
Ok(match replacement {
|
Ok(match replacement {
|
||||||
@@ -86,7 +85,7 @@ fn process_row(
|
|||||||
|
|
||||||
let result = run_block(
|
let result = run_block(
|
||||||
&captured_block.block,
|
&captured_block.block,
|
||||||
&*context,
|
&context,
|
||||||
input_stream,
|
input_stream,
|
||||||
ExternalRedirection::Stdout,
|
ExternalRedirection::Stdout,
|
||||||
);
|
);
|
||||||
@@ -184,7 +183,7 @@ fn update(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||||||
let field = Arc::new(field);
|
let field = Arc::new(field);
|
||||||
|
|
||||||
Ok(input
|
Ok(input
|
||||||
.map(move |input| {
|
.flat_map(move |input| {
|
||||||
let tag = name_tag.clone();
|
let tag = name_tag.clone();
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
let replacement = replacement.clone();
|
let replacement = replacement.clone();
|
||||||
@@ -195,6 +194,5 @@ fn update(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|||||||
Err(e) => ActionStream::one(Err(e)),
|
Err(e) => ActionStream::one(Err(e)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.flatten()
|
|
||||||
.into_action_stream())
|
.into_action_stream())
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user