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:
JT
2021-11-15 08:25:57 +13:00
committed by GitHub
parent e76451866d
commit 0f107b2830
30 changed files with 333 additions and 96 deletions

View 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)
}
}

View File

@ -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()],

View File

@ -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 {

View File

@ -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::*;

View File

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

View File

@ -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),

View File

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

View File

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

View File

@ -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)
}