% \iffalse %% File: l3file.dtx Copyright (C) 2009 LaTeX3 project %% %% It may be distributed and/or modified under the conditions of the %% LaTeX Project Public License (LPPL), either version 1.3c of this %% license or (at your option) any later version. The latest version %% of this license is in the file %% %% http://www.latex-project.org/lppl.txt %% %% This file is part of the ``expl3 bundle'' (The Work in LPPL) %% and all files in that bundle must be distributed together. %% %% The released version of this bundle is available from CTAN. %% %% ----------------------------------------------------------------------- %% %% The development version of the bundle can be found at %% %% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% %%%%%%%%%%% %% NOTE: %% %%%%%%%%%%% %% %% Snapshots taken from the repository represent work in progress and may %% not work or may contain conflicting material! We therefore ask %% people _not_ to put them into distributions, archives, etc. without %% prior consultation with the LaTeX Project Team. %% %% ----------------------------------------------------------------------- %% % %<*driver|package> \RequirePackage{l3names} % %\fi \GetIdInfo$Id: l3file.dtx 1352 2009-05-28 11:50:39Z morten $ {L3 Experimental file loading} %\iffalse %<*driver> %\fi \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse \documentclass[full]{l3doc} \begin{document} \DocInput{l3file.dtx} \end{document} % % \fi % % \title{The \textsf{l3file} package\thanks{This file % has version number \fileversion, last % revised \filedate.}\\ % File Loading} % \author{\Team} % \date{\filedate} % \maketitle % % \begin{documentation} % %\section{Loading files} % % The need to test if a file is available and to load a file if found is % covered at a low level here. % %\begin{function}{ % \file_if_exist_p:n| % \file_if_exist:n / (TF) %} % \begin{syntax} % "\file_if_exist:nTF" % \end{syntax} % Tests if exists. % \begin{texnote} % This is \LaTeXe's \cs{IfFileExists}, although it does not return % name of the file (\emph{cf.}~\cs{@filef@und}). % \end{texnote} %\end{function} % %\begin{function}{\file_add_path:nN} % \begin{syntax} % "\file_add_path:nN" % \end{syntax} % Searches for on the \TeX\ path and using % \cs{l_file_search_path_clist}. If is found, is set % to the file name plus any path information needed. If is not % found, will be blank. % \begin{texnote} % This is similar to obtaining \cs{@filef@und} from \LaTeXe's % \cs{IfFileExists}. % \end{texnote} %\end{function} % %\begin{function}{\file_input:n} % \begin{syntax} % "\file_input:n" % \end{syntax} % Inputs if it found (according to the same rule as for % \cs{file_if_exist:n}. % \begin{texnote} % This acts in a similar way to \LaTeXe's \cs{input}, as it will not % lead to a \TeX\ loop if the file is not found. % \end{texnote} %\end{function} % %\begin{function}{\file_input_no_record:n} % \begin{syntax} % "\file_input_no_record:n" % \end{syntax} % Inputs if it found (according to the same rule as for % \cs{file_if_exist:n}, but does not add it to % \cs{g_file_record_clist}. The file is still added to % \cs{g_file_record_full_clist}. % \begin{texnote} % This is similar to \LaTeXe's \cs{@input@}. % \end{texnote} %\end{function} % %\begin{function}{ % \file_input_no_check:n| % \file_input_no_check_no_record:n| %} % \begin{syntax} % "\file_input_no_check:n" % \end{syntax} % Inputs directly without checking if it exists. The % \texttt{no_record} version does not record the input in % \begin{texnote}\cs{g_file_record_clist}. % These are simple wrappers around the \TeX\ \cs{input} primitive % \end{texnote} %\end{function} % %\begin{function}{ % \file_list:| % \file_list_full:| %} % \begin{syntax} % "\file_list:" % \end{syntax} % Lists files loaded in current \LaTeX\ run: the \texttt{full} version % lists all files. %\end{function} % %\section{Variables and constants} % %\begin{variable}{ % \g_file_record_clist| % \g_file_record_full_clist %} % Used to track the files that have been loaded. %\end{variable} % %\begin{variable}{\l_file_search_path_clist} % List of paths to search for a file in addition to those searched by % \TeX. % \begin{texnote} % This is \cs{input@path} in \LaTeXe. % \end{texnote} %\end{variable} % %\begin{variable}{\l_file_test_read_stream} % Input stream used to carry out file tests. %\end{variable} % %\begin{variable}{\l_file_tmp_bool} % Internal scratch switch. %\end{variable} % %\begin{variable}{\l_file_tmp_tl} % Internal scratch token list variable. %\end{variable} % % \end{documentation} % % \begin{implementation} % % \section{\pkg{l3file} implementation} % % The usual lead-off. % \begin{macrocode} %<*package> \ProvidesExplPackage {\filename}{\filedate}{\fileversion}{\filedescription} \package_check_loaded_expl: % %<*initex|package> % \end{macrocode} % %\begin{macro}{\g_file_record_clist} %\begin{macro}{\g_file_record_full_clist} % When files are read with logging, the names are added here. There are % two lists, one for everything and one for only those items which might % later be listed (as in \LaTeXe's \cs{listfiles}). % \begin{macrocode} \clist_new:N \g_file_record_clist \clist_new:N \g_file_record_full_clist % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\l_file_search_path_clist} % Checking input needs a stream to work with % \begin{macrocode} \clist_new:N \l_file_search_path_clist % \end{macrocode} %\end{macro} % %\begin{macro}{\l_file_test_read_stream} % Checking input needs a stream to work with % \begin{macrocode} \ior_new:N \l_file_test_read_stream % \end{macrocode} %\end{macro} % %\begin{macro}{\l_file_tmp_bool} % A flag is needed for internal purposes. % \begin{macrocode} \bool_new:N \l_file_tmp_bool % \end{macrocode} %\end{macro} % %\begin{macro}{\l_file_tmp_tl} % A scratch token list variable. % \begin{macrocode} \tl_new:N \l_file_tmp_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\file_if_exist_p:n} %\begin{macro}[TF]{\file_if_exist:n} %\begin{macro}[aux]{\file_if_exist_path:n} %\begin{macro}[aux]{\file_if_exist_aux:n} % Checking if a file exists takes place in two parts. First, there is % a simple check ``here''. If that fails, then there is a loop over % the current search path. % \begin{macrocode} \prg_new_conditional:Nnn \file_if_exist:n {p,TF,T,F} { \ior_open:Nn \l_file_test_read_stream {#1} \ior_if_eof:NTF \l_file_test_read_stream { \file_if_exist_path:n {#1} }{ \ior_close:N \l_file_test_read_stream \prg_return_true: } } \cs_new_nopar:Nn \file_if_exist_path:n { \bool_set_false:N \l_file_tmp_bool \cs_set_nopar:Nn \file_if_exist_aux:n { \ior_open:Nn \l_file_test_read_stream { #1 ##1 } \ior_if_eof:NF \l_file_test_read_stream { \bool_set_true:N \l_file_tmp_bool \clist_map_break: } } % %<*package> \cs_if_exist:NT \input@path { \cs_set_eq:NN \l_file_search_path_clist \input@path } % %<*initex|package> \clist_map_function:NN \l_file_search_path_clist \file_if_exist_aux:n \ior_close:N \l_file_test_read_stream \bool_if:NTF \l_file_tmp_bool { \prg_return_true: }{ \prg_return_false: } } \cs_new_nopar:Nn \file_if_exist_aux:n { } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\file_add_path:nN} %\begin{macro}[aux]{\file_add_path_search:n} %\begin{macro}[aux]{\file_add_path_aux:n} % Checking if a file exists takes place in two parts. First, there is % a simple check ``here''. If that fails, then there is a loop over % the current search path. % \begin{macrocode} \cs_new_nopar:Nn \file_add_path:nN { \tl_clear:N #2 \ior_open:Nn \l_file_test_read_stream {#1} \ior_if_eof:NTF \l_file_test_read_stream { \file_add_path_search:nN {#1} #2 }{ \tl_set:Nn #2 {#1} } \ior_close:N \l_file_test_read_stream } \cs_new_nopar:Nn \file_add_path_search:nN { \cs_set_nopar:Nn \file_add_path_aux:n { \ior_open:Nn \l_file_test_read_stream { ##1 #1 } \ior_if_eof:NF \l_file_test_read_stream { \tl_set:Nn #2 { ##1 #1 } \clist_map_break: } } % %<*package> \cs_if_exist:NT \input@path { \cs_set_eq:NN \l_file_search_path_clist \input@path } % %<*initex|package> \clist_map_function:NN \l_file_search_path_clist \file_add_path_aux:n } \cs_new_nopar:Nn \file_add_path_aux:n { } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\file_input:n} %\begin{macro}{\file_input_no_record:n} % \cs{file_add_path:nN} will return an empty token list variable if the % file is not found. This is used rather than \cs{file_if_exist:nT} here % as it saves running the same loop twice. % \begin{macrocode} \cs_new:Nn \file_input:n { \file_add_path:nN {#1} \l_file_tmp_tl \tl_if_empty:NF \l_file_tmp_tl { \file_input_no_check:n \l_file_tmp_tl } } \cs_new:Nn \file_input_no_record:n { \file_add_path:nN {#1} \l_file_tmp_tl \tl_if_empty:NF \l_file_tmp_tl { \file_input_no_check_no_record:n \l_file_tmp_tl } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\file_input_no_check:n} % File input records what is going on before setting to work. % \begin{macrocode} \cs_new_nopar:Nn \file_input_no_check:n { \clist_gput_right:Nx \g_file_record_clist {#1} \wlog{ADDING: #1} % %<*package> \@addtofilelist {#1} % %<*initex|package> \clist_gput_right:Nx \g_file_record_full_clist {#1} \tex_input:D #1 ~ } % \end{macrocode} %\end{macro} %\begin{macro}{\file_input_no_check_no_record:n} % Inputting a file without adding to the main record is basically the % same: even in this case the file goes on the full log. % \begin{macrocode} \cs_new_nopar:Nn \file_input_no_check_no_record:n { \clist_gput_right:Nx \g_file_record_full_clist {#1} \tex_input:D #1 ~ } % \end{macrocode} %\end{macro} % %\begin{macro}{\file_list:} %\begin{macro}{\file_list_full:} %\begin{macro}[aux]{\file_list:N} % Two functions to list all files used to the log: the \texttt{full} % version includes everything whereas the standard version uses the % shorter record. % \begin{macrocode} \cs_new_nopar:Nn \file_list: { \file_list:N \g_file_record_clist } \cs_new_nopar:Nn \file_list_full: { \file_list:N \g_file_record_full_clist } \cs_new_nopar:Nn \file_list:N { \clist_remove_duplicates:N #1 \iow_log:x { *~File~List~* } \clist_map_function:NN #1 \file_list_aux:n \iow_log:x { ************* } } \cs_new_nopar:Nn \file_list_aux:n { \iow_log:x { #1 } } % \end{macrocode} %\end{macro} %\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. % \begin{macrocode} % %<*package> % \begin{macrocode} \AtBeginDocument{ \clist_put_right:NV \g_file_record_clist \@filelist \clist_put_right:NV \g_file_record_full_clist \@filelist } % % \end{macrocode} % % \end{implementation} % % \PrintIndex