summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3file.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2019-03-05 22:35:14 +0000
committerKarl Berry <karl@freefriends.org>2019-03-05 22:35:14 +0000
commit68872ff6a2a91fa0e84763fc9316493d82075c95 (patch)
tree0546ec4c414553802e31a423aec44f74d252f645 /Master/texmf-dist/source/latex/l3kernel/l3file.dtx
parent541c4ddf7c5b402b9cfe8af5ef4e49ffa15d3e83 (diff)
l3 (5mar19)
git-svn-id: svn://tug.org/texlive/trunk@50246 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3file.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3file.dtx252
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}