flams_stex/quickparse/latex/
directives.rs1use 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}