diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3str.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3str.dtx | 181 |
1 files changed, 125 insertions, 56 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3str.dtx b/Master/texmf-dist/source/latex/l3kernel/l3str.dtx index c73c8ed9f35..2a5b4d952db 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3str.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3str.dtx @@ -37,7 +37,7 @@ \documentclass[full]{l3doc} %</driver> %<*driver|package> -\GetIdInfo$Id: l3str.dtx 5368 2014-08-24 22:32:57Z bruno $ +\GetIdInfo$Id: l3str.dtx 5545 2015-03-01 21:24:44Z joseph $ {L3 Strings} %</driver|package> %<*driver> @@ -139,7 +139,8 @@ % is logically \texttt{true}. % \end{function} % -% \begin{function}[added = 2013-07-24, EXP, TF]{\str_case:nn, \str_case:on} +% \begin{function}[added = 2013-07-24, updated = 2015-02-28, EXP, TF] +% {\str_case:nn, \str_case:on, \str_case:nV, \str_case:nv} % \begin{syntax} % \cs{str_case:nnTF} \Arg{test string} \\ % ~~|{| \\ @@ -190,7 +191,67 @@ % % \section{String manipulation} % -% \begin{function}[rEXP, added = 2014-06-19]{\str_fold_case:n} +% \begin{function}[rEXP, added = 2015-03-01] +% { +% \str_lower_case:n, \str_lower_case:f, +% \str_upper_case:n, \str_upper_case:f +% } +% \begin{syntax} +% \cs{str_lower_case:n} \Arg{tokens} +% \cs{str_upper_case:n} \Arg{tokens} +% \end{syntax} +% Converts the input \meta{tokens} to their string representation, as +% described for \cs{tl_to_str:n}, and then to the lower or upper +% case representation using a one-to-one mapping as described by the +% Unicode Consortium file |UnicodeData.txt|. +% +% These functions are intended for case changing programmatic data in +% places where upper/lower case distinctions are meaningful. One example +% would be automatically generating a function name from user input where +% some case changing is needed. In this situation the input is programmatic, +% not textual, case does have meaning and a language-independent one-to-one +% mapping is appropriate. For example +% \begin{verbatim} +% \cs_new_protected:Npn \myfunc:nn #1#2 +% { +% \cs_set_protected:cpn +% { +% user +% \str_upper_case:f { \tl_head:n {#1} } +% \str_lower_case:f { \tl_tail:n {#1} } +% } +% { #2 } +% } +% \end{verbatim} +% would be used to generate a function with an auto-generated name consisting +% of the upper case equivalent of the supplied name followed by the lower +% case equivalent of the rest of the input. +% +% These functions should \emph{not} be used for +% \begin{itemize} +% \item Caseless comparisons: use \cs{str_fold_case:n} for this +% situation (case folding is district from lower casing). +% \item Case changing text for typesetting: see the \cs{tl_lower_case:n(n)}, +% \cs{tl_upper_case:n(n)} and \cs{tl_mixed_case:n(n)} functions which +% correctly deal with context-dependence and other factors appropriate +% to text case changing. +% \end{itemize} +% +% \begin{texnote} +% As with all \pkg{expl3} functions, the input supported by +% \cs{str_fold_case:n} is \emph{engine-native} characters which are or +% interoperate with \textsc{utf-8}. As such, when used with \pdfTeX{} +% \emph{only} the Latin alphabet characters A--Z will be case-folded +% (\emph{i.e.}~the \textsc{ascii} range which coincides with +% \textsc{utf-8}). Full \textsc{utf-8} support is available with both +% \XeTeX{} and \LuaTeX{}, subject only to the fact that \XeTeX{} in +% particular has issues with characters of code above hexadecimal +% $0\mathrm{xFFF}$ when interacting with \cs{tl_to_str:n}. +% \end{texnote} +% \end{function} +% +% \begin{function}[rEXP, added = 2014-06-19, updated = 2015-03-01] +% {\str_fold_case:n} % \begin{syntax} % \cs{str_fold_case:n} \Arg{tokens} % \end{syntax} @@ -412,8 +473,10 @@ % \begin{macro}[int, EXP]{\@@_if_eq_x_return:nn} % \end{macro} % -% \begin{macro}[EXP]{\str_case:nn, \str_case:on, \str_case_x:nn} -% \begin{macro}[EXP, TF]{\str_case:nn, \str_case:on, \str_case_x:nn} +% \begin{macro}[EXP] +% {\str_case:nn, \str_case:on, \str_case:nV, \str_case:nv, \str_case_x:nn} +% \begin{macro}[EXP, TF] +% {\str_case:nn, \str_case:on, \str_case:nV, \str_case:nv, \str_case_x:nn} % \begin{macro}[EXP, aux]{\@@_case:nnTF, \@@_case_x:nnTF} % \begin{macro}[aux, EXP] % {\@@_case:nw, \@@_case_x:nw, \@@_case_end:nw} @@ -442,10 +505,10 @@ } \cs_new:Npn \@@_case:nnTF #1#2#3#4 { \@@_case:nw {#1} #2 {#1} { } \q_mark {#3} \q_mark {#4} \q_stop } -\cs_generate_variant:Nn \str_case:nn { o } -\cs_generate_variant:Nn \str_case:nnT { o } -\cs_generate_variant:Nn \str_case:nnF { o } -\cs_generate_variant:Nn \str_case:nnTF { o } +\cs_generate_variant:Nn \str_case:nn { o , nV , nv } +\cs_generate_variant:Nn \str_case:nnT { o , nV , nv } +\cs_generate_variant:Nn \str_case:nnF { o , nV , nv } +\cs_generate_variant:Nn \str_case:nnTF { o , nV , nv } \cs_new:Npn \@@_case:nw #1#2#3 { \str_if_eq:nnTF {#1} {#2} @@ -489,65 +552,71 @@ % % \subsection{String manipulation} % -% \begin{macro}[EXP]{\str_fold_case:n} -% \begin{macro}[aux, EXP]{\@@_fold_auxi:w} -% \begin{macro}[aux, EXP]{\@@_fold_auxii:N} -% \begin{macro}[aux, EXP]{\@@_fold_auxiii:NNNNNNNN} -% \begin{macro}[aux, EXP]{\@@_fold_end:w} -% To convert a string to the \enquote{caseless} form, the first stage is to -% remove tokenization. Once that is done, provided the transformed chars are -% also detokenized then there is no need to worry about category codes. -% Spaces need to be retained as part of the mapping, so there is a little -% work to do in the set up. Data to support this process is loaded later in -% the \pkg{expl3} bundle. +% \begin{macro}[EXP] +% { +% \str_fold_case:n, +% \str_lower_case:n, \str_lower_case:f, +% \str_upper_case:n, \str_upper_case:f +% } +% \begin{macro}[aux, EXP]{\__str_change_case:nn} +% \begin{macro}[aux, EXP]{\__str_change_case_aux:nn} +% \begin{macro}[aux, EXP]{\__str_change_case_loop:nw} +% \begin{macro}[aux, EXP]{\__str_change_case_space:n} +% \begin{macro}[aux, EXP]{\__str_change_case_char:nN} +% \begin{macro}[aux, EXP]{\__str_change_case_char:NNNNNNNNn} +% Case changing for programmatic reasons is done by first detokenizing +% input then doing a simple loop that only has to worry about spaces +% and everything else. The output is detokenized to allow data sharing +% with text-based case changing. The key idea here of splitting up the +% data files based on the character code of the current character is +% shared with the text case changer too. % \begin{macrocode} -\cs_new:Npn \str_fold_case:n #1 +\cs_new:Npn \str_fold_case:n #1 { \__str_change_case:nn {#1} { fold } } +\cs_new:Npn \str_lower_case:n #1 { \__str_change_case:nn {#1} { lower } } +\cs_new:Npn \str_upper_case:n #1 { \__str_change_case:nn {#1} { upper } } +\cs_generate_variant:Nn \str_lower_case:n { f } +\cs_generate_variant:Nn \str_upper_case:n { f } +\cs_new:Npn \__str_change_case:nn #1 { - \exp_after:wN \@@_fold_auxi:w \tl_to_str:n {#1} - { ~ \c_empty_tl } \@@_fold_end:w ? ~ + \exp_after:wN \__str_change_case_aux:nn \exp_after:wN + { \tl_to_str:n {#1} } } -% \end{macrocode} -% A loop using spaces as delimiters: done in this way there is no issue with -% spaces in the input. Notice that there is a second inner loop with -% \cs{@@_fold_auxii:N} for each \enquote{word}. -% \begin{macrocode} -\cs_new:Npn \@@_fold_auxi:w #1 ~ +\cs_new:Npn \__str_change_case_aux:nn #1#2 { - \@@_fold_auxii:N #1 { ~ \c_space_tl } - \@@_fold_auxi:w + \__str_change_case_loop:nw {#2} #1 \q_recursion_tail \q_recursion_stop } -% \end{macrocode} -% The idea here is to take a single token and convert it to its decimal -% character code. This can then be used to split up the input into $100$ -% separate manageable lists for comparison on a case-by-case basis. -% \begin{macrocode} -\cs_new:Npn \@@_fold_auxii:N #1 +\cs_new:Npn \__str_change_case_loop:nw #1#2 \q_recursion_stop { - \exp_after:wN \@@_fold_auxiii:NNNNNNNN - \int_use:N \__int_eval:w 1000000 + `#1 \__int_eval_end: #1 + \tl_if_head_is_space:nTF {#2} + { \__str_change_case_space:n } + { \__str_change_case_char:nN } + {#1} #2 \q_recursion_stop } -% \end{macrocode} -% At this stage, use a slow-but-expandable string case selection to look -% for a matching char. If one is not found then retain the input as-is. -% This also does some cleanup to allow a simple termination of the two -% loops. -% \begin{macrocode} -\cs_new:Npn \@@_fold_auxiii:NNNNNNNN #1#2#3#4#5#6#7#8 +\use:x + { \cs_new:Npn \exp_not:N \__str_change_case_space:n ##1 \c_space_tl } + { + \c_space_tl + \__str_change_case_loop:nw {#1} + } +\cs_new:Npn \__str_change_case_char:nN #1#2 { - \exp_args:NNv \str_case_x:nnF #8 - { c_@@_fold_ #6 _X_ #7 _tl } + \quark_if_recursion_tail_stop:N #2 + \exp_args:Nf \tl_to_str:n { - #8 - \exp_after:wN \use_none:n #8 + \exp_after:wN \__str_change_case_char:NNNNNNNNn + \int_use:N \__int_eval:w 1000000 + `#2 \__int_eval_end: #2 {#1} } - \@@_fold_auxii:N + \__str_change_case_loop:nw {#1} + } +\cs_new:Npn \__str_change_case_char:NNNNNNNNn #1#2#3#4#5#6#7#8#9 + { + \str_case:nvF #8 + { c__unicode_ #9 _ #6 _X_ #7 _tl } + { #8 } } % \end{macrocode} -% When the end is reached, clean everything up leaving the converted -% string in the input stream. -% \begin{macrocode} -\cs_new:Npn \@@_fold_end:w ? #1 \@@_fold_auxi:w { } -% \end{macrocode} +% \end{macro} +% \end{macro} % \end{macro} % \end{macro} % \end{macro} |