From f0e93c2fa97979c37c2a4e50a6edc0124ea1382e Mon Sep 17 00:00:00 2001
From: Kangaxx-0 <85712372+Kangaxx-0@users.noreply.github.com>
Date: Sat, 10 Dec 2022 05:26:42 -0800
Subject: [PATCH] into cellpath command (#7417)
# Description
Address part of feature request #7337, add a small command `into
cellpath` to allow string -> cellpath auto-conversion, with this change,
we could run
```
let p = 'ls.use_ls_colors'
$env.config | upsert ($p | nito cellpath) false
```
Note - This pr only covers `String` -> `CellPath`, any other conversions
should be considered as expected?
# Tests + Formatting
Don't forget to add tests that cover your changes.
Make sure you've run and fixed any issues with these commands:
- [x] `cargo fmt --all -- --check` to check standard code formatting
(`cargo fmt --all` applies these changes)
- [x] `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- [x] `cargo test --workspace` to check that all tests pass
# After Submitting
If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
---
.../src/conversions/into/cellpath.rs | 121 ++++++++++++++++++
crates/nu-command/src/conversions/into/mod.rs | 2 +
crates/nu-command/src/default_context.rs | 1 +
.../tests/commands/into_cellpath.rs | 14 ++
crates/nu-command/tests/commands/mod.rs | 1 +
src/tests.rs | 21 +++
src/tests/test_env.rs | 10 ++
7 files changed, 170 insertions(+)
create mode 100644 crates/nu-command/src/conversions/into/cellpath.rs
create mode 100644 crates/nu-command/tests/commands/into_cellpath.rs
diff --git a/crates/nu-command/src/conversions/into/cellpath.rs b/crates/nu-command/src/conversions/into/cellpath.rs
new file mode 100644
index 0000000000..a0e035f094
--- /dev/null
+++ b/crates/nu-command/src/conversions/into/cellpath.rs
@@ -0,0 +1,121 @@
+use nu_protocol::ast::{CellPath, PathMember};
+
+use nu_protocol::{
+ ast::Call,
+ engine::{Command, EngineState, Stack},
+ Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Type, Value,
+};
+#[derive(Clone)]
+pub struct SubCommand;
+
+impl Command for SubCommand {
+ fn name(&self) -> &str {
+ "into cellpath"
+ }
+
+ fn signature(&self) -> Signature {
+ Signature::build("into cellpath")
+ .input_output_types(vec![(Type::String, Type::CellPath)])
+ .category(Category::Conversions)
+ }
+
+ fn usage(&self) -> &str {
+ "Convert value to a cellpath."
+ }
+
+ fn search_terms(&self) -> Vec<&str> {
+ vec!["convert"]
+ }
+
+ fn run(
+ &self,
+ engine_state: &EngineState,
+ _stack: &mut Stack,
+ call: &Call,
+ input: PipelineData,
+ ) -> Result {
+ into_cellpath(engine_state, call, input)
+ }
+
+ fn examples(&self) -> Vec {
+ vec![
+ Example {
+ description: "Convert from string to cellpath",
+ example: " 'config.show_banner' | into cellpath",
+ result: Some(Value::CellPath {
+ val: CellPath {
+ members: vec![
+ PathMember::String {
+ val: "config".to_string(),
+ span: Span::new(1, 21),
+ },
+ PathMember::String {
+ val: "show_banner".to_string(),
+ span: Span::new(1, 21),
+ },
+ ],
+ },
+ span: Span::new(1, 21),
+ }),
+ },
+ Example {
+ description: "Convert from string to cellpath",
+ example: " 'a' | into cellpath",
+ result: Some(Value::CellPath {
+ val: CellPath {
+ members: vec![PathMember::String {
+ val: "a".to_string(),
+ span: Span::new(38, 41),
+ }],
+ },
+ span: Span::new(1, 2),
+ }),
+ },
+ ]
+ }
+}
+
+fn into_cellpath(
+ _: &EngineState,
+ call: &Call,
+ input: PipelineData,
+) -> Result {
+ let input = input.into_value(call.head);
+ let res = match input {
+ Value::String { val, span } => parse_string_into_cellapth(val, span),
+ other => Value::Error {
+ error: ShellError::UnsupportedInput(
+ "'into cellpath' does not support this input".into(),
+ other.span().unwrap_or(call.head),
+ ),
+ },
+ };
+ Ok(res.into_pipeline_data())
+}
+
+fn parse_string_into_cellapth(val: String, span: Span) -> Value {
+ let parts = val.split('.').collect::>();
+ let mut cellpath: Vec = vec![];
+ for part in parts {
+ cellpath.push(PathMember::String {
+ val: part.to_string(),
+ span,
+ })
+ }
+ Value::CellPath {
+ val: CellPath { members: cellpath },
+ span,
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn test_examples() {
+ use crate::test_examples;
+
+ test_examples(SubCommand {})
+ }
+}
diff --git a/crates/nu-command/src/conversions/into/mod.rs b/crates/nu-command/src/conversions/into/mod.rs
index ee0ad71d5c..cbe562b840 100644
--- a/crates/nu-command/src/conversions/into/mod.rs
+++ b/crates/nu-command/src/conversions/into/mod.rs
@@ -1,5 +1,6 @@
mod binary;
mod bool;
+mod cellpath;
mod command;
mod datetime;
mod decimal;
@@ -12,6 +13,7 @@ mod string;
pub use self::bool::SubCommand as IntoBool;
pub use self::filesize::SubCommand as IntoFilesize;
pub use binary::SubCommand as IntoBinary;
+pub use cellpath::SubCommand as IntoCellPath;
pub use command::Into;
pub use datetime::SubCommand as IntoDatetime;
pub use decimal::SubCommand as IntoDecimal;
diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs
index 70b6462f15..6dd0f6e2e6 100644
--- a/crates/nu-command/src/default_context.rs
+++ b/crates/nu-command/src/default_context.rs
@@ -370,6 +370,7 @@ pub fn create_default_context() -> EngineState {
IntoDuration,
IntoFilesize,
IntoInt,
+ IntoCellPath,
IntoRecord,
IntoString,
};
diff --git a/crates/nu-command/tests/commands/into_cellpath.rs b/crates/nu-command/tests/commands/into_cellpath.rs
new file mode 100644
index 0000000000..94b0b19f83
--- /dev/null
+++ b/crates/nu-command/tests/commands/into_cellpath.rs
@@ -0,0 +1,14 @@
+use nu_test_support::{nu, pipeline};
+
+#[test]
+fn into_pathcell_string() {
+ let actual = nu!(
+ cwd: ".", pipeline(
+ r#"
+ 'nu.is.awesome' | into cellpath
+ "#
+ ));
+ dbg!(&actual.out);
+
+ assert!(actual.out.contains("nu.is.awesome"));
+}
diff --git a/crates/nu-command/tests/commands/mod.rs b/crates/nu-command/tests/commands/mod.rs
index 3f89a8cffa..3740beb522 100644
--- a/crates/nu-command/tests/commands/mod.rs
+++ b/crates/nu-command/tests/commands/mod.rs
@@ -34,6 +34,7 @@ mod headers;
mod help;
mod histogram;
mod insert;
+mod into_cellpath;
mod into_filesize;
mod into_int;
mod last;
diff --git a/src/tests.rs b/src/tests.rs
index b5f5c2e8ae..fc4ba64b5c 100644
--- a/src/tests.rs
+++ b/src/tests.rs
@@ -25,6 +25,8 @@ use tempfile::NamedTempFile;
pub type TestResult = Result<(), Box>;
+const DEFAULT_CONFIG: &str = "./crates/nu-utils/src/sample_config/default_config.nu";
+
pub fn run_test_with_env(input: &str, expected: &str, env: &HashMap<&str, &str>) -> TestResult {
let mut file = NamedTempFile::new()?;
let name = file.path();
@@ -54,6 +56,25 @@ pub fn run_test(input: &str, expected: &str) -> TestResult {
run_cmd_and_assert(cmd, expected)
}
+#[cfg(test)]
+pub fn run_test_with_default_config(input: &str, expected: &str) -> TestResult {
+ let mut file = NamedTempFile::new()?;
+ let name = file.path();
+
+ let mut cmd = Command::cargo_bin("nu")?;
+ cmd.arg("--config");
+ cmd.arg(DEFAULT_CONFIG);
+ cmd.arg(name);
+ cmd.env(
+ "PWD",
+ std::env::current_dir().expect("Can't get current dir"),
+ );
+
+ writeln!(file, "{}", input)?;
+
+ run_cmd_and_assert(cmd, expected)
+}
+
#[cfg(test)]
fn run_cmd_and_assert(mut cmd: Command, expected: &str) -> TestResult {
let output = cmd.output()?;
diff --git a/src/tests/test_env.rs b/src/tests/test_env.rs
index 23f2aaf42d..95b248017a 100644
--- a/src/tests/test_env.rs
+++ b/src/tests/test_env.rs
@@ -1,5 +1,7 @@
use crate::tests::{run_test, TestResult};
+use super::run_test_with_default_config;
+
#[test]
fn shorthand_env_1() -> TestResult {
run_test(r#"FOO=BAZ $env.FOO"#, "BAZ")
@@ -22,3 +24,11 @@ fn convert_non_string_env_var_to_nothing() -> TestResult {
"nothing",
)
}
+
+#[test]
+fn convert_string_to_env_var_cellpath() -> TestResult {
+ run_test_with_default_config(
+ r#"let p = 'ls.use_ls_colors'; $env.config | upsert ($p | into cellpath) false | get ls.use_ls_colors"#,
+ "false",
+ )
+}