This answer is based on egreg's, simplified. If one wants to get the last item (brace group or single non-space non-[begin/end]-group token) in a list of tokens, simply use \tl_item:Nn \foo { -1 }
. If one wants to get the last token, the easiest way is to use the (experimental) l3regex module, as egreg noted. Here I define \velleman_get_last:nN
, which expects two arguments: some tokens, and a control sequence in which to store the result.
In most cases, \regex_extract_once:nnN { . \Z } { <tokens> } \result
will do the trick: the regular expression means "any token (.
), followed by the end (\Z
) of the input ". The line just below that converts from the result of \regex_extract_once:nnN
(currently a sequence) to a token list. The only case that needs to be treated specially is when the last token is an explicit end-group character. This cannot be put into a macro to give the result: we test for that with \regex_match:nnTF { \cE. \Z }
, where the regex means "a catcode (\c
) end-group (E
) token with arbitrary character code (.
), followed by the end (\Z
) of the input", and in that case, we put \c_group_end_token
, an implicit end-group token, into the token list.
\documentclass{article}
\usepackage{expl3,l3regex,l3str}
\def\A{abc}
\def\B{ab{c}}
\def\C{ab{c} }
\def\D{ab\linebreak}
\ExplSyntaxOn
%
\seq_new:N \l_velleman_last_seq
\tl_new:N \l_velleman_last_tl
\cs_new_protected:Npn \velleman_get_last:nN #1#2
{
\regex_match:nnTF { \cE. \Z } {#1}
{ \tl_set:Nn #2 { \c_group_end_token } }
{
\regex_extract_once:nnN { . \Z } {#1} \l_velleman_last_seq
\tl_set:Nx #2 { \seq_item:Nn \l_velleman_last_seq { 1 } }
}
}
\cs_generate_variant:Nn \velleman_get_last:nN { V }
%
\cs_new_protected:Npn \test:N #1
{
\velleman_get_last:VN #1 \l_tmpa_tl
\msg_term:n
{
Last ~ item: ~ ' \tl_item:Nn #1 { -1 } ' \\
Last ~ token: ~ ' \tl_to_str:N \l_tmpa_tl '
}
}
\test:N \A
\test:N \B
\test:N \C
\test:N \D
\ExplSyntaxOff
\stop
#1
; i.e.\firsttokof{{12}34} = 12
. Getting rid of those braces is a lot of work.