summaryrefslogtreecommitdiff
path: root/src/ast/parser/headings.rs
blob: 260efa495e06bf2bd32e3d856b90393abbab198c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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<u16>,
}

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::<HeadingTmp>("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
}