mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 07:16:05 +02:00
Add a config variable with engine support (#332)
* Add a config variable with engine support * Add a config variable with engine support * Oops, cleanup
This commit is contained in:
40
crates/nu-protocol/src/config.rs
Normal file
40
crates/nu-protocol/src/config.rs
Normal file
@ -0,0 +1,40 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{ShellError, Value};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct Config {
|
||||
pub filesize_metric: bool,
|
||||
pub table_mode: String,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Config {
|
||||
Config {
|
||||
filesize_metric: false,
|
||||
table_mode: "rounded".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Value {
|
||||
pub fn into_config(self) -> Result<Config, ShellError> {
|
||||
let v = self.as_record()?;
|
||||
|
||||
let mut config = Config::default();
|
||||
|
||||
for (key, value) in v.0.iter().zip(v.1) {
|
||||
match key.as_str() {
|
||||
"filesize_metric" => {
|
||||
config.filesize_metric = value.as_bool()?;
|
||||
}
|
||||
"table_mode" => {
|
||||
config.table_mode = value.as_string()?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
}
|
@ -136,13 +136,14 @@ pub struct EngineState {
|
||||
pub const NU_VARIABLE_ID: usize = 0;
|
||||
pub const SCOPE_VARIABLE_ID: usize = 1;
|
||||
pub const IN_VARIABLE_ID: usize = 2;
|
||||
pub const CONFIG_VARIABLE_ID: usize = 3;
|
||||
|
||||
impl EngineState {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
files: im::vector![],
|
||||
file_contents: im::vector![],
|
||||
vars: im::vector![Type::Unknown, Type::Unknown, Type::Unknown],
|
||||
vars: im::vector![Type::Unknown, Type::Unknown, Type::Unknown, Type::Unknown],
|
||||
decls: im::vector![],
|
||||
blocks: im::vector![],
|
||||
scope: im::vector![ScopeFrame::new()],
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{ShellError, Value, VarId};
|
||||
use crate::{Config, ShellError, Value, VarId, CONFIG_VARIABLE_ID};
|
||||
|
||||
/// A runtime value stack used during evaluation
|
||||
///
|
||||
@ -42,6 +42,7 @@ impl Stack {
|
||||
if let Some(v) = self.vars.get(&var_id) {
|
||||
return Ok(v.clone());
|
||||
}
|
||||
|
||||
Err(ShellError::InternalError("variable not found".into()))
|
||||
}
|
||||
|
||||
@ -67,6 +68,11 @@ impl Stack {
|
||||
// FIXME: this is probably slow
|
||||
output.env_vars = self.env_vars.clone();
|
||||
|
||||
let config = self
|
||||
.get_var(CONFIG_VARIABLE_ID)
|
||||
.expect("internal error: config is missing");
|
||||
output.vars.insert(CONFIG_VARIABLE_ID, config);
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
@ -81,6 +87,18 @@ impl Stack {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get_config(&self) -> Result<Config, ShellError> {
|
||||
let config = self.get_var(CONFIG_VARIABLE_ID);
|
||||
|
||||
match config {
|
||||
Ok(config) => config.into_config(),
|
||||
Err(e) => {
|
||||
println!("Can't find {} in {:?}", CONFIG_VARIABLE_ID, self);
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_stack(&self) {
|
||||
println!("vars:");
|
||||
for (var, val) in &self.vars {
|
||||
|
@ -1,4 +1,5 @@
|
||||
pub mod ast;
|
||||
mod config;
|
||||
pub mod engine;
|
||||
mod example;
|
||||
mod id;
|
||||
@ -11,7 +12,8 @@ mod ty;
|
||||
mod value;
|
||||
pub use value::Value;
|
||||
|
||||
pub use engine::{IN_VARIABLE_ID, NU_VARIABLE_ID, SCOPE_VARIABLE_ID};
|
||||
pub use config::*;
|
||||
pub use engine::{CONFIG_VARIABLE_ID, IN_VARIABLE_ID, NU_VARIABLE_ID, SCOPE_VARIABLE_ID};
|
||||
pub use example::*;
|
||||
pub use id::*;
|
||||
pub use pipeline_data::*;
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::sync::{atomic::AtomicBool, Arc};
|
||||
|
||||
use crate::{ast::PathMember, ShellError, Span, Value, ValueStream};
|
||||
use crate::{ast::PathMember, Config, ShellError, Span, Value, ValueStream};
|
||||
|
||||
/// The foundational abstraction for input and output to commands
|
||||
///
|
||||
@ -51,10 +51,10 @@ impl PipelineData {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn collect_string(self, separator: &str) -> String {
|
||||
pub fn collect_string(self, separator: &str, config: &Config) -> String {
|
||||
match self {
|
||||
PipelineData::Value(v) => v.into_string(separator),
|
||||
PipelineData::Stream(s) => s.into_string(separator),
|
||||
PipelineData::Value(v) => v.into_string(separator, config),
|
||||
PipelineData::Stream(s) => s.into_string(separator, config),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ pub enum ShellError {
|
||||
#[diagnostic(code(nu::shell::internal_error), url(docsrs))]
|
||||
InternalError(String),
|
||||
|
||||
#[error("Variable not found")]
|
||||
#[error("Variable not found!!!")]
|
||||
#[diagnostic(code(nu::shell::variable_not_found), url(docsrs))]
|
||||
VariableNotFoundAtRuntime(#[label = "variable not found"] Span),
|
||||
|
||||
|
@ -15,7 +15,7 @@ use std::collections::HashMap;
|
||||
use std::{cmp::Ordering, fmt::Debug};
|
||||
|
||||
use crate::ast::{CellPath, PathMember};
|
||||
use crate::{did_you_mean, span, BlockId, Span, Spanned, Type};
|
||||
use crate::{did_you_mean, span, BlockId, Config, Span, Spanned, Type};
|
||||
|
||||
use crate::ShellError;
|
||||
|
||||
@ -106,6 +106,28 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_record(&self) -> Result<(&[String], &[Value]), ShellError> {
|
||||
match self {
|
||||
Value::Record { cols, vals, .. } => Ok((cols, vals)),
|
||||
x => Err(ShellError::CantConvert(
|
||||
"record".into(),
|
||||
x.get_type().to_string(),
|
||||
self.span()?,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_bool(&self) -> Result<bool, ShellError> {
|
||||
match self {
|
||||
Value::Bool { val, .. } => Ok(*val),
|
||||
x => Err(ShellError::CantConvert(
|
||||
"boolean".into(),
|
||||
x.get_type().to_string(),
|
||||
self.span()?,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the span for the current value
|
||||
pub fn span(&self) -> Result<Span, ShellError> {
|
||||
match self {
|
||||
@ -174,26 +196,26 @@ impl Value {
|
||||
}
|
||||
|
||||
/// Convert Value into string. Note that Streams will be consumed.
|
||||
pub fn into_string(self, separator: &str) -> String {
|
||||
pub fn into_string(self, separator: &str, config: &Config) -> String {
|
||||
match self {
|
||||
Value::Bool { val, .. } => val.to_string(),
|
||||
Value::Int { val, .. } => val.to_string(),
|
||||
Value::Float { val, .. } => val.to_string(),
|
||||
Value::Filesize { val, .. } => format_filesize(val),
|
||||
Value::Filesize { val, .. } => format_filesize(val, config),
|
||||
Value::Duration { val, .. } => format_duration(val),
|
||||
Value::Date { val, .. } => HumanTime::from(val).to_string(),
|
||||
Value::Range { val, .. } => {
|
||||
format!(
|
||||
"{}..{}",
|
||||
val.from.into_string(", "),
|
||||
val.to.into_string(", ")
|
||||
val.from.into_string(", ", config),
|
||||
val.to.into_string(", ", config)
|
||||
)
|
||||
}
|
||||
Value::String { val, .. } => val,
|
||||
Value::List { vals: val, .. } => format!(
|
||||
"[{}]",
|
||||
val.into_iter()
|
||||
.map(|x| x.into_string(", "))
|
||||
.map(|x| x.into_string(", ", config))
|
||||
.collect::<Vec<_>>()
|
||||
.join(separator)
|
||||
),
|
||||
@ -201,7 +223,7 @@ impl Value {
|
||||
"{{{}}}",
|
||||
cols.iter()
|
||||
.zip(vals.iter())
|
||||
.map(|(x, y)| format!("{}: {}", x, y.clone().into_string(", ")))
|
||||
.map(|(x, y)| format!("{}: {}", x, y.clone().into_string(", ", config)))
|
||||
.collect::<Vec<_>>()
|
||||
.join(separator)
|
||||
),
|
||||
@ -214,26 +236,26 @@ impl Value {
|
||||
}
|
||||
|
||||
/// Convert Value into string. Note that Streams will be consumed.
|
||||
pub fn debug_string(self, separator: &str) -> String {
|
||||
pub fn debug_string(self, separator: &str, config: &Config) -> String {
|
||||
match self {
|
||||
Value::Bool { val, .. } => val.to_string(),
|
||||
Value::Int { val, .. } => val.to_string(),
|
||||
Value::Float { val, .. } => val.to_string(),
|
||||
Value::Filesize { val, .. } => format_filesize(val),
|
||||
Value::Filesize { val, .. } => format_filesize(val, config),
|
||||
Value::Duration { val, .. } => format_duration(val),
|
||||
Value::Date { val, .. } => format!("{:?}", val),
|
||||
Value::Range { val, .. } => {
|
||||
format!(
|
||||
"{}..{}",
|
||||
val.from.into_string(", "),
|
||||
val.to.into_string(", ")
|
||||
val.from.into_string(", ", config),
|
||||
val.to.into_string(", ", config)
|
||||
)
|
||||
}
|
||||
Value::String { val, .. } => val,
|
||||
Value::List { vals: val, .. } => format!(
|
||||
"[{}]",
|
||||
val.into_iter()
|
||||
.map(|x| x.into_string(", "))
|
||||
.map(|x| x.into_string(", ", config))
|
||||
.collect::<Vec<_>>()
|
||||
.join(separator)
|
||||
),
|
||||
@ -241,7 +263,7 @@ impl Value {
|
||||
"{{{}}}",
|
||||
cols.iter()
|
||||
.zip(vals.iter())
|
||||
.map(|(x, y)| format!("{}: {}", x, y.clone().into_string(", ")))
|
||||
.map(|(x, y)| format!("{}: {}", x, y.clone().into_string(", ", config)))
|
||||
.collect::<Vec<_>>()
|
||||
.join(separator)
|
||||
),
|
||||
@ -1171,14 +1193,14 @@ pub fn format_duration(duration: i64) -> String {
|
||||
)
|
||||
}
|
||||
|
||||
fn format_filesize(num_bytes: i64) -> String {
|
||||
fn format_filesize(num_bytes: i64, config: &Config) -> String {
|
||||
let byte = byte_unit::Byte::from_bytes(num_bytes as u128);
|
||||
|
||||
if byte.get_bytes() == 0u128 {
|
||||
return "—".to_string();
|
||||
}
|
||||
|
||||
let byte = byte.get_appropriate_unit(false);
|
||||
let byte = byte.get_appropriate_unit(config.filesize_metric);
|
||||
|
||||
match byte.get_unit() {
|
||||
byte_unit::ByteUnit::B => format!("{} B ", byte.get_value()),
|
||||
|
@ -6,7 +6,7 @@ use crate::*;
|
||||
pub struct RowStream(Rc<RefCell<dyn Iterator<Item = Vec<Value>>>>);
|
||||
|
||||
impl RowStream {
|
||||
pub fn into_string(self, headers: Vec<String>) -> String {
|
||||
pub fn into_string(self, headers: Vec<String>, config: &Config) -> String {
|
||||
format!(
|
||||
"[{}]\n[{}]",
|
||||
headers
|
||||
@ -16,7 +16,7 @@ impl RowStream {
|
||||
.join(", "),
|
||||
self.map(|x: Vec<Value>| {
|
||||
x.into_iter()
|
||||
.map(|x| x.into_string(", "))
|
||||
.map(|x| x.into_string(", ", config))
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ")
|
||||
})
|
||||
|
@ -19,8 +19,8 @@ pub struct ValueStream {
|
||||
}
|
||||
|
||||
impl ValueStream {
|
||||
pub fn into_string(self, separator: &str) -> String {
|
||||
self.map(|x: Value| x.into_string(", "))
|
||||
pub fn into_string(self, separator: &str, config: &Config) -> String {
|
||||
self.map(|x: Value| x.into_string(", ", config))
|
||||
.collect::<Vec<String>>()
|
||||
.join(separator)
|
||||
}
|
||||
|
Reference in New Issue
Block a user