mirror of
https://github.com/nushell/nushell.git
synced 2025-06-30 06:30:08 +02:00
Update config directly at assignment (#13332)
# Description Allows `Stack` to have a modified local `Config`, which is updated immediately when `$env.config` is assigned to. This means that even within a script, commands that come after `$env.config` changes will always see those changes in `Stack::get_config()`. Also fixed a lot of cases where `engine_state.get_config()` was used even when `Stack` was available. Closes #13324. # User-Facing Changes - Config changes apply immediately after the assignment is executed, rather than whenever config is read by a command that needs it. - Potentially slower performance when executing a lot of lines that change `$env.config` one after another. Recommended to get `$env.config` into a `mut` variable first and do modifications, then assign it back. - Much faster performance when executing a script that made modifications to `$env.config`, as the changes are only parsed once. # Tests + Formatting All passing. # After Submitting - [ ] release notes
This commit is contained in:
@ -53,9 +53,8 @@ pub fn evaluate_commands(
|
||||
// Parse the source code
|
||||
let (block, delta) = {
|
||||
if let Some(ref t_mode) = table_mode {
|
||||
let mut config = engine_state.get_config().clone();
|
||||
config.table_mode = t_mode.coerce_str()?.parse().unwrap_or_default();
|
||||
engine_state.set_config(config);
|
||||
Arc::make_mut(&mut engine_state.config).table_mode =
|
||||
t_mode.coerce_str()?.parse().unwrap_or_default();
|
||||
}
|
||||
|
||||
let mut working_set = StateWorkingSet::new(engine_state);
|
||||
|
@ -1,25 +1,31 @@
|
||||
use nu_engine::documentation::get_flags_section;
|
||||
use nu_protocol::{engine::EngineState, levenshtein_distance};
|
||||
use nu_protocol::{engine::EngineState, levenshtein_distance, Config};
|
||||
use nu_utils::IgnoreCaseExt;
|
||||
use reedline::{Completer, Suggestion};
|
||||
use std::{fmt::Write, sync::Arc};
|
||||
|
||||
pub struct NuHelpCompleter(Arc<EngineState>);
|
||||
pub struct NuHelpCompleter {
|
||||
engine_state: Arc<EngineState>,
|
||||
config: Arc<Config>,
|
||||
}
|
||||
|
||||
impl NuHelpCompleter {
|
||||
pub fn new(engine_state: Arc<EngineState>) -> Self {
|
||||
Self(engine_state)
|
||||
pub fn new(engine_state: Arc<EngineState>, config: Arc<Config>) -> Self {
|
||||
Self {
|
||||
engine_state,
|
||||
config,
|
||||
}
|
||||
}
|
||||
|
||||
fn completion_helper(&self, line: &str, pos: usize) -> Vec<Suggestion> {
|
||||
let folded_line = line.to_folded_case();
|
||||
|
||||
let mut commands = self
|
||||
.0
|
||||
.engine_state
|
||||
.get_decls_sorted(false)
|
||||
.into_iter()
|
||||
.filter_map(|(_, decl_id)| {
|
||||
let decl = self.0.get_decl(decl_id);
|
||||
let decl = self.engine_state.get_decl(decl_id);
|
||||
(decl.name().to_folded_case().contains(&folded_line)
|
||||
|| decl.usage().to_folded_case().contains(&folded_line)
|
||||
|| decl
|
||||
@ -54,9 +60,12 @@ impl NuHelpCompleter {
|
||||
let _ = write!(long_desc, "Usage:\r\n > {}\r\n", sig.call_signature());
|
||||
|
||||
if !sig.named.is_empty() {
|
||||
long_desc.push_str(&get_flags_section(Some(&*self.0.clone()), &sig, |v| {
|
||||
v.to_parsable_string(", ", &self.0.config)
|
||||
}))
|
||||
long_desc.push_str(&get_flags_section(
|
||||
Some(&self.engine_state),
|
||||
Some(&self.config),
|
||||
&sig,
|
||||
|v| v.to_parsable_string(", ", &self.config),
|
||||
))
|
||||
}
|
||||
|
||||
if !sig.required_positional.is_empty()
|
||||
@ -71,7 +80,7 @@ impl NuHelpCompleter {
|
||||
let opt_suffix = if let Some(value) = &positional.default_value {
|
||||
format!(
|
||||
" (optional, default: {})",
|
||||
&value.to_parsable_string(", ", &self.0.config),
|
||||
&value.to_parsable_string(", ", &self.config),
|
||||
)
|
||||
} else {
|
||||
(" (optional)").to_string()
|
||||
@ -138,7 +147,8 @@ mod test {
|
||||
) {
|
||||
let engine_state =
|
||||
nu_command::add_shell_command_context(nu_cmd_lang::create_default_context());
|
||||
let mut completer = NuHelpCompleter::new(engine_state.into());
|
||||
let config = engine_state.get_config().clone();
|
||||
let mut completer = NuHelpCompleter::new(engine_state.into(), config);
|
||||
let suggestions = completer.complete(line, end);
|
||||
|
||||
assert_eq!(
|
||||
|
@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use nu_engine::command_prelude::*;
|
||||
use reedline::{Highlighter, StyledText};
|
||||
|
||||
@ -33,13 +35,10 @@ impl Command for NuHighlight {
|
||||
let head = call.head;
|
||||
|
||||
let signals = engine_state.signals();
|
||||
let engine_state = std::sync::Arc::new(engine_state.clone());
|
||||
let config = engine_state.get_config().clone();
|
||||
|
||||
let highlighter = crate::NuHighlighter {
|
||||
engine_state,
|
||||
stack: std::sync::Arc::new(stack.clone()),
|
||||
config,
|
||||
engine_state: Arc::new(engine_state.clone()),
|
||||
stack: Arc::new(stack.clone()),
|
||||
};
|
||||
|
||||
input.map(
|
||||
|
@ -77,13 +77,19 @@ pub(crate) fn add_menus(
|
||||
mut line_editor: Reedline,
|
||||
engine_state_ref: Arc<EngineState>,
|
||||
stack: &Stack,
|
||||
config: &Config,
|
||||
config: Arc<Config>,
|
||||
) -> Result<Reedline, ShellError> {
|
||||
//log::trace!("add_menus: config: {:#?}", &config);
|
||||
line_editor = line_editor.clear_menus();
|
||||
|
||||
for menu in &config.menus {
|
||||
line_editor = add_menu(line_editor, menu, engine_state_ref.clone(), stack, config)?
|
||||
line_editor = add_menu(
|
||||
line_editor,
|
||||
menu,
|
||||
engine_state_ref.clone(),
|
||||
stack,
|
||||
config.clone(),
|
||||
)?
|
||||
}
|
||||
|
||||
// Checking if the default menus have been added from the config file
|
||||
@ -100,7 +106,7 @@ pub(crate) fn add_menus(
|
||||
if !config
|
||||
.menus
|
||||
.iter()
|
||||
.any(|menu| menu.name.to_expanded_string("", config) == name)
|
||||
.any(|menu| menu.name.to_expanded_string("", &config) == name)
|
||||
{
|
||||
let (block, delta) = {
|
||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||
@ -137,7 +143,7 @@ pub(crate) fn add_menus(
|
||||
&menu,
|
||||
new_engine_state_ref.clone(),
|
||||
stack,
|
||||
config,
|
||||
config.clone(),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
@ -151,27 +157,27 @@ fn add_menu(
|
||||
menu: &ParsedMenu,
|
||||
engine_state: Arc<EngineState>,
|
||||
stack: &Stack,
|
||||
config: &Config,
|
||||
config: Arc<Config>,
|
||||
) -> Result<Reedline, ShellError> {
|
||||
let span = menu.menu_type.span();
|
||||
if let Value::Record { val, .. } = &menu.menu_type {
|
||||
let layout = extract_value("layout", val, span)?.to_expanded_string("", config);
|
||||
let layout = extract_value("layout", val, span)?.to_expanded_string("", &config);
|
||||
|
||||
match layout.as_str() {
|
||||
"columnar" => add_columnar_menu(line_editor, menu, engine_state, stack, config),
|
||||
"columnar" => add_columnar_menu(line_editor, menu, engine_state, stack, &config),
|
||||
"list" => add_list_menu(line_editor, menu, engine_state, stack, config),
|
||||
"ide" => add_ide_menu(line_editor, menu, engine_state, stack, config),
|
||||
"description" => add_description_menu(line_editor, menu, engine_state, stack, config),
|
||||
_ => Err(ShellError::UnsupportedConfigValue {
|
||||
expected: "columnar, list, ide or description".to_string(),
|
||||
value: menu.menu_type.to_abbreviated_string(config),
|
||||
value: menu.menu_type.to_abbreviated_string(&config),
|
||||
span: menu.menu_type.span(),
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
Err(ShellError::UnsupportedConfigValue {
|
||||
expected: "only record type".to_string(),
|
||||
value: menu.menu_type.to_abbreviated_string(config),
|
||||
value: menu.menu_type.to_abbreviated_string(&config),
|
||||
span: menu.menu_type.span(),
|
||||
})
|
||||
}
|
||||
@ -282,9 +288,9 @@ pub(crate) fn add_list_menu(
|
||||
menu: &ParsedMenu,
|
||||
engine_state: Arc<EngineState>,
|
||||
stack: &Stack,
|
||||
config: &Config,
|
||||
config: Arc<Config>,
|
||||
) -> Result<Reedline, ShellError> {
|
||||
let name = menu.name.to_expanded_string("", config);
|
||||
let name = menu.name.to_expanded_string("", &config);
|
||||
let mut list_menu = ListMenu::default().with_name(&name);
|
||||
|
||||
let span = menu.menu_type.span();
|
||||
@ -311,7 +317,7 @@ pub(crate) fn add_list_menu(
|
||||
}
|
||||
}
|
||||
|
||||
let marker = menu.marker.to_expanded_string("", config);
|
||||
let marker = menu.marker.to_expanded_string("", &config);
|
||||
list_menu = list_menu.with_marker(&marker);
|
||||
|
||||
let only_buffer_difference = menu.only_buffer_difference.as_bool()?;
|
||||
@ -337,7 +343,7 @@ pub(crate) fn add_list_menu(
|
||||
}
|
||||
_ => Err(ShellError::UnsupportedConfigValue {
|
||||
expected: "block or omitted value".to_string(),
|
||||
value: menu.source.to_abbreviated_string(config),
|
||||
value: menu.source.to_abbreviated_string(&config),
|
||||
span: menu.source.span(),
|
||||
}),
|
||||
}
|
||||
@ -349,10 +355,10 @@ pub(crate) fn add_ide_menu(
|
||||
menu: &ParsedMenu,
|
||||
engine_state: Arc<EngineState>,
|
||||
stack: &Stack,
|
||||
config: &Config,
|
||||
config: Arc<Config>,
|
||||
) -> Result<Reedline, ShellError> {
|
||||
let span = menu.menu_type.span();
|
||||
let name = menu.name.to_expanded_string("", config);
|
||||
let name = menu.name.to_expanded_string("", &config);
|
||||
let mut ide_menu = IdeMenu::default().with_name(&name);
|
||||
|
||||
if let Value::Record { val, .. } = &menu.menu_type {
|
||||
@ -417,7 +423,7 @@ pub(crate) fn add_ide_menu(
|
||||
} else {
|
||||
return Err(ShellError::UnsupportedConfigValue {
|
||||
expected: "bool or record".to_string(),
|
||||
value: border.to_abbreviated_string(config),
|
||||
value: border.to_abbreviated_string(&config),
|
||||
span: border.span(),
|
||||
});
|
||||
}
|
||||
@ -441,7 +447,7 @@ pub(crate) fn add_ide_menu(
|
||||
_ => {
|
||||
return Err(ShellError::UnsupportedConfigValue {
|
||||
expected: "\"left\", \"right\" or \"prefer_right\"".to_string(),
|
||||
value: description_mode.to_abbreviated_string(config),
|
||||
value: description_mode.to_abbreviated_string(&config),
|
||||
span: description_mode.span(),
|
||||
});
|
||||
}
|
||||
@ -509,7 +515,7 @@ pub(crate) fn add_ide_menu(
|
||||
}
|
||||
}
|
||||
|
||||
let marker = menu.marker.to_expanded_string("", config);
|
||||
let marker = menu.marker.to_expanded_string("", &config);
|
||||
ide_menu = ide_menu.with_marker(&marker);
|
||||
|
||||
let only_buffer_difference = menu.only_buffer_difference.as_bool()?;
|
||||
@ -535,7 +541,7 @@ pub(crate) fn add_ide_menu(
|
||||
}
|
||||
_ => Err(ShellError::UnsupportedConfigValue {
|
||||
expected: "block or omitted value".to_string(),
|
||||
value: menu.source.to_abbreviated_string(config),
|
||||
value: menu.source.to_abbreviated_string(&config),
|
||||
span,
|
||||
}),
|
||||
}
|
||||
@ -547,9 +553,9 @@ pub(crate) fn add_description_menu(
|
||||
menu: &ParsedMenu,
|
||||
engine_state: Arc<EngineState>,
|
||||
stack: &Stack,
|
||||
config: &Config,
|
||||
config: Arc<Config>,
|
||||
) -> Result<Reedline, ShellError> {
|
||||
let name = menu.name.to_expanded_string("", config);
|
||||
let name = menu.name.to_expanded_string("", &config);
|
||||
let mut description_menu = DescriptionMenu::default().with_name(&name);
|
||||
|
||||
let span = menu.menu_type.span();
|
||||
@ -608,7 +614,7 @@ pub(crate) fn add_description_menu(
|
||||
}
|
||||
}
|
||||
|
||||
let marker = menu.marker.to_expanded_string("", config);
|
||||
let marker = menu.marker.to_expanded_string("", &config);
|
||||
description_menu = description_menu.with_marker(&marker);
|
||||
|
||||
let only_buffer_difference = menu.only_buffer_difference.as_bool()?;
|
||||
@ -617,7 +623,7 @@ pub(crate) fn add_description_menu(
|
||||
let span = menu.source.span();
|
||||
match &menu.source {
|
||||
Value::Nothing { .. } => {
|
||||
let completer = Box::new(NuHelpCompleter::new(engine_state));
|
||||
let completer = Box::new(NuHelpCompleter::new(engine_state, config));
|
||||
Ok(line_editor.with_menu(ReedlineMenu::WithCompleter {
|
||||
menu: Box::new(description_menu),
|
||||
completer,
|
||||
@ -638,7 +644,7 @@ pub(crate) fn add_description_menu(
|
||||
}
|
||||
_ => Err(ShellError::UnsupportedConfigValue {
|
||||
expected: "closure or omitted value".to_string(),
|
||||
value: menu.source.to_abbreviated_string(config),
|
||||
value: menu.source.to_abbreviated_string(&config),
|
||||
span: menu.source.span(),
|
||||
}),
|
||||
}
|
||||
|
@ -297,7 +297,7 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
|
||||
perf!("env-change hook", start_time, use_color);
|
||||
|
||||
let engine_reference = Arc::new(engine_state.clone());
|
||||
let config = engine_state.get_config();
|
||||
let config = stack.get_config(engine_state);
|
||||
|
||||
start_time = std::time::Instant::now();
|
||||
// Find the configured cursor shapes for each mode
|
||||
@ -323,7 +323,6 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
|
||||
engine_state: engine_reference.clone(),
|
||||
// STACK-REFERENCE 1
|
||||
stack: stack_arc.clone(),
|
||||
config: config.clone(),
|
||||
}))
|
||||
.with_validator(Box::new(NuValidator {
|
||||
engine_state: engine_reference.clone(),
|
||||
|
@ -6,7 +6,7 @@ use nu_parser::{flatten_block, parse, FlatShape};
|
||||
use nu_protocol::{
|
||||
ast::{Block, Expr, Expression, PipelineRedirection, RecordItem},
|
||||
engine::{EngineState, Stack, StateWorkingSet},
|
||||
Config, Span,
|
||||
Span,
|
||||
};
|
||||
use reedline::{Highlighter, StyledText};
|
||||
use std::sync::Arc;
|
||||
@ -14,15 +14,14 @@ use std::sync::Arc;
|
||||
pub struct NuHighlighter {
|
||||
pub engine_state: Arc<EngineState>,
|
||||
pub stack: Arc<Stack>,
|
||||
pub config: Config,
|
||||
}
|
||||
|
||||
impl Highlighter for NuHighlighter {
|
||||
fn highlight(&self, line: &str, _cursor: usize) -> StyledText {
|
||||
trace!("highlighting: {}", line);
|
||||
|
||||
let highlight_resolved_externals =
|
||||
self.engine_state.get_config().highlight_resolved_externals;
|
||||
let config = self.stack.get_config(&self.engine_state);
|
||||
let highlight_resolved_externals = config.highlight_resolved_externals;
|
||||
let mut working_set = StateWorkingSet::new(&self.engine_state);
|
||||
let block = parse(&mut working_set, None, line.as_bytes(), false);
|
||||
let (shapes, global_span_offset) = {
|
||||
@ -88,7 +87,7 @@ impl Highlighter for NuHighlighter {
|
||||
.to_string();
|
||||
|
||||
let mut add_colored_token = |shape: &FlatShape, text: String| {
|
||||
output.push((get_shape_color(shape.as_str(), &self.config), text));
|
||||
output.push((get_shape_color(shape.as_str(), &config), text));
|
||||
};
|
||||
|
||||
match shape.1 {
|
||||
@ -128,9 +127,9 @@ impl Highlighter for NuHighlighter {
|
||||
let start = part.start - span.start;
|
||||
let end = part.end - span.start;
|
||||
let text = next_token[start..end].to_string();
|
||||
let mut style = get_shape_color(shape.as_str(), &self.config);
|
||||
let mut style = get_shape_color(shape.as_str(), &config);
|
||||
if highlight {
|
||||
style = get_matching_brackets_style(style, &self.config);
|
||||
style = get_matching_brackets_style(style, &config);
|
||||
}
|
||||
output.push((style, text));
|
||||
}
|
||||
|
Reference in New Issue
Block a user