Skip to main content

ratex_parser/functions/
href.rs

1use std::collections::HashMap;
2
3use crate::error::{ParseError, ParseResult};
4use crate::functions::{define_function_full, ArgType, FunctionContext, FunctionSpec};
5use crate::parse_node::ParseNode;
6
7pub fn register(map: &mut HashMap<&'static str, FunctionSpec>) {
8    define_function_full(
9        map,
10        &["\\href"],
11        "href",
12        2,
13        0,
14        Some(vec![ArgType::Url, ArgType::Original]),
15        false,
16        true,
17        true,
18        false,
19        false,
20        handle_href,
21    );
22
23    define_function_full(
24        map,
25        &["\\url"],
26        "href",
27        1,
28        0,
29        Some(vec![ArgType::Url]),
30        false,
31        true,
32        true,
33        false,
34        false,
35        handle_url,
36    );
37}
38
39fn handle_href(
40    ctx: &mut FunctionContext,
41    args: Vec<ParseNode>,
42    _opt_args: Vec<Option<ParseNode>>,
43) -> ParseResult<ParseNode> {
44    let mut args = args.into_iter();
45    let url_arg = args.next().unwrap();
46    let body_arg = args.next().unwrap();
47
48    let href = match url_arg {
49        ParseNode::Url { url, .. } => url,
50        _ => return Err(ParseError::msg("Expected URL")),
51    };
52
53    Ok(ParseNode::Href {
54        mode: ctx.parser.mode,
55        href,
56        body: ParseNode::ord_argument(body_arg),
57        loc: None,
58    })
59}
60
61fn handle_url(
62    ctx: &mut FunctionContext,
63    args: Vec<ParseNode>,
64    _opt_args: Vec<Option<ParseNode>>,
65) -> ParseResult<ParseNode> {
66    let url_arg = args.into_iter().next().unwrap();
67
68    let url = match &url_arg {
69        ParseNode::Url { url, .. } => url.clone(),
70        _ => return Err(ParseError::msg("Expected URL")),
71    };
72
73    let chars: Vec<ParseNode> = url
74        .chars()
75        .map(|c| ParseNode::TextOrd {
76            mode: crate::parse_node::Mode::Text,
77            text: c.to_string(),
78            loc: None,
79        })
80        .collect();
81
82    let text_node = ParseNode::Text {
83        mode: ctx.parser.mode,
84        body: chars,
85        font: Some("\\texttt".to_string()),
86        loc: None,
87    };
88
89    Ok(ParseNode::Href {
90        mode: ctx.parser.mode,
91        href: url,
92        body: vec![text_node],
93        loc: None,
94    })
95}