mirror of
https://github.com/TxtDot/dalet-rs.git
synced 2024-11-05 17:33:58 +03:00
feat: format cli command, fix format trim
This commit is contained in:
parent
68cd970a1f
commit
6338097658
6 changed files with 114 additions and 60 deletions
|
@ -40,13 +40,15 @@ This is element
|
|||
br
|
||||
|
||||
# if no tag is specified but a '{- text}' is present, then the 'p' tag is placed
|
||||
# '\n' is deleted in this format. If a break line is needed in a paragraph, use ' \n'.
|
||||
# '\n' is replaced with ' ' in this format.
|
||||
{-
|
||||
Check Dalet too
|
||||
This is one paragraph
|
||||
}
|
||||
|
||||
{- This is another paragraph ({- text\}) }
|
||||
{-
|
||||
This is another paragraph ({- text\})
|
||||
}
|
||||
|
||||
row "center" [
|
||||
link "https://github.com/txtdot/txtdot": Homepage
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[command(name = "cimengine", bin_name = "cimengine")]
|
||||
#[command(about = "CIMEngine build tools")]
|
||||
#[command(name = "dalet", bin_name = "dalet")]
|
||||
#[command(about = "dalet cli")]
|
||||
pub struct Cli {
|
||||
#[command(subcommand)]
|
||||
pub cmd: Commands,
|
||||
|
@ -10,4 +12,7 @@ pub struct Cli {
|
|||
|
||||
#[derive(Debug, Subcommand)]
|
||||
#[clap(author, version, about)]
|
||||
pub enum Commands {}
|
||||
pub enum Commands {
|
||||
/// Format file
|
||||
Format { path: PathBuf },
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::{
|
||||
lexer::types::{Spanned, Token},
|
||||
utils::set_indent,
|
||||
utils::{prepend_indent, set_indent},
|
||||
};
|
||||
|
||||
fn additional_str<'src>(
|
||||
|
@ -83,72 +83,72 @@ pub fn format<'src>(spanned_tokens: &Vec<Spanned<Token<'src>>>) -> String {
|
|||
}
|
||||
Token::RSquare => {
|
||||
current_indent -= 1;
|
||||
format!("{}\n", set_indent("]", current_indent))
|
||||
format!("{}\n", prepend_indent("]", current_indent))
|
||||
}
|
||||
|
||||
Token::NumberArgument(n) => format!("{n}"),
|
||||
Token::TextArgument(t) => format!(" \"{t}\""),
|
||||
Token::TextBody(t) => format!(": {}\n", t.trim()),
|
||||
Token::TextBody(t) => format!(": {}\n", t),
|
||||
Token::MLText(t) => format!(
|
||||
" {{\n{}\n{}\n",
|
||||
set_indent(t, current_indent + 1),
|
||||
set_indent("}", current_indent)
|
||||
prepend_indent("}", current_indent)
|
||||
),
|
||||
Token::MLMSText(n, t) => format!(
|
||||
" {{~{n}\n{}\n{}\n",
|
||||
set_indent(t, current_indent + 1),
|
||||
set_indent("}", current_indent)
|
||||
prepend_indent("}", current_indent)
|
||||
),
|
||||
Token::RMLText(t) => format!(" {{#{t}}}\n"),
|
||||
Token::Comment(c) => format!("{}\n", set_indent(&format!("#{c}"), current_indent)),
|
||||
Token::Comment(c) => format!("{}\n", prepend_indent(&format!("#{c}"), current_indent)),
|
||||
|
||||
Token::TextTag(t) => format!("{}\n", set_indent(t, current_indent)),
|
||||
Token::TextTag(t) => format!("{}\n", prepend_indent(t, current_indent)),
|
||||
|
||||
Token::El => set_indent("el", current_indent),
|
||||
Token::H => set_indent("h", current_indent),
|
||||
Token::P => set_indent("p", current_indent),
|
||||
Token::Br => set_indent("br", current_indent),
|
||||
Token::Ul => set_indent("ul", current_indent),
|
||||
Token::Ol => set_indent("ol", current_indent),
|
||||
Token::Row => set_indent("row", current_indent),
|
||||
Token::Link => set_indent("link", current_indent),
|
||||
Token::Navlink => set_indent("navlink", current_indent),
|
||||
Token::Btn => set_indent("btn", current_indent),
|
||||
Token::Navbtn => set_indent("navbtn", current_indent),
|
||||
Token::Img => set_indent("img", current_indent),
|
||||
Token::Table => set_indent("table", current_indent),
|
||||
Token::Tcol => set_indent("tcol", current_indent),
|
||||
Token::Tpcol => set_indent("tpcol", current_indent),
|
||||
Token::Hr => set_indent("hr", current_indent),
|
||||
Token::B => set_indent("b", current_indent),
|
||||
Token::I => set_indent("i", current_indent),
|
||||
Token::Bq => set_indent("bq", current_indent),
|
||||
Token::Footlnk => set_indent("footlnk", current_indent),
|
||||
Token::Footn => set_indent("footn", current_indent),
|
||||
Token::A => set_indent("a", current_indent),
|
||||
Token::S => set_indent("s", current_indent),
|
||||
Token::Sup => set_indent("sup", current_indent),
|
||||
Token::Sub => set_indent("sub", current_indent),
|
||||
Token::Disc => set_indent("disc", current_indent),
|
||||
Token::Block => set_indent("block", current_indent),
|
||||
Token::Carousel => set_indent("carousel", current_indent),
|
||||
Token::Code => set_indent("code", current_indent),
|
||||
Token::Pre => set_indent("pre", current_indent),
|
||||
Token::Meta => set_indent("meta", current_indent),
|
||||
Token::El => prepend_indent("el", current_indent),
|
||||
Token::H => prepend_indent("h", current_indent),
|
||||
Token::P => prepend_indent("p", current_indent),
|
||||
Token::Br => prepend_indent("br", current_indent),
|
||||
Token::Ul => prepend_indent("ul", current_indent),
|
||||
Token::Ol => prepend_indent("ol", current_indent),
|
||||
Token::Row => prepend_indent("row", current_indent),
|
||||
Token::Link => prepend_indent("link", current_indent),
|
||||
Token::Navlink => prepend_indent("navlink", current_indent),
|
||||
Token::Btn => prepend_indent("btn", current_indent),
|
||||
Token::Navbtn => prepend_indent("navbtn", current_indent),
|
||||
Token::Img => prepend_indent("img", current_indent),
|
||||
Token::Table => prepend_indent("table", current_indent),
|
||||
Token::Tcol => prepend_indent("tcol", current_indent),
|
||||
Token::Tpcol => prepend_indent("tpcol", current_indent),
|
||||
Token::Hr => prepend_indent("hr", current_indent),
|
||||
Token::B => prepend_indent("b", current_indent),
|
||||
Token::I => prepend_indent("i", current_indent),
|
||||
Token::Bq => prepend_indent("bq", current_indent),
|
||||
Token::Footlnk => prepend_indent("footlnk", current_indent),
|
||||
Token::Footn => prepend_indent("footn", current_indent),
|
||||
Token::A => prepend_indent("a", current_indent),
|
||||
Token::S => prepend_indent("s", current_indent),
|
||||
Token::Sup => prepend_indent("sup", current_indent),
|
||||
Token::Sub => prepend_indent("sub", current_indent),
|
||||
Token::Disc => prepend_indent("disc", current_indent),
|
||||
Token::Block => prepend_indent("block", current_indent),
|
||||
Token::Carousel => prepend_indent("carousel", current_indent),
|
||||
Token::Code => prepend_indent("code", current_indent),
|
||||
Token::Pre => prepend_indent("pre", current_indent),
|
||||
Token::Meta => prepend_indent("meta", current_indent),
|
||||
|
||||
Token::ElOpen => {
|
||||
let s = set_indent("[[", current_indent);
|
||||
let s = prepend_indent("[[", current_indent);
|
||||
current_indent += 1;
|
||||
format!("{s}\n")
|
||||
}
|
||||
Token::ElClose => {
|
||||
current_indent -= 1;
|
||||
format!("{}\n", set_indent("]]", current_indent))
|
||||
format!("{}\n", prepend_indent("]]", current_indent))
|
||||
}
|
||||
Token::Paragraph(t) => format!(
|
||||
"{{-\n{}\n{}\n",
|
||||
set_indent(t, current_indent + 1),
|
||||
set_indent("}", current_indent)
|
||||
prepend_indent("}", current_indent)
|
||||
),
|
||||
|
||||
Token::EmptyLine => "\n".to_owned(),
|
||||
|
|
|
@ -75,7 +75,10 @@ pub fn lexer<'src>(
|
|||
.ignore_then(just('}'))
|
||||
.labelled("Multi-line escape sequence");
|
||||
|
||||
let text = none_of("\n").repeated().to_slice();
|
||||
let text = none_of("\n")
|
||||
.repeated()
|
||||
.to_slice()
|
||||
.padded_by(text::inline_whitespace());
|
||||
|
||||
let text_body = just(':')
|
||||
.ignore_then(text)
|
||||
|
@ -90,18 +93,17 @@ pub fn lexer<'src>(
|
|||
let multiline_text_body = none_of("}\\")
|
||||
.or(escape)
|
||||
.repeated()
|
||||
.to_slice()
|
||||
.labelled("Body of multiline text");
|
||||
|
||||
let paragraph = multiline_text_body
|
||||
.clone()
|
||||
.to_slice()
|
||||
.delimited_by(just("{-"), just("}"))
|
||||
.map(Token::Paragraph)
|
||||
.labelled("Paragraph syntax");
|
||||
|
||||
let mltext = multiline_text_body
|
||||
.clone()
|
||||
.to_slice()
|
||||
.delimited_by(just('{'), just('}'))
|
||||
.map(Token::MLText)
|
||||
.labelled("Multiline text");
|
||||
|
@ -112,14 +114,13 @@ pub fn lexer<'src>(
|
|||
.labelled("Minimum spaces number");
|
||||
|
||||
mlms_n
|
||||
.then(multiline_text_body.clone().to_slice())
|
||||
.then(multiline_text_body.clone())
|
||||
.then_ignore(just("}"))
|
||||
.map(|(n, t)| Token::MLMSText(n, t))
|
||||
.labelled("Multi line text with min spaces")
|
||||
};
|
||||
|
||||
let rmltext = multiline_text_body
|
||||
.to_slice()
|
||||
.delimited_by(just("{#"), just('}'))
|
||||
.map(Token::RMLText)
|
||||
.labelled("Raw multiline text");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
pub fn trim_indent(input: &str) -> String {
|
||||
let lines: Vec<&str> = input.lines().collect();
|
||||
let lines: Vec<&str> = trim_unused(input).lines().collect();
|
||||
|
||||
// Find the minimum indentation of non-empty lines
|
||||
let min_indent = lines
|
||||
|
@ -21,28 +21,36 @@ pub fn trim_indent(input: &str) -> String {
|
|||
})
|
||||
.collect();
|
||||
|
||||
trim_newline(&trimmed_lines.join("\n")).to_owned()
|
||||
trimmed_lines.join("\n")
|
||||
}
|
||||
|
||||
pub fn set_indent(input: &str, indent: usize) -> String {
|
||||
prepend_indent(&trim_indent(input), &" ".repeat(indent))
|
||||
prepend_indent(&trim_indent(input), indent)
|
||||
}
|
||||
|
||||
fn trim_newline<'a>(s: &'a str) -> &'a str {
|
||||
fn trim_unused<'a>(s: &'a str) -> &'a str {
|
||||
let mut trim_start = 0;
|
||||
let mut been_newlines = false;
|
||||
|
||||
for start_char in s.chars() {
|
||||
if start_char != '\n' && start_char != '\r' {
|
||||
if !been_newlines
|
||||
&& (char::is_whitespace(start_char) && start_char != '\n' && start_char != '\r')
|
||||
{
|
||||
trim_start += 1;
|
||||
continue;
|
||||
} else if start_char != '\n' && start_char != '\r' {
|
||||
break;
|
||||
} else {
|
||||
been_newlines = true;
|
||||
trim_start += 1;
|
||||
}
|
||||
|
||||
trim_start += 1;
|
||||
}
|
||||
|
||||
&s[(trim_start)..].trim_end()
|
||||
}
|
||||
|
||||
fn prepend_indent(input: &str, indent: &str) -> String {
|
||||
pub fn prepend_indent(input: &str, indent: usize) -> String {
|
||||
let indent = &" ".repeat(indent);
|
||||
let lines: Vec<String> = input
|
||||
.lines()
|
||||
.map(|line| format!("{}{}", indent, line))
|
||||
|
|
40
src/main.rs
40
src/main.rs
|
@ -1,3 +1,41 @@
|
|||
mod commands;
|
||||
|
||||
fn main() {}
|
||||
use ariadne::{Color, Label, Report, ReportKind, Source};
|
||||
use chumsky::Parser;
|
||||
use clap::Parser as ClapParser;
|
||||
use commands::{Cli, Commands::*};
|
||||
use dalet::daleth::{format::format, lexer::lexer};
|
||||
use std::fs;
|
||||
|
||||
fn main() {
|
||||
let args = Cli::parse();
|
||||
|
||||
match args.cmd {
|
||||
// TODO: add parser check before format
|
||||
Format { path } => {
|
||||
let src_file = &path.to_string_lossy().to_string();
|
||||
let src = fs::read_to_string(src_file).unwrap();
|
||||
|
||||
let parsed = lexer().parse(&src);
|
||||
|
||||
match parsed.into_result() {
|
||||
Ok(t) => {
|
||||
fs::write(path, format(&t)).unwrap();
|
||||
}
|
||||
Err(e) => e.into_iter().for_each(|e| {
|
||||
Report::build(ReportKind::Error, src_file, e.span().start)
|
||||
.with_code("Compiler")
|
||||
.with_message(e.to_string().clone())
|
||||
.with_label(
|
||||
Label::new((src_file, e.span().into_range()))
|
||||
.with_message(e.to_string())
|
||||
.with_color(Color::Red),
|
||||
)
|
||||
.finish()
|
||||
.print((src_file, Source::from(&src)))
|
||||
.unwrap()
|
||||
}),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue