mirror of
https://github.com/TxtDot/dalet-rs.git
synced 2024-11-05 17:33:58 +03:00
feat: table syntax and formatting
This commit is contained in:
parent
6099dbd236
commit
d2fc37fed3
7 changed files with 172 additions and 20 deletions
|
@ -117,7 +117,7 @@ row [
|
|||
]]
|
||||
]
|
||||
|
||||
# Table has custom format if text used
|
||||
# Table has custom format
|
||||
# +| cells | - primary column
|
||||
# | cells | - secondary column
|
||||
# | Element | Description | - converts to
|
||||
|
@ -125,14 +125,14 @@ row [
|
|||
# Element
|
||||
# Description
|
||||
# ]
|
||||
# table {
|
||||
# +| Tag | Description |
|
||||
# | h | Heading |
|
||||
# | p | Paragraph |
|
||||
# | img | Image |
|
||||
# | link | Link |
|
||||
# | btn | Button |
|
||||
# | ul | Unordered list |
|
||||
# | br | Line break |
|
||||
# +| quantity | 7 |
|
||||
# }
|
||||
{> table
|
||||
[[ Tag | Description ]]
|
||||
[ h | Heading ]
|
||||
[ p | Paragraph ]
|
||||
[ img | Image ]
|
||||
[ link | Link ]
|
||||
[ btn | Button ]
|
||||
[ ul | Unordered list ]
|
||||
[ br | Line break ]
|
||||
[[ quantity | 7 ]]
|
||||
}
|
123
src/daleth/custom_parsers/mod.rs
Normal file
123
src/daleth/custom_parsers/mod.rs
Normal file
|
@ -0,0 +1,123 @@
|
|||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum TableCol<'src> {
|
||||
Primary(Vec<&'src str>),
|
||||
Secondary(Vec<&'src str>),
|
||||
}
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use chumsky::prelude::*;
|
||||
|
||||
use crate::typed::{NNBody, Tag};
|
||||
|
||||
use super::types::Span;
|
||||
|
||||
pub fn table_to_tag(rows: &Vec<TableCol>) -> Tag {
|
||||
Tag::Table(
|
||||
rows.into_iter()
|
||||
.map(|row| match row {
|
||||
TableCol::Primary(row) => Tag::Tpcol(
|
||||
row.into_iter()
|
||||
.map(|t| Tag::El(NNBody::Text(format!("{t}"))))
|
||||
.collect(),
|
||||
),
|
||||
TableCol::Secondary(row) => Tag::Tcol(
|
||||
row.into_iter()
|
||||
.map(|t| Tag::El(NNBody::Text(format!("{t}"))))
|
||||
.collect(),
|
||||
),
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn table_to_string(rows: &Vec<TableCol>) -> String {
|
||||
let mut max_len: HashMap<usize, usize> = HashMap::new();
|
||||
let mut been_primary = false;
|
||||
|
||||
let mut result = String::new();
|
||||
|
||||
for row in rows {
|
||||
let row = match row {
|
||||
TableCol::Primary(row) => {
|
||||
been_primary = true;
|
||||
row
|
||||
}
|
||||
TableCol::Secondary(row) => row,
|
||||
};
|
||||
|
||||
for i in 0..row.len() {
|
||||
let current = max_len.get(&i).unwrap_or(&0);
|
||||
|
||||
if *current <= row[i].len() {
|
||||
max_len.insert(i, row[i].len());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for row in rows {
|
||||
let mut primary = false;
|
||||
let row = match row {
|
||||
TableCol::Primary(row) => {
|
||||
primary = true;
|
||||
result.push_str("[[ ");
|
||||
|
||||
row
|
||||
}
|
||||
TableCol::Secondary(row) => {
|
||||
if been_primary {
|
||||
result.push_str(" [ ");
|
||||
} else {
|
||||
result.push_str("[ ");
|
||||
}
|
||||
|
||||
row
|
||||
}
|
||||
};
|
||||
|
||||
let mut cells: Vec<String> = vec![];
|
||||
|
||||
for (i, col) in row.iter().enumerate() {
|
||||
let max = max_len.get(&i).unwrap_or(&0);
|
||||
|
||||
cells.push(format!("{}{}", col, " ".repeat(max - col.len())))
|
||||
}
|
||||
|
||||
result.push_str(&cells.join(" | "));
|
||||
|
||||
if primary {
|
||||
result.push_str(" ]]\n");
|
||||
} else {
|
||||
result.push_str(" ]\n");
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn table_parser<'src>(
|
||||
) -> impl Parser<'src, &'src str, Vec<TableCol<'src>>, extra::Err<Rich<'src, char, Span>>> {
|
||||
let escape = just('\\')
|
||||
.ignore_then(choice((just('|'), just(']'), just('\\'))))
|
||||
.labelled("Table escape sequence");
|
||||
|
||||
let cell = none_of("\\|]")
|
||||
.or(escape)
|
||||
.repeated()
|
||||
.to_slice()
|
||||
.map(|s: &str| s.trim());
|
||||
|
||||
let col_body = cell.separated_by(just("|")).collect();
|
||||
|
||||
let primary_col = just("[[")
|
||||
.ignore_then(col_body)
|
||||
.then_ignore(just("]]"))
|
||||
.map(TableCol::Primary);
|
||||
|
||||
let secondary_col = just("[")
|
||||
.ignore_then(col_body)
|
||||
.then_ignore(just("]"))
|
||||
.map(TableCol::Secondary);
|
||||
|
||||
primary_col.or(secondary_col).padded().repeated().collect()
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
use super::{
|
||||
custom_parsers::table_to_string,
|
||||
lexer::types::Token,
|
||||
types::Spanned,
|
||||
utils::{prepend_indent, set_indent},
|
||||
|
@ -151,6 +152,11 @@ pub fn format<'src>(spanned_tokens: &Vec<Spanned<Token<'src>>>) -> String {
|
|||
set_indent(t, current_indent + 1),
|
||||
prepend_indent("}", current_indent)
|
||||
),
|
||||
Token::TableSyntax(rows) => format!(
|
||||
"{{> table\n{}\n{}\n",
|
||||
set_indent(&table_to_string(rows), current_indent + 1),
|
||||
prepend_indent("}", current_indent)
|
||||
),
|
||||
|
||||
Token::EmptyLine => "\n".to_owned(),
|
||||
};
|
||||
|
|
|
@ -3,7 +3,10 @@ pub mod types;
|
|||
use chumsky::prelude::*;
|
||||
use types::*;
|
||||
|
||||
use super::types::{Span, Spanned};
|
||||
use super::{
|
||||
custom_parsers::table_parser,
|
||||
types::{Span, Spanned},
|
||||
};
|
||||
|
||||
pub fn lexer<'src>(
|
||||
) -> impl Parser<'src, &'src str, Vec<Spanned<Token<'src>>>, extra::Err<Rich<'src, char, Span>>> {
|
||||
|
@ -112,10 +115,7 @@ fn textual<'src>() -> impl Parser<'src, &'src str, Token<'src>, extra::Err<Rich<
|
|||
.ignore_then(choice((just('}'), just('\\'))))
|
||||
.labelled("Multi-line escape sequence");
|
||||
|
||||
let text = none_of("\n")
|
||||
.repeated()
|
||||
.to_slice()
|
||||
.padded_by(text::inline_whitespace());
|
||||
let text = none_of("\n").repeated().to_slice().map(|s: &str| s.trim());
|
||||
|
||||
let text_body = just(':')
|
||||
.ignore_then(text)
|
||||
|
@ -139,6 +139,11 @@ fn textual<'src>() -> impl Parser<'src, &'src str, Token<'src>, extra::Err<Rich<
|
|||
.map(Token::Paragraph)
|
||||
.labelled("Paragraph syntax");
|
||||
|
||||
let table_syntax = table_parser()
|
||||
.delimited_by(just("{> table"), just("}"))
|
||||
.map(Token::TableSyntax)
|
||||
.labelled("Table syntax");
|
||||
|
||||
let mltext = multiline_text_body
|
||||
.clone()
|
||||
.delimited_by(just('{'), just('}'))
|
||||
|
@ -162,7 +167,15 @@ fn textual<'src>() -> impl Parser<'src, &'src str, Token<'src>, extra::Err<Rich<
|
|||
.map(Token::MLRText)
|
||||
.labelled("Raw multiline text");
|
||||
|
||||
choice((paragraph, mlmstext, rmltext, mltext, text_body, text_tag))
|
||||
choice((
|
||||
table_syntax,
|
||||
paragraph,
|
||||
mlmstext,
|
||||
rmltext,
|
||||
mltext,
|
||||
text_body,
|
||||
text_tag,
|
||||
))
|
||||
}
|
||||
|
||||
fn comment<'src>() -> impl Parser<'src, &'src str, Token<'src>, extra::Err<Rich<'src, char, Span>>>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use core::fmt;
|
||||
|
||||
use crate::daleth::custom_parsers::TableCol;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Token<'src> {
|
||||
// Symbols
|
||||
|
@ -28,6 +30,7 @@ pub enum Token<'src> {
|
|||
// Special
|
||||
TextTag(&'src str),
|
||||
Paragraph(&'src str),
|
||||
TableSyntax(Vec<TableCol<'src>>),
|
||||
|
||||
// Special for formatting, ignored for parse
|
||||
Comment(&'src str),
|
||||
|
@ -115,6 +118,7 @@ impl<'src> fmt::Display for Token<'src> {
|
|||
Token::Code => write!(f, "code"),
|
||||
Token::Pre => write!(f, "pre"),
|
||||
Token::Meta => write!(f, "meta"),
|
||||
Token::TableSyntax(_) => write!(f, "table syntax"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
pub mod custom_parsers;
|
||||
pub mod format;
|
||||
pub mod lexer;
|
||||
pub mod parser;
|
||||
pub mod types;
|
||||
pub mod utils;
|
||||
mod utils;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
pub mod types;
|
||||
|
||||
use super::{
|
||||
custom_parsers::table_to_tag,
|
||||
lexer::types::Token,
|
||||
types::Span,
|
||||
utils::{set_spaces, trim_indent},
|
||||
|
@ -178,11 +179,15 @@ pub fn tag<'tokens, 'src: 'tokens>(
|
|||
}
|
||||
.labelled("Paragraph");
|
||||
|
||||
let table_syntax = select! {
|
||||
Token::TableSyntax(rows) => table_to_tag(&rows)
|
||||
};
|
||||
|
||||
choice((
|
||||
el, h, p, br, ul, ol, row, link, navlink, btn, navbtn, img, table, tcol, tpcol, hr, b,
|
||||
i, bq, footlnk, footn, a, s, sup, sub, disc,
|
||||
))
|
||||
.or(choice((block, carousel, code, pre, meta)))
|
||||
.or(choice((el_text, el_tags, paragraph)))
|
||||
.or(choice((el_text, el_tags, paragraph, table_syntax)))
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue