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
37 changed files with 992 additions and 1206 deletions

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(),
},