% \iffalse meta-comment
%
% printfilelist.dtx
% Copyright 2024-2026 Gorkem Aksaray <aksarayg@tcd.ie>
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
% of this license or (at your option) any later version.
% The latest version of this license is in
%   https://www.latex-project.org/lppl.txt
% and version 1.3c or later is part of all distributions of LaTeX
% version 2008 or later.
%
% This work has the LPPL maintenance status `maintained'.
% 
% The Current Maintainer of this work is Gorkem Aksaray.
%
% This work consists of the files printfilelist.dtx, printfilelist.ins,
% and the derived files printfilelist.sty and printfilelist.pdf.
%
% \fi
%
% \iffalse
%<*driver>
\ProvidesFile{printfilelist.dtx}
%</driver>
%<package>\NeedsTeXFormat{LaTeX2e}[2003/12/01]
%<package>\ProvidesPackage{printfilelist}
%<*package>
    [2026/06/07 v1.1.0 Print a list of the files used by the current document]
%</package>
%
%<*driver>
\documentclass{ltxdoc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage[indent=15pt]{parskip}
\usepackage[dvipsnames]{xcolor}
\usepackage{microtype}
\usepackage{hyperref}
\hypersetup{
  colorlinks,
  linkcolor=Red,
  urlcolor=RoyalBlue,
  citecolor=RoyalBlue,
  pdftitle={The printfilelist package},
  pdfauthor={Gorkem Aksaray},
  pdfsubject={Print a list of the files used by the current document}}
\newcommand{\email}[1]{\href{mailto:#1}{\nolinkurl{#1}}}
\RecordChanges
\begin{document}
  \DocInput{printfilelist.dtx}
  \PrintChanges
\end{document}
%</driver>
% \fi
%
% \CheckSum{121}
%
% \CharacterTable
%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%   Digits        \0\1\2\3\4\5\6\7\8\9
%   Exclamation   \!     Double quote  \"     Hash (number) \#
%   Dollar        \$     Percent       \%     Ampersand     \&
%   Acute accent  \'     Left paren    \(     Right paren   \)
%   Asterisk      \*     Plus          \+     Comma         \,
%   Minus         \-     Point         \.     Solidus       \/
%   Colon         \:     Semicolon     \;     Less than     \<
%   Equals        \=     Greater than  \>     Question mark \?
%   Commercial at \@     Left bracket  \[     Backslash     \\
%   Right bracket \]     Circumflex    \^     Underscore    \_
%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%   Right brace   \}     Tilde         \~}
%
% \changes{v1.0.0}{2024/01/02}{Initial version}
% \changes{v1.1.0}{2026/06/07}{Rewritten to use only the LaTeX kernel,
%    removing the xstring and suffix dependencies; the file list is now read
%    live so the package may be loaded anywhere in the preamble; the starred
%    form prints a compact, inline, comma-separated list of names; a note is
%    printed when no file matches the filter; removed the internal file-list
%    alias}
%
% \GetFileInfo{printfilelist.dtx}
%
% \title{The \textsf{printfilelist} package}
% \author{Gorkem Aksaray \\ \email{aksarayg@tcd.ie}}
% \date{\fileversion~from \filedate}
%
% \maketitle
%
% \noindent Source repo:
% \url{https://github.com/gaksaray/printfilelist}.
%
% \section{Introduction}
%
% This is a \LaTeX\ package for inspecting the files used by the current
% document. It provides two commands: |\printfilelist|, which prints a list
% of all the files (with an option to filter them), and |\ispackageloaded|,
% which prints whether a given package is loaded or not. Both commands can
% be issued at any point within the document body. The package has no
% dependencies beyond the \LaTeX\ kernel.
%
% \section{Usage}
%
% Load the package anywhere in the preamble:
% \begin{verbatim}
%   \usepackage{printfilelist}
% \end{verbatim}\vspace{-\baselineskip}
% The load position does not matter: the package records every input file used
% by the document, and the two commands below read that list wherever they are
% called.
%
% \DescribeMacro{\printfilelist\oarg{filter}}
% Prints the files used by the current document, one per line, together with
% their version information. The optional \meta{filter} keeps only the
% files whose name contains the given text; for example,
% \begin{verbatim}
%   \printfilelist[.sty]
% \end{verbatim}\vspace{-\baselineskip}
% lists only the |.sty| files. The default filter, |.|, keeps any file that
% has an extension, while an empty filter, |\printfilelist[]|, keeps every
% recorded file. If nothing matches, a short note is printed instead.
%
% \DescribeMacro{\printfilelist*\oarg{filter}}
% The starred form prints a compact, comma-separated list of file names only,
% without version information. It is set as ordinary inline text, so it may be
% embedded in running prose, as in |Files: \printfilelist*[]|.
%
% \DescribeMacro{\ispackageloaded\marg{package}}
% Prints whether \meta{package} is loaded, together with its version if it is.
% The starred form, |\ispackageloaded*|, prints only ``is loaded'' or ``is not
% loaded''. This command recognizes packages (|.sty| files) only, not document
% classes.
%
% \section{Notes}
%
% The package issues |\listfiles| when loaded; this is what makes the kernel
% keep the file list until the commands above are used. As a side effect,
% \LaTeX\ also writes the file list to the |.log| at the end of the run. The
% package always omits its own entry, |printfilelist.sty|. The detailed form
% of |\printfilelist| forms its own paragraph, while the starred form is inline;
% neither is intended for a moving argument such as a section title.
%
% \StopEventually{}
%
% \section{Implementation}
%
% The kernel accumulates the names of all input files in |\@filelist|, but
% discards it at |\begin{document}| unless |\listfiles| has been issued.
% Issuing it here keeps the list available for the commands below.
%    \begin{macrocode}
\listfiles
%    \end{macrocode}
%
% \begin{macro}{\ispackageloaded}
% The kernel records a loaded package in the control sequence
% |\ver@|\meta{name}|.sty|. The unstarred form prints that version; the
% starred form reports only whether the package is present.
%    \begin{macrocode}
\newcommand{\ispackageloaded}{\@ifstar\pfl@ispl@star\pfl@ispl@plain}
\newcommand{\pfl@ispl@plain}[1]{%
    \if\relax\detokenize{#1}\relax\else
        \ifcsname ver@#1.sty\endcsname
            \texttt{#1.sty}: \csname ver@#1.sty\endcsname%
        \else
            \texttt{#1} is not loaded%
        \fi
    \fi
}
\newcommand{\pfl@ispl@star}[1]{%
    \if\relax\detokenize{#1}\relax\else
        \ifcsname ver@#1.sty\endcsname
            \texttt{#1} is loaded%
        \else
            \texttt{#1} is not loaded%
        \fi
    \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\printfilelist}
% The star selects the compact, inline form; without it, the detailed
% one-per-line listing is produced. Either way the list is read live from
% |\@filelist| when the command is called.
%    \begin{macrocode}
\newif\ifpfl@inline
\newif\ifpfl@found
\newcommand{\printfilelist}{\@ifstar{\pfl@inlinetrue\pfl@run}{\pfl@inlinefalse\pfl@run}}
\newcommand{\pfl@run}[1][.]{%
    \begingroup
    \ifpfl@inline\else\par\fi
    \pfl@foundfalse
    \@for\pfl@file:=\@filelist\do{%
        \expandafter\pfl@test\expandafter{\pfl@file}{#1}%
    }%
    \ifpfl@found\else
        \ifpfl@inline\pfl@nomatch\else\noindent\pfl@nomatch\par\fi
    \fi
    \ifpfl@inline\else\par\fi
    \endgroup
}
%    \end{macrocode}
% The message shown when nothing matches the filter; redefine it to change the
% wording. Its framing (inline or paragraph) is supplied by |\pfl@run|.
%    \begin{macrocode}
\newcommand{\pfl@nomatch}{\textit{No matching files.}}
%    \end{macrocode}
% Each recorded file is tested against the filter, and the package's own file
% is always skipped. Matching uses the kernel's |\in@|, which compares tokens
% literally and does not expand its arguments, so the name held in |\pfl@file|
% is expanded into the test with |\expandafter|.
%    \begin{macrocode}
\newcommand{\pfl@test}[2]{%
    \in@{printfilelist.sty}{#1}%
    \ifin@\else
        \if\relax\detokenize{#2}\relax
            \pfl@printline
        \else
            \in@{#2}{#1}%
            \ifin@\pfl@printline\fi
        \fi
    \fi
}
%    \end{macrocode}
% This prints one entry: in the compact form a comma precedes every entry
% except the first (tracked by |\ifpfl@found|), while in the detailed form the
% name is followed by its version, if any, on its own line.
%    \begin{macrocode}
\newcommand{\pfl@printline}{%
    \ifpfl@inline
        \ifpfl@found,\space\fi
        \pfl@foundtrue
        \texttt{\pfl@file}%
    \else
        \pfl@foundtrue
        \noindent\texttt{\pfl@file}%
        \ifcsname ver@\pfl@file\endcsname
            : \csname ver@\pfl@file\endcsname%
        \fi
        \par
    \fi
}
%    \end{macrocode}
% \end{macro}
%
% \Finale
\endinput
