ratex_parser/functions/
tag.rs1use std::collections::HashMap;
2
3use crate::error::{ParseError, ParseResult};
4use crate::functions::{define_function_full, FunctionContext, FunctionSpec};
5use crate::parse_node::{Mode, ParseNode};
6
7pub fn register(map: &mut HashMap<&'static str, FunctionSpec>) {
8 define_function_full(
9 map,
10 &["\\tag"],
11 "tag",
12 0,
13 0,
14 None,
15 true,
16 false,
17 true,
18 false,
19 true,
20 handle_tag,
21 );
22}
23
24fn handle_tag(
25 ctx: &mut FunctionContext,
26 _args: Vec<ParseNode>,
27 _opt_args: Vec<Option<ParseNode>>,
28) -> ParseResult<ParseNode> {
29 ctx.parser.consume_spaces()?;
30 let star = if ctx.parser.fetch()?.text == "*" {
31 ctx.parser.consume();
32 true
33 } else {
34 false
35 };
36
37 let arg = ctx
38 .parser
39 .parse_group("\\tag", None)?
40 .ok_or_else(|| ParseError::msg("\\tag requires an argument"))?;
41
42 let inner = match arg {
43 ParseNode::OrdGroup { body, .. } => body,
44 other => vec![other],
45 };
46
47 let tag = if star {
48 inner
49 } else {
50 let mut v = Vec::with_capacity(inner.len() + 2);
51 v.push(ParseNode::MathOrd {
52 mode: Mode::Math,
53 text: "(".to_string(),
54 loc: None,
55 });
56 v.extend(inner);
57 v.push(ParseNode::MathOrd {
58 mode: Mode::Math,
59 text: ")".to_string(),
60 loc: None,
61 });
62 v
63 };
64
65 Ok(ParseNode::Tag {
66 mode: ctx.parser.mode,
67 body: vec![],
68 tag,
69 loc: None,
70 })
71}