summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2015-09-22 22:26:04 +0000
committerKarl Berry <karl@freefriends.org>2015-09-22 22:26:04 +0000
commitf1f4767bbed8d529512166e9ebc17c398bf22888 (patch)
treef30d0120390ea88ad9977aadb443354ca0cb05d4 /Master/texmf-dist/source/latex
parentfb3db65044ad57f73474204792b8df34ee59d9e7 (diff)
gtl (22sep15)
git-svn-id: svn://tug.org/texlive/trunk@38434 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex')
-rw-r--r--Master/texmf-dist/source/latex/gtl/gtl.dtx495
1 files changed, 413 insertions, 82 deletions
diff --git a/Master/texmf-dist/source/latex/gtl/gtl.dtx b/Master/texmf-dist/source/latex/gtl/gtl.dtx
index d823c651253..b4f622066bf 100644
--- a/Master/texmf-dist/source/latex/gtl/gtl.dtx
+++ b/Master/texmf-dist/source/latex/gtl/gtl.dtx
@@ -1,5 +1,5 @@
% \iffalse
-%% File: gtl.dtx Copyright (C) 2013 Bruno Le Floch
+%% File: gtl.dtx Copyright (C) 2013,2015 Bruno Le Floch
%%
%% It may be distributed and/or modified under the conditions of the
%% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -23,9 +23,9 @@
%
% \title{The \textsf{gtl} package: \\
% manipulate unbalanced lists of tokens\thanks{This
-% file has version number 0.0a, last revised 2013/07/28.}}
+% file has version number 0.1, last revised 2015/09/21.}}
% \author{Bruno Le Floch}
-% \date{2013/07/28}
+% \date{2015/09/21}
%
% \maketitle
% \tableofcontents
@@ -41,6 +41,293 @@
% manipulates instead lists of tokens which may be unbalanced, with more
% begin-group or more end-group characters.
%
+% A technical comment: currently, all begin-group characters are
+% assumed to have the character code of ``|{|'' and all end-group
+% characters that of~``|}|''.
+%
+% Please report bugs (or suggestions) on the issue tracker
+% (\url{https://github.com/blefloch/latex-gtl/issues}).
+%
+% ^^A The following code checks the test coverage
+% \begingroup\ExplSyntaxOn
+% \msg_new:nnn { gtldoc } { discarded } { Discarded~some~material~after~closing~brace~of~{function}~or~TEST~or~TESTEXP~argument:~``#1'' }
+% \msg_new:nnn { gtldoc } { bad-test } { TEST~or~TESTEXP~followed~by~unexpected~character~``#1'' }
+% \msg_new:nnn { gtldoc } { multi-function } { Some~functions~are~defined~twice }
+% \msg_new:nnn { gtldoc } { doc-no-test } { ``#1''~is~documented~but~has~no~test }
+% \msg_new:nnn { gtldoc } { test-no-doc } { ``#1''~is~tested~but~not~documented }
+% \msg_new:nnn { gtldoc } { junk } { There~is~some~unexpected~junk.~Giving~up~on~this~line. }
+% \tl_new:N \l__gtldoc_arg_tl
+% \seq_new:N \l__gtldoc_internal_seq
+% \cs_generate_variant:Nn \use:nn { no }
+% \cs_generate_variant:Nn \tl_if_in:nnTF { no }
+% \cs_generate_variant:Nn \tl_if_in:nnT { no }
+% \cs_generate_variant:Nn \tl_remove_all:Nn { Nx }
+% \cs_generate_variant:Nn \seq_set_filter:NNn { NNx }
+% \group_begin:
+% \seq_new:N \l__gtldoc_fn_seq
+% \iow_new:N \g__gtldoc_ior
+% \tl_new:N \l__gtldoc_internal_tl
+% \str_new:N \l__gtldoc_TF_str
+% \seq_new:N \l__gtldoc_arg_seq
+% \seq_new:N \l__gtldoc_arg_TF_seq
+% \cs_new:Npn \__gtldoc_remove_backslash:N #1
+% { \exp_after:wN \token_if_eq_charcode:NNF \c_backslash_str #1 {#1} }
+% \cs_new_protected:Npn \gtldoc_get_fn:n #1
+% {
+% \seq_clear:N \l__gtldoc_fn_seq
+% \clist_map_inline:nn {#1}
+% {
+% \__gtldoc_get_fn:nn { function } {#1} ^^A todo: this is wasteful, going through the file twice!
+% \__gtldoc_get_fn:nn { variable } {#1}
+% }
+% }
+% \cs_new_protected:Npn \__gtldoc_get_fn:nn #1
+% {
+% \exp_args:Noo \__gtldoc_get_fn_aux:nnn
+% { \tl_to_str:n { begin } } { \tl_to_str:n { {#1} } }
+% }
+% \cs_new_eq:NN \__gtldoc_test:w ?
+% \cs_new_eq:NN \__gtldoc_skip:w ?
+% \cs_new_protected:Npn \__gtldoc_get_fn_aux:nnn #1#2#3
+% {
+% \cs_gset_protected:Npn \__gtldoc_test:w ##1 #1 ##2 #2 { }
+% \cs_gset_protected_nopar:Npn \__gtldoc_skip:w ##1 #1 ##2 #2
+% {
+% \tl_clear:N \l__gtldoc_arg_tl
+% \str_clear:N \l__gtldoc_TF_str
+% \tl_if_blank:nF {##2}
+% {
+% \msg_error:nn { gtldoc } { junk }
+% \use_none_delimit_by_q_recursion_stop:w
+% }
+% \__gtldoc_aux:N
+% }
+% \ior_open:Nn \g__gtldoc_ior {#3}
+% \ior_str_map_inline:Nn \g__gtldoc_ior
+% {
+% \tl_if_in:noT {##1} { \tl_to_str:n { end { documentation } } } ^^A careful if you remove spaces!
+% { \ior_map_break: }
+% \tl_if_empty:oF { \__gtldoc_test:w ##1 #1 #2 }
+% { \__gtldoc_skip:w ##1 \q_recursion_tail \q_recursion_stop }
+% }
+% \ior_close:N \g__gtldoc_ior
+% }
+% \cs_new_protected:Npn \__gtldoc_aux:N #1
+% {
+% \token_if_eq_meaning:NNT #1 \q_recursion_tail
+% { \__gtldoc_more:Nw \__gtldoc_aux:N }
+% \str_case_x:nnF {#1}
+% {
+% \c_percent_str { \__gtldoc_aux:N } ^^A ignore percent
+% ^ { \__gtldoc_hat:N } ^^A check for "^^A"
+% [ { \__gtldoc_opt:w }
+% \c_left_brace_str { \__gtldoc_arg:w }
+% }
+% { \__gtldoc_varg:N #1 }
+% }
+% \cs_new_protected:Npn \__gtldoc_more:Nw #1 #2 \q_recursion_stop
+% { ^^A grab one more line and restart the loop
+% \ior_get_str:NN \g__gtldoc_ior \l__gtldoc_internal_tl
+% \exp_after:wN #1 \l__gtldoc_internal_tl
+% \q_recursion_tail \q_recursion_stop
+% }
+% \cs_new_protected:Npn \__gtldoc_hat:N #1
+% {
+% \token_if_eq_charcode:NNTF #1 ^
+% { \__gtldoc_hat_hat:N }
+% { \__gtldoc_varg:N ^ #1 }
+% }
+% \cs_new_protected:Npn \__gtldoc_hat_hat:N #1 ^^A in principle we should worry about crazy people doing ^^01 or ^^5b etc
+% {
+% \token_if_eq_charcode:NNTF #1 A
+% { \__gtldoc_more:Nw \__gtldoc_aux:N } ^^A we found a comment
+% { \__gtldoc_varg:N ^ ^ #1 }
+% }
+% \cs_new_protected:Npn \__gtldoc_opt:w #1 \q_recursion_tail
+% {
+% \tl_if_in:nnTF {#1} { ] }
+% { \__gtldoc_opt_aux:w #1 \q_recursion_tail }
+% { \__gtldoc_more:Nw \__gtldoc_opt:w }
+% }
+% \cs_new_protected:Npn \__gtldoc_opt_aux:w #1 ]
+% {
+% \tl_if_in:noTF {#1} { \tl_to_str:n { pTF } }
+% { \str_set:Nn \l__gtldoc_TF_str { pTF } }
+% {
+% \tl_if_in:noT {#1} { \tl_to_str:n { TF } }
+% { \str_set:Nn \l__gtldoc_TF_str { TF } }
+% }
+% \__gtldoc_aux:N
+% }
+% \cs_new_protected_nopar:Npn \__gtldoc_arg:w
+% { \exp_after:wN \__gtldoc_varg:N \c_right_brace_str }
+% \cs_new_protected:Npn \__gtldoc_varg:N #1
+% { \exp_args:No \__gtldoc_varg_aux:n { \token_to_str:N #1 } }
+% \cs_new_protected:Npn \__gtldoc_varg_aux:n #1
+% {
+% \cs_gset_protected:Npn \__gtldoc_varg_aux:w ##1 #1 { {##1} }
+% \cs_gset_protected:Npn \__gtldoc_varg_loop:w ##1 \q_recursion_tail
+% {
+% \tl_if_in:noTF {##1} {#1}
+% {
+% \exp_after:wN \__gtldoc_varg_last:nw
+% \__gtldoc_varg_aux:w ##1 \q_recursion_tail
+% }
+% {
+% \tl_put_right:Nx \l__gtldoc_arg_tl { ##1 \iow_char:N \^^M }
+% \__gtldoc_more:Nw \__gtldoc_varg_loop:w
+% }
+% }
+% \__gtldoc_varg_loop:w
+% }
+% \cs_new_eq:NN \__gtldoc_varg_aux:w ?
+% \cs_new_eq:NN \__gtldoc_varg_loop:w ?
+% \cs_new_protected:Npn \__gtldoc_varg_last:nw
+% #1#2 \q_recursion_tail \q_recursion_stop
+% {
+% \tl_if_blank:nF {#2}
+% { \msg_warning:nnn { gtldoc } { discarded } {#2} }
+% \tl_put_right:Nn \l__gtldoc_arg_tl {#1}
+% \tl_remove_all:Nx \l__gtldoc_arg_tl { \iow_char:N \^^M \iow_char:N \% } ^^A from l3doc
+% \tl_remove_all:Nx \l__gtldoc_arg_tl { \tl_to_str:n { ^ ^ A } } ^^A from l3doc
+% \tl_remove_all:Nx \l__gtldoc_arg_tl { \iow_char:N \^^I } ^^A from l3doc
+% \tl_remove_all:Nx \l__gtldoc_arg_tl { \iow_char:N \^^M } ^^A from l3doc
+% ^^A \@@_replace_at_at:N \l_@@_tmpa_tl ^^A from l3doc but not done here
+% \exp_args:NNx \seq_set_from_clist:Nn \l__gtldoc_arg_seq
+% { \tl_to_str:N \l__gtldoc_arg_tl }
+% \str_if_empty:NF \l__gtldoc_TF_str
+% {
+% \seq_clear:N \l__gtldoc_arg_TF_seq
+% \seq_map_inline:Nn \l__gtldoc_arg_seq
+% {
+% \seq_put_right:Nx \l__gtldoc_arg_TF_seq { ##1 TF }
+% \seq_put_right:Nx \l__gtldoc_arg_TF_seq { ##1 T }
+% \seq_put_right:Nx \l__gtldoc_arg_TF_seq { ##1 F }
+% \str_if_eq_x:nnT { \l__gtldoc_TF_str } { pTF }
+% { \seq_put_right:Nx \l__gtldoc_arg_TF_seq { \__gtldoc_pred:w ##1 } }
+% }
+% \seq_set_map:NNn \l__gtldoc_arg_seq
+% \l__gtldoc_arg_TF_seq { \tl_to_str:n {##1} }
+% }
+% \seq_concat:NNN \l__gtldoc_fn_seq \l__gtldoc_fn_seq \l__gtldoc_arg_seq
+% }
+% \use:no { \cs_new:Npn \__gtldoc_pred:w #1 } { \token_to_str:N : } { #1 _p: }
+% \group_end:
+% \group_begin:
+% \seq_new:N \l__gtldoc_tested_fn_seq
+% \cs_new_protected:Npn \gtldoc_get_tests:n #1
+% {
+% \seq_clear:N \l__gtldoc_tested_fn_seq
+% \clist_map_function:nN {#1} \__gtldoc_get_test:n
+% }
+% \cs_new_protected:Npn \__gtldoc_get_test:n #1
+% {
+% \ior_open:Nn \g__gtldoc_ior {#1}
+% \ior_str_map_inline:Nn \g__gtldoc_ior
+% { \__gtldoc_test_aux:n {##1} }
+% \ior_close:N \g__gtldoc_ior
+% }
+% \cs_gset_protected:Npn \__gtldoc_tmp:nn #1#2
+% {
+% \cs_new_protected:Npn \__gtldoc_test_skipi:w ##1 #1 { }
+% \cs_new_protected:Npn \__gtldoc_test_skipii:w ##1 #2 { }
+% \cs_new_protected:Npn \__gtldoc_test_aux:n ##1
+% {
+% \tl_if_empty:oF { \__gtldoc_test_skipi:w ##1 #1 }
+% {
+% \tl_if_empty:oTF { \__gtldoc_test_skipii:w ##1 #2 }
+% { \__gtldoc_test_auxi:w } { \__gtldoc_test_auxii:w }
+% ##1 \q_recursion_tail \q_recursion_stop
+% }
+% }
+% \cs_new_protected:Npn \__gtldoc_test_auxi:w ##1 #1
+% { \__gtldoc_test_auxiii:N }
+% \cs_new_protected:Npn \__gtldoc_test_auxii:w ##1 #2
+% { \__gtldoc_test_auxiii:N }
+% }
+% \exp_args:Noo \__gtldoc_tmp:nn
+% { \token_to_str:N \TEST }
+% { \token_to_str:N \TESTEXP }
+% \cs_new_protected:Npn \__gtldoc_test_auxiii:N #1
+% {
+% \token_if_eq_meaning:NNT \q_recursion_tail #1
+% { \__gtldoc_more:Nw \__gtldoc_test_auxiii:N }
+% \exp_after:wN \token_if_eq_charcode:NNTF \c_left_brace_str #1
+% { \__gtldoc_test_arg:w }
+% {
+% \msg_error:nnn { gtldoc } { bad-test } {#1}
+% \use_none_delimit_by_q_recursion_stop:w
+% }
+% }
+% \cs_new_protected_nopar:Npn \__gtldoc_test_arg:w
+% {
+% \tl_clear:N \l__gtldoc_arg_tl
+% \exp_args:No \__gtldoc_test_arg_aux:N \c_right_brace_str
+% }
+% \cs_new_protected:Npn \__gtldoc_test_arg_aux:N #1
+% {
+% \cs_gset_protected:Npn \__gtldoc_test_arg_aux:w ##1 #1 { {##1} }
+% \cs_gset_protected:Npn \__gtldoc_test_arg_loop:w ##1 \q_recursion_tail
+% {
+% \tl_if_in:noTF {##1} {#1}
+% {
+% \exp_after:wN \__gtldoc_test_arg_last:nw
+% \__gtldoc_test_arg_aux:w ##1 \q_recursion_tail
+% }
+% {
+% \tl_put_right:Nn \l__gtldoc_arg_tl {##1}
+% \__gtldoc_more:Nw \__gtldoc_test_arg_loop:w
+% }
+% }
+% \__gtldoc_test_arg_loop:w
+% }
+% \cs_new_eq:NN \__gtldoc_test_arg_aux:w ?
+% \cs_new_eq:NN \__gtldoc_test_arg_loop:w ?
+% \cs_new_protected:Npn \__gtldoc_test_arg_last:nw
+% #1#2 \q_recursion_tail \q_recursion_stop
+% {
+% \tl_if_blank:nF {#2}
+% { \msg_warning:nnn { gtldoc } { discarded } {#2} }
+% \tl_put_right:Nn \l__gtldoc_arg_tl {#1}
+% \exp_args:NNx \seq_set_from_clist:Nn \l__gtldoc_arg_seq
+% { \tl_to_str:N \l__gtldoc_arg_tl }
+% \seq_set_filter:NNx \l__gtldoc_arg_seq \l__gtldoc_arg_seq
+% { \exp_not:N \tl_if_head_eq_charcode_p:nN {####1} \c_backslash_str }
+% \seq_concat:NNN \l__gtldoc_tested_fn_seq \l__gtldoc_tested_fn_seq \l__gtldoc_arg_seq
+% }
+% \group_end:
+% \gtldoc_get_fn:n { gtl.dtx }
+% \gtldoc_get_tests:n
+% {
+% ../../testfiles/gtl000.lvt ,
+% ../../testfiles/gtl001.lvt ,
+% ../../testfiles/gtl002.lvt ,
+% ../../testfiles/gtl003.lvt ,
+% ../../testfiles/gtl004.lvt ,
+% ../../testfiles/gtl005.lvt ,
+% ../../testfiles/gtl006.lvt
+% }
+% \group_begin:
+% \seq_set_eq:NN \l__gtldoc_internal_seq \l__gtldoc_fn_seq
+% \seq_remove_duplicates:N \l__gtldoc_internal_seq
+% \int_compare:nF
+% { \seq_count:N \l__gtldoc_internal_seq = \seq_count:N \l__gtldoc_fn_seq }
+% {
+% \msg_error:nn { gtldoc } { multi-function }
+% \seq_set_eq:NN \l__gtldoc_fn_seq \l__gtldoc_internal_seq
+% }
+% \seq_remove_duplicates:N \l__gtldoc_tested_fn_seq
+% \seq_map_inline:Nn \l__gtldoc_fn_seq
+% {
+% \seq_if_in:NnTF \l__gtldoc_tested_fn_seq {#1}
+% { \seq_remove_all:Nn \l__gtldoc_tested_fn_seq {#1} }
+% { \msg_error:nnn { gtldoc } { doc-no-test } {#1} }
+% }
+% \seq_map_inline:Nn \l__gtldoc_tested_fn_seq
+% { \msg_error:nnn { gtldoc } { test-no-doc } {#1} }
+% \group_end:
+% \endgroup
+%
% \subsection{Creating and initialising extended token lists}
%
% \begin{function}{\gtl_new:N}
@@ -214,6 +501,7 @@
% \cs{gtl_pop_left:N} \meta{gtl~var}
% \end{syntax}
% Remove the first token from \meta{gtl~var_1}.
+% If the \meta{gtl~var_1} is empty nothing happens.
% \end{function}
%
% \begin{function}{\gtl_pop_left:NN, \gtl_gpop_left:NN}
@@ -222,7 +510,8 @@
% \end{syntax}
% Stores the first token from \meta{gtl~var_1} in \meta{gtl~var_2} as
% an single-token extended token list, and remove it from
-% \meta{gtl~var_1}.
+% \meta{gtl~var_1}. If the \meta{gtl~var_1} is empty it remains so,
+% and \meta{gtl~var_2} is set to contain \cs{q_no_value}.
% \end{function}
%
% \begin{function}[EXP,pTF]{\gtl_if_head_eq_catcode:NN}
@@ -364,11 +653,12 @@
% input stream.
% \end{function}
%
-% \begin{function}{\gtl_show:N}
+% \begin{function}{\gtl_show:N, \gtl_log:N}
% \begin{syntax}
% \cs{gtl_show:N} \meta{gtl~var}
% \end{syntax}
-% Displays the content of the \meta{gtl~var} on the terminal.
+% Displays the content of the \meta{gtl~var} on the terminal or in
+% the log file.
% \end{function}
%
% \begin{function}[EXP]{\gtl_to_str:N}
@@ -418,7 +708,7 @@
% \end{itemize}
%
% We could add (with lots of work) the expandable function
-% \begin{syntax}
+% \begin{quote}\ttfamily\obeylines\obeyspaces
% \cs{gtl_concat:nF}
% \{
% \Arg{tl_1} \Arg{start_1} \Arg{stop_1}
@@ -427,13 +717,13 @@
% \Arg{tl_n} \Arg{start_n} \Arg{stop_n}
% \}
% \Arg{false code}
-% \end{syntax}
-% For each triplet, this function builds the sub-token list of <tl_i>
-% corresponding to the tokens ranging from position <start_i> to
-% position <stop_i> of <tl_i>. The results obtained for each triplet
+% \end{quote}
+% For each triplet, this function builds the sub-token list of \meta{tl_i}
+% corresponding to the tokens ranging from position \meta{start_i} to
+% position \meta{stop_i} of \meta{tl_i}. The results obtained for each triplet
% are then concatenated. If nothing bad happens (see below), the
-% concatenation is left in the input stream, and the <false code> is
-% removed. Two cases can lead to running the <false code> (and dropping
+% concatenation is left in the input stream, and the \meta{false code} is
+% removed. Two cases can lead to running the \meta{false code} (and dropping
% the first argument altogether). The first case is when the number of
% brace groups in \cs{gtl_concat:nF} is not a multiple of 3. The second
% case is when the concatenation gives rise to an unbalanced token list:
@@ -454,9 +744,9 @@
% \end{macrocode}
%
% \begin{macrocode}
-\RequirePackage{expl3}[2013/07/01]
+\RequirePackage{expl3}[2015/09/11]
\ProvidesExplPackage
- {gtl} {2013/07/28} {0.0a} {Manipulate unbalanced lists of tokens}
+ {gtl} {2015/09/21} {0.1} {Manipulate unbalanced lists of tokens}
% \end{macrocode}
%
% \begin{macrocode}
@@ -528,17 +818,22 @@
% \{ \Arg{b_1} \ldots{} \Arg{b_n} \}
% \Arg{c}
% \{ \Arg{e_p} \ldots{} \Arg{e_1} \}
-% \cs{s__stop}
% \end{quote}
% Note that the \meta{e_i} are in a reversed order, as this makes the
% ends of extended token lists more accessible. Balanced token lists
% have $n = p = 0$: the first and third parts are empty, while the
% second contains the tokens.
%
+% In the following code comments, the balanced token lists \meta{b_i}
+% are called ``leading chunks'', \meta{c} is called ``middle chunk'',
+% and \meta{e_i} are called ``trailing chunks''. It is important to
+% note that a balanced sub-list of a gtl must be entirely contained in
+% one of the chunk.
+%
% \begin{variable}{\s_@@}
% This marker appears at the start of extended token lists.
% \begin{macrocode}
-\__scan_new:N \s_@@
+\cs_new_eq:NN \s_@@ \scan_stop:
% \end{macrocode}
% \end{variable}
%
@@ -548,8 +843,8 @@
% \gtl_set:Nx, \gtl_gset:Nx, \gtl_const:Nx
% }
% Storing a balanced token list into an extended token list variable
-% simply means adding \cs{s_@@}, \cs{s__stop}, and two empty brace
-% groups.
+% simply means adding \cs{s_@@} and two empty brace
+% groups: there are no leading nor trailing chunks.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \gtl_set:Nn { \@@_set:NNn \tl_set:Nn }
\cs_new_protected_nopar:Npn \gtl_gset:Nn { \@@_set:NNn \tl_gset:Nn }
@@ -558,7 +853,7 @@
\cs_new_protected_nopar:Npn \gtl_gset:Nx { \@@_set:NNn \tl_gset:Nx }
\cs_new_protected_nopar:Npn \gtl_const:Nx { \@@_set:NNn \tl_const:Nx }
\cs_new_protected:Npn \@@_set:NNn #1#2#3
- { #1 #2 { \s_@@ { } {#3} { } \s__stop } }
+ { #1 #2 { \s_@@ { } {#3} { } } }
% \end{macrocode}
% \end{macro}
%
@@ -571,11 +866,12 @@
% \end{variable}
%
% \begin{variable}{\c_group_begin_gtl, \c_group_end_gtl}
-% An extended token list with exactly one begin-group/end-group
-% character.
+% Extended token lists with exactly one begin-group/end-group
+% character are built by including a single (empty) leading or
+% trailing chunk.
% \begin{macrocode}
-\tl_const:Nn \c_group_end_gtl { \s_@@ { { } } { } { } \s__stop }
-\tl_const:Nn \c_group_begin_gtl { \s_@@ { } { } { { } } \s__stop }
+\tl_const:Nn \c_group_end_gtl { \s_@@ { { } } { } { } }
+\tl_const:Nn \c_group_begin_gtl { \s_@@ { } { } { { } } }
% \end{macrocode}
% \end{variable}
%
@@ -630,21 +926,24 @@
%
% \begin{macro}{\gtl_put_left:Nn, \gtl_gput_left:Nn}
% \begin{macro}[aux, rEXP]{\@@_put_left:wn}
+% If there is no leading chunk in the gtl variable, then add the new
+% material to the middle chunk. Otherwise add it to the first
+% leading chunk, namely the first brace group in the first argument
+% of \cs{@@_put_left:wn}.
% \begin{macrocode}
\cs_new_protected:Npn \gtl_put_left:Nn #1#2
{ \tl_set:Nx #1 { \exp_after:wN \@@_put_left:wn #1 {#2} } }
\cs_new_protected:Npn \gtl_gput_left:Nn #1#2
{ \tl_gset:Nx #1 { \exp_after:wN \@@_put_left:wn #1 {#2} } }
-\cs_new:Npn \@@_put_left:wn \s_@@ #1#2#3 \s__stop #4
+\cs_new:Npn \@@_put_left:wn \s_@@ #1#2#3 #4
{
\tl_if_empty:nTF {#1}
- { \exp_not:n { \s_@@ { } { #4 #2 } {#3} \s__stop } }
+ { \exp_not:n { \s_@@ { } { #4 #2 } {#3} } }
{
\s_@@
{ \exp_not:o { \@@_brace:nn {#4} #1 } }
{ \exp_not:n {#2} }
{ \exp_not:n {#3} }
- \s__stop
}
}
% \end{macrocode}
@@ -653,21 +952,21 @@
%
% \begin{macro}{\gtl_put_right:Nn, \gtl_gput_right:Nn}
% \begin{macro}[aux, rEXP]{\@@_put_right:wn}
+% Symmetric of \cs{gtl_put_left:Nn}.
% \begin{macrocode}
\cs_new_protected:Npn \gtl_put_right:Nn #1#2
{ \tl_set:Nx #1 { \exp_after:wN \@@_put_right:wn #1 {#2} } }
\cs_new_protected:Npn \gtl_gput_right:Nn #1#2
{ \tl_gset:Nx #1 { \exp_after:wN \@@_put_right:wn #1 {#2} } }
-\cs_new:Npn \@@_put_right:wn \s_@@ #1#2#3 \s__stop #4
+\cs_new:Npn \@@_put_right:wn \s_@@ #1#2#3 #4
{
\tl_if_empty:nTF {#3}
- { \exp_not:n { \s_@@ {#1} { #2 #4 } { } \s__stop } }
+ { \exp_not:n { \s_@@ {#1} { #2 #4 } { } } }
{
\s_@@
{ \exp_not:n {#1} }
{ \exp_not:n {#2} }
{ \exp_not:o { \@@_brace_swap:nn {#4} #3 } }
- \s__stop
}
}
% \end{macrocode}
@@ -692,7 +991,6 @@
% \{ \Arg{b_1} \ldots{} \Arg{b_n} \}
% \Arg{c}
% \{ \Arg{e_p} \ldots{} \Arg{e_1} \}
-% \cs{s__stop}
% \end{quote}
% is not an easy task. The \meta{e} parts of the first join with the
% \meta{b} parts of the second to make balanced pairs, and the
@@ -703,7 +1001,7 @@
{ \tl_set:Nx #1 { \exp_last_two_unbraced:Noo \@@_concat:ww #2 #3 } }
\cs_new_protected:Npn \gtl_gconcat:NNN #1#2#3
{ \tl_gset:Nx #1 { \exp_last_two_unbraced:Noo \@@_concat:ww #2 #3 } }
-\cs_new:Npn \@@_concat:ww \s_@@ #1#2#3 \s__stop \s_@@ #4#5#6 \s__stop
+\cs_new:Npn \@@_concat:ww \s_@@ #1#2#3 \s_@@ #4#5#6
{
\tl_if_blank:nTF {#3}
{
@@ -717,7 +1015,6 @@
{ \@@_concat_auxiv:nnnn }
}
{#1} {#2} {#3} {#4} {#5} {#6}
- \s__stop
}
\cs_new:Npn \@@_concat_aux:nnnnnn #1#2#3#4#5#6
{ \exp_not:n { \s_@@ {#1} { #2 #5 } {#6} } }
@@ -755,14 +1052,14 @@
#1#2 \q_mark #3#4 \q_mark #5#6
{
\@@_concat:ww
- \s_@@ {#5} { #6 { #1 #3 } } { } \s__stop
+ \s_@@ {#5} { #6 { #1 #3 } } { }
\s_@@ {#4}
}
\cs_new:Npn \@@_concat_auxvi:nnwnwnn
#1#2#3 \q_mark #4#5 \q_mark #6#7
{
\@@_concat:ww
- \s_@@ {#6} {#7} { { #2 { #1 #4 } } #3 } \s__stop
+ \s_@@ {#6} {#7} { { #2 { #1 #4 } } #3 }
\s_@@ {#5}
}
% \end{macrocode}
@@ -771,8 +1068,7 @@
%
% \subsection{Showing extended token lists}
%
-% ^^A todo: document \gtl_to_str:n
-% \begin{macro}[EXP]{\gtl_to_str:N, \gtl_to_str:n}
+% \begin{macro}[EXP]{\gtl_to_str:N}
% \begin{macro}[EXP, aux]
% {
% \@@_to_str:w,
@@ -784,8 +1080,7 @@
% }
% \begin{macrocode}
\cs_new:Npn \gtl_to_str:N #1 { \exp_after:wN \@@_to_str:w #1 }
-\cs_new:Npn \gtl_to_str:n #1 { \@@_to_str:w #1 }
-\cs_new:Npn \@@_to_str:w \s_@@ #1#2#3 \s__stop
+\cs_new:Npn \@@_to_str:w \s_@@ #1#2#3
{ \@@_to_str_loopi:nnw { } #1 \q_nil \q_mark {#2} {#3} }
\cs_new:Npx \@@_to_str_loopi:nnw #1#2
{
@@ -823,26 +1118,40 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\gtl_show:N}
-% Display the variable name, then its string representation.
+% \begin{macro}{\gtl_show:N, \gtl_log:N}
+% \begin{macro}[aux]{\@@_show:NNN}
+% Display the variable name, then its string representation. Before
+% that, test that the variable indeed exists, and if appropriate
+% throw an error message by sending the undefined variable to
+% \cs{tl_show:N} or \cs{tl_log:N}.
% \begin{macrocode}
-\cs_new_protected:Npn \gtl_show:N #1
- { \exp_args:Nx \tl_show:n { \token_to_str:N #1 = \gtl_to_str:N #1 } }
+\cs_new_protected_nopar:Npn \gtl_show:N
+ { \@@_show:NNN \tl_show:n \tl_show:N }
+\cs_new_protected_nopar:Npn \gtl_log:N
+ { \@@_show:NNN \tl_log:n \tl_log:N }
+\cs_new_protected:Npn \@@_show:NNN #1#2#3
+ {
+ \gtl_if_exist:NTF #3
+ { \exp_args:Nx #1 { \token_to_str:N #3 = \gtl_to_str:N #3 } }
+ { #2 #3 }
+ }
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
% \subsection{Extended token list conditionals}
%
% \begin{macro}[EXP, pTF]{\gtl_if_eq:NN}
-% Two extended token lists are equal if their contents agree.
+% Two extended token lists are equal if the underlying token lists
+% are the same.
% \begin{macrocode}
-\prg_new_conditional:Npnn \gtl_if_eq:NN #1#2 { p , T , F , TF }
- { \tl_if_eq:NNTF #1 #2 { \prg_return_true: } { \prg_return_false: } }
+\prg_new_eq_conditional:NNn \gtl_if_eq:NN \tl_if_eq:NN
+ { p , T , F , TF }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP, pTF]{\gtl_if_empty:N}
-% An extended token list is empty if it is equal to the empty one.
+% An extended token list is empty if it is equal to the empty gtl.
% \begin{macrocode}
\prg_new_conditional:Npnn \gtl_if_empty:N #1 { p , T , F , TF }
{
@@ -854,10 +1163,11 @@
%
% \begin{macro}[EXP, pTF]{\gtl_if_tl:N}
% \begin{macro}[EXP,aux]{\@@_if_tl_return:w}
+% A gtl is balanced if it has neither leading nor trailing chunk.
% \begin{macrocode}
\prg_new_conditional:Npnn \gtl_if_tl:N #1 { p , T , F , TF }
{ \exp_after:wN \@@_if_tl_return:w #1 }
-\cs_new:Npn \@@_if_tl_return:w \s_@@ #1#2#3 \s__stop
+\cs_new:Npn \@@_if_tl_return:w \s_@@ #1#2#3
{
\tl_if_empty:nTF { #1 #3 }
{ \prg_return_true: } { \prg_return_false: }
@@ -868,22 +1178,30 @@
%
% \begin{macro}[EXP, pTF]{\gtl_if_single_token:N}
% \begin{macro}[EXP,aux]{\@@_if_single_token_return:w}
+% If there are neither leading nor trailing chunks then the gtl is a
+% single token if and only if the middle chunk is a single token.
+% Otherwise the gtl is a single token only if it is exactly a
+% begin-group or an end-group token.
% \begin{macrocode}
\prg_new_conditional:Npnn \gtl_if_single_token:N #1 { p , T , F , TF }
- { \exp_after:wN \@@_if_single_token_return:w #1 }
-\cs_new:Npn \@@_if_single_token_return:w \s_@@ #1#2#3 \s__stop
+ { \exp_after:wN \@@_if_single_token_return:w #1 #1 }
+\cs_new:Npn \@@_if_single_token_return:w \s_@@ #1#2#3 #4
{
- \bool_if:nTF
+ \tl_if_empty:nTF { #1 #3 }
{
- \tl_if_empty_p:n {#2}
- && \tl_if_single_p:n { #1 #3 }
- && \tl_if_empty_p:o { \use:n #1 #3 }
- ||
- \tl_if_single_token_p:n {#2}
- && \tl_if_empty_p:n { #1 #3 }
+ \tl_if_single_token:nTF {#2}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ {
+ \gtl_if_eq:NNTF #4 \c_group_begin_gtl
+ { \prg_return_true: }
+ {
+ \gtl_if_eq:NNTF #4 \c_group_end_gtl
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
}
- { \prg_return_true: }
- { \prg_return_false: }
}
% \end{macrocode}
% \end{macro}
@@ -891,10 +1209,13 @@
%
% \begin{macro}[EXP,pTF]{\gtl_if_blank:N}
% \begin{macro}[EXP,aux]{\@@_if_blank_return:w}
+% A gtl is blank if its middle chunk is blank and it has no leading
+% nor trailing chunk (those would lead to |#1| or |#3| containing
+% brace groups).
% \begin{macrocode}
\prg_new_conditional:Npnn \gtl_if_blank:N #1 { p , T , F , TF }
{ \exp_after:wN \@@_if_blank_return:w #1 }
-\cs_new:Npn \@@_if_blank_return:w \s_@@ #1#2#3 \s__stop
+\cs_new:Npn \@@_if_blank_return:w \s_@@ #1#2#3
{
\tl_if_blank:nTF { #1 #2 #3 }
{ \prg_return_true: }
@@ -911,6 +1232,11 @@
% \gtl_if_head_is_space:N,
% \gtl_if_head_is_N_type:N,
% }
+% Based on a five-way test \cs{@@_head:wnnnnn} defined later. The
+% five cases are: the gtl is empty, it starts with a begin-group,
+% with an end-group, with a space, or with an N-type token. In the
+% last case, the token is left in the input stream after the brace
+% group, hence the need for \cs{use_none:n} here.
% \begin{macrocode}
\prg_new_conditional:Npnn \gtl_if_head_is_group_begin:N #1
{ p , T , F , TF }
@@ -1026,7 +1352,7 @@
% cases (when the first token is |N|-type), it performs |#8|~followed
% by the first token.
% \begin{macrocode}
-\cs_new:Npn \@@_head:wnnnnn \s_@@ #1#2#3 \s__stop #4#5#6#7#8
+\cs_new:Npn \@@_head:wnnnnn \s_@@ #1#2#3 #4#5#6#7#8
{
\tl_if_empty:nTF {#1}
{
@@ -1120,10 +1446,16 @@
% }
% \begin{macrocode}
\cs_new_protected:Npn \gtl_pop_left:N #1
- { \tl_set:Nx #1 { \exp_after:wN \@@_pop_left:w #1 } }
+ {
+ \gtl_if_empty:NF #1
+ { \tl_set:Nx #1 { \exp_after:wN \@@_pop_left:w #1 } }
+ }
\cs_new_protected:Npn \gtl_gpop_left:N #1
- { \tl_gset:Nx #1 { \exp_after:wN \@@_pop_left:w #1 } }
-\cs_new:Npn \@@_pop_left:w \s_@@ #1#2#3 \s__stop
+ {
+ \gtl_if_empty:NF #1
+ { \tl_gset:Nx #1 { \exp_after:wN \@@_pop_left:w #1 } }
+ }
+\cs_new:Npn \@@_pop_left:w \s_@@ #1#2#3
{
\tl_if_empty:nTF {#1}
{
@@ -1138,7 +1470,6 @@
\s_@@
{ }
\@@_pop_left_auxii:nnnw { } { } #1 \q_nil \q_stop
- \s__stop
}
\cs_new:Npn \@@_pop_left_auxii:nnnw #1#2#3
{
@@ -1158,7 +1489,6 @@
{ \tl_if_head_is_group:nT {#1} { { \tl_head:n {#1} } } }
{ \tl_if_head_is_space:nTF {#1} { \exp_not:f } { \tl_tail:n } {#1} }
{ \exp_not:n {#2} }
- \s__stop
}
\cs_new:Npn \@@_pop_left_auxv:nnn #1#2#3
{
@@ -1166,7 +1496,6 @@
{ \if_false: { \fi: \@@_pop_left_auxvi:n #1 } }
{ \exp_not:n {#2} }
{ \exp_not:n {#3} }
- \s__stop
}
\cs_new:Npn \@@_pop_left_auxvi:n #1
{
@@ -1205,22 +1534,29 @@
%
% \begin{macro}[EXP]{\gtl_left_tl:N}
% \begin{macro}[EXP,aux]{\@@_left_tl:w}
+% If there is no leading chunk, return the middle chunk, otherwise
+% the first leading chunk.
% \begin{macrocode}
\cs_new:Npn \gtl_left_tl:N #1
{ \exp_after:wN \@@_left_tl:w #1 }
-\cs_new:Npn \@@_left_tl:w \s_@@ #1#2#3 \s__stop
+\cs_new:Npn \@@_left_tl:w \s_@@ #1#2#3
{ \tl_if_empty:nTF {#1} { \exp_not:n {#2} } { \tl_head:n {#1} } }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\gtl_pop_left_tl:N, \gtl_gpop_left_tl:N}
+% If there is no left chunk, remove the middle chunk, hence the
+% resulting gtl will start with two empty brace groups (one for the
+% absence of leading chunk, and one for the emptyness of the middle
+% chunk). If there are left chunks replace the first one by an empty
+% chunk.
% \begin{macrocode}
\cs_new_protected:Npn \gtl_pop_left_tl:N #1
{ \tl_set:Nx #1 { \exp_after:wN \@@_pop_left_tl:w #1 } }
\cs_new_protected:Npn \gtl_gpop_left_tl:N #1
{ \tl_gset:Nx #1 { \exp_after:wN \@@_pop_left_tl:w #1 } }
-\cs_new:Npn \@@_pop_left_tl:w \s_@@ #1#2#3 \s__stop
+\cs_new:Npn \@@_pop_left_tl:w \s_@@ #1#2#3
{
\s_@@
\tl_if_empty:nTF {#1}
@@ -1230,7 +1566,6 @@
{ \exp_not:n {#2} }
}
{ \exp_not:n {#3} }
- \s__stop
}
% \end{macrocode}
% \end{macro}
@@ -1246,7 +1581,7 @@
% \begin{macrocode}
\cs_new:Npn \gtl_left_item:NF #1
{ \exp_after:wN \@@_left_item:wF #1 }
-\cs_new:Npn \@@_left_item:wF \s_@@ #1#2#3 \s__stop
+\cs_new:Npn \@@_left_item:wF \s_@@ #1#2#3
{ \@@_left_item_auxi:nwF #1 {#2} \q_stop }
\cs_new:Npn \@@_left_item_auxi:nwF #1#2 \q_stop #3
{ \tl_if_blank:nTF {#1} {#3} { \tl_head:n {#1} } }
@@ -1271,7 +1606,7 @@
\prg_new_protected_conditional:Npnn \gtl_gpop_left_item:NN #1#2 { TF , T , F }
{ \exp_after:wN \@@_pop_left_item:wNNN #1#2 \tl_gset:Nx #1 }
\cs_new_protected:Npn \@@_pop_left_item:wNNN
- \s_@@ #1#2#3 \s__stop #4#5#6
+ \s_@@ #1#2#3 #4#5#6
{
\tl_if_empty:nTF {#1}
{
@@ -1281,7 +1616,7 @@
#5 #6
{
\s_@@ { } { \tl_tail:n {#2} }
- { \exp_not:n {#3} } \s__stop
+ { \exp_not:n {#3} }
}
\prg_return_true:
}
@@ -1303,7 +1638,6 @@
{ { \tl_tail:n {#1} } \@@_strip_nil_mark:w #2 \q_mark }
{ \exp_not:n {#3} }
{ \exp_not:n {#4} }
- \s__stop
}
\prg_return_true:
}
@@ -1332,7 +1666,7 @@
% \begin{macrocode}
\cs_new:Npn \gtl_left_text:NF #1
{ \exp_after:wN \@@_left_text:wF #1 }
-\cs_new:Npn \@@_left_text:wF \s_@@ #1#2#3 \s__stop
+\cs_new:Npn \@@_left_text:wF \s_@@ #1#2#3
{
\tl_if_empty:nTF {#1}
{ \@@_left_text_auxi:nwF {#2} \q_stop }
@@ -1362,7 +1696,7 @@
{ \tl_set:Nx #1 { \exp_after:wN \@@_pop_left_text:w #1 } }
\cs_new_protected:Npn \gtl_gpop_left_text:N #1
{ \tl_gset:Nx #1 { \exp_after:wN \@@_pop_left_text:w #1 } }
-\cs_new:Npn \@@_pop_left_text:w \s_@@ #1#2#3 \s__stop
+\cs_new:Npn \@@_pop_left_text:w \s_@@ #1#2#3
{
\s_@@
\tl_if_empty:nTF {#1}
@@ -1375,7 +1709,6 @@
{ \exp_not:n {#2} }
}
{ \exp_not:n {#3} }
- \s__stop
}
\cs_new:Npn \@@_pop_left_text_auxi:n #1
{
@@ -1432,11 +1765,11 @@
% \begin{macrocode}
\cs_new:Npn \gtl_extra_end:N #1
{ \exp_after:wN \@@_extra_end:w #1 }
-\cs_new:Npn \@@_extra_end:w \s_@@ #1#2#3 \s__stop
+\cs_new:Npn \@@_extra_end:w \s_@@ #1#2#3
{ \@@_tl_count:n {#1} }
\cs_new:Npn \gtl_extra_begin:N #1
{ \exp_after:wN \@@_extra_begin:w #1 }
-\cs_new:Npn \@@_extra_begin:w \s_@@ #1#2#3 \s__stop
+\cs_new:Npn \@@_extra_begin:w \s_@@ #1#2#3
{ \@@_tl_count:n {#3} }
% \end{macrocode}
% \end{macro}
@@ -1453,7 +1786,7 @@
% \begin{macrocode}
\cs_new:Npn \gtl_count_tokens:N #1
{ \exp_after:wN \@@_count_tokens:w #1 }
-\cs_new:Npn \@@_count_tokens:w \s_@@ #1#2#3 \s__stop
+\cs_new:Npn \@@_count_tokens:w \s_@@ #1#2#3
{
\int_eval:n
{ \c_minus_one \@@_count_auxi:nw #1 {#2} #3 \q_nil \q_stop }
@@ -1497,8 +1830,6 @@
% \end{macro}
% \end{macro}
%
-% \subsection{Messages}
-%
% \begin{macrocode}
%</package>
% \end{macrocode}