diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3file.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3file.dtx | 252 |
1 files changed, 182 insertions, 70 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx index a8262e75962..f81f3a488b5 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -164,9 +164,10 @@ % % \subsection{Reading from files} % -% \begin{function}[added = 2012-06-24]{\ior_get:NN} +% \begin{function}[noTF, added = 2012-06-24, updated = 2019-02-17]{\ior_get:NN} % \begin{syntax} % \cs{ior_get:NN} \meta{stream} \meta{token list variable} +% \cs{ior_get:NNTF} \meta{stream} \meta{token list variable} \meta{true code} \meta{false code} % \end{syntax} % Function that reads one or more lines (until an equal number of left % and right braces are found) from the input \meta{stream} and stores @@ -191,6 +192,8 @@ % \end{verbatim} % Also notice that if multiple lines are read to match braces % then the resulting token list can contain \cs{par} tokens. +% In the non-branching version, where the file is not found the \meta{tl var} +% is set to \cs{q_no_value}. % \begin{texnote} % This protected macro is a wrapper around the \TeX{} primitive % \tn{read}. Regardless of settings, \TeX{} replaces trailing space @@ -203,9 +206,11 @@ % \end{texnote} % \end{function} % -% \begin{function}[added = 2016-12-04]{\ior_str_get:NN} +% \begin{function}[noTF, added = 2016-12-04, updated = 2019-02-17] +% {\ior_str_get:NN} % \begin{syntax} % \cs{ior_str_get:NN} \meta{stream} \meta{token list variable} +% \cs{ior_str_get:NNTF} \meta{stream} \meta{token list variable} \meta{true code} \meta{false code} % \end{syntax} % Function that reads one line from the input \meta{stream} and stores % the result locally in the \meta{token list} variable. If the @@ -223,6 +228,8 @@ % \end{verbatim} % results in a token list |a b c| with the letters |a|, |b|, and |c| % having category code~12. +% In the non-branching version, where the file is not found the \meta{tl var} +% is set to \cs{q_no_value}. % \begin{texnote} % This protected macro is a wrapper around the \eTeX{} primitive % \tn{readline}. Regardless of settings, \TeX{} removes trailing @@ -313,17 +320,17 @@ % \end{texnote} % \end{function} % -%\begin{function}[updated = 2012-02-10, EXP, pTF]{\ior_if_eof:N} -% \begin{syntax} -% \cs{ior_if_eof_p:N} \meta{stream} \\ -% \cs{ior_if_eof:NTF} \meta{stream} \Arg{true code} \Arg{false code} -% \end{syntax} -% Tests if the end of a \meta{stream} has been reached during a reading -% operation. The test also returns a \texttt{true} value if -% the \meta{stream} is not open. -%\end{function} +% \begin{function}[updated = 2012-02-10, EXP, pTF]{\ior_if_eof:N} +% \begin{syntax} +% \cs{ior_if_eof_p:N} \meta{stream} \\ +% \cs{ior_if_eof:NTF} \meta{stream} \Arg{true code} \Arg{false code} +% \end{syntax} +% Tests if the end of a \meta{stream} has been reached during a reading +% operation. The test also returns a \texttt{true} value if +% the \meta{stream} is not open. +% \end{function} % -% \section{Writing to files} +% \subsection{Writing to files} % % \begin{function}[updated = 2012-06-05]{\iow_now:Nn, \iow_now:Nx, \iow_now:cn, \iow_now:cx} % \begin{syntax} @@ -592,8 +599,7 @@ % \cs{l_file_search_path_seq}. % \end{function} % -% \begin{function}[added = 2019-01-16]{\file_get:nnN} -% \begin{function}[TF, added = 2019-01-16]{\file_get:nnN} +% \begin{function}[noTF, added = 2019-01-16, updated = 2019-02-16]{\file_get:nnN} % \begin{syntax} % \cs{file_get:nnN} \Arg{filename} \Arg{setup} \meta{tl} % \cs{file_get:nnNTF} \Arg{filename} \Arg{setup} \meta{tl} \Arg{true code} \Arg{false code} @@ -601,23 +607,25 @@ % Defines \meta{tl} to the contents of \meta{filename}. % Category codes may need to be set appropriately via the \meta{setup} % argument. -% While \cs{file_get:nnN} produces an error if the file is not found, -% \cs{file_get:nnNTF} runs the \meta{true code} (after the assignment -% to \meta{tl}) if the file is found and \meta{false code} otherwise. -% \end{function} +% The non-branching version sets the \meta{tl} to \cs{q_no_value} if the file is +% not found. The branching version runs the \meta{true code} after the +% assignment to \meta{tl} if the file is found, and \meta{false code} +% otherwise. % \end{function} % -% \begin{function}[updated = 2017-06-26] +% \begin{function}[noTF, updated = 2019-02-16] % {\file_get_full_name:nN, \file_get_full_name:VN} % \begin{syntax} -% \cs{file_get_full_name:nN} \Arg{file name} \meta{str var} +% \cs{file_get_full_name:nN} \Arg{file name} \meta{tl} +% \cs{file_get_full_name:nNTF} \Arg{file name} \meta{tl} \Arg{true code} \Arg{false code} % \end{syntax} % Searches for \meta{file name} in the path as detailed for -% \cs{file_if_exist:nTF}, and if found sets the \meta{str var} the +% \cs{file_if_exist:nTF}, and if found sets the \meta{tl var} the % fully-qualified name of the file, \emph{i.e.}~the path and file name. % This includes an extension |.tex| when the given \meta{file name} % has no extension but the file found has that extension. -% If the file is not found then the \meta{str var} is empty. +% In the non-branching version, the \meta{tl var} will be set to +% \cs{q_no_value} in the case that the file does not exist. % \end{function} % % \begin{function}[added = 2017-06-23, updated = 2017-06-26] @@ -782,10 +790,10 @@ % \end{macrocode} % \end{macro} % -% \begin{variable}{\l_@@_file_name_str} +% \begin{variable}{\l_@@_file_name_tl} % Data storage. % \begin{macrocode} -\str_new:N \l_@@_file_name_str +\tl_new:N \l_@@_file_name_tl % \end{macrocode} % \end{variable} % @@ -797,13 +805,12 @@ % \begin{macrocode} \prg_new_protected_conditional:Npnn \ior_open:Nn #1#2 { T , F , TF } { - \file_get_full_name:nN {#2} \l_@@_file_name_str - \str_if_empty:NTF \l_@@_file_name_str - { \prg_return_false: } + \file_get_full_name:nNTF {#2} \l_@@_file_name_tl { - \__kernel_ior_open:No #1 \l_@@_file_name_str + \__kernel_ior_open:No #1 \l_@@_file_name_tl \prg_return_true: } + { \prg_return_false: } } \prg_generate_conditional_variant:Nnn \ior_open:Nn { c } { T , F , TF } % \end{macrocode} @@ -955,19 +962,35 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}{\ior_get:NN} +% \begin{macro}{\ior_get:NN, \@@_get:NN} +% \begin{macro}[TF]{\ior_get:NN} % And here we read from files. % \begin{macrocode} \cs_new_protected:Npn \ior_get:NN #1#2 + { \ior_get:NNF #1 #2 { \tl_set:Nn #2 { \q_no_value } } } +\cs_new_protected:Npn \@@_get:NN #1#2 { \tex_read:D #1 to #2 } +\prg_new_protected_conditional:Npnn \ior_get:NN #1#2 { T , F , TF } + { + \ior_if_eof:NTF #1 + { \prg_return_false: } + { + \@@_get:NN #1 #2 + \prg_return_true: + } + } % \end{macrocode} % \end{macro} +% \end{macro} % -% \begin{macro}{\ior_str_get:NN} +% \begin{macro}{\ior_str_get:NN, \@@_str_get:NN} +% \begin{macro}[TF]{\ior_str_get:NN} % Reading as strings is a more complicated wrapper, as we wish to % remove the endline character and restore it afterwards. % \begin{macrocode} \cs_new_protected:Npn \ior_str_get:NN #1#2 + { \ior_str_get:NNF #1 #2 { \tl_set:Nn #2 { \q_no_value } } } +\cs_new_protected:Npn \@@_str_get:NN #1#2 { \exp_args:Nno \use:n { @@ -976,8 +999,18 @@ \int_set:Nn \tex_endlinechar:D } { \int_use:N \tex_endlinechar:D } } +\prg_new_protected_conditional:Npnn \ior_str_get:NN #1#2 { T , F , TF } + { + \ior_if_eof:NTF #1 + { \prg_return_false: } + { + \@@_str_get:NN #1 #2 + \prg_return_true: + } + } % \end{macrocode} % \end{macro} +% \end{macro} % % \begin{macro}[EXP]{\ior_map_break:, \ior_map_break:n} % Usual map breaking functions. @@ -1001,9 +1034,9 @@ % stream has only one \enquote{current line}. % \begin{macrocode} \cs_new_protected:Npn \ior_map_inline:Nn - { \@@_map_inline:NNn \ior_get:NN } + { \@@_map_inline:NNn \@@_get:NN } \cs_new_protected:Npn \ior_str_map_inline:Nn - { \@@_map_inline:NNn \ior_str_get:NN } + { \@@_map_inline:NNn \@@_str_get:NN } \cs_new_protected:Npn \@@_map_inline:NNn { \int_gincr:N \g__kernel_prg_map_int @@ -1173,10 +1206,10 @@ % \end{macrocode} % \end{macro} % -% \begin{variable}{\l_@@_file_name_str} +% \begin{variable}{\l_@@_file_name_tl} % Data storage. % \begin{macrocode} -\str_new:N \l_@@_file_name_str +\tl_new:N \l_@@_file_name_tl % \end{macrocode} % \end{variable} % @@ -1187,10 +1220,10 @@ % \begin{macrocode} \cs_new_protected:Npn \iow_open:Nn #1#2 { - \__kernel_file_name_sanitize:nN {#2} \l_@@_file_name_str + \__kernel_file_name_sanitize:nN {#2} \l_@@_file_name_tl \iow_close:N #1 \seq_gpop:NNTF \g_@@_streams_seq \l_@@_stream_tl - { \@@_open_stream:NV #1 \l_@@_file_name_str } + { \@@_open_stream:NV #1 \l_@@_file_name_tl } %<*initex> { \__kernel_msg_fatal:nn { kernel } { output-streams-exhausted } } %</initex> @@ -1198,7 +1231,7 @@ { \@@_new:N #1 \tl_set:Nx \l_@@_stream_tl { \int_eval:n {#1} } - \@@_open_stream:NV #1 \l_@@_file_name_str + \@@_open_stream:NV #1 \l_@@_file_name_tl } %</package> } @@ -1332,8 +1365,8 @@ \cs_set_protected:Npn \iow_term:x { \iow_now:Nx \c_term_iow } \cs_new_protected:Npn \iow_term:n { \iow_now:Nn \c_term_iow } % \end{macrocode} -%\end{macro} -%\end{macro} +% \end{macro} +% \end{macro} % % \subsubsection{Special characters for writing} % @@ -2092,11 +2125,11 @@ % \end{macrocode} % \end{variable} % -% \begin{variable}{\l_@@_base_name_str, \l_@@_full_name_str} +% \begin{variable}{\l_@@_base_name_tl, \l_@@_full_name_tl} % For storing the basename and full path whilst passing data internally. % \begin{macrocode} -\str_new:N \l_@@_base_name_str -\str_new:N \l_@@_full_name_str +\tl_new:N \l_@@_base_name_tl +\tl_new:N \l_@@_full_name_tl % \end{macrocode} % \end{variable} % @@ -2144,8 +2177,6 @@ \char_set_active_eq:NN ##1 \l_@@_internal_tl } \tl_set:Nx \l_@@_internal_tl {#1} - \tl_set:Nx \l_@@_internal_tl - { \tl_to_str:N \l_@@_internal_tl } \exp_args:NNNV \group_end: \str_set:Nn #2 \l_@@_internal_tl } @@ -2190,19 +2221,18 @@ \cs_new_protected:Npn \file_get:nnN #1#2#3 { \file_get:nnNF {#1} {#2} #3 - { \__kernel_file_missing:n {#1} } + { \tl_set:Nn #3 { \q_no_value } } } \prg_new_protected_conditional:Npnn \file_get:nnN #1#2#3 { T , F , TF } { - \file_get_full_name:nN {#1} \l_@@_full_name_str - \str_if_empty:NTF \l_@@_full_name_str - { \prg_return_false: } + \file_get_full_name:nNTF {#1} \l_@@_full_name_tl { \exp_args:NV \@@_get_aux:nnN - \l_@@_full_name_str + \l_@@_full_name_tl {#2} #3 \prg_return_true: } + { \prg_return_false: } } \cs_new_protected:Npn \@@_get_aux:nnN #1#2#3 { @@ -2229,6 +2259,7 @@ % \end{macro} % % \begin{macro}{\file_get_full_name:nN, \file_get_full_name:VN} +% \begin{macro}[TF]{\file_get_full_name:nN, \file_get_full_name:VN} % \begin{macro}{\@@_get_full_name_search:nN} % The way to test if a file exists is to try to open it: if it does % not exist then \TeX{} reports end-of-file. A search is made @@ -2242,7 +2273,13 @@ % \begin{macrocode} \cs_new_protected:Npn \file_get_full_name:nN #1#2 { - \__kernel_file_name_sanitize:nN {#1} \l_@@_base_name_str + \file_get_full_name:nNF {#1} #2 + { \tl_set:Nn #2 { \q_no_value } } + } +\cs_generate_variant:Nn \file_get_full_name:nN { V } +\prg_new_protected_conditional:Npnn \file_get_full_name:nN #1#2 { T , F , TF } + { + \__kernel_file_name_sanitize:nN {#1} \l_@@_base_name_tl \@@_get_full_name_search:nN { } \use:n \seq_map_inline:Nn \l_file_search_path_seq { \@@_get_full_name_search:nN { ##1 / } \seq_map_break:n } @@ -2253,35 +2290,43 @@ { \@@_get_full_name_search:nN { ##1 } \tl_map_break:n } } %</package> - \str_clear:N \l_@@_full_name_str + \tl_set:Nn \l_@@_full_name_tl { \q_no_value } \prg_break_point: - \str_if_empty:NF \l_@@_full_name_str + \quark_if_no_value:NTF \l_@@_full_name_tl + { + \ior_close:N \g_@@_internal_ior + \prg_return_false: + } { - \exp_args:NV \file_parse_full_name:nNNN \l_@@_full_name_str + \exp_args:NV \file_parse_full_name:nNNN \l_@@_full_name_tl \l_@@_dir_str \l_@@_name_str \l_@@_ext_str \str_if_empty:NT \l_@@_ext_str { \__kernel_ior_open:No \g_@@_internal_ior - { \l_@@_full_name_str .tex } + { \l_@@_full_name_tl .tex } \ior_if_eof:NF \g_@@_internal_ior - { \str_put_right:Nn \l_@@_full_name_str { .tex } } + { \tl_put_right:Nn \l_@@_full_name_tl { .tex } } } + \ior_close:N \g_@@_internal_ior + \tl_set_eq:NN #2 \l_@@_full_name_tl + \prg_return_true: } - \str_set_eq:NN #2 \l_@@_full_name_str - \ior_close:N \g_@@_internal_ior } -\cs_generate_variant:Nn \file_get_full_name:nN { V } +\cs_generate_variant:Nn \file_get_full_name:nNT { V } +\cs_generate_variant:Nn \file_get_full_name:nNF { V } +\cs_generate_variant:Nn \file_get_full_name:nNTF { V } \cs_new_protected:Npn \@@_get_full_name_search:nN #1#2 { \@@_name_quote:nN - { \tl_to_str:n {#1} \l_@@_base_name_str } - \l_@@_full_name_str - \__kernel_ior_open:No \g_@@_internal_ior \l_@@_full_name_str + { \tl_to_str:n {#1} \l_@@_base_name_tl } + \l_@@_full_name_tl + \__kernel_ior_open:No \g_@@_internal_ior \l_@@_full_name_tl \ior_if_eof:NF \g_@@_internal_ior { #2 { \prg_break: } } } % \end{macrocode} % \end{macro} % \end{macro} +% \end{macro} % % \begin{macro}[TF]{\file_if_exist:n} % The test for the existence of a file is a wrapper around the function to @@ -2291,10 +2336,9 @@ % \begin{macrocode} \prg_new_protected_conditional:Npnn \file_if_exist:n #1 { T , F , TF } { - \file_get_full_name:nN {#1} \l_@@_full_name_str - \str_if_empty:NTF \l_@@_full_name_str - { \prg_return_false: } + \file_get_full_name:nNTF {#1} \l_@@_full_name_tl { \prg_return_true: } + { \prg_return_false: } } % \end{macrocode} % \end{macro} @@ -2304,9 +2348,9 @@ % \begin{macrocode} \cs_new_protected:Npn \__kernel_file_missing:n #1 { - \__kernel_file_name_sanitize:nN {#1} \l_@@_base_name_str + \__kernel_file_name_sanitize:nN {#1} \l_@@_base_name_tl \__kernel_msg_error:nnx { kernel } { file-not-found } - { \l_@@_base_name_str } + { \l_@@_base_name_tl } } % \end{macrocode} % \end{macro} @@ -2323,10 +2367,9 @@ % \begin{macrocode} \cs_new_protected:Npn \file_input:n #1 { - \file_get_full_name:nN {#1} \l_@@_full_name_str - \str_if_empty:NTF \l_@@_full_name_str + \file_get_full_name:nNTF {#1} \l_@@_full_name_tl + { \@@_input:V \l_@@_full_name_tl } { \__kernel_file_missing:n {#1} } - { \@@_input:V \l_@@_full_name_str } } \cs_new_protected:Npn \@@_input:n #1 { @@ -2491,6 +2534,75 @@ %</package> % \end{macrocode} % +% \subsection{GetIfInfo} +% +% \begin{macro}{\GetIdInfo} +% \begin{macro}{\@@_id_info_auxi:w, \@@_id_info_auxii:w, \@@_id_info_auxiii:w} +% As documented in \pkg{expl3.dtx} this function extracts file name +% etc from an \textsc{svn} \texttt{Id} line. This used to be how we +% got version number and so on in all modules, so it had to be defined +% in \pkg{l3bootstrap}. Now it's more convenient to define it after +% we have set up quite a lot of tools, and \pkg{l3file} seems the +% least unreasonable place for it. +% +% The idea here is to extract out the information needed from a standard +% \textsc{svn} \texttt{Id} line, but to avoid a line that would get +% changed when the file is checked in. Hence the fact that none of the +% lines here include both a dollar sign and the \texttt{Id} keyword! +% \begin{macrocode} +\cs_new_protected:Npn \GetIdInfo + { + \group_begin: + \char_set_catcode_space:n { 32 } + \exp_after:wN + \group_end: + \@@_id_info_auxi:w + } +% \end{macrocode} +% A first check for a completely empty \textsc{svn} field. If that is +% not the case, there is a second case when a file created using +% \texttt{svn cp} but has not been checked in. That leaves a special +% marker \texttt{-1} version, which has no further data. Dealing +% correctly with that is the reason for the space in the line to use +% \cs{@@_id_info_auxii:w}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_id_info_auxi:w $ #1 $ #2 + { + \tl_set:Nn \ExplFileDescription {#2} + \str_if_eq:nnTF {#1} { Id } + { + \tl_set:Nn \ExplFileDate { 0000/00/00 } + \tl_set:Nn \ExplFileName { [unknown] } + \tl_set:Nn \ExplFileExtension { [unknown~extension] } + \tl_set:Nn \ExplFileVersion {-1} + } + { \@@_id_info_auxii:w #1 ~ \q_stop } + } +% \end{macrocode} +% Here, |#1| is |Id|, |#2| is the file name, |#3| is the extension, +% |#4| is the version, |#5| is the check in date and |#6| is the check +% in time and user, plus some trailing spaces. If |#4| is the marker +% |-1| value then |#5| and |#6| are empty. +% \begin{macrocode} +\cs_new_protected:Npn \@@_id_info_auxii:w + #1 ~ #2.#3 ~ #4 ~ #5 ~ #6 \q_stop + { + \tl_set:Nn \ExplFileName {#2} + \tl_set:Nn \ExplFileExtension {#3} + \tl_set:Nn \ExplFileVersion {#4} + \str_if_eq:nnTF {#4} {-1} + { \tl_set:Nn \ExplFileDate { 0000/00/00 } } + { \@@_id_info_auxiii:w #5 - 0 - 0 - \q_stop } + } +% \end{macrocode} +% Convert an \textsc{svn}-style date into a \LaTeX{}-style one. +% \begin{macrocode} +\cs_new_protected:Npn \@@_id_info_auxiii:w #1 - #2 - #3 - #4 \q_stop + { \tl_set:Nn \ExplFileDate { #1/#2/#3 } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \subsection{Messages} % % \begin{macrocode} |