summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3file.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2017-07-15 21:27:01 +0000
committerKarl Berry <karl@freefriends.org>2017-07-15 21:27:01 +0000
commitb1ce47fe4d0e1f06d1b019c3c6eb5f1b0ecd5e14 (patch)
tree58362abe4b603bb5f6db898b9b835bc8af730b3e /Master/texmf-dist/source/latex/l3kernel/l3file.dtx
parent03b8dcfa3435f0265dfad4fd09aaab8f4ff9c617 (diff)
l3 (15jul17)
git-svn-id: svn://tug.org/texlive/trunk@44813 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.dtx891
1 files changed, 577 insertions, 314 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx
index a3ceb04d1cf..8f6235bca9c 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx
@@ -23,7 +23,8 @@
%<*driver>
\documentclass[full]{l3doc}
\begin{document}
- \DocInput{\jobname.dtx}
+\DocInput{\jobname.dtx}
+\PrintIndex
\end{document}
%</driver>
% \fi
@@ -41,7 +42,7 @@
% }^^A
% }
%
-% \date{Released 2017/05/29}
+% \date{Released 2017/07/15}
%
% \maketitle
%
@@ -52,28 +53,54 @@
% others are used to work with files on a line by line basis and have prefix
% \cs[no-index]{ior_\ldots} (reading) or \cs[no-index]{iow_\ldots} (writing).
%
-% It is important to remember that when reading external files \TeX{} will
-% attempt to locate them both the operating system path and entries in the
+% It is important to remember that when reading external files \TeX{}
+% attempts to locate them both the operating system path and entries in the
% \TeX{} file database (most \TeX{} systems use such a database). Thus the
% \enquote{current path} for \TeX{} is somewhat broader than that for other
% programs.
%
% For functions which expect a \meta{file name} argument, this argument
% may contain both literal items and expandable content, which should on
-% full expansion be the desired file name. Any active characters (as
-% declared in \cs{l_char_active_seq}) will \emph{not} be expanded,
-% allowing the direct use of these in file names. File names will be quoted
+% full expansion be the desired file name. Active characters (as
+% declared in \cs{l_char_active_seq}) are \emph{not} be expanded,
+% allowing the direct use of these in file names. File names are quoted
% using |"| tokens if they contain spaces: as a result, |"| tokens are
% \emph{not} permitted in file names.
%
% \section{File operation functions}
%
-% \begin{variable}{\g_file_current_name_tl}
-% Contains the name of the current \LaTeX{} file. This variable
-% should not be modified: it is intended for information only. It
-% will be equal to \cs{c_sys_jobname_str} at the start of a \LaTeX{}
-% run and will be modified each time a file is read using
-% \cs{file_input:n}.
+% \begin{variable}[added = 2017-06-21]
+% {
+% \g_file_curr_dir_str,
+% \g_file_curr_name_str,
+% \g_file_curr_ext_str
+% }
+% Contain the directory, name and extension of the current file. The
+% directory is empty if the file was loaded without an explicit
+% path (\emph{i.e.}~if it is in the \TeX{} search path), and does
+% \emph{not} end in |/| other than the case that it is exactly equal
+% to the root directory. The \meta{name} and \meta{ext} parts together
+% make up the file name, thus the \meta{name} part may be thought of
+% as the \enquote{job name} for the current file. Note that \TeX{} does
+% not provide information on the \meta{ext} part for the main (top
+% level) file and that this file always has an empty \meta{dir} component.
+% Also, the \meta{name} here will be equal to \cs{c_sys_jobname_str},
+% which may be different from the real file name (if set using
+% |--jobname|, for example).
+% \end{variable}
+%
+% \begin{variable}[added = 2017-06-18]{\l_file_search_path_seq}
+% Each entry is the path to a directory which should be searched when
+% seeking a file. Each path can be relative or absolute, and should
+% not include the trailing slash. The entries are not expanded when
+% used so may contain active characters but should not feature any
+% variable content. Spaces need not be quoted.
+%
+% \begin{texnote}
+% When working as a package in \LaTeXe{}, \pkg{expl3} will
+% automatically append the current \tn{input@path} to the
+% set of values from \cs{l_file_search_path_seq}.
+% \end{texnote}
% \end{variable}
%
% \begin{function}[TF, updated = 2012-02-10]{\file_if_exist:n}
@@ -82,21 +109,48 @@
% \end{syntax}
% Searches for \meta{file name} using the current \TeX{} search
% path and the additional paths controlled by
-% \cs{file_path_include:n}).
+% \cs{l_file_search_path_seq}.
% \end{function}
%
-% \begin{function}[updated = 2012-02-10]{\file_add_path:nN}
+% \begin{function}[updated = 2017-06-26]
+% {\file_get_full_name:nN, \file_get_full_name:VN}
% \begin{syntax}
-% \cs{file_add_path:nN} \Arg{file name} \meta{tl var}
+% \cs{file_get_full_name:nN} \Arg{file name} \meta{str var}
% \end{syntax}
% Searches for \meta{file name} in the path as detailed for
-% \cs{file_if_exist:nTF}, and if found sets the \meta{tl var} the
+% \cs{file_if_exist:nTF}, and if found sets the \meta{str var} the
% fully-qualified name of the file, \emph{i.e.}~the path and file name.
-% If the file is not found then the \meta{tl var} will contain the
-% marker \cs{q_no_value}.
+% 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.
% \end{function}
%
-% \begin{function}[updated = 2012-02-17]{\file_input:n}
+% \begin{function}[added = 2017-06-23, updated = 2017-06-26]
+% {\file_parse_full_name:nNNN}
+% \begin{syntax}
+% \cs{file_parse_full_name:nNNN} \Arg{full name} \meta{dir} \meta{name} \meta{ext}
+% \end{syntax}
+% Parses the \meta{full name} and splits it into three parts, each of
+% which is returned by setting the appropriate local string variable:
+% \begin{itemize}
+% \item The \meta{dir}: everything up to the last |/| (path separator)
+% in the \meta{file path}. As with system \texttt{PATH} variables
+% and related functions, the \meta{dir} does \emph{not} include the
+% trailing |/| unless it points to the root directory. If there is no path (only
+% a file name), \meta{dir} is empty.
+% \item The \meta{name}: everything after the last |/| up to the last |.|,
+% where both of those characters are optional. The \meta{name} may
+% contain multiple |.| characters. It is empty if \meta{full name}
+% consists only of a directory name.
+% \item The \meta{ext}: everything after the last |.| (including the dot).
+% The \meta{ext} is empty if there is no |.| after the last |/|.
+% \end{itemize}
+% This function does not expand the \meta{full name} before turning it
+% to a string. It assume that the \meta{full name} either contains no
+% quote (|"|) characters or is surrounded by a pair of quotes.
+% \end{function}
+%
+% \begin{function}[updated = 2017-06-26]{\file_input:n}
% \begin{syntax}
% \cs{file_input:n} \Arg{file name}
% \end{syntax}
@@ -104,42 +158,23 @@
% \cs{file_if_exist:nTF}, and if found reads in the file as
% additional \LaTeX{} source. All files read are recorded
% for information and the file name stack is updated by this
-% function. An error will be raised if the file is not found.
+% function. An error is raised if the file is not found.
% \end{function}
%
-% \begin{function}[updated = 2012-07-04]{\file_path_include:n}
+% \begin{function}{\file_show_list:, \file_log_list:}
% \begin{syntax}
-% \cs{file_path_include:n} \Arg{path}
+% \cs{file_show_list:}
+% \cs{file_log_list:}
% \end{syntax}
-% Adds \meta{path} to the list of those used to search when reading
-% files. The assignment is local.
-% The \meta{path} is processed in the same way as a \meta{file name},
-% \emph{i.e.}, with \texttt{x}-type expansion except active
-% characters.
-% \end{function}
-%
-% \begin{function}[updated = 2012-07-04]{\file_path_remove:n}
-% \begin{syntax}
-% \cs{file_path_remove:n} \Arg{path}
-% \end{syntax}
-% Removes \meta{path} from the list of those used to search when reading
-% files. The assignment is local.
-% The \meta{path} is processed in the same way as a \meta{file name},
-% \emph{i.e.}, with \texttt{x}-type expansion except active
-% characters.
-% \end{function}
-%
-% \begin{function}{\file_list:}
-% \begin{syntax}
-% \cs{file_list:}
-% \end{syntax}
-% This function will list all files loaded using \cs{file_input:n}
-% in the log file.
+% These functions list all files loaded by \LaTeXe{} commands that
+% populate \tn{@filelist} or by \cs{file_input:n}. While
+% \cs{file_show_list:} displays the list in the terminal,
+% \cs{file_log_list:} outputs it to the log file only.
% \end{function}
%
% \subsection{Input--output stream management}
%
-% As \TeX{} is limited to $16$ input streams and $16$ output streams, direct
+% As \TeX{} engines have a limited number of input and output streams, direct
% use of the streams by the programmer is not supported in \LaTeX3. Instead, an
% internal pool of streams is maintained, and these are allocated and
% deallocated as needed by other modules. As a result, the programmer should
@@ -172,6 +207,7 @@
% \meta{stream} is available for access immediately and will remain
% allocated to \meta{file name} until a \cs{ior_close:N} instruction
% is given or the \TeX{} run ends.
+% If the file is not found, an error is raised.
% \end{function}
%
% \begin{function}[added = 2013-01-12, TF]{\ior_open:Nn, \ior_open:cn}
@@ -197,7 +233,7 @@
% open it is closed before the new operation begins. The
% \meta{stream} is available for access immediately and will remain
% allocated to \meta{file name} until a \cs{iow_close:N} instruction
-% is given or the \TeX{} run ends. Opening a file for writing will clear
+% is given or the \TeX{} run ends. Opening a file for writing clears
% any existing content in the file (\emph{i.e.}~writing is \emph{not}
% additive).
% \end{function}
@@ -213,13 +249,20 @@
% to other programmers.
% \end{function}
%
-% \begin{function}[updated = 2015-08-01]{\ior_list_streams:, \iow_list_streams:}
+% \begin{function}[added = 2017-06-27]
+% {
+% \ior_show_list:, \ior_log_list:,
+% \iow_show_list:, \iow_log_list:
+% }
% \begin{syntax}
-% \cs{ior_list_streams:}
-% \cs{iow_list_streams:}
+% \cs{ior_show_list:}
+% \cs{ior_log_list:}
+% \cs{iow_show_list:}
+% \cs{iow_log_list:}
% \end{syntax}
-% Displays a list of the file names associated with each open
-% stream: intended for tracking down problems.
+% Display (to the terminal or log file) a list of the file names
+% associated with each open (read or write) stream. This is intended
+% for tracking down problems.
% \end{function}
%
% \subsection{Reading from files}
@@ -232,15 +275,15 @@
% and right braces are found) from the input \meta{stream} and stores
% the result locally in the \meta{token list} variable. If the
% \meta{stream} is not open, input is requested from the terminal.
-% The material read from the \meta{stream} will be tokenized by \TeX{}
+% The material read from the \meta{stream} is tokenized by \TeX{}
% according to the category codes and \tn{endlinechar} in force when
% the function is used. Assuming normal settings, any lines which do
-% not end in a comment character~|%| will have the line ending
+% not end in a comment character~|%| have the line ending
% converted to a space, so for example input
% \begin{verbatim}
% a b c
% \end{verbatim}
-% will result in a token list \verb*|a b c |. Any blank line is
+% results in a token list \verb*|a b c |. Any blank line is
% converted to the token \cs{par}. Therefore, blank lines can be
% skipped by using a test such as
% \begin{verbatim}
@@ -273,15 +316,15 @@
% The material is read from the \meta{stream} as a series of tokens with
% category code $12$ (other), with the exception of space
% characters which are given category code $10$ (space).
-% Multiple whitespace characters are retained by this process. It will
-% always only read one line and any blank lines in the input
-% will result in the \meta{token list variable} being empty. Unlike
+% Multiple whitespace characters are retained by this process. It
+% always only reads one line and any blank lines in the input
+% result in the \meta{token list variable} being empty. Unlike
% \cs{ior_get:NN}, line ends do not receive any special treatment. Thus
% input
% \begin{verbatim}
% a b c
% \end{verbatim}
-% will result in a token list |a b c| with the letters |a|, |b|, and |c|
+% results in a token list |a b c| with the letters |a|, |b|, and |c|
% having category code~12.
% \begin{texnote}
% This protected macro is a wrapper around the \eTeX{} primitive
@@ -299,8 +342,8 @@
% Applies the \meta{inline function} to each set of \meta{lines}
% obtained by calling \cs{ior_get:NN} until reaching the end of the
% file. \TeX{} ignores any trailing new-line marker from the file it
-% reads. The \meta{inline function} should consist of code which will
-% receive the \meta{line} as |#1|.
+% reads. The \meta{inline function} should consist of code which
+% receives the \meta{line} as |#1|.
% \end{function}
%
% \begin{function}[added = 2012-02-11]{\ior_str_map_inline:Nn}
@@ -312,7 +355,7 @@
% as a series of tokens with category code $12$ (other), with the
% exception of space characters which are given category code $10$
% (space). The \meta{inline function} should consist of code which
-% will receive the \meta{line} as |#1|.
+% receives the \meta{line} as |#1|.
% Note that \TeX{} removes trailing space and tab characters
% (character codes 32 and 9) from every line upon input. \TeX{} also
% ignores any trailing new-line marker from the file it reads.
@@ -323,8 +366,8 @@
% \cs{ior_map_break:}
% \end{syntax}
% Used to terminate a \cs[no-index]{ior_map_\ldots} function before all
-% lines from the \meta{stream} have been processed. This will
-% normally take place within a conditional statement, for example
+% lines from the \meta{stream} have been processed. This
+% normally takes place within a conditional statement, for example
% \begin{verbatim}
% \ior_map_inline:Nn \l_my_ior
% {
@@ -335,12 +378,12 @@
% }
% }
% \end{verbatim}
-% Use outside of a \cs[no-index]{ior_map_\ldots} scenario will lead to low
+% Use outside of a \cs[no-index]{ior_map_\ldots} scenario leads to low
% level \TeX{} errors.
% \begin{texnote}
% When the mapping is broken, additional tokens may be inserted by the
% internal macro \cs{__prg_break_point:Nn} before further items are taken
-% from the input stream. This will depend on the design of the mapping
+% from the input stream. This depends on the design of the mapping
% function.
% \end{texnote}
% \end{function}
@@ -351,8 +394,8 @@
% \end{syntax}
% Used to terminate a \cs[no-index]{ior_map_\ldots} function before all
% lines in the \meta{stream} have been processed, inserting
-% the \meta{tokens} after the mapping has ended. This will
-% normally take place within a conditional statement, for example
+% the \meta{tokens} after the mapping has ended. This
+% normally takes place within a conditional statement, for example
% \begin{verbatim}
% \ior_map_inline:Nn \l_my_ior
% {
@@ -363,13 +406,13 @@
% }
% }
% \end{verbatim}
-% Use outside of a \cs[no-index]{ior_map_\ldots} scenario will lead to low
+% Use outside of a \cs[no-index]{ior_map_\ldots} scenario leads to low
% level \TeX{} errors.
% \begin{texnote}
% When the mapping is broken, additional tokens may be inserted by the
% internal macro \cs{__prg_break_point:Nn} before the \meta{tokens} are
% inserted into the input stream.
-% This will depend on the design of the mapping function.
+% This depends on the design of the mapping function.
% \end{texnote}
% \end{function}
%
@@ -379,7 +422,7 @@
% \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 will also return a \texttt{true} value if
+% operation. The test also returns a \texttt{true} value if
% the \meta{stream} is not open.
%\end{function}
%
@@ -410,7 +453,11 @@
% file immediately: it is a dedicated version of \cs{iow_now:Nn}.
% \end{function}
%
-% \begin{function}{\iow_shipout:Nn, \iow_shipout:Nx, \iow_shipout:cn, \iow_shipout:cx}
+% \begin{function}
+% {
+% \iow_shipout:Nn, \iow_shipout:Nx,
+% \iow_shipout:cn, \iow_shipout:cx
+% }
% \begin{syntax}
% \cs{iow_shipout:Nn} \meta{stream} \Arg{tokens}
% \end{syntax}
@@ -423,13 +470,17 @@
% \begin{texnote}
% When using \pkg{expl3} with a format other than \LaTeX{}, new line
% characters inserted using \cs{iow_newline:} or using the
-% line-wrapping code \cs{iow_wrap:nnnN} will not be recognized in
+% line-wrapping code \cs{iow_wrap:nnnN} are not recognized in
% the argument of \cs{iow_shipout:Nn}. This may lead to the
-% insertion of additionnal unwanted line-breaks.
+% insertion of additional unwanted line-breaks.
% \end{texnote}
% \end{function}
%
-% \begin{function}[updated = 2012-09-08]{\iow_shipout_x:Nn, \iow_shipout_x:Nx, \iow_shipout_x:cn, \iow_shipout_x:cx}
+% \begin{function}[updated = 2012-09-08]
+% {
+% \iow_shipout_x:Nn, \iow_shipout_x:Nx,
+% \iow_shipout_x:cn, \iow_shipout_x:cx
+% }
% \begin{syntax}
% \cs{iow_shipout_x:Nn} \meta{stream} \Arg{tokens}
% \end{syntax}
@@ -443,9 +494,9 @@
% This is a wrapper around the \TeX{} primitive \tn{write}.
% When using \pkg{expl3} with a format other than \LaTeX{}, new line
% characters inserted using \cs{iow_newline:} or using the
-% line-wrapping code \cs{iow_wrap:nnnN} will not be recognized in
+% line-wrapping code \cs{iow_wrap:nnnN} are not recognized in
% the argument of \cs{iow_shipout:Nn}. This may lead to the
-% insertion of additionnal unwanted line-breaks.
+% insertion of additional unwanted line-breaks.
% \end{texnote}
% \end{function}
%
@@ -472,8 +523,8 @@
% expansion (\emph{e.g.}~in the second argument of \cs{iow_now:Nn}).
% \begin{texnote}
% When using \pkg{expl3} with a format other than \LaTeX{}, the
-% character inserted by \cs{iow_newline:} will not be recognized by
-% \TeX{}, which may lead to the insertion of additionnal unwanted
+% character inserted by \cs{iow_newline:} is not recognized by
+% \TeX{}, which may lead to the insertion of additional unwanted
% line-breaks. This issue only affects \cs{iow_shipout:Nn},
% \cs{iow_shipout_x:Nn} and direct uses of primitive operations.
% \end{texnote}
@@ -485,10 +536,10 @@
% \begin{syntax}
% \cs{iow_wrap:nnnN} \Arg{text} \Arg{run-on text} \Arg{set up} \meta{function}
% \end{syntax}
-% This function will wrap the \meta{text} to a fixed number of
+% This function wraps the \meta{text} to a fixed number of
% characters per line. At the start of each line which is wrapped,
-% the \meta{run-on text} will be inserted. The line character count
-% targeted will be the value of \cs{l_iow_line_count_int} minus the
+% the \meta{run-on text} is inserted. The line character count
+% targeted is the value of \cs{l_iow_line_count_int} minus the
% number of characters in the \meta{run-on text} for all lines except
% the first, for which the target number of characters is simply
% \cs{l_iow_line_count_int} since there is no run-on text. The
@@ -512,12 +563,12 @@
% \cs{tl_to_str:n}, \cs{tl_to_str:N}, \emph{etc.}
%
% The result of the wrapping operation is passed as a braced argument to the
-% \meta{function}, which will typically be a wrapper around a write
+% \meta{function}, which is typically a wrapper around a write
% operation. The output of \cs{iow_wrap:nnnN} (\emph{i.e.}~the argument
-% passed to the \meta{function}) will consist of characters of category
+% passed to the \meta{function}) consists of characters of category
% \enquote{other} (category code~12), with the exception of spaces which
-% will have category \enquote{space} (category code~10). This means that the
-% output will \emph{not} expand further when written to a file.
+% have category \enquote{space} (category code~10). This means that the
+% output does \emph{not} expand further when written to a file.
%
% \begin{texnote}
% Internally, \cs{iow_wrap:nnnN} carries out an \texttt{x}-type expansion
@@ -534,7 +585,7 @@
% \cs{iow_indent:n} \Arg{text}
% \end{syntax}
% In the first argument of \cs{iow_wrap:nnnN} (for instance in messages),
-% indents \meta{text} by four spaces. This function will not cause
+% indents \meta{text} by four spaces. This function does not cause
% a line break, and only affects lines which start within the scope
% of the \meta{text}. In case the indented \meta{text} should appear
% on separate lines from the surrounding text, use |\\| to force
@@ -558,7 +609,7 @@
%
% \begin{variable}{\c_term_ior}
% Constant input stream for reading from the terminal. Reading from this
-% stream using \cs{ior_get:NN} or similar will result in a prompt from
+% stream using \cs{ior_get:NN} or similar results in a prompt from
% \TeX{} of the form
% \begin{verbatim}
% <tl>=
@@ -593,23 +644,39 @@
% Used to test for the existence of files when opening.
% \end{variable}
%
-% \begin{variable}{\l__file_internal_name_tl}
-% Used to return the full name of a file for internal use. This is
-% set by \cs{file_if_exist:nTF} and \cs{__file_if_exist:nT}, and
-% the value may then be used to load a file directly provided no
-% further operations intervene.
+% \begin{variable}{\l__file_base_name_str, \l__file_full_name_str}
+% Used to store and transfer the file name (including extension)
+% and (partial) file path whilst reading files. (The file base is the
+% base name plus any preceding directory name.)
% \end{variable}
%
-% \begin{function}[added = 2012-02-09]{\__file_name_sanitize:nn}
+% \begin{function}[added = 2017-06-25]{\__file_missing:n}
% \begin{syntax}
-% \cs{__file_name_sanitize:nn} \Arg{name} \Arg{tokens}
+% \cs{__file_missing:n} \Arg{name}
+% \end{syntax}
+% Expands the \meta{name} as per \cs{__file_name_sanitize:nN} then
+% produces an error message indicating that that file was not found.
+% \end{function}
+%
+% \begin{function}[added = 2017-06-19]{\__file_name_sanitize:nN}
+% \begin{syntax}
+% \cs{__file_name_sanitize:nN} \Arg{name} \meta{str var}
% \end{syntax}
% Exhaustively-expands the \meta{name} with the exception of any
% category \meta{active} (catcode~$13$) tokens, which are not expanded.
% The list of \meta{active} tokens is taken from \cs{l_char_active_seq}.
-% The \meta{sanitized name} is then inserted (in braces) after the
-% \meta{tokens}, which should further process the file name. If any
-% spaces are found in the name after expansion, an error is raised.
+% The \meta{str var} is then set to the \meta{sanitized name}.
+% \end{function}
+%
+% \begin{function}[added = 2017-06-19, updated = 2017-06-25]
+% {\__file_name_quote:nN}
+% \begin{syntax}
+% \cs{__file_name_quote:nN} \Arg{name} \meta{str var}
+% \end{syntax}
+% Expands the \meta{name} (without special-casing active tokens), then
+% sets the \meta{str var} to the \meta{name} quoted using |"| at each
+% end if required by the presence of spaces in the \meta{name}. Any existing
+% |"| tokens is removed and if their number is odd an error is raised.
% \end{function}
%
% \subsection{Internal input--output functions}
@@ -625,7 +692,7 @@
% higher-level
% functions which have already fully expanded the \meta{file name} and which
% need to perform multiple open or close operations. See for example the
-% implementation of \cs{file_add_path:nN},
+% implementation of \cs{file_get_full_name:nN},
% \end{function}
%
% \begin{function}[added = 2014-08-23]{\__iow_with:Nnn}
@@ -659,31 +726,64 @@
%
% \subsection{File operations}
%
-% \begin{variable}{\g_file_current_name_tl}
+% \begin{variable}
+% {
+% \g_file_curr_dir_str ,
+% \g_file_curr_ext_str ,
+% \g_file_curr_name_str
+% }
% The name of the current file should be available at all times.
% For the format the file name needs to be picked up at the start of the
-% file. In \LaTeXe{} package mode the current file name is collected from
+% run. In \LaTeXe{} package mode the current file name is collected from
% \tn{@currname}.
% \begin{macrocode}
-\tl_new:N \g_file_current_name_tl
+\str_new:N \g_file_curr_dir_str
+\str_new:N \g_file_curr_ext_str
+\str_new:N \g_file_curr_name_str
%<*initex>
\tex_everyjob:D \exp_after:wN
{
\tex_the:D \tex_everyjob:D
- \tl_gset:Nx \g_file_current_name_tl { \tex_jobname:D }
+ \str_gset:Nx \g_file_curr_name_str { \tex_jobname:D }
}
%</initex>
%<*package>
\cs_if_exist:NT \@currname
- { \tl_gset_eq:NN \g_file_current_name_tl \@currname }
+ { \str_gset_eq:NN \g_file_curr_name_str \@currname }
%</package>
% \end{macrocode}
% \end{variable}
%
% \begin{variable}{\g_@@_stack_seq}
-% The input list of files is stored as a sequence stack.
+% The input list of files is stored as a sequence stack. In package
+% mode we can recover the information from the details held by
+% \LaTeXe{} (we must be in the preamble and loaded using \tn{usepackage}
+% or \tn{RequirePackage}). As \LaTeXe{} doesn't store directory and
+% name separately, we stick to the same convention here.
% \begin{macrocode}
\seq_new:N \g_@@_stack_seq
+%<*package>
+\group_begin:
+ \cs_set_protected:Npn \@@_tmp:w #1#2#3
+ {
+ \tl_if_blank:nTF {#1}
+ {
+ \cs_set:Npn \@@_tmp:w ##1 " ##2 " ##3 \q_stop { { } {##2} { } }
+ \seq_gput_right:Nx \g_@@_stack_seq
+ {
+ \exp_after:wN \@@_tmp:w \tex_jobname:D
+ " \tex_jobname:D " \q_stop
+ }
+ }
+ {
+ \seq_gput_right:Nn \g_@@_stack_seq { { } {#1} {#2} }
+ \@@_tmp:w
+ }
+ }
+ \cs_if_exist:NT \@currnamestack
+ { \exp_after:wN \@@_tmp:w \@currnamestack }
+\group_end:
+%</package>
% \end{macrocode}
% \end{variable}
%
@@ -699,53 +799,55 @@
\tex_everyjob:D \exp_after:wN
{
\tex_the:D \tex_everyjob:D
- \seq_gput_right:NV \g_@@_record_seq \g_file_current_name_tl
+ \seq_gput_right:NV \g_@@_record_seq \g_file_curr_name_str
}
%</initex>
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_@@_internal_tl}
-% Used as a short-term scratch variable. It may be possible to reuse
-% \cs{l_@@_internal_name_tl} there.
+% \begin{variable}{\l_@@_tmp_tl}
+% Used as a short-term scratch variable.
% \begin{macrocode}
-\tl_new:N \l_@@_internal_tl
+\tl_new:N \l_@@_tmp_tl
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_@@_internal_name_tl}
-% Used to return the fully-qualified name of a file.
+% \begin{variable}{\l__file_base_name_str, \l__file_full_name_str}
+% For storing the basename and full path whilst passing data internally.
% \begin{macrocode}
-\tl_new:N \l_@@_internal_name_tl
+\str_new:N \l__file_base_name_str
+\str_new:N \l__file_full_name_str
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_@@_search_path_seq}
-% The current search path.
+% \begin{variable}{\l_@@_dir_str, \l_@@_ext_str, \l_@@_name_str}
+% Used in parsing a path into parts: in contrast to the above, these are
+% never used outside of the current module.
% \begin{macrocode}
-\seq_new:N \l_@@_search_path_seq
+\str_new:N \l_@@_dir_str
+\str_new:N \l_@@_ext_str
+\str_new:N \l_@@_name_str
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_@@_saved_search_path_seq}
-% The current search path has to be saved for package use.
+% \begin{variable}{\l_file_search_path_seq}
+% The current search path.
% \begin{macrocode}
-%<*package>
-\seq_new:N \l_@@_saved_search_path_seq
-%</package>
+\seq_new:N \l_file_search_path_seq
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_@@_internal_seq}
+% \begin{variable}{\l_@@_tmp_seq}
% Scratch space for comma list conversion in package mode.
% \begin{macrocode}
%<*package>
-\seq_new:N \l_@@_internal_seq
+\seq_new:N \l_@@_tmp_seq
%</package>
% \end{macrocode}
% \end{variable}
%
-% \begin{macro}[int]{\@@_name_sanitize:nn}
+% \begin{macro}[int]{\__file_name_sanitize:nN}
+% \begin{macro}[int]{\__file_name_quote:nN}
% \begin{macro}[int, aux]{\@@_name_sanitize_aux:n}
% For converting a token list to a string where active characters are treated
% as strings from the start. The logic to the quoting normalisation is the
@@ -753,100 +855,90 @@
% assuming they balance strip all of them out before quoting the entire name
% if it contains spaces.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_name_sanitize:nn #1#2
+\cs_new_protected:Npn \__file_name_sanitize:nN #1#2
{
\group_begin:
\seq_map_inline:Nn \l_char_active_seq
{
- \tl_set:Nx \l_@@_internal_tl { \iow_char:N ##1 }
- \char_set_active_eq:NN ##1 \l_@@_internal_tl
- }
- \tl_set:Nx \l_@@_internal_name_tl {#1}
- \tl_set:Nx \l_@@_internal_name_tl
- { \tl_to_str:N \l_@@_internal_name_tl }
- \int_compare:nNnTF
- {
- \int_mod:nn
- {
- 0 \tl_map_function:NN \l_@@_internal_name_tl
- \@@_name_sanitize_aux:n
- }
- { 2 }
- }
- = 0
- {
- \tl_remove_all:Nn \l_@@_internal_name_tl { " }
- \tl_if_in:NnT \l_@@_internal_name_tl { ~ }
- {
- \tl_set:Nx \l_@@_internal_name_tl
- { " \exp_not:V \l_@@_internal_name_tl " }
- }
- }
- {
- \__msg_kernel_error:nnx
- { kernel } { unbalanced-quote-in-filename }
- { \l_@@_internal_name_tl }
- }
- \use:x
- {
- \group_end:
- \exp_not:n {#2} { \l_@@_internal_name_tl }
+ \tl_set:Nx \l_@@_tmp_tl { \iow_char:N ##1 }
+ \char_set_active_eq:NN ##1 \l_@@_tmp_tl
}
+ \tl_set:Nx \l_@@_tmp_tl {#1}
+ \tl_set:Nx \l_@@_tmp_tl
+ { \tl_to_str:N \l_@@_tmp_tl }
+ \exp_args:NNNV \group_end:
+ \str_set:Nn #2 \l_@@_tmp_tl
}
-\cs_new:Npn \@@_name_sanitize_aux:n #1
+\cs_new_protected:Npn \__file_name_quote:nN #1#2
+ {
+ \str_set:Nx #2 {#1}
+ \int_if_even:nF
+ { 0 \tl_map_function:NN #2 \@@_name_quote_aux:n }
+ {
+ \__msg_kernel_error:nnx
+ { kernel } { unbalanced-quote-in-filename } {#2}
+ }
+ \tl_remove_all:Nn #2 { " }
+ \tl_if_in:NnT #2 { ~ }
+ { \str_set:Nx #2 { " \exp_not:V #2 " } }
+ }
+\cs_new:Npn \@@_name_quote_aux:n #1
{ \token_if_eq_charcode:NNT #1 " { + 1 } }
% \end{macrocode}
% \end{macro}
% \end{macro}
+% \end{macro}
%
-% \begin{macro}{\file_add_path:nN}
-% \begin{macro}[aux]{\@@_add_path:nN, \@@_add_path_search:nN}
-% The way to test if a file exists is to try to open it: if it does not
-% exist then \TeX{} will report end-of-file. For files which are in the
-% current directory, this is straight-forward. For other locations, a
-% search has to be made looking at each potential path in turn. The first
-% location is of course treated as the correct one. If nothing is found,
-% |#2| is returned empty.
+% \begin{macro}{\file_get_full_name:nN, \file_get_full_name:VN}
+% \begin{macro}[aux]{\@@_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
+% looking at each potential path in turn (starting from the current
+% directory). The first location is of course treated as the correct
+% one: this is done by jumping to \cs{__prg_break_point:}. If nothing
+% is found, |#2| is returned empty. A special case when there is no
+% extension is that once the first location is found we test the
+% existence of the file with |.tex| extension in that directory, and
+% if it exists we include the |.tex| extension in the result.
% \begin{macrocode}
-\cs_new_protected:Npn \file_add_path:nN #1
- { \@@_name_sanitize:nn {#1} { \@@_add_path:nN } }
-\cs_new_protected:Npn \@@_add_path:nN #1#2
+\cs_new_protected:Npn \file_get_full_name:nN #1#2
{
- \__ior_open:Nn \g_@@_internal_ior {#1}
- \ior_if_eof:NTF \g_@@_internal_ior
- { \@@_add_path_search:nN {#1} #2 }
- { \tl_set:Nn #2 {#1} }
- \ior_close:N \g_@@_internal_ior
- }
-\cs_new_protected:Npn \@@_add_path_search:nN #1#2
- {
- \tl_set:Nn #2 { \q_no_value }
+ \__file_name_sanitize:nN {#1} \l__file_base_name_str
+ \@@_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 }
%<*package>
\cs_if_exist:NT \input@path
{
- \seq_set_eq:NN \l_@@_saved_search_path_seq
- \l_@@_search_path_seq
- \seq_set_split:NnV \l_@@_internal_seq { , } \input@path
- \seq_concat:NNN \l_@@_search_path_seq
- \l_@@_search_path_seq \l_@@_internal_seq
+ \tl_map_inline:Nn \input@path
+ { \@@_get_full_name_search:nN { ##1 } \tl_map_break:n }
}
%</package>
- \seq_map_inline:Nn \l_@@_search_path_seq
+ \str_clear:N \l__file_full_name_str
+ \__prg_break_point:
+ \str_if_empty:NF \l__file_full_name_str
{
- \__ior_open:Nn \g_@@_internal_ior { ##1 #1 }
- \ior_if_eof:NF \g_@@_internal_ior
+ \exp_args:NV \file_parse_full_name:nNNN \l__file_full_name_str
+ \l_@@_dir_str \l_@@_name_str \l_@@_ext_str
+ \str_if_empty:NT \l_@@_ext_str
{
- \tl_set:Nx #2 { ##1 #1 }
- \seq_map_break:
+ \__ior_open:No \g_@@_internal_ior
+ { \l__file_full_name_str .tex }
+ \ior_if_eof:NF \g_@@_internal_ior
+ { \str_put_right:Nn \l__file_full_name_str { .tex } }
}
}
-%<*package>
- \cs_if_exist:NT \input@path
- {
- \seq_set_eq:NN \l_@@_search_path_seq
- \l_@@_saved_search_path_seq
- }
-%</package>
+ \str_set_eq:NN #2 \l__file_full_name_str
+ \ior_close:N \g_@@_internal_ior
+ }
+\cs_generate_variant:Nn \file_get_full_name:nN { V }
+\cs_new_protected:Npn \@@_get_full_name_search:nN #1#2
+ {
+ \__file_name_quote:nN
+ { \tl_to_str:n {#1} \l__file_base_name_str }
+ \l__file_full_name_str
+ \__ior_open:No \g_@@_internal_ior \l__file_full_name_str
+ \ior_if_eof:NF \g_@@_internal_ior { #2 { \__prg_break: } }
}
% \end{macrocode}
% \end{macro}
@@ -854,24 +946,37 @@
%
% \begin{macro}[TF]{\file_if_exist:n}
% The test for the existence of a file is a wrapper around the function to
-% add a path to a file. If the file was found, the path will contain
+% add a path to a file. If the file was found, the path contains
% something, whereas if the file was not located then the return value
-% will be \cs{q_no_value}.
+% is empty.
% \begin{macrocode}
\prg_new_protected_conditional:Npnn \file_if_exist:n #1 { T , F , TF }
{
- \file_add_path:nN {#1} \l_@@_internal_name_tl
- \quark_if_no_value:NTF \l_@@_internal_name_tl
+ \file_get_full_name:nN {#1} \l__file_full_name_str
+ \str_if_empty:NTF \l__file_full_name_str
{ \prg_return_false: }
{ \prg_return_true: }
}
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}[int]{\__file_missing:n}
+% An error message for a missing file, also used in \cs{ior_open:Nn}.
+% \begin{macrocode}
+\cs_new_protected:Npn \__file_missing:n #1
+ {
+ \__file_name_sanitize:nN {#1} \l__file_base_name_str
+ \__msg_kernel_error:nnx { kernel } { file-not-found }
+ { \l__file_base_name_str }
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\file_input:n}
-% \begin{macro}[int]{\@@_if_exist:nT}
% \begin{macro}[aux]{\@@_input:n, \@@_input:V}
-% \begin{macro}[aux]{\@@_input_aux:n, \@@_input_aux:o}
+% \begin{macro}[aux]{\@@_input_push:n}
+% \begin{macro}[aux]{\@@_input_pop:}
+% \begin{macro}[aux]{\@@_input_pop:nnn}
% Loading a file is done in a safe way, checking first that the file
% exists and loading only if it does. Push the file name on the
% \cs{g_@@_stack_seq}, and add it to the file list, either
@@ -879,31 +984,13 @@
% \begin{macrocode}
\cs_new_protected:Npn \file_input:n #1
{
- \@@_if_exist:nT {#1}
- { \@@_input:V \l_@@_internal_name_tl }
- }
-% \end{macrocode}
-% This code is spun out as a separate function to encapsulate the
-% error message into a easy-to-reuse form.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_if_exist:nT #1#2
- {
- \file_if_exist:nTF {#1}
- {#2}
- {
- \@@_name_sanitize:nn {#1}
- { \__msg_kernel_error:nnx { kernel } { file-not-found } }
- }
+ \file_get_full_name:nN {#1} \l__file_full_name_str
+ \str_if_empty:NTF \l__file_full_name_str
+ { \__file_missing:n {#1} }
+ { \@@_input:V \l__file_full_name_str }
}
\cs_new_protected:Npn \@@_input:n #1
{
- \tl_if_in:nnTF {#1} { . }
- { \@@_input_aux:n {#1} }
- { \@@_input_aux:o { \tl_to_str:n { #1 . tex } } }
- }
-\cs_generate_variant:Nn \@@_input:n { V }
-\cs_new_protected:Npn \@@_input_aux:n #1
- {
%<*initex>
\seq_gput_right:Nn \g_@@_record_seq {#1}
%</initex>
@@ -912,68 +999,140 @@
{ \@addtofilelist {#1} }
{ \seq_gput_right:Nn \g_@@_record_seq {#1} }
%</package>
- \seq_gpush:No \g_@@_stack_seq \g_file_current_name_tl
- \tl_gset:Nn \g_file_current_name_tl {#1}
+ \@@_input_push:n {#1}
\tex_input:D #1 \c_space_tl
- \seq_gpop:NN \g_@@_stack_seq \l_@@_internal_tl
- \tl_gset_eq:NN \g_file_current_name_tl \l_@@_internal_tl
+ \@@_input_pop:
+ }
+\cs_generate_variant:Nn \@@_input:n { V }
+% \end{macrocode}
+% Keeping a track of the file data is easy enough: we store the separated
+% parts so we do not need to parse them twice.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_input_push:n #1
+ {
+ \seq_gpush:Nx \g_@@_stack_seq
+ {
+ { \g_file_curr_dir_str }
+ { \g_file_curr_name_str }
+ { \g_file_curr_ext_str }
+ }
+ \file_parse_full_name:nNNN {#1}
+ \l_@@_dir_str \l_@@_name_str \l_@@_ext_str
+ \str_gset_eq:NN \g_file_curr_dir_str \l_@@_dir_str
+ \str_gset_eq:NN \g_file_curr_name_str \l_@@_name_str
+ \str_gset_eq:NN \g_file_curr_ext_str \l_@@_ext_str
+ }
+\cs_new_protected:Npn \@@_input_pop:
+ {
+ \seq_gpop:NN \g_@@_stack_seq \l_@@_tmp_tl
+ \exp_after:wN \@@_input_pop:nnn \l_@@_tmp_tl
+ }
+\cs_new_protected:Npn \@@_input_pop:nnn #1#2#3
+ {
+ \str_gset:Nn \g_file_curr_dir_str {#1}
+ \str_gset:Nn \g_file_curr_name_str {#2}
+ \str_gset:Nn \g_file_curr_ext_str {#3}
}
-\cs_generate_variant:Nn \@@_input_aux:n { o }
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
+% \end{macro}
%
-% \begin{macro}{\file_path_include:n}
-% \begin{macro}{\file_path_remove:n}
-% \begin{macro}[aux]{\@@_path_include:n}
-% Wrapper functions to manage the search path.
+% \begin{macro}{\file_parse_full_name:nNNN}
+% \begin{macro}[aux]
+% {\@@_parse_full_name_auxi:w, \@@_parse_full_name_split:nNNNTF}
+% Parsing starts by stripping off any surrounding quotes. Then find
+% the directory |#4| by splitting at the last~|/|. (The auxiliary
+% returns \texttt{true}/\texttt{false} depending on whether it found
+% the delimiter.) We correct for the case of a file in the root |/|,
+% as in that case we wish to keep the trailing (and only) slash. Then
+% split the base name |#5| at the last dot. If there was indeed a
+% dot, |#5| contains the name and |#6| the extension without the dot,
+% which we add back for convenience. In the special case of no
+% extension given, the auxiliary stored the name into |#6|, we just
+% have to move it to |#5|.
% \begin{macrocode}
-\cs_new_protected:Npn \file_path_include:n #1
- { \@@_name_sanitize:nn {#1} { \@@_path_include:n } }
-\cs_new_protected:Npn \@@_path_include:n #1
+\cs_new_protected:Npn \file_parse_full_name:nNNN #1#2#3#4
{
- \seq_if_in:NnF \l_@@_search_path_seq {#1}
- { \seq_put_right:Nn \l_@@_search_path_seq {#1} }
+ \exp_after:wN \@@_parse_full_name_auxi:w
+ \tl_to_str:n { #1 " #1 " } \q_stop #2#3#4
}
-\cs_new_protected:Npn \file_path_remove:n #1
+\cs_new_protected:Npn \@@_parse_full_name_auxi:w #1 " #2 " #3 \q_stop #4#5#6
{
- \@@_name_sanitize:nn {#1}
- { \seq_remove_all:Nn \l_@@_search_path_seq }
+ \@@_parse_full_name_split:nNNNTF {#2} / #4 #5
+ { \str_if_empty:NT #4 { \str_set:Nn #4 { / } } }
+ { }
+ \exp_args:No \@@_parse_full_name_split:nNNNTF {#5} . #5 #6
+ { \str_put_left:Nn #6 { . } }
+ {
+ \str_set_eq:NN #5 #6
+ \str_clear:N #6
+ }
+ }
+\cs_new_protected:Npn \@@_parse_full_name_split:nNNNTF #1#2#3#4
+ {
+ \cs_set_protected:Npn \@@_tmp:w ##1 ##2 #2 ##3 \q_stop
+ {
+ \tl_if_empty:nTF {##3}
+ {
+ \str_set:Nn #4 {##2}
+ \tl_if_empty:nTF {##1}
+ {
+ \str_clear:N #3
+ \use_ii:nn
+ }
+ {
+ \str_set:Nx #3 { \str_tail:n {##1} }
+ \use_i:nn
+ }
+ }
+ { \@@_tmp:w { ##1 #2 ##2 } ##3 \q_stop }
+ }
+ \@@_tmp:w { } #1 #2 \q_stop
}
% \end{macrocode}
% \end{macro}
% \end{macro}
-% \end{macro}
%
-% \begin{macro}{\file_list:}
+% \begin{macro}{\file_show_list:, \file_log_list:}
+% \begin{macro}[aux, EXP]{\@@_list_aux:n}
% A function to list all files used to the log, without duplicates.
% In package mode, if \cs{@filelist} is still defined, we need to take
-% this list of file names into account
-% (we capture it \cs{AtBeginDocument} into
-% \cs{g_@@_record_seq}), turning each file name into a string.
+% this list of file names into account (we capture it
+% \cs{AtBeginDocument} into \cs{g_@@_record_seq}), turning it to a
+% string (this does not affect the commas of this comma list). The
+% message system is a bit finnicky (it can only display results that
+% start with |>~| and end with a dot) so that constrains the possible
+% markup. The advantage is that we get terminal and log outputs for
+% free.
% \begin{macrocode}
-\cs_new_protected:Npn \file_list:
+\cs_new_protected:Npn \file_show_list:
{
- \seq_set_eq:NN \l_@@_internal_seq \g_@@_record_seq
+ \seq_clear:N \l_@@_tmp_seq
%<*package>
\clist_if_exist:NT \@filelist
{
- \clist_map_inline:Nn \@filelist
- {
- \seq_put_right:No \l_@@_internal_seq
- { \tl_to_str:n {##1} }
- }
+ \exp_args:NNx \seq_set_from_clist:Nn \l_@@_tmp_seq
+ { \tl_to_str:N \@filelist }
}
%</package>
- \seq_remove_duplicates:N \l_@@_internal_seq
- \iow_log:n { *~File~List~* }
- \seq_map_inline:Nn \l_@@_internal_seq { \iow_log:n {##1} }
- \iow_log:n { ************* }
+ \seq_concat:NNN \l_@@_tmp_seq \l_@@_tmp_seq \g_@@_record_seq
+ \seq_remove_duplicates:N \l_@@_tmp_seq
+ \__msg_show_wrap:n
+ {
+ >~File~List~< \\
+ \seq_map_function:NN \l_@@_tmp_seq \@@_list_aux:n
+ ............
+ }
}
+\cs_new:Npn \@@_list_aux:n #1 { #1 \\ }
+\cs_new_protected:Npn \file_log_list:
+ { \__msg_log_next: \file_show_list: }
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
% When used as a package, there is a need to hold onto the standard file
% list as well as the new one here. File names recorded in
@@ -983,8 +1142,9 @@
%<*package>
\AtBeginDocument
{
- \clist_map_inline:Nn \@filelist
- { \seq_gput_right:No \g_@@_record_seq { \tl_to_str:n {#1} } }
+ \exp_args:NNx \seq_set_from_clist:Nn \l_@@_tmp_seq
+ { \tl_to_str:N \@filelist }
+ \seq_gconcat:NNN \g_@@_record_seq \g_@@_record_seq \l_@@_tmp_seq
}
%</package>
% \end{macrocode}
@@ -1070,50 +1230,35 @@
% \end{macro}
%
% \begin{macro}{\ior_open:Nn, \ior_open:cn}
-% \begin{macro}[aux]{\@@_open_aux:Nn}
-% Opening an input stream requires a bit of pre-processing. The file name
-% is sanitized to deal with active characters, before an auxiliary adds a
-% path and checks that the file really exists. If those two tests pass, then
-% pass the information on to the lower-level function which deals with
-% streams.
+% Use the conditional version, with an error if the file is not found.
% \begin{macrocode}
\cs_new_protected:Npn \ior_open:Nn #1#2
- { \__file_name_sanitize:nn {#2} { \@@_open_aux:Nn #1 } }
+ { \ior_open:NnF #1 {#2} { \__file_missing:n {#2} } }
\cs_generate_variant:Nn \ior_open:Nn { c }
-\cs_new_protected:Npn \@@_open_aux:Nn #1#2
- {
- \file_add_path:nN {#2} \l__file_internal_name_tl
- \quark_if_no_value:NTF \l__file_internal_name_tl
- { \__msg_kernel_error:nnx { kernel } { file-not-found } {#2} }
- { \@@_open:No #1 \l__file_internal_name_tl }
- }
% \end{macrocode}
% \end{macro}
-% \end{macro}
%
% \begin{macro}[TF]{\ior_open:Nn, \ior_open:cn}
-% \begin{macro}[aux]{\@@_open_aux:NnTF}
-% Much the same idea for opening a read with a conditional, except the
-% auxiliary function does not issue an error if the file is not found.
+% An auxiliary searches for the file in the \TeX{}, \LaTeXe{} and
+% \LaTeX3 paths. Then pass the file found to the lower-level function
+% which deals with streams. The |full_name| is empty when the file is
+% not found.
% \begin{macrocode}
\prg_new_protected_conditional:Npnn \ior_open:Nn #1#2 { T , F , TF }
- { \__file_name_sanitize:nn {#2} { \@@_open_aux:NnTF #1 } }
-\cs_generate_variant:Nn \ior_open:NnT { c }
-\cs_generate_variant:Nn \ior_open:NnF { c }
-\cs_generate_variant:Nn \ior_open:NnTF { c }
-\cs_new_protected:Npn \@@_open_aux:NnTF #1#2
{
- \file_add_path:nN {#2} \l__file_internal_name_tl
- \quark_if_no_value:NTF \l__file_internal_name_tl
+ \file_get_full_name:nN {#2} \l__file_full_name_str
+ \str_if_empty:NTF \l__file_full_name_str
{ \prg_return_false: }
{
- \@@_open:No #1 \l__file_internal_name_tl
+ \@@_open:No #1 \l__file_full_name_str
\prg_return_true:
}
}
+\cs_generate_variant:Nn \ior_open:NnT { c }
+\cs_generate_variant:Nn \ior_open:NnF { c }
+\cs_generate_variant:Nn \ior_open:NnTF { c }
% \end{macrocode}
% \end{macro}
-% \end{macro}
%
% \begin{macro}[int]{\@@_new:N}
% In package mode, streams are reserved using \tn{newread} before they
@@ -1190,8 +1335,8 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\ior_list_streams:}
-% \begin{macro}[aux]{\@@_list_streams:Nn}
+% \begin{macro}{\ior_show_list:, \ior_log_list:}
+% \begin{macro}[aux]{\@@_list:Nn}
% Show the property lists, but with some \enquote{pretty printing}.
% See the \pkg{l3msg} module. The first argument of the message is
% |ior| (as opposed to |iow|) and the second is empty if no read
@@ -1200,9 +1345,11 @@
% translating |ior|/|iow| to English. The list of streams is
% formatted using \cs{__msg_show_item_unbraced:nn}.
% \begin{macrocode}
-\cs_new_protected:Npn \ior_list_streams:
- { \@@_list_streams:Nn \g_@@_streams_prop { ior } }
-\cs_new_protected:Npn \@@_list_streams:Nn #1#2
+\cs_new_protected:Npn \ior_show_list:
+ { \@@_list:Nn \g_@@_streams_prop { ior } }
+\cs_new_protected:Npn \ior_log_list:
+ { \__msg_log_next: \ior_show_list: }
+\cs_new_protected:Npn \@@_list:Nn #1#2
{
\__msg_show_pre:nnxxxx { LaTeX / kernel } { show-streams }
{#2} { \prop_if_empty:NF #1 { ? } } { } { }
@@ -1437,19 +1584,16 @@
% \end{macro}
%
% \begin{macro}{\iow_open:Nn, \iow_open:cn}
-% \begin{macro}[int]{\@@_open:Nn}
-% \begin{macro}[aux]{\@@_open_stream:Nn}
+% \begin{macro}[aux]{\@@_open_stream:Nn, \@@_open_stream:NV}
% The same idea as for reading, but without the path and without the need
% to allow for a conditional version.
% \begin{macrocode}
\cs_new_protected:Npn \iow_open:Nn #1#2
- { \__file_name_sanitize:nn {#2} { \@@_open:Nn #1 } }
-\cs_generate_variant:Nn \iow_open:Nn { c }
-\cs_new_protected:Npn \@@_open:Nn #1#2
{
+ \__file_name_sanitize:nN {#2} \l__file_base_name_str
\iow_close:N #1
\seq_gpop:NNTF \g_@@_streams_seq \l_@@_stream_tl
- { \@@_open_stream:Nn #1 {#2} }
+ { \@@_open_stream:NV #1 \l__file_base_name_str }
%<*initex>
{ \__msg_kernel_fatal:nn { kernel } { output-streams-exhausted } }
%</initex>
@@ -1457,21 +1601,21 @@
{
\@@_new:N #1
\tl_set:Nx \l_@@_stream_tl { \int_eval:n {#1} }
- \@@_open_stream:Nn #1 {#2}
+ \@@_open_stream:NV #1 \l__file_base_name_str
}
%</package>
}
-\cs_generate_variant:Nn \@@_open:Nn { No }
+\cs_generate_variant:Nn \iow_open:Nn { c }
\cs_new_protected:Npn \@@_open_stream:Nn #1#2
{
\tex_global:D \tex_chardef:D #1 = \l_@@_stream_tl \scan_stop:
\prop_gput:NVn \g_@@_streams_prop #1 {#2}
\tex_immediate:D \tex_openout:D #1 #2 \scan_stop:
}
+\cs_generate_variant:Nn \@@_open_stream:Nn { NV }
% \end{macrocode}
% \end{macro}
% \end{macro}
-% \end{macro}
%
% \begin{macro}{\iow_close:N, \iow_close:c}
% Closing a stream is not quite the reverse of opening one. First,
@@ -1494,13 +1638,15 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\iow_list_streams:}
-% \begin{macro}{\@@_list_streams:Nn}
+% \begin{macro}{\iow_show_list:, \iow_log_list:}
+% \begin{macro}{\@@_list:Nn}
% Done as for input, but with a copy of the auxiliary so the name is correct.
% \begin{macrocode}
-\cs_new_protected:Npn \iow_list_streams:
- { \@@_list_streams:Nn \g_@@_streams_prop { iow } }
-\cs_new_eq:NN \@@_list_streams:Nn \__ior_list_streams:Nn
+\cs_new_protected:Npn \iow_show_list:
+ { \@@_list:Nn \g_@@_streams_prop { iow } }
+\cs_new_protected:Npn \iow_log_list:
+ { \__msg_log_next: \iow_show_list: }
+\cs_new_eq:NN \@@_list:Nn \__ior_list:Nn
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1745,7 +1891,7 @@
% valid and otherwise to \cs{@@_indent_error:n}. The first places the
% instruction for increasing the indentation before its argument, and
% the instruction for unindenting afterwards. The second produces an
-% error expandably. Note that there will be no forced line-break, so
+% error expandably. Note that there are no forced line-break, so
% the indentation only changes when the next line is started.
% \begin{macrocode}
\cs_new_protected:Npn \iow_indent:n #1
@@ -1800,7 +1946,7 @@
% done, reset \cs{iow_indent:n} to its error definition: it only works
% in the first argument of \cs{iow_wrap:nnnN}.
% \begin{macrocode}
-%<*initex>
+%<*initex>
\tl_set:Nx \l_@@_wrap_tl {#1}
%</initex>
%<*package>
@@ -1817,7 +1963,7 @@
\int_set:Nn \l_@@_line_target_int
{ \l_iow_line_count_int - \str_count:N \l_@@_newline_tl + 1 }
% \end{macrocode}
-% There is then a loop over the input, which will store the wrapped
+% There is then a loop over the input, which stores the wrapped
% result in \cs{l_@@_wrap_tl}. After the loop, the resulting text is
% passed on to the function which has been given as a post-processor.
% The \cs{tl_to_str:N} step converts the \enquote{other} spaces back
@@ -1829,7 +1975,7 @@
#4 { \tl_to_str:N \l_@@_wrap_tl }
}
% \end{macrocode}
-% As using the generic loader will mean that \cs{protected@edef} is
+% As using the generic loader means that \cs{protected@edef} is
% not available, it's not placed directly in the wrap function but is set
% up as an auxiliary. In the generic loader this can then be redefined.
% \begin{macrocode}
@@ -1842,9 +1988,9 @@
%
% \begin{macro}[aux]{\@@_wrap_do:, \@@_wrap_start:w}
% Escape spaces. Set up a few variables, in particular the initial
-% value of \cs{l_@@_wrap_tl}: the space will stop the
+% value of \cs{l_@@_wrap_tl}: the space stops the
% \texttt{f}-expansion of the main wrapping function and
-% \cs{use_none:n} will remove a newline marker inserted by later code.
+% \cs{use_none:n} removes a newline marker inserted by later code.
% The main loop consists of repeatedly calling the \texttt{chunk}
% auxiliary to wrap chunks delimited by (newline or indentation)
% markers.
@@ -2026,7 +2172,7 @@
% \texttt{break_first} auxiliary calls the \texttt{break_none}
% auxiliary. In that case, if the current line is empty, the complete
% word (including |##4|, characters beyond what we had grabbed) is
-% added to the line, making it over-long. Otherwise, the word will be
+% added to the line, making it over-long. Otherwise, the word is
% used for the following line (and the last space of the line so far
% is removed because it was inserted due to the presence of a marker).
% \begin{macrocode}
@@ -2217,6 +2363,65 @@
%
% \subsection{Deprecated functions}
%
+% \begin{variable}[deprecated = 2018-12-31]{\g_file_current_name_tl}
+% For removal after 2018-12-31.
+% \begin{macrocode}
+\tl_new:N \g_file_current_name_tl
+\tl_gset:Nn \g_file_current_name_tl { \g_file_curr_name_str }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}[deprecated = 2018-12-31]{\file_path_include:n}
+% \begin{macro}[deprecated = 2018-12-31]{\file_path_remove:n}
+% \begin{macro}[deprecated = 2018-12-31, aux]{\__file_path_include:n}
+% Wrapper functions to manage the search path.
+% \begin{macrocode}
+\cs_new_protected:Npn \file_path_include:n #1
+ {
+ \__msg_kernel_warning:nnxxx { kernel } { deprecated-command }
+ { 2018-12-31 }
+ { \token_to_str:N \file_path_include:n }
+ {
+ \token_to_str:N \seq_put_right:Nn \c_space_tl
+ \token_to_str:N \l_file_search_path_seq
+ }
+ \__file_name_sanitize:nN {#1} \l__file_full_name_str
+ \seq_if_in:NVF \l_file_search_path_seq \l__file_full_name_str
+ { \seq_put_right:NV \l_file_search_path_seq \l__file_full_name_str }
+ }
+\cs_new_protected:Npn \file_path_remove:n #1
+ {
+ \__msg_kernel_warning:nnxxx { kernel } { deprecated-command }
+ { 2018-12-31 }
+ { \token_to_str:N \file_path_remove:n }
+ {
+ \token_to_str:N \seq_remove_all:Nn \c_space_tl
+ \token_to_str:N \l_file_search_path_seq
+ }
+ \__file_name_sanitize:nN {#1} \l__file_full_name_str
+ \seq_remove_all:NV \l_file_search_path_seq \l__file_full_name_str
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[deprecated = 2018-12-31]{\file_add_path:nN}
+% For removal after 2018-12-31.
+% \begin{macrocode}
+\cs_new_protected:Npn \file_add_path:nN #1#2
+ {
+ \__msg_kernel_warning:nnxxx { kernel } { deprecated-command }
+ { 2018-12-31 }
+ { \token_to_str:N \file_add_path:nN }
+ { \token_to_str:N \file_get_full_name:nN }
+ \file_get_full_name:nN {#1} #2
+ \str_if_empty:NT #2
+ { \tl_set:Nn #2 { \q_no_value } }
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}[added = 2012-06-24, updated = 2012-07-31, deprecated=2017-12-31]{\ior_get_str:NN}
% For removal after 2017-12-31.
% \begin{macrocode}
@@ -2232,6 +2437,64 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}[deprecated = 2018-12-31]{\file_list:}
+% Renamed to \cs{file_log_list:}. For removal after 2018-12-31.
+% \begin{macrocode}
+\cs_new_protected:Npn \file_list:
+ {
+ \__msg_kernel_warning:nnxxx { kernel } { deprecated-command }
+ { 2018-12-31 }
+ { \token_to_str:N \file_list: }
+ { \token_to_str:N \file_log_list: }
+ \cs_gset_eq:NN \file_list: \file_log_list:
+ \file_log_list:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[added = 2014-08-22, updated = 2015-08-01, deprecated = 2018-12-31]
+% {\ior_list_streams:, \ior_log_streams:, \iow_list_streams:, \iow_log_streams:}
+% These got a more consistent naming.
+% \begin{macrocode}
+\cs_new_protected:Npn \ior_list_streams:
+ {
+ \__msg_kernel_warning:nnxxx { kernel } { deprecated-command }
+ { 2018-12-31 }
+ { \token_to_str:N \ior_list_streams: }
+ { \token_to_str:N \ior_show_list: }
+ \cs_gset_eq:NN \ior_list_streams: \ior_show_list:
+ \ior_show_list:
+ }
+\cs_new_protected:Npn \ior_log_streams:
+ {
+ \__msg_kernel_warning:nnxxx { kernel } { deprecated-command }
+ { 2018-12-31 }
+ { \token_to_str:N \ior_log_streams: }
+ { \token_to_str:N \ior_log_list: }
+ \cs_gset_eq:NN \ior_log_streams: \ior_log_list:
+ \ior_log_list:
+ }
+\cs_new_protected:Npn \iow_list_streams:
+ {
+ \__msg_kernel_warning:nnxxx { kernel } { deprecated-command }
+ { 2018-12-31 }
+ { \token_to_str:N \iow_list_streams: }
+ { \token_to_str:N \iow_show_list: }
+ \cs_gset_eq:NN \iow_list_streams: \iow_show_list:
+ \iow_show_list:
+ }
+\cs_new_protected:Npn \iow_log_streams:
+ {
+ \__msg_kernel_warning:nnxxx { kernel } { deprecated-command }
+ { 2018-12-31 }
+ { \token_to_str:N \iow_log_streams: }
+ { \token_to_str:N \iow_log_list: }
+ \cs_gset_eq:NN \iow_log_streams: \iow_log_list:
+ \iow_log_list:
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macrocode}
%</initex|package>
% \end{macrocode}