use std::mem::replace; use crate::ast::{ Line, parser::{ParserInternalStatus, ParserMatchResult}, }; #[derive(Default)] struct HeadingTmp { /// 当前输入的层级 lvl: u8, /// 是否正在输入标题前缀 typing_heading_prefix: bool, /// 是否正在输入标题内容 typing_heading_content: bool, // 第一个 Sharp 符号的位置 first_sharp_col: Option, } pub(crate) fn proc(c: &char, inr: &mut ParserInternalStatus) -> ParserMatchResult { // 如果本行在剔除开头所有字符后仍不为 # 开头,则说明本行无法用于标题解析 let lookback = inr.lookback.clone(); if !lookback.trim_start().starts_with('#') { // 本行不是标题行,放弃整行的解析 return ParserMatchResult::Abort; } // 当前行 let row = inr.row; let col = inr.col; // 获得临时数据 let tmp = inr.get_tmp_or_init::("headings_tmp"); // 如果是行首,则初始化 tmp 数据 if col == 0 { tmp.lvl = 0; tmp.typing_heading_prefix = false; tmp.typing_heading_content = false; tmp.first_sharp_col = None; } match c { // 键入了 # 符号 '#' => { // 如果正在输入标题前缀,则层级增加 if tmp.typing_heading_prefix { tmp.lvl += 1; // 如果层级大于 6 (6级标题) if tmp.lvl > 6 { // 语法异常,抛出 return ParserMatchResult::SyntaxError { begin_col: tmp.first_sharp_col.unwrap_or(col), begin_row: row, end_col: col, end_row: row, msg: "Heading level cannot exceed 6".to_string(), }; } } // 如果不在输入标题 else { // 记录为正在输入前缀 tmp.typing_heading_prefix = true; // 设置层级为 1 tmp.lvl = 1; // 标记第一个 # 符号的位置 tmp.first_sharp_col = Some(col); } } // 输入了空格 ' ' => { // 如果正在输入标题前缀 if tmp.typing_heading_prefix { // 标记为没输入前缀,并切换为正在输入内容 tmp.typing_heading_prefix = false; tmp.typing_heading_content = true; } } // 输入了换行 '\n' => { // 如果正在输入标题内容 if tmp.typing_heading_content { // 拿出所有 records_tokens let tokens = replace(&mut inr.records_tokens, Vec::new()); // 建立标题行 let line = Line { row, tokens }; // 追加行 inr.records_lines.push(line); } } _ => return ParserMatchResult::Sad, } ParserMatchResult::Done }