Skip to main content

retex_engine/
cmd.rs

1//! Command codes and their ranges.
2//!
3//! The numbering follows LuaTeX's `token.commands()`. TeX relies on the
4//! order of command codes: expandable commands come after `max_command`,
5//! internal quantities lie between `min_internal` and `max_internal`, and
6//! commands after `max_non_prefixed_command` are assignments.
7
8pub use crate::cmd_gen::Cmd;
9
10impl Cmd {
11    /// The largest category code of a character token (`max_char_code`).
12    pub const MAX_CHAR_CODE: Cmd = Cmd::DelimNum;
13    /// The smallest command that can follow `\the` (`min_internal`).
14    pub const MIN_INTERNAL: Cmd = Cmd::CharGiven;
15    /// The largest command that cannot be prefixed by `\global`.
16    pub const MAX_NON_PREFIXED: Cmd = Cmd::LastItem;
17    /// The largest command that can follow `\the` (`max_internal`).
18    pub const MAX_INTERNAL: Cmd = Cmd::Register;
19    /// The largest unexpandable command (`max_command`).
20    pub const MAX_COMMAND: Cmd = Cmd::SetFontId;
21
22    /// The command with numeric code `n`.
23    #[inline]
24    pub fn from_u8(n: u8) -> Cmd {
25        Cmd::ALL[n as usize]
26    }
27
28    /// Whether the command is expandable.
29    #[inline]
30    pub fn is_expandable(self) -> bool {
31        self > Cmd::MAX_COMMAND
32    }
33
34    /// Whether the command is a macro call (`call` … `long_outer_call`).
35    #[inline]
36    pub fn is_call(self) -> bool {
37        self >= Cmd::Call && self <= Cmd::LongOuterCall
38    }
39
40    /// Whether the command is an outer macro or a special outer marker
41    /// (`cur_cmd >= outer_call`).
42    #[inline]
43    pub fn is_outer_or_special(self) -> bool {
44        self >= Cmd::OuterCall
45    }
46
47    /// Whether the command denotes an internal quantity. LuaTeX's
48    /// direction parameters (`\pardirection`, `\pardir`, …) come after
49    /// `max_internal` but are read as quantities too (observed).
50    #[inline]
51    pub fn is_internal(self) -> bool {
52        (self >= Cmd::MIN_INTERNAL && self <= Cmd::MAX_INTERNAL)
53            || matches!(self, Cmd::AssignDirection | Cmd::AssignDir)
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn ranges_are_ordered() {
63        assert!(Cmd::MAX_CHAR_CODE < Cmd::CharNum);
64        assert!(Cmd::MIN_INTERNAL <= Cmd::MAX_NON_PREFIXED);
65        assert!(Cmd::MAX_NON_PREFIXED < Cmd::ToksRegister);
66        assert!(Cmd::MAX_INTERNAL < Cmd::Advance);
67        assert!(Cmd::MAX_COMMAND < Cmd::UndefinedCs);
68        assert!(Cmd::UndefinedCs.is_expandable());
69        assert!(!Cmd::SetFontId.is_expandable());
70        assert!(Cmd::LongOuterCall.is_call());
71        assert_eq!(Cmd::from_u8(147), Cmd::Call);
72    }
73}