Use IntoValue in config code (#13751)

# Description

Cleans up and refactors the config code using the `IntoValue` macro.
Shoutout to @cptpiepmatz for making the macro!

# User-Facing Changes

Should be none.

# After Submitting

Somehow refactor the reverse transformation.
This commit is contained in:
Ian Manske 2024-09-05 00:44:23 -07:00 committed by GitHub
parent 4792328d0e
commit abd230e12e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
37 changed files with 992 additions and 1206 deletions

View File

@ -55,7 +55,7 @@ impl Command for History {
HistoryFileFormat::Sqlite => {
history_path.push("history.sqlite3");
}
HistoryFileFormat::PlainText => {
HistoryFileFormat::Plaintext => {
history_path.push("history.txt");
}
}
@ -75,7 +75,7 @@ impl Command for History {
.ok()
}
HistoryFileFormat::PlainText => FileBackedHistory::with_file(
HistoryFileFormat::Plaintext => FileBackedHistory::with_file(
history.max_size as usize,
history_path.clone().into(),
)
@ -87,7 +87,7 @@ impl Command for History {
};
match history.file_format {
HistoryFileFormat::PlainText => Ok(history_reader
HistoryFileFormat::Plaintext => Ok(history_reader
.and_then(|h| {
h.search(SearchQuery::everything(SearchDirection::Forward, None))
.ok()

View File

@ -51,7 +51,9 @@ impl CommandCompletion {
if working_set
.permanent_state
.config
.max_external_completion_results
.completions
.external
.max_results
> executables.len() as i64
&& !executables.contains(
&item
@ -211,7 +213,7 @@ impl Completer for CommandCompletion {
working_set,
span,
offset,
config.enable_external_completion,
config.completions.external.enable,
options.match_algorithm,
)
} else {

View File

@ -46,9 +46,9 @@ impl NuCompleter {
let config = self.engine_state.get_config();
let options = CompletionOptions {
case_sensitive: config.case_sensitive_completions,
match_algorithm: config.completion_algorithm.into(),
sort: config.completion_sort,
case_sensitive: config.completions.case_sensitive,
match_algorithm: config.completions.algorithm.into(),
sort: config.completions.sort,
..Default::default()
};
@ -208,7 +208,7 @@ impl NuCompleter {
// We got no results for internal completion
// now we can check if external completer is set and use it
if let Some(closure) = config.external_completer.as_ref() {
if let Some(closure) = config.completions.external.completer.as_ref() {
if let Some(external_result) =
self.external_completion(closure, &spans, fake_offset, new_span)
{
@ -338,7 +338,9 @@ impl NuCompleter {
}
// Try to complete using an external completer (if set)
if let Some(closure) = config.external_completer.as_ref() {
if let Some(closure) =
config.completions.external.completer.as_ref()
{
if let Some(external_result) = self.external_completion(
closure,
&spans,

View File

@ -167,7 +167,7 @@ pub fn complete_item(
.rfind(|c: &char| is_separator(*c))
.unwrap_or(SEP);
let cwd_pathbuf = Path::new(cwd).to_path_buf();
let ls_colors = (engine_state.config.use_ls_colors_completions
let ls_colors = (engine_state.config.completions.use_ls_colors
&& engine_state.config.use_ansi_coloring)
.then(|| {
let ls_colors_env_str = match stack.get_env_var(engine_state, "LS_COLORS") {

View File

@ -245,7 +245,7 @@ pub(crate) fn get_history_path(storage_path: &str, mode: HistoryFileFormat) -> O
nu_path::config_dir().map(|mut history_path| {
history_path.push(storage_path);
history_path.push(match mode {
HistoryFileFormat::PlainText => HISTORY_FILE_TXT,
HistoryFileFormat::Plaintext => HISTORY_FILE_TXT,
HistoryFileFormat::Sqlite => HISTORY_FILE_SQLITE,
});
history_path.into()

View File

@ -53,7 +53,7 @@ pub fn evaluate_commands(
// Parse the source code
let (block, delta) = {
if let Some(ref t_mode) = table_mode {
Arc::make_mut(&mut engine_state.config).table_mode =
Arc::make_mut(&mut engine_state.config).table.mode =
t_mode.coerce_str()?.parse().unwrap_or_default();
}
@ -88,7 +88,7 @@ pub fn evaluate_commands(
}
if let Some(t_mode) = table_mode {
Arc::make_mut(&mut engine_state.config).table_mode =
Arc::make_mut(&mut engine_state.config).table.mode =
t_mode.coerce_str()?.parse().unwrap_or_default();
}

View File

@ -118,13 +118,13 @@ pub(crate) fn update_prompt(
// Now that we have the prompt string lets ansify it.
// <133 A><prompt><133 B><command><133 C><command output>
let left_prompt_string = if config.shell_integration_osc633 {
let left_prompt_string = if config.shell_integration.osc633 {
if stack.get_env_var(engine_state, "TERM_PROGRAM") == Some(Value::test_string("vscode")) {
// We're in vscode and we have osc633 enabled
Some(format!(
"{VSCODE_PRE_PROMPT_MARKER}{configured_left_prompt_string}{VSCODE_POST_PROMPT_MARKER}"
))
} else if config.shell_integration_osc133 {
} else if config.shell_integration.osc133 {
// If we're in VSCode but we don't find the env var, but we have osc133 set, then use it
Some(format!(
"{PRE_PROMPT_MARKER}{configured_left_prompt_string}{POST_PROMPT_MARKER}"
@ -132,7 +132,7 @@ pub(crate) fn update_prompt(
} else {
configured_left_prompt_string.into()
}
} else if config.shell_integration_osc133 {
} else if config.shell_integration.osc133 {
Some(format!(
"{PRE_PROMPT_MARKER}{configured_left_prompt_string}{POST_PROMPT_MARKER}"
))

View File

@ -159,8 +159,8 @@ fn add_menu(
stack: &Stack,
config: Arc<Config>,
) -> Result<Reedline, ShellError> {
let span = menu.menu_type.span();
if let Value::Record { val, .. } = &menu.menu_type {
let span = menu.r#type.span();
if let Value::Record { val, .. } = &menu.r#type {
let layout = extract_value("layout", val, span)?.to_expanded_string("", &config);
match layout.as_str() {
@ -170,15 +170,15 @@ fn add_menu(
"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),
span: menu.menu_type.span(),
value: menu.r#type.to_abbreviated_string(&config),
span: menu.r#type.span(),
}),
}
} else {
Err(ShellError::UnsupportedConfigValue {
expected: "only record type".to_string(),
value: menu.menu_type.to_abbreviated_string(&config),
span: menu.menu_type.span(),
value: menu.r#type.to_abbreviated_string(&config),
span: menu.r#type.span(),
})
}
}
@ -224,11 +224,11 @@ pub(crate) fn add_columnar_menu(
stack: &Stack,
config: &Config,
) -> Result<Reedline, ShellError> {
let span = menu.menu_type.span();
let span = menu.r#type.span();
let name = menu.name.to_expanded_string("", config);
let mut columnar_menu = ColumnarMenu::default().with_name(&name);
if let Value::Record { val, .. } = &menu.menu_type {
if let Value::Record { val, .. } = &menu.r#type {
columnar_menu = match extract_value("columns", val, span) {
Ok(columns) => {
let columns = columns.as_int()?;
@ -299,8 +299,8 @@ pub(crate) fn add_list_menu(
let name = menu.name.to_expanded_string("", &config);
let mut list_menu = ListMenu::default().with_name(&name);
let span = menu.menu_type.span();
if let Value::Record { val, .. } = &menu.menu_type {
let span = menu.r#type.span();
if let Value::Record { val, .. } = &menu.r#type {
list_menu = match extract_value("page_size", val, span) {
Ok(page_size) => {
let page_size = page_size.as_int()?;
@ -352,11 +352,11 @@ pub(crate) fn add_ide_menu(
stack: &Stack,
config: Arc<Config>,
) -> Result<Reedline, ShellError> {
let span = menu.menu_type.span();
let span = menu.r#type.span();
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 {
if let Value::Record { val, .. } = &menu.r#type {
ide_menu = match extract_value("min_completion_width", val, span) {
Ok(min_completion_width) => {
let min_completion_width = min_completion_width.as_int()?;
@ -536,8 +536,8 @@ pub(crate) fn add_description_menu(
let name = menu.name.to_expanded_string("", &config);
let mut description_menu = DescriptionMenu::default().with_name(&name);
let span = menu.menu_type.span();
if let Value::Record { val, .. } = &menu.menu_type {
let span = menu.r#type.span();
if let Value::Record { val, .. } = &menu.r#type {
description_menu = match extract_value("columns", val, span) {
Ok(columns) => {
let columns = columns.as_int()?;

View File

@ -72,11 +72,11 @@ pub fn evaluate_repl(
let mut entry_num = 0;
// Let's grab the shell_integration configs
let shell_integration_osc2 = config.shell_integration_osc2;
let shell_integration_osc7 = config.shell_integration_osc7;
let shell_integration_osc9_9 = config.shell_integration_osc9_9;
let shell_integration_osc133 = config.shell_integration_osc133;
let shell_integration_osc633 = config.shell_integration_osc633;
let shell_integration_osc2 = config.shell_integration.osc2;
let shell_integration_osc7 = config.shell_integration.osc7;
let shell_integration_osc9_9 = config.shell_integration.osc9_9;
let shell_integration_osc133 = config.shell_integration.osc133;
let shell_integration_osc633 = config.shell_integration.osc633;
let nu_prompt = NushellPrompt::new(
shell_integration_osc133,
@ -322,9 +322,9 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
start_time = std::time::Instant::now();
// Find the configured cursor shapes for each mode
let cursor_config = CursorConfig {
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),
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", start_time, use_color);
@ -352,8 +352,8 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
// STACK-REFERENCE 2
stack_arc.clone(),
)))
.with_quick_completions(config.quick_completions)
.with_partial_completions(config.partial_completions)
.with_quick_completions(config.completions.quick)
.with_partial_completions(config.completions.partial)
.with_ansi_colors(config.use_ansi_coloring)
.with_cwd(Some(
engine_state
@ -457,12 +457,12 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
.with_completer(Box::<DefaultCompleter>::default());
// Let's grab the shell_integration configs
let shell_integration_osc2 = config.shell_integration_osc2;
let shell_integration_osc7 = config.shell_integration_osc7;
let shell_integration_osc9_9 = config.shell_integration_osc9_9;
let shell_integration_osc133 = config.shell_integration_osc133;
let shell_integration_osc633 = config.shell_integration_osc633;
let shell_integration_reset_application_mode = config.shell_integration_reset_application_mode;
let shell_integration_osc2 = config.shell_integration.osc2;
let shell_integration_osc7 = config.shell_integration.osc7;
let shell_integration_osc9_9 = config.shell_integration.osc9_9;
let shell_integration_osc133 = config.shell_integration.osc133;
let shell_integration_osc633 = config.shell_integration.osc633;
let shell_integration_reset_application_mode = config.shell_integration.reset_application_mode;
// TODO: we may clone the stack, this can lead to major performance issues
// so we should avoid it or making stack cheaper to clone.
@ -1173,7 +1173,7 @@ fn update_line_editor_history(
history_session_id: Option<HistorySessionId>,
) -> Result<Reedline, ErrReport> {
let history: Box<dyn reedline::History> = match history.file_format {
HistoryFileFormat::PlainText => Box::new(
HistoryFileFormat::Plaintext => Box::new(
FileBackedHistory::with_file(history.max_size as usize, history_path)
.into_diagnostic()?,
),
@ -1211,10 +1211,10 @@ fn confirm_stdin_is_terminal() -> Result<()> {
fn map_nucursorshape_to_cursorshape(shape: NuCursorShape) -> Option<SetCursorStyle> {
match shape {
NuCursorShape::Block => Some(SetCursorStyle::SteadyBlock),
NuCursorShape::UnderScore => Some(SetCursorStyle::SteadyUnderScore),
NuCursorShape::Underscore => Some(SetCursorStyle::SteadyUnderScore),
NuCursorShape::Line => Some(SetCursorStyle::SteadyBar),
NuCursorShape::BlinkBlock => Some(SetCursorStyle::BlinkingBlock),
NuCursorShape::BlinkUnderScore => Some(SetCursorStyle::BlinkingUnderScore),
NuCursorShape::BlinkUnderscore => Some(SetCursorStyle::BlinkingUnderScore),
NuCursorShape::BlinkLine => Some(SetCursorStyle::BlinkingBar),
NuCursorShape::Inherit => None,
}

View File

@ -167,7 +167,7 @@ fn rm(
}
let span = call.head;
let rm_always_trash = stack.get_config(engine_state).rm_always_trash;
let rm_always_trash = stack.get_config(engine_state).rm.always_trash;
if !TRASH_SUPPORTED {
if rm_always_trash {

View File

@ -258,7 +258,7 @@ fn parse_table_config(
let flatten_separator: Option<String> = call.get_flag(state, stack, "flatten-separator")?;
let abbrivation: Option<usize> = call
.get_flag(state, stack, "abbreviated")?
.or_else(|| stack.get_config(state).table_abbreviation_threshold);
.or_else(|| stack.get_config(state).table.abbreviated_row_count);
let table_view = match (expand, collapse) {
(false, false) => TableView::General,
(_, true) => TableView::Collapsed,
@ -269,7 +269,7 @@ fn parse_table_config(
},
};
let theme =
get_theme_flag(call, state, stack)?.unwrap_or_else(|| stack.get_config(state).table_mode);
get_theme_flag(call, state, stack)?.unwrap_or_else(|| stack.get_config(state).table.mode);
let index = get_index_flag(call, state, stack)?;
let term_width = get_width_param(width_param);
@ -520,7 +520,7 @@ fn handle_record(
}
}
let indent = (config.table_indent.left, config.table_indent.right);
let indent = (config.table.padding.left, config.table.padding.right);
let opts = TableOpts::new(
&config,
styles,
@ -821,7 +821,7 @@ impl PagingTableCreator {
self.engine_state.signals(),
self.head,
self.cfg.term_width,
(cfg.table_indent.left, cfg.table_indent.right),
(cfg.table.padding.left, cfg.table.padding.right),
self.cfg.theme,
self.cfg.index.unwrap_or(0) + self.row_offset,
self.cfg.index.is_none(),
@ -1010,7 +1010,7 @@ fn render_path_name(
ls_colors: &LsColors,
span: Span,
) -> Option<Value> {
if !config.use_ls_colors {
if !config.ls.use_ls_colors {
return None;
}
@ -1024,10 +1024,10 @@ fn render_path_name(
// clickable links don't work in remote SSH sessions
let in_ssh_session = std::env::var("SSH_CLIENT").is_ok();
//TODO: Deprecated show_clickable_links_in_ls in favor of shell_integration_osc8
let show_clickable_links = config.show_clickable_links_in_ls
let show_clickable_links = config.ls.clickable_links
&& !in_ssh_session
&& has_metadata
&& config.shell_integration_osc8;
&& config.shell_integration.osc8;
let ansi_style = style.map(Style::to_nu_ansi_term_style).unwrap_or_default();
@ -1074,7 +1074,7 @@ fn create_empty_placeholder(
stack: &Stack,
) -> String {
let config = stack.get_config(engine_state);
if !config.table_show_empty {
if !config.table.show_empty {
return String::new();
}

View File

@ -1,5 +1,6 @@
use proc_macro2::Span;
use std::collections::HashMap;
use syn::ext::IdentExt;
use syn::Ident;
use crate::attributes::{ContainerAttributes, MemberAttributes};
@ -33,18 +34,17 @@ impl NameResolver {
/// If a duplicate identifier is detected, it returns [`DeriveError::NonUniqueName`].
pub fn resolve_ident<M>(
&mut self,
ident: &'_ Ident,
container_attrs: &'_ ContainerAttributes,
member_attrs: &'_ MemberAttributes,
ident: &Ident,
container_attrs: &ContainerAttributes,
member_attrs: &MemberAttributes,
default: impl Into<Option<Case>>,
) -> Result<String, DeriveError<M>> {
let span = ident.span();
let rename_all = container_attrs.rename_all;
let rename = member_attrs.rename.as_ref();
let ident = match (rename, rename_all) {
(Some(rename), _) => rename.to_string(),
(None, Some(case)) => ident.to_case(case),
(None, None) => ident.to_case(default),
let ident = if let Some(rename) = &member_attrs.rename {
rename.clone()
} else {
let case = container_attrs.rename_all.or(default.into());
ident.unraw().to_case(case)
};
if let Some(seen) = self.seen_names.get(&ident) {

View File

@ -177,8 +177,8 @@ impl ExploreConfig {
pub fn from_nu_config(config: &Config) -> Self {
let mut ret = Self::default();
ret.table.column_padding_left = config.table_indent.left;
ret.table.column_padding_right = config.table_indent.right;
ret.table.column_padding_left = config.table.padding.left;
ret.table.column_padding_right = config.table.padding.right;
let explore_cfg_hash_map = config.explore.clone();
let colors = get_color_map(&explore_cfg_hash_map);

View File

@ -36,8 +36,8 @@ fn try_build_map(
signals,
Span::unknown(),
usize::MAX,
(config.table_indent.left, config.table_indent.right),
config.table_mode,
(config.table.padding.left, config.table.padding.right),
config.table.mode,
0,
false,
);
@ -63,8 +63,8 @@ fn try_build_list(
signals,
Span::unknown(),
usize::MAX,
(config.table_indent.left, config.table_indent.right),
config.table_mode,
(config.table.padding.left, config.table.padding.right),
config.table.mode,
0,
false,
);

View File

@ -1,12 +1,8 @@
use std::str::FromStr;
use super::prelude::*;
use crate as nu_protocol;
use crate::engine::Closure;
use serde::{Deserialize, Serialize};
use crate::{record, Config, Span, Value};
use super::helper::ReconstructVal;
#[derive(Serialize, Deserialize, Clone, Copy, Debug, Default)]
#[derive(Clone, Copy, Debug, Default, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
pub enum CompletionAlgorithm {
#[default]
Prefix,
@ -25,17 +21,7 @@ impl FromStr for CompletionAlgorithm {
}
}
impl ReconstructVal for CompletionAlgorithm {
fn reconstruct_value(&self, span: Span) -> Value {
let str = match self {
CompletionAlgorithm::Prefix => "prefix",
CompletionAlgorithm::Fuzzy => "fuzzy",
};
Value::string(str, span)
}
}
#[derive(Serialize, Deserialize, Clone, Copy, Debug, Default, PartialEq)]
#[derive(Clone, Copy, Debug, Default, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
pub enum CompletionSort {
#[default]
Smart,
@ -54,31 +40,44 @@ impl FromStr for CompletionSort {
}
}
impl ReconstructVal for CompletionSort {
fn reconstruct_value(&self, span: Span) -> Value {
let str = match self {
Self::Smart => "smart",
Self::Alphabetical => "alphabetical",
};
Value::string(str, span)
#[derive(Clone, Debug, IntoValue, Serialize, Deserialize)]
pub struct ExternalCompleterConfig {
pub enable: bool,
pub max_results: i64,
pub completer: Option<Closure>,
}
impl Default for ExternalCompleterConfig {
fn default() -> Self {
Self {
enable: true,
max_results: 100,
completer: None,
}
}
}
pub(super) fn reconstruct_external_completer(config: &Config, span: Span) -> Value {
if let Some(closure) = config.external_completer.as_ref() {
Value::closure(closure.clone(), span)
} else {
Value::nothing(span)
}
#[derive(Clone, Debug, IntoValue, Serialize, Deserialize)]
pub struct CompleterConfig {
pub sort: CompletionSort,
pub case_sensitive: bool,
pub quick: bool,
pub partial: bool,
pub algorithm: CompletionAlgorithm,
pub external: ExternalCompleterConfig,
pub use_ls_colors: bool,
}
pub(super) fn reconstruct_external(config: &Config, span: Span) -> Value {
Value::record(
record! {
"max_results" => Value::int(config.max_external_completion_results, span),
"completer" => reconstruct_external_completer(config, span),
"enable" => Value::bool(config.enable_external_completion, span),
},
span,
)
impl Default for CompleterConfig {
fn default() -> Self {
Self {
sort: CompletionSort::default(),
case_sensitive: false,
quick: true,
partial: true,
algorithm: CompletionAlgorithm::default(),
external: ExternalCompleterConfig::default(),
use_ls_colors: true,
}
}
}

View File

@ -0,0 +1,8 @@
use super::prelude::*;
use crate as nu_protocol;
#[derive(Clone, Debug, Default, IntoValue, Serialize, Deserialize)]
pub struct DatetimeFormatConfig {
pub normal: Option<String>,
pub table: Option<String>,
}

View File

@ -0,0 +1,17 @@
use super::prelude::*;
use crate as nu_protocol;
#[derive(Clone, Debug, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
pub struct FilesizeConfig {
pub metric: bool,
pub format: String,
}
impl Default for FilesizeConfig {
fn default() -> Self {
Self {
metric: false,
format: "auto".into(),
}
}
}

View File

@ -1,17 +1,13 @@
use crate::{Record, ShellError, Span, Value};
use crate::{IntoValue, Record, ShellError, Span, Value};
use std::{collections::HashMap, fmt::Display, str::FromStr};
pub(super) trait ReconstructVal {
fn reconstruct_value(&self, span: Span) -> Value;
}
pub(super) fn process_string_enum<T, E>(
config_point: &mut T,
config_path: &[&str],
value: &mut Value,
errors: &mut Vec<ShellError>,
) where
T: FromStr<Err = E> + ReconstructVal,
T: FromStr<Err = E> + Clone + IntoValue,
E: Display,
{
let span = value.span();
@ -32,7 +28,7 @@ pub(super) fn process_string_enum<T, E>(
inner: vec![],
});
// Reconstruct
*value = config_point.reconstruct_value(span);
*value = config_point.clone().into_value(span);
}
}
} else {
@ -44,7 +40,7 @@ pub(super) fn process_string_enum<T, E>(
inner: vec![],
});
// Reconstruct
*value = config_point.reconstruct_value(span);
*value = config_point.clone().into_value(span);
}
}

View File

@ -0,0 +1,41 @@
use super::prelude::*;
use crate as nu_protocol;
#[derive(Clone, Copy, Debug, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
pub enum HistoryFileFormat {
/// Store history as an SQLite database with additional context
Sqlite,
/// store history as a plain text file where every line is one command (without any context such as timestamps)
Plaintext,
}
impl FromStr for HistoryFileFormat {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_ascii_lowercase().as_str() {
"sqlite" => Ok(Self::Sqlite),
"plaintext" => Ok(Self::Plaintext),
_ => Err("expected either 'sqlite' or 'plaintext'"),
}
}
}
#[derive(Clone, Copy, Debug, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
pub struct HistoryConfig {
pub max_size: i64,
pub sync_on_enter: bool,
pub file_format: HistoryFileFormat,
pub isolation: bool,
}
impl Default for HistoryConfig {
fn default() -> Self {
Self {
max_size: 100_000,
sync_on_enter: true,
file_format: HistoryFileFormat::Plaintext,
isolation: false,
}
}
}

View File

@ -1,8 +1,9 @@
use crate::{Config, Record, ShellError, Span, Value};
use serde::{Deserialize, Serialize};
use super::prelude::*;
use crate as nu_protocol;
use crate::ShellError;
/// Definition of a parsed hook from the config object
#[derive(Serialize, Deserialize, Clone, Debug)]
#[derive(Clone, Debug, IntoValue, PartialEq, Serialize, Deserialize)]
pub struct Hooks {
pub pre_prompt: Option<Value>,
pub pre_execution: Option<Value>,
@ -65,24 +66,3 @@ pub(super) fn create_hooks(value: &Value) -> Result<Hooks, ShellError> {
}),
}
}
pub(super) fn reconstruct_hooks(config: &Config, span: Span) -> Value {
let mut hook = Record::new();
if let Some(ref value) = config.hooks.pre_prompt {
hook.push("pre_prompt", value.clone());
}
if let Some(ref value) = config.hooks.pre_execution {
hook.push("pre_execution", value.clone());
}
if let Some(ref value) = config.hooks.env_change {
hook.push("env_change", value.clone());
}
if let Some(ref value) = config.hooks.display_output {
hook.push("display_output", value.clone());
}
if let Some(ref value) = config.hooks.command_not_found {
hook.push("command_not_found", value.clone());
}
Value::record(hook, span)
}

View File

@ -0,0 +1,17 @@
use super::prelude::*;
use crate as nu_protocol;
#[derive(Clone, Copy, Debug, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
pub struct LsConfig {
pub use_ls_colors: bool,
pub clickable_links: bool,
}
impl Default for LsConfig {
fn default() -> Self {
Self {
use_ls_colors: true,
clickable_links: true,
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,7 @@
use super::helper::ReconstructVal;
use crate::{Config, Record, Span, Value};
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use super::prelude::*;
use crate as nu_protocol;
#[derive(Serialize, Deserialize, Clone, Debug, Copy)]
#[derive(Clone, Copy, Debug, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
pub enum ErrorStyle {
Plain,
Fancy,
@ -20,26 +18,3 @@ impl FromStr for ErrorStyle {
}
}
}
impl ReconstructVal for ErrorStyle {
fn reconstruct_value(&self, span: Span) -> Value {
Value::string(
match self {
ErrorStyle::Fancy => "fancy",
ErrorStyle::Plain => "plain",
},
span,
)
}
}
pub(super) fn reconstruct_datetime_format(config: &Config, span: Span) -> Value {
let mut record = Record::new();
if let Some(normal) = &config.datetime_normal_format {
record.push("normal", Value::string(normal, span));
}
if let Some(table) = &config.datetime_table_format {
record.push("table", Value::string(table, span));
}
Value::record(record, span)
}

View File

@ -1,15 +1,11 @@
use super::helper::{process_bool_config, report_invalid_key, report_invalid_value};
use super::prelude::*;
use crate as nu_protocol;
use crate::ShellError;
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use crate::{record, ShellError, Span, Value};
use super::helper::{
process_bool_config, report_invalid_key, report_invalid_value, ReconstructVal,
};
/// Configures when plugins should be stopped if inactive
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
#[derive(Clone, Debug, Default, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
pub struct PluginGcConfigs {
/// The config to use for plugins not otherwise specified
pub default: PluginGcConfig,
@ -61,23 +57,11 @@ impl PluginGcConfigs {
});
} else {
report_invalid_value("should be a record", value.span(), errors);
*value = self.reconstruct_value(value.span());
*value = self.clone().into_value(value.span());
}
}
}
impl ReconstructVal for PluginGcConfigs {
fn reconstruct_value(&self, span: Span) -> Value {
Value::record(
record! {
"default" => self.default.reconstruct_value(span),
"plugins" => reconstruct_plugins(&self.plugins, span),
},
span,
)
}
}
fn process_plugins(
path: &[&str],
value: &mut Value,
@ -100,7 +84,7 @@ fn process_plugins(
report_invalid_value("should be a record", value.span(), errors);
if let Some(conf) = plugins.get(key) {
// Reconstruct the value if it existed before
*value = conf.reconstruct_value(value.span());
*value = conf.clone().into_value(value.span());
true
} else {
// Remove it if it didn't
@ -111,18 +95,8 @@ fn process_plugins(
}
}
fn reconstruct_plugins(plugins: &HashMap<String, PluginGcConfig>, span: Span) -> Value {
Value::record(
plugins
.iter()
.map(|(key, val)| (key.to_owned(), val.reconstruct_value(span)))
.collect(),
span,
)
}
/// Configures when a plugin should be stopped if inactive
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct PluginGcConfig {
/// True if the plugin should be stopped automatically
pub enabled: bool,
@ -139,6 +113,16 @@ impl Default for PluginGcConfig {
}
}
impl IntoValue for PluginGcConfig {
fn into_value(self, span: Span) -> Value {
record! {
"enabled" => self.enabled.into_value(span),
"stop_after" => Value::duration(self.stop_after, span),
}
.into_value(span)
}
}
impl PluginGcConfig {
fn process(&mut self, path: &[&str], value: &mut Value, errors: &mut Vec<ShellError>) {
if let Value::Record { val, .. } = value {
@ -177,23 +161,11 @@ impl PluginGcConfig {
})
} else {
report_invalid_value("should be a record", value.span(), errors);
*value = self.reconstruct_value(value.span());
*value = self.clone().into_value(value.span());
}
}
}
impl ReconstructVal for PluginGcConfig {
fn reconstruct_value(&self, span: Span) -> Value {
Value::record(
record! {
"enabled" => Value::bool(self.enabled, span),
"stop_after" => Value::duration(self.stop_after, span),
},
span,
)
}
}
fn join_path<'a>(a: &[&'a str], b: &[&'a str]) -> Vec<&'a str> {
a.iter().copied().chain(b.iter().copied()).collect()
}
@ -201,6 +173,7 @@ fn join_path<'a>(a: &[&'a str], b: &[&'a str]) -> Vec<&'a str> {
#[cfg(test)]
mod tests {
use super::*;
use nu_protocol::{record, Span};
fn test_pair() -> (PluginGcConfigs, Value) {
(
@ -247,6 +220,6 @@ mod tests {
#[test]
fn reconstruct() {
let (input, expected) = test_pair();
assert_eq!(expected, input.reconstruct_value(Span::test_data()));
assert_eq!(expected, input.into_value(Span::test_data()));
}
}

View File

@ -0,0 +1,3 @@
pub use crate::{record, IntoValue, Span, Value};
pub use serde::{Deserialize, Serialize};
pub use std::str::FromStr;

View File

@ -1,11 +1,9 @@
use std::str::FromStr;
use super::{extract_value, helper::ReconstructVal};
use crate::{record, Config, ShellError, Span, Value};
use serde::{Deserialize, Serialize};
use super::{extract_value, prelude::*};
use crate as nu_protocol;
use crate::ShellError;
/// Definition of a parsed keybinding from the config object
#[derive(Serialize, Deserialize, Clone, Debug)]
#[derive(Clone, Debug, IntoValue, Serialize, Deserialize)]
pub struct ParsedKeybinding {
pub modifier: Value,
pub keycode: Value,
@ -14,23 +12,23 @@ pub struct ParsedKeybinding {
}
/// Definition of a parsed menu from the config object
#[derive(Serialize, Deserialize, Clone, Debug)]
#[derive(Clone, Debug, IntoValue, Serialize, Deserialize)]
pub struct ParsedMenu {
pub name: Value,
pub marker: Value,
pub only_buffer_difference: Value,
pub style: Value,
pub menu_type: Value,
pub r#type: Value,
pub source: Value,
}
/// Definition of a Nushell CursorShape (to be mapped to crossterm::cursor::CursorShape)
#[derive(Serialize, Deserialize, Clone, Debug, Copy, Default)]
#[derive(Clone, Copy, Debug, Default, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
pub enum NuCursorShape {
UnderScore,
Underscore,
Line,
Block,
BlinkUnderScore,
BlinkUnderscore,
BlinkLine,
BlinkBlock,
#[default]
@ -44,66 +42,24 @@ impl FromStr for NuCursorShape {
match s.to_ascii_lowercase().as_str() {
"line" => Ok(NuCursorShape::Line),
"block" => Ok(NuCursorShape::Block),
"underscore" => Ok(NuCursorShape::UnderScore),
"underscore" => Ok(NuCursorShape::Underscore),
"blink_line" => Ok(NuCursorShape::BlinkLine),
"blink_block" => Ok(NuCursorShape::BlinkBlock),
"blink_underscore" => Ok(NuCursorShape::BlinkUnderScore),
"blink_underscore" => Ok(NuCursorShape::BlinkUnderscore),
"inherit" => Ok(NuCursorShape::Inherit),
_ => Err("expected either 'line', 'block', 'underscore', 'blink_line', 'blink_block', 'blink_underscore' or 'inherit'"),
}
}
}
impl ReconstructVal for NuCursorShape {
fn reconstruct_value(&self, span: Span) -> Value {
Value::string(
match self {
NuCursorShape::Line => "line",
NuCursorShape::Block => "block",
NuCursorShape::UnderScore => "underscore",
NuCursorShape::BlinkLine => "blink_line",
NuCursorShape::BlinkBlock => "blink_block",
NuCursorShape::BlinkUnderScore => "blink_underscore",
NuCursorShape::Inherit => "inherit",
},
span,
)
}
#[derive(Clone, Copy, Debug, Default, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
pub struct CursorShapeConfig {
pub emacs: NuCursorShape,
pub vi_insert: NuCursorShape,
pub vi_normal: NuCursorShape,
}
#[derive(Serialize, Deserialize, Clone, Debug, Copy)]
pub enum HistoryFileFormat {
/// Store history as an SQLite database with additional context
Sqlite,
/// store history as a plain text file where every line is one command (without any context such as timestamps)
PlainText,
}
impl FromStr for HistoryFileFormat {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_ascii_lowercase().as_str() {
"sqlite" => Ok(Self::Sqlite),
"plaintext" => Ok(Self::PlainText),
_ => Err("expected either 'sqlite' or 'plaintext'"),
}
}
}
impl ReconstructVal for HistoryFileFormat {
fn reconstruct_value(&self, span: Span) -> Value {
Value::string(
match self {
HistoryFileFormat::Sqlite => "sqlite",
HistoryFileFormat::PlainText => "plaintext",
},
span,
)
}
}
#[derive(Serialize, Deserialize, Clone, Debug, Default, Copy)]
#[derive(Clone, Copy, Debug, Default, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
pub enum EditBindings {
Vi,
#[default]
@ -122,18 +78,6 @@ impl FromStr for EditBindings {
}
}
impl ReconstructVal for EditBindings {
fn reconstruct_value(&self, span: Span) -> Value {
Value::string(
match self {
EditBindings::Vi => "vi",
EditBindings::Emacs => "emacs",
},
span,
)
}
}
/// Parses the config object to extract the strings that will compose a keybinding for reedline
pub(super) fn create_keybindings(value: &Value) -> Result<Vec<ParsedKeybinding>, ShellError> {
let span = value.span();
@ -172,34 +116,6 @@ pub(super) fn create_keybindings(value: &Value) -> Result<Vec<ParsedKeybinding>,
}
}
pub(super) fn reconstruct_keybindings(config: &Config, span: Span) -> Value {
Value::list(
config
.keybindings
.iter()
.map(
|ParsedKeybinding {
modifier,
keycode,
mode,
event,
}| {
Value::record(
record! {
"modifier" => modifier.clone(),
"keycode" => keycode.clone(),
"mode" => mode.clone(),
"event" => event.clone(),
},
span,
)
},
)
.collect(),
span,
)
}
/// Parses the config object to extract the strings that will compose a keybinding for reedline
pub fn create_menus(value: &Value) -> Result<Vec<ParsedMenu>, ShellError> {
let span = value.span();
@ -211,7 +127,7 @@ pub fn create_menus(value: &Value) -> Result<Vec<ParsedMenu>, ShellError> {
let only_buffer_difference =
extract_value("only_buffer_difference", val, span)?.clone();
let style = extract_value("style", val, span)?.clone();
let menu_type = extract_value("type", val, span)?.clone();
let r#type = extract_value("type", val, span)?.clone();
// Source is an optional value
let source = match extract_value("source", val, span) {
@ -224,7 +140,7 @@ pub fn create_menus(value: &Value) -> Result<Vec<ParsedMenu>, ShellError> {
only_buffer_difference,
marker,
style,
menu_type,
r#type,
source,
};
@ -243,35 +159,3 @@ pub fn create_menus(value: &Value) -> Result<Vec<ParsedMenu>, ShellError> {
_ => Ok(Vec::new()),
}
}
pub(super) fn reconstruct_menus(config: &Config, span: Span) -> Value {
Value::list(
config
.menus
.iter()
.map(
|ParsedMenu {
name,
only_buffer_difference,
marker,
style,
menu_type, // WARNING: this is not the same name as what is used in Config.nu! ("type")
source,
}| {
Value::record(
record! {
"name" => name.clone(),
"only_buffer_difference" => only_buffer_difference.clone(),
"marker" => marker.clone(),
"style" => style.clone(),
"type" => menu_type.clone(),
"source" => source.clone(),
},
span,
)
},
)
.collect(),
span,
)
}

View File

@ -0,0 +1,16 @@
use super::prelude::*;
use crate as nu_protocol;
#[derive(Clone, Copy, Debug, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
pub struct RmConfig {
pub always_trash: bool,
}
#[allow(clippy::derivable_impls)]
impl Default for RmConfig {
fn default() -> Self {
Self {
always_trash: false,
}
}
}

View File

@ -0,0 +1,28 @@
use super::prelude::*;
use crate as nu_protocol;
#[derive(Clone, Copy, Debug, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
pub struct ShellIntegrationConfig {
pub osc2: bool,
pub osc7: bool,
pub osc8: bool,
pub osc9_9: bool,
pub osc133: bool,
pub osc633: bool,
pub reset_application_mode: bool,
}
#[allow(clippy::derivable_impls)]
impl Default for ShellIntegrationConfig {
fn default() -> Self {
Self {
osc2: false,
osc7: false,
osc8: false,
osc9_9: false,
osc133: false,
osc633: false,
reset_application_mode: false,
}
}
}

View File

@ -1,9 +1,8 @@
use super::helper::ReconstructVal;
use crate::{record, Config, ShellError, Span, Value};
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use super::prelude::*;
use crate as nu_protocol;
use crate::ShellError;
#[derive(Serialize, Deserialize, Clone, Copy, Debug, Default)]
#[derive(Clone, Copy, Debug, Default, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
pub enum TableMode {
Basic,
Thin,
@ -51,33 +50,7 @@ impl FromStr for TableMode {
}
}
impl ReconstructVal for TableMode {
fn reconstruct_value(&self, span: Span) -> Value {
Value::string(
match self {
TableMode::Basic => "basic",
TableMode::Thin => "thin",
TableMode::Light => "light",
TableMode::Compact => "compact",
TableMode::WithLove => "with_love",
TableMode::CompactDouble => "compact_double",
TableMode::Rounded => "rounded",
TableMode::Reinforced => "reinforced",
TableMode::Heavy => "heavy",
TableMode::None => "none",
TableMode::Psql => "psql",
TableMode::Markdown => "markdown",
TableMode::Dots => "dots",
TableMode::Restructured => "restructured",
TableMode::AsciiRounded => "ascii_rounded",
TableMode::BasicCompact => "basic_compact",
},
span,
)
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum FooterMode {
/// Never show the footer
Never,
@ -108,21 +81,18 @@ impl FromStr for FooterMode {
}
}
impl ReconstructVal for FooterMode {
fn reconstruct_value(&self, span: Span) -> Value {
Value::string(
match self {
FooterMode::Always => "always".to_string(),
FooterMode::Never => "never".to_string(),
FooterMode::Auto => "auto".to_string(),
FooterMode::RowCount(c) => c.to_string(),
},
span,
)
impl IntoValue for FooterMode {
fn into_value(self, span: Span) -> Value {
match self {
FooterMode::Always => "always".into_value(span),
FooterMode::Never => "never".into_value(span),
FooterMode::Auto => "auto".into_value(span),
FooterMode::RowCount(c) => c.to_string().into_value(span),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[derive(Clone, Copy, Debug, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
pub enum TableIndexMode {
/// Always show indexes
Always,
@ -145,22 +115,9 @@ impl FromStr for TableIndexMode {
}
}
impl ReconstructVal for TableIndexMode {
fn reconstruct_value(&self, span: Span) -> Value {
Value::string(
match self {
TableIndexMode::Always => "always",
TableIndexMode::Never => "never",
TableIndexMode::Auto => "auto",
},
span,
)
}
}
/// A Table view configuration, for a situation where
/// we need to limit cell width in order to adjust for a terminal size.
#[derive(Serialize, Deserialize, Clone, Debug)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum TrimStrategy {
/// Wrapping strategy.
///
@ -196,7 +153,7 @@ impl TrimStrategy {
impl Default for TrimStrategy {
fn default() -> Self {
TrimStrategy::Wrap {
Self::Wrap {
try_to_keep_words: true,
}
}
@ -289,45 +246,89 @@ fn try_parse_trim_methodology(value: &Value) -> Option<TrimStrategy> {
None
}
pub(super) fn reconstruct_trim_strategy(config: &Config, span: Span) -> Value {
match &config.trim_strategy {
TrimStrategy::Wrap { try_to_keep_words } => Value::record(
record! {
"methodology" => Value::string("wrapping", span),
"wrapping_try_keep_words" => Value::bool(*try_to_keep_words, span),
},
span,
),
TrimStrategy::Truncate { suffix } => Value::record(
match suffix {
Some(s) => record! {
"methodology" => Value::string("truncating", span),
"truncating_suffix" => Value::string(s.clone(), span),
},
None => record! {
"methodology" => Value::string("truncating", span),
"truncating_suffix" => Value::nothing(span),
},
},
span,
),
impl IntoValue for TrimStrategy {
fn into_value(self, span: Span) -> Value {
match self {
TrimStrategy::Wrap { try_to_keep_words } => {
record! {
"methodology" => "wrapping".into_value(span),
"wrapping_try_keep_words" => try_to_keep_words.into_value(span),
}
}
TrimStrategy::Truncate { suffix } => {
record! {
"methodology" => "truncating".into_value(span),
"truncating_suffix" => suffix.into_value(span),
}
}
}
.into_value(span)
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct TableIndent {
pub left: usize,
pub right: usize,
}
pub(super) fn reconstruct_padding(config: &Config, span: Span) -> Value {
// For better completions always reconstruct the record version even though unsigned int would
// be supported, `as` conversion is sane as it came from an i64 original
Value::record(
record!(
"left" => Value::int(config.table_indent.left as i64, span),
"right" => Value::int(config.table_indent.right as i64, span),
),
span,
)
impl IntoValue for TableIndent {
fn into_value(self, span: Span) -> Value {
record! {
"left" => (self.left as i64).into_value(span),
"right" => (self.right as i64).into_value(span),
}
.into_value(span)
}
}
impl Default for TableIndent {
fn default() -> Self {
Self { left: 1, right: 1 }
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct TableConfig {
pub mode: TableMode,
pub index_mode: TableIndexMode,
pub show_empty: bool,
pub padding: TableIndent,
pub trim: TrimStrategy,
pub header_on_separator: bool,
pub abbreviated_row_count: Option<usize>,
}
impl IntoValue for TableConfig {
fn into_value(self, span: Span) -> Value {
let abbv_count = self
.abbreviated_row_count
.map(|t| t as i64)
.into_value(span);
record! {
"mode" => self.mode.into_value(span),
"index_mode" => self.index_mode.into_value(span),
"show_empty" => self.show_empty.into_value(span),
"padding" => self.padding.into_value(span),
"trim" => self.trim.into_value(span),
"header_on_separator" => self.header_on_separator.into_value(span),
"abbreviated_row_count" => abbv_count,
}
.into_value(span)
}
}
impl Default for TableConfig {
fn default() -> Self {
Self {
mode: TableMode::Rounded,
index_mode: TableIndexMode::Always,
show_empty: true,
trim: TrimStrategy::default(),
header_on_separator: false,
padding: TableIndent::default(),
abbreviated_row_count: None,
}
}
}

View File

@ -95,7 +95,7 @@ pub(crate) fn create_nu_constant(engine_state: &EngineState, span: Span) -> Valu
HistoryFileFormat::Sqlite => {
path.push("history.sqlite3");
}
HistoryFileFormat::PlainText => {
HistoryFileFormat::Plaintext => {
path.push("history.txt");
}
}

View File

@ -8,8 +8,8 @@ pub fn format_filesize_from_conf(num_bytes: i64, config: &Config) -> String {
// and filesize_metric is false, return KiB
format_filesize(
num_bytes,
config.filesize_format.as_str(),
Some(config.filesize_metric),
&config.filesize.format,
Some(config.filesize.metric),
)
}

View File

@ -832,7 +832,7 @@ impl Value {
Value::Float { val, .. } => val.to_string(),
Value::Filesize { val, .. } => format_filesize_from_conf(*val, config),
Value::Duration { val, .. } => format_duration(*val),
Value::Date { val, .. } => match &config.datetime_normal_format {
Value::Date { val, .. } => match &config.datetime_format.normal {
Some(format) => self.format_datetime(val, format),
None => {
format!(
@ -886,7 +886,7 @@ impl Value {
/// - "[record {n} fields]"
pub fn to_abbreviated_string(&self, config: &Config) -> String {
match self {
Value::Date { val, .. } => match &config.datetime_table_format {
Value::Date { val, .. } => match &config.datetime_format.table {
Some(format) => self.format_datetime(val, format),
None => HumanTime::from(*val).to_string(),
},

View File

@ -23,8 +23,8 @@ pub fn create_nu_table_config(
with_index: out.with_index,
with_header: out.with_header,
split_color: Some(lookup_separator_color(comp)),
trim: config.trim_strategy.clone(),
header_on_border: config.table_move_header,
trim: config.table.trim.clone(),
header_on_border: config.table.header_on_separator,
expand,
}
}
@ -62,7 +62,8 @@ pub fn error_sign(style_computer: &StyleComputer) -> (String, TextStyle) {
}
pub fn wrap_text(text: &str, width: usize, config: &Config) -> String {
string_wrap(text, width, is_cfg_trim_keep_words(config))
let keep_words = config.table.trim == TrimStrategy::wrap(true);
string_wrap(text, width, keep_words)
}
pub fn get_header_style(style_computer: &StyleComputer) -> TextStyle {
@ -163,15 +164,6 @@ fn convert_with_precision(val: &str, precision: usize) -> Result<String, ShellEr
Ok(format!("{val_float:.precision$}"))
}
fn is_cfg_trim_keep_words(config: &Config) -> bool {
matches!(
config.trim_strategy,
TrimStrategy::Wrap {
try_to_keep_words: true
}
)
}
pub fn load_theme(mode: TableMode) -> TableTheme {
match mode {
TableMode::Basic => TableTheme::basic(),

View File

@ -36,7 +36,7 @@ fn collapsed_table(
return Ok(None);
}
let indent = (config.table_indent.left, config.table_indent.right);
let indent = (config.table.padding.left, config.table.padding.right);
let table = table.draw(style_computer, &theme, indent);
Ok(Some(table))

View File

@ -26,8 +26,8 @@ impl JustTable {
fn create_table(input: &[Value], opts: TableOpts<'_>) -> Result<Option<String>, ShellError> {
match table(input, &opts)? {
Some(mut out) => {
let left = opts.config.table_indent.left;
let right = opts.config.table_indent.right;
let left = opts.config.table.padding.left;
let right = opts.config.table.padding.right;
out.table.set_indent(left, right);
colorize_space(out.table.get_records_mut(), opts.style_computer);
@ -59,8 +59,8 @@ fn kv_table(record: &Record, opts: TableOpts<'_>) -> StringResult {
let mut out = TableOutput::new(table, false, true);
let left = opts.config.table_indent.left;
let right = opts.config.table_indent.right;
let left = opts.config.table.padding.left;
let right = opts.config.table.padding.right;
out.table.set_indent(left, right);
let table_config =

View File

@ -67,7 +67,7 @@ impl<'a> TableOpts<'a> {
}
fn has_index(opts: &TableOpts<'_>, headers: &[String]) -> bool {
let with_index = match opts.config.table_index_mode {
let with_index = match opts.config.table.index_mode {
TableIndexMode::Always => true,
TableIndexMode::Never => false,
TableIndexMode::Auto => headers.iter().any(|header| header == INDEX_COLUMN_NAME),