texlang_stdlib/
endlinechar.rs

1//! The `\endlinechar` primitive
2
3use texlang::traits::*;
4use texlang::*;
5
6#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7pub struct Component {
8    end_line_char_raw: i32,
9}
10
11impl Default for Component {
12    fn default() -> Self {
13        Self {
14            end_line_char_raw: ('\r' as u32).try_into().unwrap(),
15        }
16    }
17}
18
19/// Get the `\endlinechar` command.
20pub fn get_endlinechar<S: HasComponent<Component>>() -> command::BuiltIn<S> {
21    variable::Command::new_singleton(
22        |state: &S, _: variable::Index| -> &i32 { &state.component().end_line_char_raw },
23        |state: &mut S, _: variable::Index| -> &mut i32 {
24            &mut state.component_mut().end_line_char_raw
25        },
26    )
27    .into()
28}
29
30#[inline]
31pub fn end_line_char<S: HasComponent<Component>>(state: &S) -> Option<char> {
32    let raw = state.component().end_line_char_raw;
33    if (0..128).contains(&raw) {
34        // All of the conversions are guaranteed to succeed because
35        // raw is in the ASCII range.
36        Some(char::try_from(u32::try_from(raw).unwrap()).unwrap())
37    } else {
38        None
39    }
40}
41
42#[cfg(test)]
43mod test {
44    use std::collections::HashMap;
45
46    use super::*;
47    use crate::{def, prefix};
48    use texlang::vm::implement_has_component;
49    use texlang_testing::*;
50
51    #[derive(Default)]
52    struct State {
53        conditional: Component,
54        prefix: prefix::Component,
55        testing: TestingComponent,
56    }
57
58    impl TexlangState for State {
59        fn end_line_char(&self) -> Option<char> {
60            end_line_char(self)
61        }
62    }
63
64    implement_has_component![State {
65        conditional: Component,
66        prefix: prefix::Component,
67        testing: TestingComponent,
68    }];
69
70    fn built_in_commands() -> HashMap<&'static str, command::BuiltIn<State>> {
71        HashMap::from([("def", def::get_def()), ("endlinechar", get_endlinechar())])
72    }
73
74    test_suite![expansion_equality_tests(
75        (
76            case_1,
77            "\\endlinechar=`\\A Hello\nWorld\nMundo\n",
78            "Hello WorldAMundoA"
79        ),
80        (
81            case_2,
82            "\\endlinechar=-1 Hello\nWorld\nMundo\n",
83            "Hello WorldMundo"
84        ),
85        (
86            case_3,
87            "\\endlinechar=-1 Hello\nWorld  \nMundo\n",
88            "Hello WorldMundo"
89        ),
90        (case_4, "\\endlinechar=`\\A\nHello\nWorld\n", "Hello WorldA"),
91    ),];
92}