mirror of
https://github.com/nushell/nushell.git
synced 2025-07-14 13:25:47 +02:00
This commit extracts five new crates: - nu-source, which contains the core source-code handling logic in Nu, including Text, Span, and also the pretty.rs-based debug logic - nu-parser, which is the parser and expander logic - nu-protocol, which is the bulk of the types and basic conveniences used by plugins - nu-errors, which contains ShellError, ParseError and error handling conveniences - nu-textview, which is the textview plugin extracted into a crate One of the major consequences of this refactor is that it's no longer possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so a lot of types became more concrete (Value became a concrete type instead of Spanned<Value>, for example). This also turned a number of inherent methods in the main nu crate into plain functions (impl Value {} became a bunch of functions in the `value` namespace in `crate::data::value`).
125 lines
3.5 KiB
Rust
125 lines
3.5 KiB
Rust
use crate::hir::syntax_shape::{ExpandContext, ExpandSyntax};
|
|
use crate::parse::tokens::RawNumber;
|
|
use crate::parse::tokens::Token;
|
|
use crate::parse::tokens::UnspannedToken;
|
|
use crate::parse::unit::Unit;
|
|
use crate::{hir::TokensIterator, TokenNode};
|
|
use nom::branch::alt;
|
|
use nom::bytes::complete::tag;
|
|
use nom::character::complete::digit1;
|
|
use nom::combinator::{all_consuming, opt, value};
|
|
use nom::IResult;
|
|
use nu_errors::ParseError;
|
|
use nu_source::{b, DebugDocBuilder, HasSpan, PrettyDebugWithSource, Span, Spanned, SpannedItem};
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct UnitSyntax {
|
|
pub unit: (RawNumber, Spanned<Unit>),
|
|
pub span: Span,
|
|
}
|
|
|
|
impl PrettyDebugWithSource for UnitSyntax {
|
|
fn pretty_debug(&self, source: &str) -> DebugDocBuilder {
|
|
b::typed(
|
|
"unit",
|
|
self.unit.0.pretty_debug(source) + b::space() + self.unit.1.pretty_debug(source),
|
|
)
|
|
}
|
|
}
|
|
|
|
impl HasSpan for UnitSyntax {
|
|
fn span(&self) -> Span {
|
|
self.span
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Copy, Clone)]
|
|
pub struct UnitShape;
|
|
|
|
impl ExpandSyntax for UnitShape {
|
|
type Output = UnitSyntax;
|
|
|
|
fn name(&self) -> &'static str {
|
|
"unit"
|
|
}
|
|
|
|
fn expand_syntax<'a, 'b>(
|
|
&self,
|
|
token_nodes: &'b mut TokensIterator<'a>,
|
|
context: &ExpandContext,
|
|
) -> Result<UnitSyntax, ParseError> {
|
|
let peeked = token_nodes.peek_any().not_eof("unit")?;
|
|
|
|
let span = match peeked.node {
|
|
TokenNode::Token(Token {
|
|
unspanned: UnspannedToken::Bare,
|
|
span,
|
|
}) => *span,
|
|
_ => return Err(peeked.type_error("unit")),
|
|
};
|
|
|
|
let unit = unit_size(span.slice(context.source), span);
|
|
|
|
let (_, (number, unit)) = match unit {
|
|
Err(_) => return Err(ParseError::mismatch("unit", "word".spanned(span))),
|
|
Ok((number, unit)) => (number, unit),
|
|
};
|
|
|
|
peeked.commit();
|
|
Ok(UnitSyntax {
|
|
unit: (number, unit),
|
|
span,
|
|
})
|
|
}
|
|
}
|
|
|
|
fn unit_size(input: &str, bare_span: Span) -> IResult<&str, (RawNumber, Spanned<Unit>)> {
|
|
let (input, digits) = digit1(input)?;
|
|
|
|
let (input, dot) = opt(tag("."))(input)?;
|
|
|
|
let (input, number) = match dot {
|
|
Some(dot) => {
|
|
let (input, rest) = digit1(input)?;
|
|
(
|
|
input,
|
|
RawNumber::decimal(Span::new(
|
|
bare_span.start(),
|
|
bare_span.start() + digits.len() + dot.len() + rest.len(),
|
|
)),
|
|
)
|
|
}
|
|
|
|
None => (
|
|
input,
|
|
RawNumber::int(Span::new(
|
|
bare_span.start(),
|
|
bare_span.start() + digits.len(),
|
|
)),
|
|
),
|
|
};
|
|
|
|
let (input, unit) = all_consuming(alt((
|
|
value(Unit::Byte, alt((tag("B"), tag("b")))),
|
|
value(Unit::Kilobyte, alt((tag("KB"), tag("kb"), tag("Kb")))),
|
|
value(Unit::Megabyte, alt((tag("MB"), tag("mb"), tag("Mb")))),
|
|
value(Unit::Gigabyte, alt((tag("GB"), tag("gb"), tag("Gb")))),
|
|
value(Unit::Terabyte, alt((tag("TB"), tag("tb"), tag("Tb")))),
|
|
value(Unit::Petabyte, alt((tag("PB"), tag("pb"), tag("Pb")))),
|
|
value(Unit::Second, tag("s")),
|
|
value(Unit::Minute, tag("m")),
|
|
value(Unit::Hour, tag("h")),
|
|
value(Unit::Day, tag("d")),
|
|
value(Unit::Week, tag("w")),
|
|
value(Unit::Month, tag("M")),
|
|
value(Unit::Year, tag("y")),
|
|
)))(input)?;
|
|
|
|
let start_span = number.span().end();
|
|
|
|
Ok((
|
|
input,
|
|
(number, unit.spanned(Span::new(start_span, bare_span.end()))),
|
|
))
|
|
}
|