Refactor config updates (#13802)

# Description
This PR standardizes updates to the config through a new
`UpdateFromValue` trait. For now, this trait is private in case we need
to make changes to it.

Note that this PR adds some additional `ShellError` cases to create
standard error messages for config errors. A follow-up PR will move
usages of the old error cases to these new ones. This PR also uses
`Type::custom` in lots of places (e.g., for string enums). Not sure if
this is something we want to encourage.

# User-Facing Changes
Should be none.
This commit is contained in:
Ian Manske
2024-10-11 09:40:32 -07:00
committed by GitHub
parent 02313e6819
commit fce6146576
32 changed files with 1343 additions and 1487 deletions

View File

@@ -3,7 +3,7 @@ use crate::{
ArgumentStack, EngineState, ErrorHandlerStack, Redirection, StackCallArgGuard,
StackCollectValueGuard, StackIoGuard, StackOutDest, DEFAULT_OVERLAY_NAME,
},
Config, OutDest, ShellError, Span, Value, VarId, ENV_VARIABLE_ID, NU_VARIABLE_ID,
Config, IntoValue, OutDest, ShellError, Span, Value, VarId, ENV_VARIABLE_ID, NU_VARIABLE_ID,
};
use std::{
collections::{HashMap, HashSet},
@@ -211,12 +211,13 @@ impl Stack {
///
/// The config will be updated with successfully parsed values even if an error occurs.
pub fn update_config(&mut self, engine_state: &EngineState) -> Result<(), ShellError> {
if let Some(mut config) = self.get_env_var(engine_state, "config").cloned() {
let existing_config = self.get_config(engine_state);
let (new_config, error) = config.parse_as_config(&existing_config);
self.config = Some(new_config.into());
if let Some(value) = self.get_env_var(engine_state, "config") {
let old = self.get_config(engine_state);
let mut config = (*old).clone();
let error = config.update_from_value(&old, value);
// The config value is modified by the update, so we should add it again
self.add_env_var("config".into(), config);
self.add_env_var("config".into(), config.clone().into_value(value.span()));
self.config = Some(config.into());
match error {
None => Ok(()),
Some(err) => Err(err),