mirror of
https://github.com/nushell/nushell
synced 2024-12-25 04:23:10 +00:00
lookup closures/blockids and get content in config flatten
(#14635)
# Description This PR continues to tweak `config flatten` by looking up the closures and block_ids and extracts the content into the produced record. Example ![image](https://github.com/user-attachments/assets/99a9db54-e477-40b2-8468-bbadcf0aa5b7) # 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:
parent
7029d24f42
commit
f2e8c391a2
2 changed files with 60 additions and 13 deletions
|
@ -53,16 +53,21 @@ impl Command for ConfigFlatten {
|
|||
};
|
||||
// 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)?;
|
||||
let flattened_values =
|
||||
convert_string_to_value(&flattened_config_str, engine_state, 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> {
|
||||
fn convert_string_to_value(
|
||||
string_input: &str,
|
||||
engine_state: &EngineState,
|
||||
span: Span,
|
||||
) -> Result<Value, ShellError> {
|
||||
match nu_json::from_str(string_input) {
|
||||
Ok(value) => Ok(convert_nujson_to_value(value, span)),
|
||||
Ok(value) => Ok(convert_nujson_to_value(None, value, engine_state, span)),
|
||||
|
||||
Err(x) => match x {
|
||||
nu_json::Error::Syntax(_, row, col) => {
|
||||
|
@ -91,22 +96,42 @@ fn convert_string_to_value(string_input: &str, span: Span) -> Result<Value, Shel
|
|||
}
|
||||
}
|
||||
|
||||
fn convert_nujson_to_value(value: nu_json::Value, span: Span) -> Value {
|
||||
fn convert_nujson_to_value(
|
||||
key: Option<String>,
|
||||
value: nu_json::Value,
|
||||
engine_state: &EngineState,
|
||||
span: Span,
|
||||
) -> Value {
|
||||
match value {
|
||||
nu_json::Value::Array(array) => Value::list(
|
||||
array
|
||||
.into_iter()
|
||||
.map(|x| convert_nujson_to_value(x, span))
|
||||
.map(|x| convert_nujson_to_value(key.clone(), x, engine_state, 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::I64(i) => {
|
||||
if let Some(closure_str) = expand_closure(key.clone(), i, engine_state) {
|
||||
Value::string(closure_str, span)
|
||||
} else {
|
||||
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)))
|
||||
.map(|(k, v)| {
|
||||
let mut key = k.clone();
|
||||
// Keep .Closure.val and .block_id as part of the key during conversion to value
|
||||
let value = convert_nujson_to_value(Some(key.clone()), v, engine_state, span);
|
||||
// Replace .Closure.val and .block_id from the key after the conversion
|
||||
if key.contains(".Closure.val") || key.contains(".block_id") {
|
||||
key = key.replace(".Closure.val", "").replace(".block_id", "");
|
||||
}
|
||||
(key, value)
|
||||
})
|
||||
.collect(),
|
||||
span,
|
||||
),
|
||||
|
@ -121,6 +146,8 @@ fn convert_nujson_to_value(value: nu_json::Value, span: Span) -> Value {
|
|||
},
|
||||
span,
|
||||
)
|
||||
} else if let Some(closure_str) = expand_closure(key.clone(), u as i64, engine_state) {
|
||||
Value::string(closure_str, span)
|
||||
} else {
|
||||
Value::int(u as i64, span)
|
||||
}
|
||||
|
@ -129,6 +156,24 @@ fn convert_nujson_to_value(value: nu_json::Value, span: Span) -> Value {
|
|||
}
|
||||
}
|
||||
|
||||
// If the block_id is a real block id, then it should expand into the closure contents, otherwise return None
|
||||
fn expand_closure(
|
||||
key: Option<String>,
|
||||
block_id: i64,
|
||||
engine_state: &EngineState,
|
||||
) -> Option<String> {
|
||||
match key {
|
||||
Some(key) if key.contains(".Closure.val") || key.contains(".block_id") => engine_state
|
||||
.try_get_block(nu_protocol::BlockId::new(block_id as usize))
|
||||
.and_then(|block| block.span)
|
||||
.map(|span| {
|
||||
let contents = engine_state.get_span_contents(span);
|
||||
String::from_utf8_lossy(contents).to_string()
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
|
|
@ -227,9 +227,6 @@ impl<'a> JsonFlattener<'a> {
|
|||
if filtered_key.contains(".Record.val") {
|
||||
filtered_key = filtered_key.replace(".Record.val", "");
|
||||
}
|
||||
if filtered_key.contains(".Closure.val") {
|
||||
filtered_key = filtered_key.replace(".Closure.val", "");
|
||||
}
|
||||
if filtered_key.contains(".List.vals") {
|
||||
filtered_key = filtered_key.replace(".List.vals", "");
|
||||
}
|
||||
|
@ -239,9 +236,14 @@ impl<'a> JsonFlattener<'a> {
|
|||
if filtered_key.contains(".Bool.val") {
|
||||
filtered_key = filtered_key.replace(".Bool.val", "");
|
||||
}
|
||||
if filtered_key.contains(".block_id") {
|
||||
filtered_key = filtered_key.replace(".block_id", "");
|
||||
}
|
||||
// For now, let's skip replacing these because they tell us which
|
||||
// numbers are closures and blocks which is useful for extracting the content
|
||||
// if filtered_key.contains(".Closure.val") {
|
||||
// filtered_key = filtered_key.replace(".Closure.val", "");
|
||||
// }
|
||||
// if filtered_key.contains(".block_id") {
|
||||
// filtered_key = filtered_key.replace(".block_id", "");
|
||||
// }
|
||||
filtered_key
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue