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