From e9496583810103ce9491f27b03b5611087e4c39f Mon Sep 17 00:00:00 2001 From: Fernando Herrera Date: Mon, 20 Dec 2021 01:05:33 +0000 Subject: [PATCH] nothing variable (#527) * nothing variable * corrected comments * added color to nothing like bool * compare nothing with values * comparison tests --- crates/nu-cli/src/syntax_highlight.rs | 5 + crates/nu-color-config/src/shape_color.rs | 161 ++++------------------ crates/nu-engine/src/eval.rs | 1 + crates/nu-parser/src/flatten.rs | 5 + crates/nu-parser/src/parser.rs | 11 ++ crates/nu-parser/src/type_check.rs | 4 + crates/nu-parser/tests/test_parser.rs | 46 +++++++ crates/nu-protocol/src/ast/expr.rs | 1 + crates/nu-protocol/src/ast/expression.rs | 2 + crates/nu-protocol/src/value/mod.rs | 38 +++-- crates/nu-protocol/tests/test_value.rs | 45 ++++++ 11 files changed, 167 insertions(+), 152 deletions(-) create mode 100644 crates/nu-protocol/tests/test_value.rs diff --git a/crates/nu-cli/src/syntax_highlight.rs b/crates/nu-cli/src/syntax_highlight.rs index 7a3d903e67..f4cd8ee20b 100644 --- a/crates/nu-cli/src/syntax_highlight.rs +++ b/crates/nu-cli/src/syntax_highlight.rs @@ -44,6 +44,11 @@ impl Highlighter for NuHighlighter { get_shape_color(shape.1.to_string(), &self.config), next_token, )), + FlatShape::Nothing => output.push(( + // nushell Nothing + get_shape_color(shape.1.to_string(), &self.config), + next_token, + )), FlatShape::Bool => { // nushell ? output.push(( diff --git a/crates/nu-color-config/src/shape_color.rs b/crates/nu-color-config/src/shape_color.rs index e73ddd891e..4cc12ab3b7 100644 --- a/crates/nu-color-config/src/shape_color.rs +++ b/crates/nu-color-config/src/shape_color.rs @@ -3,143 +3,28 @@ use nu_ansi_term::{Color, Style}; use nu_protocol::Config; pub fn get_shape_color(shape: String, conf: &Config) -> Style { - match shape.as_ref() { - "flatshape_garbage" => { - if conf.color_config.contains_key("flatshape_garbage") { - let int_color = &conf.color_config["flatshape_garbage"]; - lookup_ansi_color_style(int_color.to_string()) - } else { - Style::new().fg(Color::White).on(Color::Red).bold() - } - } - "flatshape_bool" => { - if conf.color_config.contains_key("flatshape_bool") { - let int_color = &conf.color_config["flatshape_bool"]; - lookup_ansi_color_style(int_color.to_string()) - } else { - Style::new().fg(Color::LightCyan) - } - } - "flatshape_int" => { - if conf.color_config.contains_key("flatshape_int") { - let int_color = &conf.color_config["flatshape_int"]; - lookup_ansi_color_style(int_color.to_string()) - } else { - Style::new().fg(Color::Purple).bold() - } - } - "flatshape_float" => { - if conf.color_config.contains_key("flatshape_float") { - let int_color = &conf.color_config["flatshape_float"]; - lookup_ansi_color_style(int_color.to_string()) - } else { - Style::new().fg(Color::Purple).bold() - } - } - "flatshape_range" => { - if conf.color_config.contains_key("flatshape_range") { - let int_color = &conf.color_config["flatshape_range"]; - lookup_ansi_color_style(int_color.to_string()) - } else { - Style::new().fg(Color::Yellow).bold() - } - } - "flatshape_internalcall" => { - if conf.color_config.contains_key("flatshape_internalcall") { - let int_color = &conf.color_config["flatshape_internalcall"]; - lookup_ansi_color_style(int_color.to_string()) - } else { - Style::new().fg(Color::Cyan).bold() - } - } - "flatshape_external" => { - if conf.color_config.contains_key("flatshape_external") { - let int_color = &conf.color_config["flatshape_external"]; - lookup_ansi_color_style(int_color.to_string()) - } else { - Style::new().fg(Color::Cyan) - } - } - "flatshape_externalarg" => { - if conf.color_config.contains_key("flatshape_externalarg") { - let int_color = &conf.color_config["flatshape_externalarg"]; - lookup_ansi_color_style(int_color.to_string()) - } else { - Style::new().fg(Color::Green).bold() - } - } - "flatshape_literal" => { - if conf.color_config.contains_key("flatshape_literal") { - let int_color = &conf.color_config["flatshape_literal"]; - lookup_ansi_color_style(int_color.to_string()) - } else { - Style::new().fg(Color::Blue) - } - } - "flatshape_operator" => { - if conf.color_config.contains_key("flatshape_operator") { - let int_color = &conf.color_config["flatshape_operator"]; - lookup_ansi_color_style(int_color.to_string()) - } else { - Style::new().fg(Color::Yellow) - } - } - "flatshape_signature" => { - if conf.color_config.contains_key("flatshape_signature") { - let int_color = &conf.color_config["flatshape_signature"]; - lookup_ansi_color_style(int_color.to_string()) - } else { - Style::new().fg(Color::Green).bold() - } - } - "flatshape_string" => { - if conf.color_config.contains_key("flatshape_string") { - let int_color = &conf.color_config["flatshape_string"]; - lookup_ansi_color_style(int_color.to_string()) - } else { - Style::new().fg(Color::Green) - } - } - "flatshape_filepath" => { - if conf.color_config.contains_key("flatshape_filepath") { - let int_color = &conf.color_config["flatshape_filepath"]; - lookup_ansi_color_style(int_color.to_string()) - } else { - Style::new().fg(Color::Cyan) - } - } - "flatshape_globpattern" => { - if conf.color_config.contains_key("flatshape_globpattern") { - let int_color = &conf.color_config["flatshape_globpattern"]; - lookup_ansi_color_style(int_color.to_string()) - } else { - Style::new().fg(Color::Cyan).bold() - } - } - "flatshape_variable" => { - if conf.color_config.contains_key("flatshape_variable") { - let int_color = &conf.color_config["flatshape_variable"]; - lookup_ansi_color_style(int_color.to_string()) - } else { - Style::new().fg(Color::Purple) - } - } - "flatshape_flag" => { - if conf.color_config.contains_key("flatshape_flag") { - let int_color = &conf.color_config["flatshape_flag"]; - lookup_ansi_color_style(int_color.to_string()) - } else { - Style::new().fg(Color::Blue).bold() - } - } - "flatshape_custom" => { - if conf.color_config.contains_key("flatshape_custom") { - let int_color = &conf.color_config["flatshape_custom"]; - lookup_ansi_color_style(int_color.to_string()) - } else { - Style::new().bold() - } - } - _ => Style::default(), + match conf.color_config.get(shape.as_str()) { + Some(int_color) => lookup_ansi_color_style(int_color.to_string()), + None => match shape.as_ref() { + "flatshape_garbage" => Style::new().fg(Color::White).on(Color::Red).bold(), + "flatshape_bool" => Style::new().fg(Color::LightCyan), + "flatshape_int" => Style::new().fg(Color::Purple).bold(), + "flatshape_float" => Style::new().fg(Color::Purple).bold(), + "flatshape_range" => Style::new().fg(Color::Yellow).bold(), + "flatshape_internalcall" => Style::new().fg(Color::Cyan).bold(), + "flatshape_external" => Style::new().fg(Color::Cyan), + "flatshape_externalarg" => Style::new().fg(Color::Green).bold(), + "flatshape_literal" => Style::new().fg(Color::Blue), + "flatshape_operator" => Style::new().fg(Color::Yellow), + "flatshape_signature" => Style::new().fg(Color::Green).bold(), + "flatshape_string" => Style::new().fg(Color::Green), + "flatshape_filepath" => Style::new().fg(Color::Cyan), + "flatshape_globpattern" => Style::new().fg(Color::Cyan).bold(), + "flatshape_variable" => Style::new().fg(Color::Purple), + "flatshape_flag" => Style::new().fg(Color::Blue).bold(), + "flatshape_custom" => Style::new().bold(), + "flatshape_nothing" => Style::new().fg(Color::LightCyan), + _ => Style::default(), + }, } } diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index 9a5a972b9d..9498bb299b 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -346,6 +346,7 @@ pub fn eval_expression( }), Expr::Signature(_) => Ok(Value::Nothing { span: expr.span }), Expr::Garbage => Ok(Value::Nothing { span: expr.span }), + Expr::Nothing => Ok(Value::Nothing { span: expr.span }), } } diff --git a/crates/nu-parser/src/flatten.rs b/crates/nu-parser/src/flatten.rs index 7ae19fa89c..d4efe69a23 100644 --- a/crates/nu-parser/src/flatten.rs +++ b/crates/nu-parser/src/flatten.rs @@ -7,6 +7,7 @@ use std::fmt::{Display, Formatter, Result}; #[derive(Debug, Eq, PartialEq, Ord, PartialOrd)] pub enum FlatShape { Garbage, + Nothing, Bool, Int, Float, @@ -29,6 +30,7 @@ impl Display for FlatShape { fn fmt(&self, f: &mut Formatter) -> Result { match self { FlatShape::Garbage => write!(f, "flatshape_garbage"), + FlatShape::Nothing => write!(f, "flatshape_nothing"), FlatShape::Bool => write!(f, "flatshape_bool"), FlatShape::Int => write!(f, "flatshape_int"), FlatShape::Float => write!(f, "flatshape_float"), @@ -127,6 +129,9 @@ pub fn flatten_expression( Expr::Garbage => { vec![(expr.span, FlatShape::Garbage)] } + Expr::Nothing => { + vec![(expr.span, FlatShape::Nothing)] + } Expr::Int(_) => { vec![(expr.span, FlatShape::Int)] } diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 9842f3ac97..2b7c69de7f 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -1186,6 +1186,16 @@ pub fn parse_variable_expr( }, None, ); + } else if contents == b"$nothing" { + return ( + Expression { + expr: Expr::Nothing, + span, + ty: Type::Nothing, + custom_completion: None, + }, + None, + ); } else if contents == b"$nu" { return ( Expression { @@ -3483,6 +3493,7 @@ pub fn find_captures_in_expr( } Expr::ImportPattern(_) => {} Expr::Garbage => {} + Expr::Nothing => {} Expr::GlobPattern(_) => {} Expr::Int(_) => {} Expr::Keyword(_, _, expr) => { diff --git a/crates/nu-parser/src/type_check.rs b/crates/nu-parser/src/type_check.rs index 80fdc15058..a9f54f59eb 100644 --- a/crates/nu-parser/src/type_check.rs +++ b/crates/nu-parser/src/type_check.rs @@ -252,6 +252,8 @@ pub fn math_result_type( (Type::Filesize, Type::Filesize) => (Type::Bool, None), (x, y) if x == y => (Type::Bool, None), + (Type::Nothing, _) => (Type::Bool, None), + (_, Type::Nothing) => (Type::Bool, None), (Type::Unknown, _) => (Type::Bool, None), (_, Type::Unknown) => (Type::Bool, None), _ => { @@ -276,6 +278,8 @@ pub fn math_result_type( (Type::Duration, Type::Duration) => (Type::Bool, None), (Type::Filesize, Type::Filesize) => (Type::Bool, None), + (Type::Nothing, _) => (Type::Bool, None), + (_, Type::Nothing) => (Type::Bool, None), (Type::Unknown, _) => (Type::Bool, None), (_, Type::Unknown) => (Type::Bool, None), _ => { diff --git a/crates/nu-parser/tests/test_parser.rs b/crates/nu-parser/tests/test_parser.rs index 1b708f27e6..6c70c474b7 100644 --- a/crates/nu-parser/tests/test_parser.rs +++ b/crates/nu-parser/tests/test_parser.rs @@ -178,6 +178,52 @@ pub fn parse_call_missing_req_flag() { assert!(matches!(err, Some(ParseError::MissingRequiredFlag(..)))); } +#[test] +fn test_nothing_comparisson_eq() { + let engine_state = EngineState::new(); + let mut working_set = StateWorkingSet::new(&engine_state); + let (block, err) = parse(&mut working_set, None, b"2 == $nothing", true); + + assert!(err.is_none()); + assert!(block.len() == 1); + match &block[0] { + Statement::Pipeline(Pipeline { expressions }) => { + assert!(expressions.len() == 1); + assert!(matches!( + &expressions[0], + Expression { + expr: Expr::BinaryOp(..), + .. + } + )) + } + _ => panic!("No match"), + } +} + +#[test] +fn test_nothing_comparisson_neq() { + let engine_state = EngineState::new(); + let mut working_set = StateWorkingSet::new(&engine_state); + let (block, err) = parse(&mut working_set, None, b"2 != $nothing", true); + + assert!(err.is_none()); + assert!(block.len() == 1); + match &block[0] { + Statement::Pipeline(Pipeline { expressions }) => { + assert!(expressions.len() == 1); + assert!(matches!( + &expressions[0], + Expression { + expr: Expr::BinaryOp(..), + .. + } + )) + } + _ => panic!("No match"), + } +} + mod range { use super::*; use nu_protocol::ast::{RangeInclusion, RangeOperator}; diff --git a/crates/nu-protocol/src/ast/expr.rs b/crates/nu-protocol/src/ast/expr.rs index bdd0c61e8d..446df034cb 100644 --- a/crates/nu-protocol/src/ast/expr.rs +++ b/crates/nu-protocol/src/ast/expr.rs @@ -33,5 +33,6 @@ pub enum Expr { FullCellPath(Box), ImportPattern(ImportPattern), Signature(Box), + Nothing, Garbage, } diff --git a/crates/nu-protocol/src/ast/expression.rs b/crates/nu-protocol/src/ast/expression.rs index 374a970781..ca3393a59b 100644 --- a/crates/nu-protocol/src/ast/expression.rs +++ b/crates/nu-protocol/src/ast/expression.rs @@ -148,6 +148,7 @@ impl Expression { false } Expr::Garbage => false, + Expr::Nothing => false, Expr::GlobPattern(_) => false, Expr::Int(_) => false, Expr::Keyword(_, _, expr) => expr.has_in_variable(working_set), @@ -291,6 +292,7 @@ impl Expression { } Expr::ImportPattern(_) => {} Expr::Garbage => {} + Expr::Nothing => {} Expr::GlobPattern(_) => {} Expr::Int(_) => {} Expr::Keyword(_, _, expr) => expr.replace_in_variable(working_set, new_var_id), diff --git a/crates/nu-protocol/src/value/mod.rs b/crates/nu-protocol/src/value/mod.rs index 9a3c97e734..70606dcc57 100644 --- a/crates/nu-protocol/src/value/mod.rs +++ b/crates/nu-protocol/src/value/mod.rs @@ -1141,13 +1141,18 @@ impl Value { val: matches!(ordering, Ordering::Equal), span, }), - None => Err(ShellError::OperatorMismatch { - op_span: op, - lhs_ty: self.get_type(), - lhs_span: self.span()?, - rhs_ty: rhs.get_type(), - rhs_span: rhs.span()?, - }), + None => match (self, rhs) { + (Value::Nothing { .. }, _) | (_, Value::Nothing { .. }) => { + Ok(Value::Bool { val: false, span }) + } + _ => Err(ShellError::OperatorMismatch { + op_span: op, + lhs_ty: self.get_type(), + lhs_span: self.span()?, + rhs_ty: rhs.get_type(), + rhs_span: rhs.span()?, + }), + }, } } pub fn ne(&self, op: Span, rhs: &Value) -> Result { @@ -1162,13 +1167,18 @@ impl Value { val: !matches!(ordering, Ordering::Equal), span, }), - None => Err(ShellError::OperatorMismatch { - op_span: op, - lhs_ty: self.get_type(), - lhs_span: self.span()?, - rhs_ty: rhs.get_type(), - rhs_span: rhs.span()?, - }), + None => match (self, rhs) { + (Value::Nothing { .. }, _) | (_, Value::Nothing { .. }) => { + Ok(Value::Bool { val: true, span }) + } + _ => Err(ShellError::OperatorMismatch { + op_span: op, + lhs_ty: self.get_type(), + lhs_span: self.span()?, + rhs_ty: rhs.get_type(), + rhs_span: rhs.span()?, + }), + }, } } diff --git a/crates/nu-protocol/tests/test_value.rs b/crates/nu-protocol/tests/test_value.rs new file mode 100644 index 0000000000..65cbc3e33f --- /dev/null +++ b/crates/nu-protocol/tests/test_value.rs @@ -0,0 +1,45 @@ +use nu_protocol::{Span, Value}; + +#[test] +fn test_comparison_nothing() { + let values = vec![ + Value::Int { + val: 1, + span: Span::test_data(), + }, + Value::String { + val: "string".into(), + span: Span::test_data(), + }, + Value::Float { + val: 1.0, + span: Span::test_data(), + }, + ]; + + let nothing = Value::Nothing { + span: Span::test_data(), + }; + + for value in values { + assert!(matches!( + value.eq(Span::test_data(), ¬hing), + Ok(Value::Bool { val: false, .. }) + )); + + assert!(matches!( + value.ne(Span::test_data(), ¬hing), + Ok(Value::Bool { val: true, .. }) + )); + + assert!(matches!( + nothing.eq(Span::test_data(), &value), + Ok(Value::Bool { val: false, .. }) + )); + + assert!(matches!( + nothing.ne(Span::test_data(), &value), + Ok(Value::Bool { val: true, .. }) + )); + } +}