mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 08:36:10 +02:00
add config flatten
command (#14621)
# Description This is supposed to be a Quality-of-Life command that just makes some things easier when dealing with a nushell config. Really all it does is show you the current config in a flattened state. That's it. I was thinking this could be useful when comparing config settings between old and new config files. There are still room for improvements. For instance, closures are listed as an int. They can be updated with a `view source <int>` pipeline but that could all be built in too.  The command works by getting the current configuration, serializing it to json, then flattening that json. BTW, there's a new flatten_json.rs in nu-utils. Theoretically all this mess could be done in a custom command script, but it's proven to be exceedingly difficult based on the work from discord. Here's some more complex items to flatten.  # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # 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 toolkit.nu; toolkit test stdlib"` 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 > ``` --> # 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. -->
This commit is contained in:
@ -351,6 +351,7 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
|
||||
WithEnv,
|
||||
ConfigNu,
|
||||
ConfigEnv,
|
||||
ConfigFlatten,
|
||||
ConfigMeta,
|
||||
ConfigReset,
|
||||
};
|
||||
|
150
crates/nu-command/src/env/config/config_flatten.rs
vendored
Normal file
150
crates/nu-command/src/env/config/config_flatten.rs
vendored
Normal file
@ -0,0 +1,150 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
use nu_utils::JsonFlattener; // Ensure this import is present // Ensure this import is present
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ConfigFlatten;
|
||||
|
||||
impl Command for ConfigFlatten {
|
||||
fn name(&self) -> &str {
|
||||
"config flatten"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build(self.name())
|
||||
.category(Category::Debug)
|
||||
.input_output_types(vec![(Type::Nothing, Type::record())])
|
||||
}
|
||||
|
||||
fn description(&self) -> &str {
|
||||
"Show the current configuration in a flattened form."
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![Example {
|
||||
description: "Show the current configuration in a flattened form",
|
||||
example: "config flatten",
|
||||
result: None,
|
||||
}]
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
_stack: &mut Stack,
|
||||
call: &Call,
|
||||
_input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
// Get the Config instance from the EngineState
|
||||
let config = engine_state.get_config();
|
||||
// Serialize the Config instance to JSON
|
||||
let serialized_config =
|
||||
serde_json::to_value(&**config).map_err(|err| ShellError::GenericError {
|
||||
error: format!("Failed to serialize config to json: {err}"),
|
||||
msg: "".into(),
|
||||
span: Some(call.head),
|
||||
help: None,
|
||||
inner: vec![],
|
||||
})?;
|
||||
// Create a JsonFlattener instance with appropriate arguments
|
||||
let flattener = JsonFlattener {
|
||||
separator: ".",
|
||||
alt_array_flattening: false,
|
||||
preserve_arrays: true,
|
||||
};
|
||||
// Flatten the JSON value
|
||||
let flattened_config_str = flattener.flatten(&serialized_config).to_string();
|
||||
let flattened_values = convert_string_to_value(&flattened_config_str, call.head)?;
|
||||
|
||||
Ok(flattened_values.into_pipeline_data())
|
||||
}
|
||||
}
|
||||
|
||||
// From here below is taken from `from json`. Would be nice to have a nu-utils-value crate that could be shared
|
||||
fn convert_string_to_value(string_input: &str, span: Span) -> Result<Value, ShellError> {
|
||||
match nu_json::from_str(string_input) {
|
||||
Ok(value) => Ok(convert_nujson_to_value(value, span)),
|
||||
|
||||
Err(x) => match x {
|
||||
nu_json::Error::Syntax(_, row, col) => {
|
||||
let label = x.to_string();
|
||||
let label_span = convert_row_column_to_span(row, col, string_input);
|
||||
Err(ShellError::GenericError {
|
||||
error: "Error while parsing JSON text".into(),
|
||||
msg: "error parsing JSON text".into(),
|
||||
span: Some(span),
|
||||
help: None,
|
||||
inner: vec![ShellError::OutsideSpannedLabeledError {
|
||||
src: string_input.into(),
|
||||
error: "Error while parsing JSON text".into(),
|
||||
msg: label,
|
||||
span: label_span,
|
||||
}],
|
||||
})
|
||||
}
|
||||
x => Err(ShellError::CantConvert {
|
||||
to_type: format!("structured json data ({x})"),
|
||||
from_type: "string".into(),
|
||||
span,
|
||||
help: None,
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_nujson_to_value(value: nu_json::Value, span: Span) -> Value {
|
||||
match value {
|
||||
nu_json::Value::Array(array) => Value::list(
|
||||
array
|
||||
.into_iter()
|
||||
.map(|x| convert_nujson_to_value(x, span))
|
||||
.collect(),
|
||||
span,
|
||||
),
|
||||
nu_json::Value::Bool(b) => Value::bool(b, span),
|
||||
nu_json::Value::F64(f) => Value::float(f, span),
|
||||
nu_json::Value::I64(i) => Value::int(i, span),
|
||||
nu_json::Value::Null => Value::nothing(span),
|
||||
nu_json::Value::Object(k) => Value::record(
|
||||
k.into_iter()
|
||||
.map(|(k, v)| (k, convert_nujson_to_value(v, span)))
|
||||
.collect(),
|
||||
span,
|
||||
),
|
||||
nu_json::Value::U64(u) => {
|
||||
if u > i64::MAX as u64 {
|
||||
Value::error(
|
||||
ShellError::CantConvert {
|
||||
to_type: "i64 sized integer".into(),
|
||||
from_type: "value larger than i64".into(),
|
||||
span,
|
||||
help: None,
|
||||
},
|
||||
span,
|
||||
)
|
||||
} else {
|
||||
Value::int(u as i64, span)
|
||||
}
|
||||
}
|
||||
nu_json::Value::String(s) => Value::string(s, span),
|
||||
}
|
||||
}
|
||||
|
||||
// Converts row+column to a Span, assuming bytes (1-based rows)
|
||||
fn convert_row_column_to_span(row: usize, col: usize, contents: &str) -> Span {
|
||||
let mut cur_row = 1;
|
||||
let mut cur_col = 1;
|
||||
|
||||
for (offset, curr_byte) in contents.bytes().enumerate() {
|
||||
if curr_byte == b'\n' {
|
||||
cur_row += 1;
|
||||
cur_col = 1;
|
||||
}
|
||||
if cur_row >= row && cur_col >= col {
|
||||
return Span::new(offset, offset);
|
||||
} else {
|
||||
cur_col += 1;
|
||||
}
|
||||
}
|
||||
|
||||
Span::new(contents.len(), contents.len())
|
||||
}
|
@ -22,7 +22,6 @@ impl Command for ConfigNu {
|
||||
"Print a commented `config.nu` with documentation instead.",
|
||||
Some('s'),
|
||||
)
|
||||
// TODO: Signature narrower than what run actually supports theoretically
|
||||
}
|
||||
|
||||
fn description(&self) -> &str {
|
||||
|
3
crates/nu-command/src/env/config/mod.rs
vendored
3
crates/nu-command/src/env/config/mod.rs
vendored
@ -1,8 +1,11 @@
|
||||
mod config_;
|
||||
mod config_env;
|
||||
mod config_flatten;
|
||||
mod config_nu;
|
||||
mod config_reset;
|
||||
|
||||
pub use config_::ConfigMeta;
|
||||
pub use config_env::ConfigEnv;
|
||||
pub use config_flatten::ConfigFlatten;
|
||||
pub use config_nu::ConfigNu;
|
||||
pub use config_reset::ConfigReset;
|
||||
|
1
crates/nu-command/src/env/mod.rs
vendored
1
crates/nu-command/src/env/mod.rs
vendored
@ -5,6 +5,7 @@ mod source_env;
|
||||
mod with_env;
|
||||
|
||||
pub use config::ConfigEnv;
|
||||
pub use config::ConfigFlatten;
|
||||
pub use config::ConfigMeta;
|
||||
pub use config::ConfigNu;
|
||||
pub use config::ConfigReset;
|
||||
|
Reference in New Issue
Block a user