forked from extern/nushell
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:
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
8
crates/nu-protocol/src/config/datetime_format.rs
Normal file
8
crates/nu-protocol/src/config/datetime_format.rs
Normal 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>,
|
||||
}
|
17
crates/nu-protocol/src/config/filesize.rs
Normal file
17
crates/nu-protocol/src/config/filesize.rs
Normal 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(),
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
41
crates/nu-protocol/src/config/history.rs
Normal file
41
crates/nu-protocol/src/config/history.rs
Normal 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,
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
17
crates/nu-protocol/src/config/ls.rs
Normal file
17
crates/nu-protocol/src/config/ls.rs
Normal 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
@ -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)
|
||||
}
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
3
crates/nu-protocol/src/config/prelude.rs
Normal file
3
crates/nu-protocol/src/config/prelude.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub use crate::{record, IntoValue, Span, Value};
|
||||
pub use serde::{Deserialize, Serialize};
|
||||
pub use std::str::FromStr;
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
16
crates/nu-protocol/src/config/rm.rs
Normal file
16
crates/nu-protocol/src/config/rm.rs
Normal 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,
|
||||
}
|
||||
}
|
||||
}
|
28
crates/nu-protocol/src/config/shell_integration.rs
Normal file
28
crates/nu-protocol/src/config/shell_integration.rs
Normal 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,
|
||||
}
|
||||
}
|
||||
}
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
},
|
||||
|
Reference in New Issue
Block a user