Skip to main content

flams_stex/quickparse/latex/
directives.rs

1use std::borrow::Cow;
2
3use flams_utils::{
4    parsing::{ParseSource, StringOrStr},
5    sourcerefs::SourceRange,
6};
7
8use crate::quickparse::stex::DiagnosticLevel;
9
10use super::{
11    rules::{DynEnv, DynMacro},
12    AnyEnv, AnyMacro, Environment, EnvironmentResult, FromLaTeXToken, LaTeXParser, Macro,
13    MacroResult, ParserState,
14};
15
16#[allow(clippy::needless_pass_by_value)]
17pub fn copycmd<
18    'a,
19    Pa: ParseSource<'a>,
20    T: FromLaTeXToken<'a, Pa::Pos, Pa::Str>,
21    Err: FnMut(String, SourceRange<Pa::Pos>, DiagnosticLevel),
22    State: ParserState<'a, Pa, T, Err>,
23>(
24    parser: &mut LaTeXParser<'a, Pa, T, Err, State>,
25    args: Pa::Str,
26) {
27    if let Some((a, b)) = args.as_ref().split_once(' ') {
28        let a = a.trim();
29        let b = b.trim();
30        let old = parser.macro_rules.get(b);
31        parser.add_macro_rule(Cow::Owned(a.to_string()), old.cloned());
32    }
33}
34
35#[allow(clippy::needless_pass_by_value)]
36pub fn verbcmd<
37    'a,
38    Pa: ParseSource<'a>,
39    T: FromLaTeXToken<'a, Pa::Pos, Pa::Str>,
40    Err: FnMut(String, SourceRange<Pa::Pos>, DiagnosticLevel),
41    State: ParserState<'a, Pa, T, Err>,
42>(
43    parser: &mut LaTeXParser<'a, Pa, T, Err, State>,
44    args: Pa::Str,
45) {
46    if !args.as_ref().is_empty() {
47        parser.add_macro_rule(
48            args.as_cow(),
49            Some(AnyMacro::Ptr(super::rules::lstinline as _)),
50        );
51    }
52}
53
54#[allow(clippy::needless_pass_by_value)]
55pub fn verbenv<
56    'a,
57    Pa: ParseSource<'a>,
58    T: FromLaTeXToken<'a, Pa::Pos, Pa::Str>,
59    Err: FnMut(String, SourceRange<Pa::Pos>, DiagnosticLevel),
60    State: ParserState<'a, Pa, T, Err>,
61>(
62    parser: &mut LaTeXParser<'a, Pa, T, Err, State>,
63    args: Pa::Str,
64) {
65    if !args.as_ref().is_empty() {
66        parser.add_environment_rule(
67            args.as_cow(),
68            Some(AnyEnv::Ptr((
69                super::rules::general_listing_open as _,
70                super::rules::general_listing_close as _,
71            ))),
72        );
73    }
74}
75
76pub fn macro_dir<
77    'a,
78    Pa: ParseSource<'a>,
79    T: FromLaTeXToken<'a, Pa::Pos, Pa::Str>,
80    Err: FnMut(String, SourceRange<Pa::Pos>, DiagnosticLevel),
81    State: ParserState<'a, Pa, T, Err>,
82>(
83    parser: &mut LaTeXParser<'a, Pa, T, Err, State>,
84    args: Pa::Str,
85) {
86    if !args.as_ref().is_empty() {
87        if let Some((m, _)) = args.as_ref().split_once(' ') {
88            let len = m.len();
89            let (m, mut spec) = args.split_n(len);
90            spec.trim_ws();
91            parser.add_macro_rule(
92                m.as_cow(),
93                Some(AnyMacro::Str(DynMacro {
94                    ptr: do_macro_dir as _,
95                    arg: spec,
96                })),
97            );
98        }
99    }
100}
101
102fn do_macro_dir<
103    'a,
104    Pa: ParseSource<'a>,
105    T: FromLaTeXToken<'a, Pa::Pos, Pa::Str>,
106    Err: FnMut(String, SourceRange<Pa::Pos>, DiagnosticLevel),
107    State: ParserState<'a, Pa, T, Err>,
108>(
109    arg: &Pa::Str,
110    mut m: Macro<'a, Pa::Pos, Pa::Str>,
111    parser: &mut LaTeXParser<'a, Pa, T, Err, State>,
112) -> MacroResult<'a, Pa::Pos, Pa::Str, T> {
113    let arg = arg.as_ref();
114    do_spec(arg, &mut m, parser);
115    MacroResult::Simple(m)
116}
117
118#[inline]
119fn do_spec<
120    'a,
121    Pa: ParseSource<'a>,
122    T: FromLaTeXToken<'a, Pa::Pos, Pa::Str>,
123    Err: FnMut(String, SourceRange<Pa::Pos>, DiagnosticLevel),
124    State: ParserState<'a, Pa, T, Err>,
125>(
126    spec: &str,
127    m: &mut Macro<'a, Pa::Pos, Pa::Str>,
128    parser: &mut LaTeXParser<'a, Pa, T, Err, State>,
129) {
130    for c in spec.as_bytes() {
131        match *c {
132            b'v' => parser.skip_arg(m),
133            _ => parser.tokenizer.problem(
134                m.range.start,
135                format!("Unknown arg spec {c}"),
136                DiagnosticLevel::Error,
137            ),
138        }
139    }
140}
141
142pub fn env_dir<
143    'a,
144    Pa: ParseSource<'a>,
145    T: FromLaTeXToken<'a, Pa::Pos, Pa::Str>,
146    Err: FnMut(String, SourceRange<Pa::Pos>, DiagnosticLevel),
147    State: ParserState<'a, Pa, T, Err>,
148>(
149    parser: &mut LaTeXParser<'a, Pa, T, Err, State>,
150    args: Pa::Str,
151) {
152    if !args.as_ref().is_empty() {
153        if let Some((m, _)) = args.as_ref().split_once(' ') {
154            let len = m.len();
155            let (m, mut spec) = args.split_n(len);
156            spec.trim_ws();
157            parser.add_environment_rule(
158                m.as_cow(),
159                Some(AnyEnv::Str(DynEnv {
160                    open: do_env_dir as _,
161                    close: do_env_dir_close as _,
162                    arg: spec,
163                })),
164            );
165        }
166    }
167}
168
169fn do_env_dir<
170    'a,
171    'b,
172    'c,
173    Pa: ParseSource<'a>,
174    T: FromLaTeXToken<'a, Pa::Pos, Pa::Str>,
175    Err: FnMut(String, SourceRange<Pa::Pos>, DiagnosticLevel),
176    State: ParserState<'a, Pa, T, Err>,
177>(
178    arg: &Pa::Str,
179    e: &'b mut Environment<'a, Pa::Pos, Pa::Str, T>,
180    parser: &'c mut LaTeXParser<'a, Pa, T, Err, State>,
181) {
182    let arg = arg.as_ref();
183    do_spec(arg, &mut e.begin, parser);
184}
185
186const fn do_env_dir_close<
187    'a,
188    'b,
189    Pa: ParseSource<'a>,
190    T: FromLaTeXToken<'a, Pa::Pos, Pa::Str>,
191    Err: FnMut(String, SourceRange<Pa::Pos>, DiagnosticLevel),
192    State: ParserState<'a, Pa, T, Err>,
193>(
194    e: Environment<'a, Pa::Pos, Pa::Str, T>,
195    _: &'b mut LaTeXParser<'a, Pa, T, Err, State>,
196) -> EnvironmentResult<'a, Pa::Pos, Pa::Str, T> {
197    EnvironmentResult::Simple(e)
198}
199
200pub fn nolint<
201    'a,
202    Pa: ParseSource<'a>,
203    T: FromLaTeXToken<'a, Pa::Pos, Pa::Str>,
204    Err: FnMut(String, SourceRange<Pa::Pos>, DiagnosticLevel),
205    State: ParserState<'a, Pa, T, Err>,
206>(
207    parser: &mut LaTeXParser<'a, Pa, T, Err, State>,
208    _: Pa::Str,
209) {
210    parser.tokenizer.reader.read_until_str("%%STEXIDE dolint");
211}
212
213#[inline]
214pub fn dolint<
215    'a,
216    Pa: ParseSource<'a>,
217    T: FromLaTeXToken<'a, Pa::Pos, Pa::Str>,
218    Err: FnMut(String, SourceRange<Pa::Pos>, DiagnosticLevel),
219    State: ParserState<'a, Pa, T, Err>,
220>(
221    _: &mut LaTeXParser<'a, Pa, T, Err, State>,
222    _: Pa::Str,
223) {
224}