nushell/crates/nu-protocol/src/syntax_shape.rs

180 lines
6.0 KiB
Rust
Raw Normal View History

use std::fmt::Display;
use serde::{Deserialize, Serialize};
use crate::{DeclId, Type};
2021-09-02 03:29:43 +02:00
/// The syntactic shapes that values must match to be passed into a command. You can think of this as the type-checking that occurs when you call a function.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
2021-09-02 03:29:43 +02:00
pub enum SyntaxShape {
/// A specific match to a word or symbol
Keyword(Vec<u8>, Box<SyntaxShape>),
/// Any syntactic form is allowed
Any,
/// Strings and string-like bare words are allowed
String,
/// A dotted path to navigate the table
2021-09-07 00:02:24 +02:00
CellPath,
2021-09-02 03:29:43 +02:00
/// A dotted path to navigate the table (including variable)
2021-09-07 00:02:24 +02:00
FullCellPath,
2021-09-02 03:29:43 +02:00
/// Only a numeric (integer or decimal) value is allowed
Number,
/// A range is allowed (eg, `1..3`)
Range,
/// Only an integer value is allowed
Int,
/// A filepath is allowed
2021-10-04 21:21:31 +02:00
Filepath,
2021-09-02 03:29:43 +02:00
/// A directory is allowed
Directory,
2021-09-02 03:29:43 +02:00
/// A glob pattern is allowed, eg `foo*`
GlobPattern,
2021-09-26 20:39:19 +02:00
/// A module path pattern used for imports
ImportPattern,
2022-03-01 00:31:53 +01:00
/// A binary literal
Binary,
2021-09-02 03:29:43 +02:00
/// A block is allowed, eg `{start this thing}`
Block(Option<Vec<SyntaxShape>>),
2021-09-02 03:29:43 +02:00
/// A table is allowed, eg `[[first, second]; [1, 2]]`
Table,
/// A table is allowed, eg `[first second]`
List(Box<SyntaxShape>),
/// A filesize value is allowed, eg `10kb`
Filesize,
/// A duration value is allowed, eg `19day`
Duration,
/// A datetime value, eg `2022-02-02` or `2019-10-12T07:20:50.52+00:00`
DateTime,
2021-09-02 03:29:43 +02:00
/// An operator
Operator,
/// A math expression which expands shorthand forms on the lefthand side, eg `foo > 1`
/// The shorthand allows us to more easily reach columns inside of the row being passed in
RowCondition,
/// A general math expression, eg `1 + 2`
MathExpression,
/// A variable name
Variable,
/// A variable with optional type, `x` or `x: int`
VarWithOptType,
/// A signature for a definition, `[x:int, --foo]`
Signature,
/// A general expression, eg `1 + 2` or `foo --bar`
Expression,
2021-10-12 06:49:17 +02:00
/// A boolean value
Boolean,
2022-01-16 00:50:11 +01:00
/// A record value
Record,
/// An error value
Error,
/// A custom shape with custom completion logic
Custom(Box<SyntaxShape>, DeclId),
2021-09-02 03:29:43 +02:00
}
impl SyntaxShape {
pub fn to_type(&self) -> Type {
match self {
SyntaxShape::Any => Type::Any,
SyntaxShape::Block(_) => Type::Block,
2022-03-01 00:31:53 +01:00
SyntaxShape::Binary => Type::Binary,
SyntaxShape::CellPath => Type::Any,
SyntaxShape::Custom(custom, _) => custom.to_type(),
SyntaxShape::DateTime => Type::Date,
2021-09-02 03:29:43 +02:00
SyntaxShape::Duration => Type::Duration,
SyntaxShape::Expression => Type::Any,
2021-10-04 21:21:31 +02:00
SyntaxShape::Filepath => Type::String,
SyntaxShape::Directory => Type::String,
2021-09-02 03:29:43 +02:00
SyntaxShape::Filesize => Type::Filesize,
SyntaxShape::FullCellPath => Type::Any,
2021-09-02 03:29:43 +02:00
SyntaxShape::GlobPattern => Type::String,
SyntaxShape::Error => Type::Error,
SyntaxShape::ImportPattern => Type::Any,
2021-09-02 03:29:43 +02:00
SyntaxShape::Int => Type::Int,
SyntaxShape::List(x) => {
let contents = x.to_type();
Type::List(Box::new(contents))
}
SyntaxShape::Keyword(_, expr) => expr.to_type(),
SyntaxShape::MathExpression => Type::Any,
2021-09-02 03:29:43 +02:00
SyntaxShape::Number => Type::Number,
SyntaxShape::Operator => Type::Any,
SyntaxShape::Range => Type::Any,
2022-01-16 00:50:11 +01:00
SyntaxShape::Record => Type::Record(vec![]), // FIXME: Add actual record type
2021-09-02 03:29:43 +02:00
SyntaxShape::RowCondition => Type::Bool,
2021-10-12 06:49:17 +02:00
SyntaxShape::Boolean => Type::Bool,
SyntaxShape::Signature => Type::Signature,
2021-09-02 03:29:43 +02:00
SyntaxShape::String => Type::String,
SyntaxShape::Table => Type::List(Box::new(Type::Any)), // FIXME: Tables should have better types
SyntaxShape::VarWithOptType => Type::Any,
SyntaxShape::Variable => Type::Any,
}
}
}
impl Display for SyntaxShape {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SyntaxShape::Keyword(kw, shape) => {
write!(f, "\"{}\" {}", String::from_utf8_lossy(kw), shape)
}
SyntaxShape::Any => write!(f, "any"),
SyntaxShape::String => write!(f, "string"),
SyntaxShape::CellPath => write!(f, "cellpath"),
SyntaxShape::FullCellPath => write!(f, "cellpath"),
SyntaxShape::Number => write!(f, "number"),
SyntaxShape::Range => write!(f, "range"),
SyntaxShape::Int => write!(f, "int"),
SyntaxShape::Filepath => write!(f, "path"),
SyntaxShape::Directory => write!(f, "directory"),
SyntaxShape::GlobPattern => write!(f, "glob"),
SyntaxShape::ImportPattern => write!(f, "import"),
SyntaxShape::Block(_) => write!(f, "block"),
2022-03-01 00:31:53 +01:00
SyntaxShape::Binary => write!(f, "binary"),
SyntaxShape::Table => write!(f, "table"),
SyntaxShape::List(x) => write!(f, "list<{}>", x),
2022-01-16 00:50:11 +01:00
SyntaxShape::Record => write!(f, "record"),
SyntaxShape::Filesize => write!(f, "filesize"),
SyntaxShape::Duration => write!(f, "duration"),
SyntaxShape::DateTime => write!(f, "datetime"),
SyntaxShape::Operator => write!(f, "operator"),
SyntaxShape::RowCondition => write!(f, "condition"),
SyntaxShape::MathExpression => write!(f, "variable"),
SyntaxShape::Variable => write!(f, "var"),
SyntaxShape::VarWithOptType => write!(f, "vardecl"),
SyntaxShape::Signature => write!(f, "signature"),
SyntaxShape::Expression => write!(f, "expression"),
SyntaxShape::Boolean => write!(f, "bool"),
SyntaxShape::Error => write!(f, "error"),
SyntaxShape::Custom(x, _) => write!(f, "custom<{}>", x),
}
}
}