Command: Add config env/nu --default to print defaults (#10480)

<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

# Description
<!--
Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.

Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.
-->

Closes #5436

When I opened this issue more than a year ago, I mainly wanted the
following capacity: easily access the full env and have the hability to
update it when a new version of `nushell` comes out.

With this PR I can now do the following:

```nu
source-env ~/.config/nushell/defaults/env.nu
source     ~/.config/nushell/defaults/config.nu

# Update nushell default config & env file (run this after a version update)
def update-defaults [] {
    config env --default | save -f ~/.config/nushell/defaults/env.nu
    config nu  --default | save -f ~/.config/nushell/defaults/config.nu
}
```

Which is more than enough for me. Along with `nushell` respecting the
XDG spec on macOS (`dirs-next` should be banned for CLI tools on macOS),
this should be one of the last hurdle before fully switching for me!

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->

Two new switches to existing commands:

```nu
config env --default # Print the default env embedded at compile time in the binary
config nu  --default # Print the default config embedded at compile time in the binary
```

# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

- Added a test for the output of `config env --default`
- Added a test for the output of `config nu --default`

# 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.
-->

Are the docs for commands generated automatically or do I need to make a
PR there too ? It's no problem if so, just point me at instructions if
there are any :)
This commit is contained in:
Poliorcetics 2023-09-25 15:00:59 +02:00 committed by GitHub
parent 5326e51e4f
commit a19cac2673
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 86 additions and 14 deletions

View File

@ -2,7 +2,7 @@ use nu_engine::env_to_strings;
use nu_protocol::{ use nu_protocol::{
ast::Call, ast::Call,
engine::{Command, EngineState, Stack}, engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Type, Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Type, Value,
}; };
use super::utils::{gen_command, get_editor}; use super::utils::{gen_command, get_editor};
@ -18,7 +18,11 @@ impl Command for ConfigEnv {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build(self.name()) Signature::build(self.name())
.category(Category::Env) .category(Category::Env)
.input_output_types(vec![(Type::Nothing, Type::Nothing)]) .input_output_types(vec![
(Type::Nothing, Type::Nothing),
(Type::Nothing, Type::String),
])
.switch("default", "Print default `env.nu` file instead.", Some('d'))
// TODO: Signature narrower than what run actually supports theoretically // TODO: Signature narrower than what run actually supports theoretically
} }
@ -27,11 +31,23 @@ impl Command for ConfigEnv {
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
vec![Example { vec![
Example {
description: "allow user to open and update nu env", description: "allow user to open and update nu env",
example: "config env", example: "config env",
result: None, result: None,
}] },
Example {
description: "allow user to print default `env.nu` file",
example: "config env --default,",
result: None,
},
Example {
description: "allow saving the default `env.nu` locally",
example: "config env --default | save -f ~/.config/nushell/default_env.nu",
result: None,
},
]
} }
fn run( fn run(
@ -41,6 +57,12 @@ impl Command for ConfigEnv {
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
// `--default` flag handling
if call.has_flag("default") {
let head = call.head;
return Ok(Value::string(nu_utils::get_default_env(), head).into_pipeline_data());
}
let env_vars_str = env_to_strings(engine_state, stack)?; let env_vars_str = env_to_strings(engine_state, stack)?;
let nu_config = match engine_state.get_config_path("env-path") { let nu_config = match engine_state.get_config_path("env-path") {
Some(path) => path.clone(), Some(path) => path.clone(),

View File

@ -2,7 +2,7 @@ use nu_engine::env_to_strings;
use nu_protocol::{ use nu_protocol::{
ast::Call, ast::Call,
engine::{Command, EngineState, Stack}, engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Type, Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Type, Value,
}; };
use super::utils::{gen_command, get_editor}; use super::utils::{gen_command, get_editor};
@ -18,7 +18,15 @@ impl Command for ConfigNu {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build(self.name()) Signature::build(self.name())
.category(Category::Env) .category(Category::Env)
.input_output_types(vec![(Type::Nothing, Type::Nothing)]) .input_output_types(vec![
(Type::Nothing, Type::Nothing),
(Type::Nothing, Type::String),
])
.switch(
"default",
"Print default `config.nu` file instead.",
Some('d'),
)
// TODO: Signature narrower than what run actually supports theoretically // TODO: Signature narrower than what run actually supports theoretically
} }
@ -27,11 +35,23 @@ impl Command for ConfigNu {
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
vec![Example { vec![
Example {
description: "allow user to open and update nu config", description: "allow user to open and update nu config",
example: "config nu", example: "config nu",
result: None, result: None,
}] },
Example {
description: "allow user to print default `config.nu` file",
example: "config nu --default,",
result: None,
},
Example {
description: "allow saving the default `config.nu` locally",
example: "config nu --default | save -f ~/.config/nushell/default_config.nu",
result: None,
},
]
} }
fn run( fn run(
@ -41,6 +61,12 @@ impl Command for ConfigNu {
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
// `--default` flag handling
if call.has_flag("default") {
let head = call.head;
return Ok(Value::string(nu_utils::get_default_config(), head).into_pipeline_data());
}
let env_vars_str = env_to_strings(engine_state, stack)?; let env_vars_str = env_to_strings(engine_state, stack)?;
let nu_config = match engine_state.get_config_path("config-path") { let nu_config = match engine_state.get_config_path("config-path") {
Some(path) => path.clone(), Some(path) => path.clone(),

View File

@ -0,0 +1,11 @@
use nu_test_support::nu;
#[test]
fn print_config_env_default_to_stdout() {
let actual = nu!("config env --default");
assert_eq!(
actual.out,
nu_utils::get_default_env().replace(['\n', '\r'], "")
);
assert!(actual.err.is_empty());
}

View File

@ -0,0 +1,11 @@
use nu_test_support::nu;
#[test]
fn print_config_nu_default_to_stdout() {
let actual = nu!("config nu --default");
assert_eq!(
actual.out,
nu_utils::get_default_config().replace(['\n', '\r'], "")
);
assert!(actual.err.is_empty());
}

View File

@ -7,6 +7,8 @@ mod break_;
mod cal; mod cal;
mod cd; mod cd;
mod compact; mod compact;
mod config_env_default;
mod config_nu_default;
mod continue_; mod continue_;
mod conversions; mod conversions;
mod cp; mod cp;