move and turn into spans
This commit is contained in:
parent
bedaa49754
commit
9f401bda53
13 changed files with 1262 additions and 774 deletions
235
src/format_debug_output/spans.rs
Normal file
235
src/format_debug_output/spans.rs
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
use super::ast::*;
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub enum Kind {
|
||||
/// Parentheses e.g.
|
||||
///
|
||||
/// Stores the delimiter depth, for e.g. rainbow delimiters.
|
||||
Delimiter(usize),
|
||||
/// Separators like `=`, ':' and ','
|
||||
Separator,
|
||||
/// Numbers
|
||||
Number,
|
||||
/// Known literals, like `true`, `false`, `None`, `Ok`, `Err`
|
||||
Literal,
|
||||
/// Strings
|
||||
String,
|
||||
/// Paths
|
||||
Path,
|
||||
/// Spaces (returns original number of spaces)
|
||||
Space(usize),
|
||||
|
||||
/// Constructor: the prefix of a delimited block.
|
||||
/// i.e. `Some` in `Some(3)`
|
||||
Constructor,
|
||||
|
||||
/// String prefix, suffix, hashtags, etc
|
||||
StringSurroundings,
|
||||
|
||||
/// Any other text (the default)
|
||||
Text,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Span<'a> {
|
||||
pub text: Cow<'a, str>,
|
||||
pub kind: Kind,
|
||||
}
|
||||
|
||||
pub struct Config {
|
||||
pub collapse_space: bool,
|
||||
}
|
||||
|
||||
pub struct Context<'a> {
|
||||
config: Config,
|
||||
res: Vec<Span<'a>>,
|
||||
depth: usize,
|
||||
}
|
||||
|
||||
impl<'a> Context<'a> {
|
||||
pub fn push(&mut self, text: impl Into<Cow<'a, str>>, kind: Kind) {
|
||||
self.res.push(Span {
|
||||
text: text.into(),
|
||||
kind,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IntoSpans<'a>: private::IntoSpansImpl<'a> {}
|
||||
|
||||
pub fn into_spans<'a>(ast: impl IntoSpans<'a>, config: Config) -> Vec<Span<'a>> {
|
||||
let mut cx = Context {
|
||||
config,
|
||||
res: Vec::new(),
|
||||
depth: 0,
|
||||
};
|
||||
ast.into_spans(&mut cx);
|
||||
cx.res
|
||||
}
|
||||
|
||||
mod private {
|
||||
use super::*;
|
||||
|
||||
pub trait IntoSpansImpl<'a> {
|
||||
fn into_spans(self, cx: &mut Context<'a>);
|
||||
}
|
||||
|
||||
impl<'a, T> IntoSpans<'a> for T where T: IntoSpansImpl<'a> {}
|
||||
|
||||
impl<'a> IntoSpansImpl<'a> for Separator {
|
||||
fn into_spans(self, cx: &mut Context<'a>) {
|
||||
match self {
|
||||
Separator::Eq => cx.push("=", Kind::Separator),
|
||||
Separator::Colon => cx.push(":", Kind::Separator),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoSpansImpl<'a> for QuoteType {
|
||||
fn into_spans(self, cx: &mut Context<'a>) {
|
||||
match self {
|
||||
QuoteType::Single => cx.push("'", Kind::Separator),
|
||||
QuoteType::Double => cx.push("\"", Kind::Separator),
|
||||
QuoteType::Backtick => cx.push("`", Kind::Separator),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoSpansImpl<'a> for AnyString<'a> {
|
||||
fn into_spans(self, cx: &mut Context<'a>) {
|
||||
let Self {
|
||||
prefix,
|
||||
ty,
|
||||
contents,
|
||||
num_hashtags,
|
||||
suffix,
|
||||
} = self;
|
||||
cx.push(prefix, Kind::StringSurroundings);
|
||||
for _ in 0..num_hashtags {
|
||||
cx.push("#", Kind::StringSurroundings)
|
||||
}
|
||||
|
||||
ty.into_spans(cx);
|
||||
cx.push(contents, Kind::String);
|
||||
ty.into_spans(cx);
|
||||
|
||||
for _ in 0..num_hashtags {
|
||||
cx.push("#", Kind::StringSurroundings)
|
||||
}
|
||||
cx.push(suffix, Kind::StringSurroundings);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoSpansImpl<'a> for Path<'a> {
|
||||
fn into_spans(self, cx: &mut Context<'a>) {
|
||||
cx.push(self.to_string(), Kind::Path)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoSpansImpl<'a> for Number<'a> {
|
||||
fn into_spans(self, cx: &mut Context<'a>) {
|
||||
cx.push(self.0, Kind::Number)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoSpansImpl<'a> for Atom<'a> {
|
||||
fn into_spans(self, cx: &mut Context<'a>) {
|
||||
match self {
|
||||
Atom::Text(text) => cx.push(text, Kind::Text),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoSpansImpl<'a> for Space<'a> {
|
||||
fn into_spans(self, cx: &mut Context<'a>) {
|
||||
match self.0.len() {
|
||||
0 => {}
|
||||
1 => cx.push(self.0, Kind::Space(1)),
|
||||
n if cx.config.collapse_space => cx.push(" ", Kind::Space(n)),
|
||||
n => cx.push(self.0, Kind::Space(n)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoSpansImpl<'a> for Token<'a> {
|
||||
fn into_spans(self, cx: &mut Context<'a>) {
|
||||
match self {
|
||||
Token::True => cx.push("true", Kind::Literal),
|
||||
Token::False => cx.push("false", Kind::Literal),
|
||||
Token::None => cx.push("None", Kind::Literal),
|
||||
Token::Path(path) => path.into_spans(cx),
|
||||
Token::String(string) => string.into_spans(cx),
|
||||
Token::Number(number) => number.into_spans(cx),
|
||||
Token::Separated {
|
||||
before,
|
||||
space_before,
|
||||
separator,
|
||||
after,
|
||||
} => todo!(),
|
||||
Token::Delimited(delimited) => {
|
||||
delimited.into_spans(cx);
|
||||
}
|
||||
Token::Atom(atom) => {
|
||||
atom.into_spans(cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoSpansImpl<'a> for Segment<'a> {
|
||||
fn into_spans(self, cx: &mut Context<'a>) {
|
||||
let Self {
|
||||
leading_space,
|
||||
token,
|
||||
} = self;
|
||||
leading_space.into_spans(cx);
|
||||
token.into_spans(cx);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoSpansImpl<'a> for Segments<'a> {
|
||||
fn into_spans(self, cx: &mut Context<'a>) {
|
||||
let Self {
|
||||
segments,
|
||||
trailing_space,
|
||||
} = self;
|
||||
for segment in segments {
|
||||
segment.into_spans(cx);
|
||||
}
|
||||
trailing_space.into_spans(cx);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoSpansImpl<'a> for Delimited<'a> {
|
||||
fn into_spans(self, cx: &mut Context<'a>) {
|
||||
let Self {
|
||||
prefix,
|
||||
delimiter,
|
||||
contents,
|
||||
} = self;
|
||||
|
||||
match prefix {
|
||||
Atom::Text(text) => cx.push(text, Kind::Constructor),
|
||||
}
|
||||
|
||||
match delimiter {
|
||||
Delimiter::Paren => cx.push("(", Kind::Delimiter(cx.depth)),
|
||||
Delimiter::Bracket => cx.push("[", Kind::Delimiter(cx.depth)),
|
||||
Delimiter::Brace => cx.push("{", Kind::Delimiter(cx.depth)),
|
||||
Delimiter::Angle => cx.push("<", Kind::Delimiter(cx.depth)),
|
||||
}
|
||||
|
||||
cx.depth += 1;
|
||||
contents.into_spans(cx);
|
||||
cx.depth -= 1;
|
||||
|
||||
match delimiter {
|
||||
Delimiter::Paren => cx.push(")", Kind::Delimiter(cx.depth)),
|
||||
Delimiter::Bracket => cx.push("]", Kind::Delimiter(cx.depth)),
|
||||
Delimiter::Brace => cx.push("}", Kind::Delimiter(cx.depth)),
|
||||
Delimiter::Angle => cx.push(">", Kind::Delimiter(cx.depth)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue