% \iffalse meta-comment % % Copyright (C) 2025 Valentin Dao % % This file may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either % version 1.3 of this license or (at your option) any later % version. The latest version of this license is in: % % http://www.latex-project.org/lppl.txt % % and version 1.3c or later is part of all distributions of % LaTeX version 2008-05-04 or later. % % This work has the LPPL maintenance status 'maintained' % and the current maintainer is Valentin Dao (vdao.texdev@gmail.com). % % This work consists of the files xmeaning.ins and xmeaning.dtx. % % The repository of this work can be found at: % % https://github.com/ankaa3908/xmeaning % % \fi % \iffalse %<*readme> % % %<*driver> \documentclass{l3doc} \usepackage{intexgral} \usepackage{codedescribe} \lstset{gobble=2} \usepackage{xmeaning} \PkgInfoSetAliases \begin{document} \DocInput{xmeaning.dtx} \end{document} % % \fi % % \PkgInfoGet{xmeaning}{author}{\fileauthor} % \PkgInfoGet{xmeaning}{version}{\fileversion} % \PkgInfoGet{xmeaning}{date}{\filedate} % \PkgInfoGet{xmeaning}{creation}{\filecreationdate} % % \date{Released \filecreationdate} % % \title{^^A % The xmeaning package^^A % \thanks{This file describes v\fileversion, published \filedate.} % } % % \author{^^A % \fileauthor^^A % \thanks{E-mail: \href{mailto:vdao.texdev@gmail.com}{\ttfamily vdao.texdev@gmail.com}} % } % % \maketitle % % \begin{abstract} % The \tsobj[pkg]{xmeaning} package's main objective is to enhance the \tsobj[macro]{\meaning} primitive by enlarging the amount of given informationG. It requires \tsobj[pkg]{expl3} as well as \tsobj[pkg]{pkginfograb}. Please note that this package is considered to be highly experimental for the moment. % \end{abstract} % % \subsection*{Limitations} % % The \tsobj[macro]{\xmeaning} macro will fail under certain precise circumstances: % \begin{enumerate} % \item If the parameter text \emph{or} the replacement text of a macro contains \enquote{\verb|->|}. % \item If you use \tsobj[macro]{\xmeaning} for a constant defined using \tsobj[macro]{\chardef} or \tsobj[macro]{\mathchardef}. % \end{enumerate} % % Whether the compilation stops or succeeds, but with erroneous results, completely depends on what the argument is. % % \begin{codedescribe}[macro]{\xmeaning} % \begin{codesyntax}[macro] % \tsmacro{\xmeaning*}{list of tokens} % \end{codesyntax} % On its simplest form, \tsobj[macro]{\xmeaning} has a strictly similar usage to that of \tsobj[macro]{\meaning}. The main argument can either correspond to a character or a control sequence. With \tsobj[pkg]{xmeaning}, it is possible to specify a list of tokens to display all their meanings, avoiding the need to repeat the macro. Unlike the \TeX\ primitive, which doesn't always provide useful information, \tsobj[macro]{\xmeaning} is capable of recognising 5 \emph{token classes} among: % \begin{describelist}{option} % \describe{Characters}{A unique token.} % \describe{Character definitions}{A control sequence declared with \tsobj[macro]{\chardef} or \tsobj[macro]{\mathchardef}.} % \describe{\TeX\ registers}{Control sequences representing boxes, counts\dots} % \describe{expl3 data types}{All the variable types implemented by \LaTeX3.} % \describe{Macros}{A macro, or any control sequence that doesn't fall into the previous classes.} % \end{describelist} % By \emph{class}, we mean that the macro will produce an output adapted to each token type. Its starred variant will display the meaning of all auxiliary macros as described later. % \end{codedescribe} % % \section{Characters} % % Unlike the \tsobj[macro]{meaning} primitive, which gives us only little information regarding characters, the package lists all there is to know about them. % \begin{itemize} % \item Character code, with its ASCII, Unicode, octal and hexadecimal representations. % \item Category codes. % \item Upper or lower case code (depending on the case of the queried character)\textsuperscript\dagger. % \item Space factor code\textsuperscript\dagger. % \item Delimiter code. % \item Math code\textsuperscript\dagger. % \end{itemize} % % \begingroup % \small\textsuperscript\dagger\ These codes will be displayed only if they are not null. % \endgroup % % For math code, the package goes beyond simply displaying it, as it analyses it according to its functioning as described in the \TeX book. The same applies to the delimiter code if it is not 0. Furthermore, it is not necessary to escape special characters with a backslash. The macro may produce incorrect results if you pass it an argument that is not recognised by the encoding. If you are using an engine other than \hologo{XeLaTeX} or \hologo{LuaLaTeX}, keep this in mind. % % \begin{codestore}[char] % \xmeaning o % \end{codestore} % % \tsdemo*{char} % % \section{Character definitions} % % The package calls any character defined by \tsobj[macro]{\chardef} and \tsobj[macro]{\mathchardef} a \emph{character definition}. The advantage over the primitive \tsobj[macro]{\meaning} is that here the glyph is produced, allowing you to see the concrete result of the control sequence. It is precisely for this reason that constants defined with these two macros do not work (for example, certain plain\TeX\ constants such as \tsobj[macro]{\z@}, \tsobj[macro]{\@M}\dots). They correspond to numbers and not to real characters. Since the package cannot tell the difference, it will attempt to typeset a glyph with a character code that is certainly outside those defined by the font table. It also indicates whether the character should be used in text mode or math mode. % % \begin{codestore}[chardef] % \xmeaning{\%, \gamma} % \end{codestore} % % \tsdemo*{chardef} % % \section{Registers} % % For registers, the package simply displays its type as well as its content. % % \begin{codestore}[register] % \newtoks\temptoks % \temptoks={Token register} % \xmeaning\temptoks % \end{codestore} % % \tsdemo*{register} % % \section{Data types} % % \LaTeX3 data types are much more complex than registers. That is why a few more entries compared to registers are present. \tsobj[macro]{\xmeaning} will fail if the naming conventions for data types are not followed. % % \begin{codestore}[data types] % \ExplSyntaxOn % \tl_new:N \l_my_token_tl % \tl_set:Nn \l_my_token_tl { Token~data~type } % \xmeaning\l_my_token_tl % \ExplSyntaxOff % \end{codestore} % % \tsdemo*{data types} % % \section{Macros} % % The package produces a very complete output for macros, where the following information is typeset: % % \begin{itemize} % \item The name of the macro. % \item The type of macro. % \item The prefix of the macro (\tsobj[macro]{\long}, \tsobj[macro]{\protected}, and \tsobj[macro]{\outer})\textsuperscript\dagger. % \item The parameter text\textsuperscript\dagger. % \item The replacement text\textsuperscript\dagger. % \end{itemize} % % \begingroup % \small % \textsuperscript\dagger % Here too, these elements are only displayed if they are present. For primitives, they will always be absent. % \endgroup % % \vspace*{\baselineskip} % % The macro \emph{type} can be one of the following: % \begin{itemize} % \item \TeX primitive. % \item \TeX macro. % \item \tsobj[pkg]{expl3} primitive. % \item \tsobj[pkg]{expl3} macro. % \item argument specifier \tsobj[pkg]{expl3}, with distinction of the \emph{unbraced} variants. % \item \tsobj[pkg]{expl3} identity macro. % \item \tsobj[pkg]{xparse} macro. % \end{itemize} % % \begin{codestore}[macros] % \xmeaning{\kern, \newcommand} % \end{codestore} % % \tsdemo*{macros} % % \section{Exhaustive meaning} % % With the starred variant of \tsobj[macro]{\xmeaning}, it is possible to ask the package to display the meaning of all the auxiliary macros that make up the main argument. There is, however, no magical formula for knowing in advance what these auxiliary macros will be. The package therefore assumes that standard programming conventions are followed and, using a brute-force method, recursively applies \tsobj[macro]{\xmeaning} to all of the following macros: % % \begin{itemize} % \item \tsobj[macro]{\foo}\tsobj[meta]{\textvisiblespace}. % \item \tsobj[macro]{\foo}\tsobj[meta]{\textvisiblespace code} (for macros defined with \tsobj[pkg]{xparse}). % \item \tsobj[macro]{\foo}\tsobj[meta]{A-Z} (\verb|\fooA|, \verb|\fooB|\dots). % \item \tsobj[meta]{A-Z}\tsobj[macro]{\foo} (\verb|\Afoo|, \verb|\Bfoo|\dots). % \item Nesting of \emph{@} (\verb|\@foo|, \verb|\f@oo|\dots \verb|\foo@|). % \item Replacement of \emph{o} and \emph{a} by \emph{@} (\verb|\f@@|, \verb|\b@r|). % \item \tsobj[macro]{\foo}\tsobj[meta]{@Roman numeral} (\verb|\foo@ii|). % \item \tsobj[meta]{\_\_}\tsobj[macro]{\foo} (for internal macros of \tsobj[pkg]{expl3}). % \end{itemize} % % This method does not guarantee that if several macros are found, they are related to each other. Nor is it certain that auxiliary macros will be found even after applying all these rules, which are not absolute (after all, everyone is free to name their macros as they see fit). % % \begin{codestore}[exhaustive] % \xmeaning*{\newcommand, \integral} % \end{codestore} % % \tsdemo*{exhaustive} % % \newpage % % \section{Implementation} % % \begin{macrocode} %<*package> %<@@=xmeaning_pkg> \NeedsTeXFormat{LaTeX2e} \RequirePackage{expl3}[2025-05-14] \RequirePackage{pkginfograb} \pkginfograbProvidesExplPackage{xmeaning} { name = {xmeaning} , author = {Valentin Dao}, date = {2025-12-18}, creation = {2025-12-18}, version = {v0.1.0} , description = {Enhanced implementation of the \string\meaning\ primitive.} } \@ifpackagelater{expl3}{2025-05-14}{} { \PackageError { xmeaning } { Support~package~expl3~too~old } { expl3~version~too~old~ 'xmeaning'~requires~a~version~later~than:~2025-05-14. \MessageBreak Loading~xmeaning~will~abort. } \tex_endinput:D } \cs_new:Npn \@@_char_value_delcode:n #1 { \tex_number:D \tex_delcode:D #1 \scan_stop: } \cs_new_protected:Npn \@@_tex_halign:n #1 { \tex_halign:D { #1 } } \cs_generate_variant:Nn \regex_if_match:nnTF { neTF } \cs_generate_variant:Nn \regex_match_case:nn { ne } \cs_generate_variant:Nn \regex_match_case:nnF { neF } \cs_generate_variant:Nn \regex_extract_all:nnN { neN } \cs_generate_variant:Nn \int_to_hex:n { e } \cs_generate_variant:Nn \int_from_hex:n { e } \cs_generate_variant:Nn \int_case:nn { Vn } \cs_generate_variant:Nn \tl_range:nnn { nnV } \cs_generate_variant:Nn \char_generate:nn { en } \cs_generate_variant:Nn \token_if_cs:NTF { cTF } \cs_generate_variant:Nn \clist_put_right:Nn { Nf } \cs_generate_variant:Nn \int_compare_p:nNn { nNV } \int_new:N \l_@@_char_math_fam_int \int_new:N \l_@@_char_math_slot_int \int_new:N \l_@@_small_variant_family_int \int_new:N \l_@@_small_variant_position_int \int_new:N \l_@@_big_variant_family_int \int_new:N \l_@@_big_variant_position_int \bool_new:N \l_@@_undefined_cs_bool \bool_set_false:N \l_@@_undefined_cs_bool \bool_new:N \l_@@_exhaustive_meaning_bool \bool_set_false:N \l_@@_exhaustive_meaning_bool \tl_new:N \l_@@_register_type_tl \skip_new:N \l_@@_meaning_skip \skip_set:Nn \l_@@_meaning_skip { 6pt + 3pt - 2pt } \cs_new_protected:Npn \@@_print_clist:c #1 { \begin{enumerate} \clist_map_inline:cn { #1 } { \item ##1 } \end{enumerate} } \cs_new_protected:Npn \@@_print_seq:c #1 { \begin{enumerate} \seq_map_inline:cn { #1 } { \item ##1 } \end{enumerate} } \cs_new_protected:Npn \@@_print_prop:c #1 { \prop_map_inline:cn { #1 } { ##1~->~##2\tex_par:D } } \cs_new_protected:Npn \@@_character_meaning:N #1 { \int_set:Nn \l_tmpa_int { \int_eval:n { `#1 } } \tl_set:Ne \l_tmpb_tl { \int_to_Hex:n { \l_tmpa_int } } \tl_set:Ne \l_@@_utf_eight_representation_tl { U+ \prg_replicate:nn { \int_eval:n { 4 - \tl_count:N \l_tmpb_tl } } { 0 } \tl_use:N \l_tmpb_tl } \@@_tex_halign:n { \tex_hfil:D##&\c_space_tl=\c_space_tl\vbox_top:n{\raggedright##}\tex_cr:D Glyph & \token_to_meaning:N #1\tex_cr:D Category~code & \token_to_catcode:N #1\tex_cr:D Character~code & \int_use:N \l_tmpa_int\tex_cr:D Unicode & \tl_use:N \l_@@_utf_eight_representation_tl\tex_cr:D Octal & \int_to_oct:n { \l_tmpa_int }\tex_cr:D Hexadecimal & \int_to_hex:n { \l_tmpa_int }\tex_cr:D \bool_if:nF { \int_compare_p:nNn { \char_value_uccode:n { `#1 } } = { 0 } || \int_compare_p:nNV { \char_value_uccode:n { `#1 } } = \l_tmpa_int } { Uppercase~code & \char_value_uccode:n { `#1 }~(\char_generate:nn { \char_value_uccode:n { `#1 } } { 11 })\tex_cr:D } \bool_if:nF { \int_compare_p:nNn { \char_value_lccode:n { `#1 } } = { 0 } || \int_compare_p:nNV { \char_value_lccode:n { `#1 } } = \l_tmpa_int } { Lowercase~code & \char_value_lccode:n { `#1 }~(\char_generate:nn { \char_value_lccode:n { `#1 } } { 11 })\tex_cr:D } Space~factor~code & \char_value_sfcode:n { `#1 } \tex_cr:D Math~code & \int_to_hex:e { \char_value_mathcode:n { `#1 } } \sys_if_engine_luatex:TF { \int_set:Nn \l_tmpb_int { \Umathcharclass`#1 } \int_set:Nn \l_@@_char_math_fam_int { \Umathcharfam`#1 } \int_set:Nn \l_@@_char_math_slot_int { \Umathcharslot`#1 } } { \exp_args:NNe \int_set:Nn \l_tmpb_int { \tl_head:e { \int_to_hex:e { \char_value_mathcode:n { `#1 } } } } \exp_args:NNe \int_set:Nn \l_@@_char_math_fam_int { \exp_args:Ne \tl_item:nn { \int_to_hex:e { \char_value_mathcode:n { `#1 } } } { 2 } } \exp_args:NNe \int_set:Nn \l_@@_char_math_slot_int { \int_from_hex:e { \exp_args:Ne \tl_range:nnn { \int_to_hex:e { \char_value_mathcode:n { `#1 } } } { 3 } { 4 } } } }\tex_par:D Class:~ \int_case:Vn \l_tmpb_int { { 0 } { Ordinary } { 1 } { Large~operator } { 2 } { Binary~operation } { 3 } { Relation } { 4 } { Opening } { 5 } { Closing } { 6 } { Punctuation } { 7 } { Variable~family } }\tex_par:D Math~family:~\int_use:N \l_@@_char_math_fam_int\tex_par:D Font~position:~\int_use:N \l_@@_char_math_slot_int\tex_cr:D \int_compare:nNnF { \number\delcode`#1 } < { 0 } { Delimiter~code & \int_set:Nn \l_@@_small_variant_family_int { \tl_head:e { \@@_char_value_delcode:n { `#1 } } } \exp_args:NNe \int_set:Nn \l_@@_small_variant_position_int { \exp_args:Ne \tl_range:nnn { \@@_char_value_delcode:n { `#1 } } { 2 } { 3 } } \exp_args:NNe \int_set:Nn \l_@@_big_variant_family_int { \exp_args:Ne \tl_item:nn { \@@_char_value_delcode:n { `#1 } } { 4 } } \exp_args:NNe \int_set:Nn \l_@@_big_variant_position_int { \exp_args:Ne \tl_range:nnn { \@@_char_value_delcode:n { `#1 } } { 5 } { 6 } } \@@_char_value_delcode:n { `#1 } \tex_par:D Small~variant~family:~\int_use:N \l_@@_small_variant_family_int \tex_par:D Small~variant~position:~\int_use:N \l_@@_small_variant_position_int \tex_par:D Big~variant~family:~\int_use:N \l_@@_big_variant_family_int \tex_par:D Big~variant~position:~\int_use:N \l_@@_big_variant_position_int } \tex_crcr:D } } \cs_new_protected:Npn \@@_register_meaning:n #1 { \regex_extract_all:neN { \\([a-z]+)(\d+) } { \cs_meaning:c { #1 } } \l_tmpa_seq \str_case_e:nnF { \seq_item:Nn \l_tmpa_seq { 2 } } { { toks } { \tl_set:Nn \l_@@_register_type_tl { token } } { dimen } { \tl_set:Nn \l_@@_register_type_tl { dimension } } } { \tl_set:Ne \l_@@_register_type_tl { \seq_item:Nn \l_tmpa_seq { 2 } } } \@@_tex_halign:n { \tex_hfil:D##&\c_space_tl=\c_space_tl\vbox_top:n{\raggedright##}\tex_cr:D Register~name & \c_backslash_str #1 \tex_cr:D Type & \tl_use:N \l_@@_register_type_tl\ (no.~\seq_item:Nn \l_tmpa_seq { 3 })\tex_cr:D Content & \exp_last_unbraced:Ne \tex_the:D { \use:c { #1 } } \tex_crcr:D } } \cs_new_protected:Npn \@@_data_type_meaning:n #1 { \@@_tex_halign:n { \tex_hfil:D##&\c_space_tl=\c_space_tl\vbox_top:n{\raggedright##}\tex_cr:D Variable & \slshape \str_use:N \c_backslash_str \tl_to_str:n { #1 } \tex_cr:D Data~type & \str_case_e:nn { \seq_item:Nn \l_tmpb_seq { 4 } } { { tl } { token } { str } { string } { seq } { sequence } { int } { integer } { fp } { floating~point } { flag } { flag } { clist } { comma~list } { prop } { property~list } { dim } { dimension } { intarray } { integer~array } { fparray } { floating~point~array } { bitset } { bitset } { cctab } { category~code~table } { bool } { boolean } { regex } { regular~expression } { ior } { input/output~read~stream } { iow } { input/output~write~stream } { box } { box } { coffin } { coffin } } \tex_cr:D Content & \exp_last_unbraced:Ne \scan_stop: { \str_case_e:nn { \seq_item:Nn \l_tmpb_seq { 4 } } { { tl } { \exp_not:N \tl_use:c } { str } { \exp_not:N \str_use:c } { seq } { \exp_not:N \@@_print_seq:c } { int } { \exp_not:N \int_use:c } { fp } { \exp_not:N \fp_use:c } { flag } { \exp_not:N \flag_height:c } { clist } { \exp_not:N \@@_print_clist:c } { prop } { \exp_not:N \@@_print_prop:c } { dim } { \exp_not:N \dim_use:c } { bitset } { \exp_not:N \bitset_use:c } { bool } { \exp_not:N \bool_to_str:c } { box } { \exp_not:N \box_use:c } } } { #1 }\tex_cr:D Scope & \str_case_e:nn { \seq_item:Nn \l_tmpb_seq { 2 } } { { g } { global } { l } { local } { c } { constant } } \tex_cr:D Use & \int_case:nn { \int_eval:n { \tl_count:e { \seq_item:Nn \l_tmpb_seq { 3 } } } } { { 1 } { public } { 2 } { private } } \tex_crcr:D } } \cs_new_protected:Npn \@@_chardef_meaning:n #1 { \regex_extract_all:neN { \\(math)?char"([0-9A-Z]+) } { \cs_meaning:c { #1 } } \l_tmpa_seq \@@_tex_halign:n { \tex_hfil:D##&\c_space_tl=\c_space_tl\vbox_top:n{\raggedright##}\tex_cr:D Character~definition & \c_backslash_str #1 \tex_cr:D Glyph & \tl_if_empty:eTF { \seq_item:Nn \l_tmpa_seq { 2 } } { \char\exp_last_unbraced:Ne"{ \seq_item:Nn \l_tmpa_seq { 3 } } } { $ \mathchar\exp_last_unbraced:Ne"{ \seq_item:Nn \l_tmpa_seq { 3 } } $ } \tex_cr:D Mode & \tl_if_empty:eTF { \seq_item:Nn \l_tmpa_seq { 2 } } { text } { math } \tex_crcr:D } } \cs_new_protected:Npn \@@_macro_meaning:n #1 { \@@_tex_halign:n { \tex_hfil:D##&\c_space_tl=\c_space_tl\vbox_top:n{\raggedright##}\tex_cr:D Control~sequence & \tl_set:Nn \l_tmpa_tl { #1 } \tl_replace_all:Nnn \l_tmpa_tl { ~ } { \textvisiblespace } \slshape \str_use:N \c_backslash_str \tl_use:N \l_tmpa_tl \tex_cr:D Type & \exp_args:Nc \token_if_macro:NT { #1 } { \regex_match_case:nnF { { \w+:[NnVvcofexTFwD]* } { expl3~macro } { :{2}[NnVvcofexTFwD]_unbraced } { expl3~argument~specifier~(unbraced~type) } { :{2}[NnVvcofexTFwD]\Z } { expl3~argument~specifier } { :{3} } { expl3~identity~macro } { [a-zA-Z]\s code } { xparse~macro } } { #1 } { \TeX\ macro } } \exp_args:Nc \token_if_primitive:NT { #1 } { \regex_if_match:nnTF { tex\_\w+:D } { #1 } { expl3~primitive } { \TeX\ primitive } } \tex_cr:D \exp_args:Nc \token_if_primitive:NF { #1 } { \tl_if_empty:eF { \exp_args:Nc \cs_prefix_spec:N { #1 } } { Prefix & \exp_args:Nc \cs_prefix_spec:N { #1 } \tex_cr:D } } \exp_args:Nc \token_if_primitive:NF { #1 } { \tl_if_empty:eF { \exp_args:Nc \cs_parameter_spec:N { #1 } } { Parameters & \exp_args:Nc \cs_parameter_spec:N { #1 } \tex_cr:D } } \exp_args:Nc \token_if_primitive:NF { #1 } { Replacement~text & \cs_replacement_spec:c { #1 } } \tex_crcr:D } } \cs_new_protected:Npn \@@_control_sequence_meaning:n #1 { \cs_if_exist:cTF { #1 } { \regex_extract_all:nnNTF { \A(g|l|c)(_{1,2})\w*_([a-z]*) } { #1 } \l_tmpb_seq { \@@_data_type_meaning:n { #1 } } { \regex_match_case:neF { { \\(math)?char"([0-9A-Z]+) } { \@@_chardef_meaning:n { #1 } } { \\[a-z]+\d+ } { \@@_register_meaning:n { #1 } } } { \cs_meaning:c { #1 } } { \@@_macro_meaning:n { #1 } } } } { \bool_set_true:N \l_@@_undefined_cs_bool \bool_if:NF \l_@@_exhaustive_meaning_bool { Undefined } } } \cs_new_protected:Npn \@@_xmeaning_ii:n #1 { \group_begin: \ttfamily \frenchspacing \clist_set:Nn \l_tmpa_clist { #1 } \seq_set_from_clist:NN \l_tmpa_seq \l_tmpa_clist \seq_map_inline:Nn \l_tmpa_seq { \token_if_cs:NTF ##1 { \exp_args:Ne \@@_control_sequence_meaning:n { \cs_to_str:N ##1 } } { \@@_character_meaning:N ##1 } \bool_if:NF \l_@@_undefined_cs_bool { \skip_vertical:N \l_@@_meaning_skip } } \group_end: } \cs_new:Npn \@@_xmeaning_tl_map:nw #1#2#3 \q_stop { \str_if_eq:nnTF { #2 } { #1 } { @ } { #2 } \tl_if_empty:nF { #3 } { \@@_xmeaning_tl_map:nw { #1 } #3 \q_stop } } \cs_new:Npn \@@_xmeaning_replace_a_tokens:n #1 { \__xmeaning_tl_map:nw { a } #1 \q_stop } \cs_new:Npn \@@_xmeaning_replace_o_tokens:n #1 { \__xmeaning_tl_map:nw { o } #1 \q_stop } \cs_new_protected:Npn \@@_xmeaning_i:n #1 { \group_begin: \bool_set_true:N \l_@@_exhaustive_meaning_bool \ttfamily \frenchspacing \clist_set:Nn \l_tmpa_clist { #1 } \clist_map_inline:Nn \l_tmpa_clist { \clist_clear:N \l_tmpb_clist \tl_set:Ne \l_tmpa_tl { \token_if_cs:NTF ##1 { \cs_to_str:N ##1 } { ##1 } } \clist_put_right:Nf \l_tmpb_clist { \l_tmpa_tl\c_space_tl } \clist_put_right:Nf \l_tmpb_clist { \l_tmpa_tl\c_space_tl code} \clist_put_right:Ne \l_tmpb_clist { end\l_tmpa_tl} \exp_args:NNe \int_set:Nn \l_tmpa_int { \tl_count:V \l_tmpa_tl } \int_step_inline:nn { 26 } { \clist_put_right:Ne \l_tmpb_clist { \int_to_Alph:n { ####1 } \l_tmpa_tl, } \clist_put_right:Ne \l_tmpb_clist { \l_tmpa_tl \int_to_Alph:n { ####1 }, } } \int_step_inline:nn { 10 } { \clist_put_right:Ne \l_tmpb_clist { \l_tmpa_tl @\int_to_roman:n { ####1 } } } \int_step_inline:nnn { 0 } { \l_tmpa_int } { \clist_put_right:Ne \l_tmpb_clist { \exp_args:NV \tl_range:nnn { \l_tmpa_tl } { 1 } { ####1 } @ \exp_args:NV \tl_range:nnV { \l_tmpa_tl } { \int_eval:n{ ####1+1 } } \l_tmpa_int } } \tl_if_in:NnT \l_tmpa_tl { a } { \clist_put_right:Ne \l_tmpb_clist { \exp_args:NV \@@_xmeaning_replace_a_tokens:n \l_tmpa_tl } } \tl_if_in:NnT \l_tmpa_tl { o } { \clist_put_right:Ne \l_tmpb_clist { \exp_args:NV \@@_xmeaning_replace_o_tokens:n \l_tmpa_tl } } \clist_put_right:Ne \l_tmpb_clist { __\l_tmpa_tl } \@@_xmeaning_ii:n { ##1 } \clist_map_inline:Nn \l_tmpb_clist { \exp_args:Nc \@@_xmeaning_ii:n { ####1 } } } \group_end: } \NewDocumentCommand{\xmeaning}{ s m }{ \IfBooleanTF{#1} { \@@_xmeaning_i:n { #2 } } { \@@_xmeaning_ii:n { #2 } } } \ExplSyntaxOff % \end{macrocode}