diff options
author | Karl Berry <karl@freefriends.org> | 2017-07-15 21:27:01 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2017-07-15 21:27:01 +0000 |
commit | b1ce47fe4d0e1f06d1b019c3c6eb5f1b0ecd5e14 (patch) | |
tree | 58362abe4b603bb5f6db898b9b835bc8af730b3e /Master/texmf-dist/source/latex/l3kernel/l3file.dtx | |
parent | 03b8dcfa3435f0265dfad4fd09aaab8f4ff9c617 (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.dtx | 891 |
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} |