% \iffalse %% File: l3file.dtx Copyright (C) 2009-2010 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 1853 2010-03-21 09:11:08Z joseph $ {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} % % In contrast to the \pkg{l3io} module, which deals with the lowest % level of file management, the \pkg{l3file} module provides a higher % level interface for handling file contents. This involves providing % convenient wrappers around many of the functions in \pkg{l3io} % to make them more generally accessible. % % It is important to remember that \TeX\ will attempt to locate % files using both the operating system path and entries in the % \TeX\ file database (most \TeX\ systems use such a database). Thus % the `current path' for \TeX\ is somewhat broader than that for other % programs. % %\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_job_name_tl} at the start of a \LaTeX\ % run and will be modified each time a file is read using % \cs{file_input:n}. %\end{variable} % %\begin{function}{ % \file_if_exist:n / (TF) | % \file_if_exist:V / (TF) %} % \begin{syntax} % \cs{file_if_exist:nTF} \Arg{file name} \Arg{true code} \Arg{false code} % \end{syntax} % Searches for \meta{file name} using the current \TeX\ search % path and the additional paths controlled by % \cs{file_path_include:n}). The branching versions then leave % either \meta{true code} or \meta{false code} in the input stream, % as appropriate to the truth of the test and the variant of the % function chosen. %\end{function} % %\begin{function}{ % \file_input:n | % \file_input:V %} % \begin{syntax} % \cs{file_input:n} \Arg{file name} % \end{syntax} % Searches for \meta{file name} in the path as detailed for % \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. %\end{function} % %\begin{function}{ \file_path_include:n } % \begin{syntax} % \cs{file_path_include:n} \Arg{path} % \end{syntax} % Adds \meta{path} to the list of those used to search for files % by the \cs{file_input:n} and \cs{file_if_exist:n} function. The % assignment is local. %\end{function} % %\begin{function}{ \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 for files % by the \cs{file_input:n} and \cs{file_if_exist:n} function. The % assignment is local. %\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. %\end{function} % % \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_current_name_tl} %\begin{macro}{\g_file_stack_seq} % The name of the current file should be available at all times. % \begin{macrocode} \tl_new:N \g_file_current_name_tl \seq_new:N \g_file_stack_seq % \end{macrocode} % % For the format the file name needs to be picked up at the start of the % file. In package mode the current file name is collected from LaTeX2e. % \begin{macrocode} % %<*initex> \toks_put_right:Nn \tex_everyjob:D { \tl_gset:Nx \g_file_current_name_tl { \tex_jobname:D } } % %<*package> \tl_gset_eq:NN \g_file_current_name_tl \@currname % %<*initex|package> % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\g_file_record_seq} % The total list of files used is recorded separately from the % stack. % \begin{macrocode} \seq_new:N \g_file_record_seq % \end{macrocode} % % The current file name should be included in the file list! % \begin{macrocode} % %<*initex> \toks_put_right:Nn \tex_everyjob:D { \seq_gput_right:NV \g_file_record_seq \g_file_current_name_tl } % %<*initex|package> % \end{macrocode} %\end{macro} % %\begin{macro}{\l_file_search_path_seq} % The current search path. % \begin{macrocode} \seq_new:N \l_file_search_path_seq % \end{macrocode} %\end{macro} % %\begin{macro}{\l_file_search_path_saved_seq} % The current search path has to be saved for package use. % \begin{macrocode} % %<*package> \seq_new:N \l_file_search_path_saved_seq % %<*initex|package> % \end{macrocode} %\end{macro} % %\begin{macro}{\l_file_name_tl} %\begin{macro}{\g_file_test_stream} %\begin{macro}[TF]{\file_if_exist:n} %\begin{macro}[TF]{\file_if_exist:V} %\begin{macro}[aux]{\file_if_exist_aux:n} % Checking if a file exists takes place in two parts. First, look on % the TeX path, then look on the LaTeX path. The % token list \cs{l_file_name_tl} is used as a marker for finding % the file, and is also needed by \cs{file_input:n}. % \begin{macrocode} \tl_new:N \l_file_name_tl \prg_new_protected_conditional:Nnn \file_if_exist:n { T , F , TF } { \ior_open:Nn \g_file_test_stream {#1} \ior_if_eof:NTF \g_file_test_stream { \file_if_exist_path_aux:n {#1} } { \ior_close:N \g_file_test_stream \tl_set:Nn \l_file_name_tl {#1} \prg_return_true: } } \cs_new_protected_nopar:Npn \file_if_exist_path_aux:n #1 { \tl_clear:N \l_file_name_tl % %<*package> \cs_if_exist:NT \input@path { \seq_set_eq:NN \l_file_search_path_saved_seq \l_file_search_path_seq \clist_map_inline:Nn \input@path { \seq_put_right:Nn \l_file_search_path_seq {##1} } } % %<*initex|package> \seq_map_inline:Nn \l_file_search_path_seq { \ior_open:Nn \g_file_test_stream { ##1 #1 } \ior_if_eof:NF \g_file_test_stream { \tl_set:Nn \l_file_name_tl { ##1 #1 } \seq_map_break: } } % %<*package> \cs_if_exist:NT \input@path { \seq_set_eq:NN \l_file_search_path_seq \l_file_search_path_saved_seq } % %<*initex|package> \ior_close:N \g_file_test_stream \tl_if_empty:NTF \l_file_name_tl { \prg_return_false: } { \prg_return_true: } } \cs_generate_variant:Nn \file_if_exist:nT { V } \cs_generate_variant:Nn \file_if_exist:nF { V } \cs_generate_variant:Nn \file_if_exist:nTF { V } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\file_input:n} %\begin{macro}{\file_input:V} % Most of the work is done by the file test above. % \begin{macrocode} \cs_new_protected_nopar:Npn \file_input:n #1 { \file_if_exist:nT {#1} { % %<*package> \@addtofilelist {#1} % %<*initex|package> \seq_gpush:NV \g_file_stack_seq \g_file_current_name_tl \tl_gset:Nn \g_file_current_name_tl {#1} \tex_expandafter:D \tex_input:D \l_file_name_tl ~ \seq_gpop:NN \g_file_stack_seq \g_file_current_name_tl } } \cs_generate_variant:Nn \file_input:n { V } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\file_path_include:n} %\begin{macro}{\file_path_remove:n} % Wrapper functions to manage the search path. % \begin{macrocode} \cs_new_protected_nopar:Npn \file_path_include:n #1 { \seq_put_right:Nn \l_file_search_path_seq {#1} \seq_remove_duplicates:N \l_file_search_path_seq } \cs_new_protected_nopar:Npn \file_path_remove:n #1 { \seq_remove_element:Nn \l_file_search_path_seq {#1} } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\file_list:} %\begin{macro}[aux]{\file_list_aux:n} % A function to list all files used to the log. % \begin{macrocode} \cs_new_protected_nopar:Npn \file_list: { \seq_remove_duplicates:N \g_file_record_seq \iow_log:n { *~File~List~* } \seq_map_function:NN \g_file_record_seq \file_list_aux:n \iow_log:n { ************* } } \cs_new_protected_nopar:Npn \file_list_aux:n #1 { \iow_log:n {#1} } % \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. % \begin{macrocode} % %<*package> \AtBeginDocument{ \clist_map_inline:Nn \@filelist { \seq_put_right:Nn \g_file_record_seq {#1} } } % % \end{macrocode} % % \end{implementation} % % \PrintIndex