mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 09:35:44 +02:00
Refactor and fix Config
<->Value
mechanism (#10896)
# Description Our config exists both as a `Config` struct for internal consumption and as a `Value`. The latter is exposed through `$env.config` and can be both set and read. Thus we have a complex bug-prone mechanism, that reads a `Value` and then tries to plug anything where the value is unrepresentable in `Config` with the correct state from `Config`. The parsing involves therefore mutation of the `Value` in a nested `Record` structure. Previously this was wholy done manually, with indices. To enable deletion for example, things had to be iterated over from the back. Also things were indexed in a bunch of places. This was hard to read and an invitation for bugs. With #10876 we can now use `Record::retain_mut` to traverse the records, modify anything that needs fixing, and drop invalid fields. # Parts: - Error messages now consistently use the correct spans pointing to the problematic value and the paths displayed in some messages are also aligned with the keys used for lookup. - Reconstruction of values has been fixed for: - `table.padding` - `buffer_editor` - `hooks.command_not_found` - `datetime_format` (partial solution) - Fix validation of `table.padding` input so value is not set (and underflows `usize` causing `table` to run forever with negative values) - New proper types for settings. Fully validated enums instead of strings: - `config.edit_mode` -> `EditMode` - Don't fall back to vi-mode on invalid string - `config.table.mode` -> `TableMode` - there is still a fall back to `rounded` if given an invalid `TableMode` as argument to the `nu` binary - `config.completions.algorithm` -> `CompletionAlgorithm` - `config.error_style` -> `ErrorStyle` - don't implicitly fall back to `fancy` when given an invalid value. - This should also shrink the size of `Config` as instead of 4x24 bytes those fields now need only 4x1 bytes in `Config` - Completely removed macros relying on the scope of `Value::into_config` so we can break it up into smaller parts in the future. - Factored everything into smaller files with the types and helpers for particular topics. - `NuCursorShape` now explicitly expresses the `Inherit` setting. conversion to option only happens at the interface to `reedline`
This commit is contained in:
committed by
GitHub
parent
edbf3aaccb
commit
86cd387439
@ -1,6 +1,6 @@
|
||||
use crate::completions::{
|
||||
CommandCompletion, Completer, CompletionOptions, CustomCompletion, DirectoryCompletion,
|
||||
DotNuCompletion, FileCompletion, FlagCompletion, MatchAlgorithm, VariableCompletion,
|
||||
DotNuCompletion, FileCompletion, FlagCompletion, VariableCompletion,
|
||||
};
|
||||
use nu_engine::eval_block;
|
||||
use nu_parser::{flatten_expression, parse, FlatShape};
|
||||
@ -39,15 +39,12 @@ impl NuCompleter {
|
||||
) -> Vec<Suggestion> {
|
||||
let config = self.engine_state.get_config();
|
||||
|
||||
let mut options = CompletionOptions {
|
||||
let options = CompletionOptions {
|
||||
case_sensitive: config.case_sensitive_completions,
|
||||
match_algorithm: config.completion_algorithm.into(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
if config.completion_algorithm == "fuzzy" {
|
||||
options.match_algorithm = MatchAlgorithm::Fuzzy;
|
||||
}
|
||||
|
||||
// Fetch
|
||||
let mut suggestions =
|
||||
completer.fetch(working_set, prefix.clone(), new_span, offset, pos, &options);
|
||||
|
@ -2,6 +2,7 @@ use std::fmt::Display;
|
||||
|
||||
use fuzzy_matcher::{skim::SkimMatcherV2, FuzzyMatcher};
|
||||
use nu_parser::trim_quotes_str;
|
||||
use nu_protocol::CompletionAlgorithm;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum SortBy {
|
||||
@ -55,6 +56,15 @@ impl MatchAlgorithm {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CompletionAlgorithm> for MatchAlgorithm {
|
||||
fn from(value: CompletionAlgorithm) -> Self {
|
||||
match value {
|
||||
CompletionAlgorithm::Prefix => MatchAlgorithm::Prefix,
|
||||
CompletionAlgorithm::Fuzzy => MatchAlgorithm::Fuzzy,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for MatchAlgorithm {
|
||||
type Error = InvalidMatchAlgorithm;
|
||||
|
||||
|
@ -28,8 +28,8 @@ pub fn evaluate_commands(
|
||||
let (block, delta) = {
|
||||
if let Some(ref t_mode) = table_mode {
|
||||
let mut config = engine_state.get_config().clone();
|
||||
config.table_mode = t_mode.as_string()?;
|
||||
engine_state.set_config(&config);
|
||||
config.table_mode = t_mode.as_string()?.parse().unwrap_or_default();
|
||||
engine_state.set_config(config);
|
||||
}
|
||||
|
||||
let mut working_set = StateWorkingSet::new(engine_state);
|
||||
@ -55,7 +55,7 @@ pub fn evaluate_commands(
|
||||
Ok(pipeline_data) => {
|
||||
let mut config = engine_state.get_config().clone();
|
||||
if let Some(t_mode) = table_mode {
|
||||
config.table_mode = t_mode.as_string()?;
|
||||
config.table_mode = t_mode.as_string()?.parse().unwrap_or_default();
|
||||
}
|
||||
crate::eval_file::print_table_or_error(engine_state, stack, pipeline_data, &mut config)
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ pub(crate) fn print_table_or_error(
|
||||
};
|
||||
|
||||
// Change the engine_state config to use the passed in configuration
|
||||
engine_state.set_config(config);
|
||||
engine_state.set_config(config.clone());
|
||||
|
||||
if let PipelineData::Value(Value::Error { error, .. }, ..) = &pipeline_data {
|
||||
let working_set = StateWorkingSet::new(engine_state);
|
||||
|
@ -7,8 +7,8 @@ use nu_parser::parse;
|
||||
use nu_protocol::{
|
||||
create_menus,
|
||||
engine::{EngineState, Stack, StateWorkingSet},
|
||||
extract_value, Config, ParsedKeybinding, ParsedMenu, PipelineData, Record, ShellError, Span,
|
||||
Value,
|
||||
extract_value, Config, EditBindings, ParsedKeybinding, ParsedMenu, PipelineData, Record,
|
||||
ShellError, Span, Value,
|
||||
};
|
||||
use reedline::{
|
||||
default_emacs_keybindings, default_vi_insert_keybindings, default_vi_normal_keybindings,
|
||||
@ -537,11 +537,11 @@ pub(crate) fn create_keybindings(config: &Config) -> Result<KeybindingsMode, She
|
||||
let mut insert_keybindings = default_vi_insert_keybindings();
|
||||
let mut normal_keybindings = default_vi_normal_keybindings();
|
||||
|
||||
match config.edit_mode.as_str() {
|
||||
"emacs" => {
|
||||
match config.edit_mode {
|
||||
EditBindings::Emacs => {
|
||||
add_menu_keybindings(&mut emacs_keybindings);
|
||||
}
|
||||
_ => {
|
||||
EditBindings::Vi => {
|
||||
add_menu_keybindings(&mut insert_keybindings);
|
||||
add_menu_keybindings(&mut normal_keybindings);
|
||||
}
|
||||
@ -557,9 +557,9 @@ pub(crate) fn create_keybindings(config: &Config) -> Result<KeybindingsMode, She
|
||||
)?
|
||||
}
|
||||
|
||||
match config.edit_mode.as_str() {
|
||||
"emacs" => Ok(KeybindingsMode::Emacs(emacs_keybindings)),
|
||||
_ => Ok(KeybindingsMode::Vi {
|
||||
match config.edit_mode {
|
||||
EditBindings::Emacs => Ok(KeybindingsMode::Emacs(emacs_keybindings)),
|
||||
EditBindings::Vi => Ok(KeybindingsMode::Vi {
|
||||
insert_keybindings,
|
||||
normal_keybindings,
|
||||
}),
|
||||
|
@ -245,15 +245,9 @@ pub fn evaluate_repl(
|
||||
|
||||
// Find the configured cursor shapes for each mode
|
||||
let cursor_config = CursorConfig {
|
||||
vi_insert: config
|
||||
.cursor_shape_vi_insert
|
||||
.map(map_nucursorshape_to_cursorshape),
|
||||
vi_normal: config
|
||||
.cursor_shape_vi_normal
|
||||
.map(map_nucursorshape_to_cursorshape),
|
||||
emacs: config
|
||||
.cursor_shape_emacs
|
||||
.map(map_nucursorshape_to_cursorshape),
|
||||
vi_insert: map_nucursorshape_to_cursorshape(config.cursor_shape_vi_insert),
|
||||
vi_normal: map_nucursorshape_to_cursorshape(config.cursor_shape_vi_normal),
|
||||
emacs: map_nucursorshape_to_cursorshape(config.cursor_shape_emacs),
|
||||
};
|
||||
perf(
|
||||
"get config/cursor config",
|
||||
@ -770,14 +764,15 @@ fn update_line_editor_history(
|
||||
Ok(line_editor)
|
||||
}
|
||||
|
||||
fn map_nucursorshape_to_cursorshape(shape: NuCursorShape) -> SetCursorStyle {
|
||||
fn map_nucursorshape_to_cursorshape(shape: NuCursorShape) -> Option<SetCursorStyle> {
|
||||
match shape {
|
||||
NuCursorShape::Block => SetCursorStyle::SteadyBlock,
|
||||
NuCursorShape::UnderScore => SetCursorStyle::SteadyUnderScore,
|
||||
NuCursorShape::Line => SetCursorStyle::SteadyBar,
|
||||
NuCursorShape::BlinkBlock => SetCursorStyle::BlinkingBlock,
|
||||
NuCursorShape::BlinkUnderScore => SetCursorStyle::BlinkingUnderScore,
|
||||
NuCursorShape::BlinkLine => SetCursorStyle::BlinkingBar,
|
||||
NuCursorShape::Block => Some(SetCursorStyle::SteadyBlock),
|
||||
NuCursorShape::UnderScore => Some(SetCursorStyle::SteadyUnderScore),
|
||||
NuCursorShape::Line => Some(SetCursorStyle::SteadyBar),
|
||||
NuCursorShape::BlinkBlock => Some(SetCursorStyle::BlinkingBlock),
|
||||
NuCursorShape::BlinkUnderScore => Some(SetCursorStyle::BlinkingUnderScore),
|
||||
NuCursorShape::BlinkLine => Some(SetCursorStyle::BlinkingBar),
|
||||
NuCursorShape::Inherit => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user