% \iffalse meta-comment
%% Copyright (c) 2010-2011 by Martin Scharrer <martin@scharrer-online.de>
%% -----------------------------------------------------------------
%%
%% 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
%%
%%   http://www.latex-project.org/lppl.txt
%%
%% and version 1.3c or later is part of all distributions of LaTeX
%% version 2008/05/04 or later.
%%
%% This work has the LPPL maintenance status `maintained'.
%%
%% The Current Maintainer of this work is Martin Scharrer.
%%
%% This work consists of the files currfile.dtx, currfile.ins
%% and the derived file currfile.sty.
%%
%% $Id: currfile.dtx 2036 2011-01-09 17:51:42Z martin $
% \fi
%
% \iffalse
%<*driver>
\ProvidesFile{currfile.dtx}
%</driver>
%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%<package>\ProvidesPackage{currfile}
%<*package>
    [2011/01/09 v0.4 Current input file name and path]
%</package>
%
%<*driver>
\documentclass{ydoc}[2011/01/09]
\usepackage{currfile}[2011/01/09]
\usepackage{ifpdf}
\usepackage{booktabs}
\usepackage{hyperref}
\EnableCrossrefs
\CodelineIndex
\RecordChanges
\providecommand*\pkg{\texttt}
\providecommand*\opt{\texttt}
\let\cs\Macro
\begin{document}
  \DocInput{currfile.dtx}
  \PrintChanges
  \PrintIndex
\end{document}
%</driver>
% \fi
%
% \CheckSum{258}
%
% \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{v0.1}{2010/04/08}{Initial version}
% \changes{v0.2}{2010/04/10}{Now work for all files, not only for \cs{input} and \cs{include} files.
%  Added package option 'fink' to define the same macros as the 'fink' package.
% }
% \changes{v0.3}{2011/01/03}{Update to use new version of filehook.}
% \changes{v0.4}{2011/01/09}{Added if-macros and sanitized currfile macros.}
%
% \GetFileInfo{currfile.dtx}
%
% \DoNotIndex{\newcommand,\newenvironment,\fi,\relax,\def,\gdef,\xdef}
% \DoNotIndex{\RequirePackage,\space,\PackageError,\PackageWarning,\let}
% \DoNotIndex{\ifx,\global,\long,\dindent,\else,\empty,\expandafter}
% \DoNotIndex{\csname,\endcsname,\DeclareBoolOption,\DeclareStringOption}
% \DoNotIndex{\SetupKeyvalOptions,\begingroup,\endgroup,\@gobble,\edef}
% \DoNotIndex{\message,\jobname,\@namedef}
% 
% \ifpdf
% \hypersetup{%
%   pdfauthor   = {Martin Scharrer <martin@scharrer-online.de>},
%   pdftitle    = {The currfile package},
%   pdfsubject  = {Documentation of LaTeX package 'currfile'},
%   pdfkeywords = {current filename, filename, file, name, LaTeX, TeX}
% }%
% \fi
% \clearpage
% \null
% \vspace*{-2em}
% \begin{center}
%   {\LARGE\sffamily The \emph{currfile} Package\\[\medskipamount]}
%   {\large Martin Scharrer \\[\medskipamount]\normalsize 
%   \url{martin@scharrer-online.de}\\[.8ex]
%   \url{http://www.ctan.org/pkg/currfile/}\\[\bigskipamount]}
%   {\large Version \fileversion\ -- \filedate}\\
% \end{center}
% \vspace{1.2em}%
%
% \begin{abstract}
% This small package provides the file name and path information of the current input file as \LaTeX{} macros.
% \end{abstract}
%
% \section{Usage}
%
% \DescribeMacro{\currfiledir}
% \DescribeMacro{\currfilebase}
% \DescribeMacro{\currfileext}
% \DescribeMacro{\currfilename}
% \DescribeMacro{\currfilepath}
% The directory, base (name without extension), extension (without dot), name (=base+`|.|'+ext) and path (=dir+name) of the current file are provided by these macros.
% This means that the macros returns the file information of the file they are used in. All macros are fully expanded, i.e.\ only hold
% text and not further macros. They are also ``sanitized'' to ensure that all characters, especially special ones like `|_|', are taken verbatim.
% However this special characters might not be displayed correctly in all fonts. A good font is text-type (\Macro\ttfamily, \Macro\texttt{\ldots}),
% but other fonts can be used using the \pkg{url} package, e.g.: |\urlstyle{rm}\expandafter\nolinkurl\expandafter{\currfilename}|.
%
% Special care is taken to keep the file information of \Macro\included files till the final \Macro\clearpage command, so that page header and footer of the last page 
% will hold the correct data.
%
% Since v0.2 all files are are taken into account, i.e.\ files read using \Macro\input, \Macro\include, \Macro\InputIfFileExists, \Macro\usepackage, \Macro\RequirePackage and even
% \Macro\LoadClass and similar macros. Before v0.2 only \Macro\input or \Macro\include and the main file were taken into account.
%
%
% This package uses the \pkg{filehook} package written by the same author. See there for possible incompatibilities with classes or other packages.
%
% More detailed information can be found in the implementation section \ref{sec:impl} if required.
%
% \DescribeMacro{\ifcurrfiledir}{<text>}{<true>}{<false>}
% \DescribeMacro{\ifcurrfilebase}{<text>}{<true>}{<false>}
% \DescribeMacro{\ifcurrfileext}{<text>}{<true>}{<false>}
% \DescribeMacro{\ifcurrfilename}{<text>}{<true>}{<false>}
% \DescribeMacro{\ifcurrfilepath}{<text>}{<true>}{<false>}
% This\marginpar{\raggedright New in v0.4 from 2011/01/09} if-macros allow the comparison of \meta{text} with the current file directory, base, extension, name and path, respectively.
% The \meta{text} is fully expanded and sanitized for the comparison. Example: |\ifcurrfileext{cfg}{I'm in a config file}{No config file!}|
%
% \DescribeMacro{\ifcurrfile}{<currfile macro or text>}{<text>}{<true>}{<false>}
% Compares the given \meta{currfile macro or text} with \meta{text}. Both are taken as file name parts and are fully expanded and sanitized before the comparison.
% This general macro is a little slower then the specialised macros above but might be useful to compare different file names/paths where non of the two is the current file.
% Note that the all comparisons are done insensitive to the catcodes of the texts, which is what users want. Different comparision macros (|\ifx|, \pkg{ifthenelse}) might not do this.
%
% \subsection*{Package Options}
% The package provides two options \opt{mainext} and \opt{maindir} which can be used to provide the extension and directory of the main file.
% This is required if the above macros should be used for the main file itself and if this does has a file extension other than `|.tex|' (e.g.\ a |.dtx| file)
% or is not located in the current directory. To provide support for the macros defined by the \pkg{fink} package (see section~\ref{sec:fink}) a \pkg{fink} option exists.
%
% \section{Usage inside file hooks}
% This package uses the `EveryFile' hooks of the \pkg{filehook} package to update its macros.
% Special care is taken to do this in a way so that the macros can be used safely inside other hook code, including other `EveryFile' hooks.
% Please note that the `AtEndOfPackageFile' and `AtEndOfClassFile' hooks are executed after `AtEndOfEveryFile'
% and therefore the |currfile| macros will hold the values of the parent file, not of that package or class file.
%
% \section{Compatibility with the \texttt{fink} package}\label{sec:fink}
% The \pkg{fink} package (\emph{fi}le \emph{n}ame \emph{k}eeper) provides a similar functionality. It has inspired this package in several points (e.g.\ package
% options). However, it does not exclude package and other preamble files and does not take care to change the filename \emph{after} the \Macro\clearpage of
% \Macro\include. The author of \texttt{fink} is now discontinuing it in favour of this package.
% Existing documents which use \pkg{fink} should either rename the related macros as shown by Table~\ref{tab:fink} or use the \pkg{fink} option of \pkg{currfile} which defines
% the \pkg{fink} macros to use the \pkg{currfile} ones.
%
% Because both packages do basically the same thing, especially patch the same macros, there are incompatible and should not be loaded at the same time.
% In consent with the \pkg{fink} package author this package will undo most of the \pkg{fink} code if it was already loaded or prevent it from being loaded afterwards.
%
% \begin{table}
% \belowcaptionskip=\abovecaptionskip
% \abovecaptionskip=0pt
% \caption{Conversion from \texttt{fink} package to \texttt{currfile}.}
% \label{tab:fink}
% \centering
% \begin{tabular}{lll}
%   \toprule
%     \texttt{fink}  &  \texttt{currfile} &  Example Result        \\
%   \midrule
%      \cs{finkdir}  &  \cs{currfiledir}  & \ttfamily\currfiledir  \\
%      \cs{finkbase} &  \cs{currfilebase} & \ttfamily\currfilebase \\
%      \cs{finkext}  &  \cs{currfileext}  & \ttfamily\currfileext  \\
%      \cs{finkfile} &  \cs{currfilename} & \ttfamily\currfilename \\
%      \cs{finkpath} &  \cs{currfilepath} & \ttfamily\currfilepath \\
%   \bottomrule
% \end{tabular}
% \end{table}
%
% \StopEventually{}
%
%
% \section{Implementation}\label{sec:impl}
%
% \iffalse
%<*package>
% \fi
% \subsection{Options}
%
%    \begin{macrocode}
\RequirePackage{kvoptions}
\SetupKeyvalOptions{family=currfile,prefix=currfile@}

\@ifpackageloaded{fink}{%
    \DeclareStringOption[\fnk@mainext]{mainext}%
    \DeclareStringOption[\fnk@maindir]{maindir}%
    \DeclareBoolOption[true]{fink}%
    \PackageWarning{currfile}{Deprecated package 'fink' detected. %
      The 'fink' option will default to 'true'.^^J%
      If set to 'false' no 'fink' macros will be changed but they will stop
      working correctly!}%
}{%
    \DeclareStringOption[tex]{mainext}%
    \DeclareStringOption[\@currdir]{maindir}%
    \DeclareBoolOption[false]{fink}%
}%
\DeclareVoidOption{force}{\PassOptionsToPackage{force}{filehook}}
\RequirePackage{filehook}[2011/01/09]
\ProcessKeyvalOptions*\relax

\begingroup
\xdef\currfile@mainext{\currfile@mainext}%
\xdef\currfile@maindir{\currfile@maindir}%
\def\@tempa{./}%
\ifx\@tempa\currfile@maindir
    \global\let\currfile@maindir\empty
\fi
\endgroup
%    \end{macrocode}
%
%
% \subsection{File Hooks}
% The \pkg{filehook} package is used to execute the macros at the correct places.
% However it must be loaded before the option processed because the |fink| compatibility
% code in |filehook-fink| will modify the option list.
% The internal interface, not the user-interface, is used to make sure that the file names are valid for all other hooks.
%
%    \begin{macrocode}
\filehook@prefixwarg\filehook@every@atbegin{%
  \currfile@push
  \currfile@set{#1}%
}
\filehook@appendwarg\filehook@every@atend{%
  \currfile@pop
}
%    \end{macrocode}
%
%
% \subsection{Set Current Values}
%
% \begin{macro}{\currfile@set}
% Sets the file information which are parsed by \LaTeX's \Macro\filename@parse.
%    \begin{macrocode}
\def\currfile@set#1{%
  \begingroup
    \edef\@tempa{#1}%
    \@onelevel@sanitize\@tempa
    \expandafter\filename@parse\expandafter{\@tempa}%
    \global\let\currfiledir\filename@area
    \global\let\currfilebase\filename@base
    \xdef\currfileext{\ifx\filename@ext\relax tex\else\filename@ext\fi}%
    \xdef\currfilename{\currfilebase\ifx\currfileext\empty\else.\currfileext\fi}%
    \xdef\currfilepath{\currfiledir\currfilename}%
  \endgroup
%<debug> \expandafter\gdef\expandafter\dindent\expandafter{\dindent\space}%
%<debug> \message{^^JDEBUG: \dindent\empty Entering file '\currfilename' ^^J }%
}
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{File Stack}
% The file information are pushed and popped on a stack to save and restore them when
% entering and leaving a sub-file, respectively. This is quite similar to the way 
% \LaTeX\ saves file base names and extension as well as the `@' status (letter or other) for
% package and class files.
%
% \begin{macro}{\currfile@push}
%    \begin{macrocode}
\def\currfile@push{%
  \xdef\currfile@stack{%
    {\currfiledir}%
    {\currfilebase}%
    {\currfileext}%
    \currfile@stack
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\currfile@pop}
%    \begin{macrocode}
\def\currfile@pop{%
%<debug> \message{^^JDEBUG: \dindent\empty Leaving file '\currfilename' ^^J }%
  \ifx\currfile@stack\empty
    \PackageWarning{currfile}{File stack underflow!}%
    \global\let\currfile@stack\currfile@stackinit
  \fi
  \expandafter\currfile@pop@\currfile@stack\relax
  \relax\relax\relax
%<debug> \message{^^JDEBUG: \dindent\empty Restoring file '\currfilename' ^^J }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\currfile@pop@}
%    \begin{macrocode}
\def\currfile@pop@#1#2#3#4\relax{%
  \gdef\currfiledir{#1}%
  \gdef\currfilebase{#2}%
  \gdef\currfileext{#3}%
  \xdef\currfilename{\currfilebase\ifx\currfileext\empty\else.\currfileext\fi}%
  \xdef\currfilepath{\currfiledir\currfilename}%
  \gdef\currfile@stack{#4}%
%<debug> \expandafter\expandafter\expandafter\gdef
%<debug> \expandafter\expandafter\expandafter\dindent
%<debug> \expandafter\expandafter\expandafter{\expandafter\@gobble\dindent}%
}
%    \end{macrocode}
% \end{macro}
%
% \iffalse
%<debug> \def\dindent{}
% \fi
%
% \begin{macro}{\currfile@stack}
% \begin{macro}{\currfile@stackinit}
% Place \Macro\jobname values on stack and use this as init value.
%    \begin{macrocode}
\def\currfile@stack{}
\currfile@set{\currfile@maindir\jobname.\currfile@mainext}
\currfile@push
\let\currfile@stackinit\currfile@stack
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
% \subsection{If Macros}
% \begin{macro}{\ifcurrfilename}
%    \begin{macrocode}
\newcommand*\ifcurrfilename{\begingroup\currfile@if\currfilename}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifcurrfilebase}
%    \begin{macrocode}
\newcommand*\ifcurrfilebase{\begingroup\currfile@if\currfilebase}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifcurrfileext}
%    \begin{macrocode}
\newcommand*\ifcurrfileext{\begingroup\currfile@if\currfileext}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifcurrfiledir}
%    \begin{macrocode}
\newcommand*\ifcurrfiledir{\begingroup\currfile@if\currfiledir}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifcurrfilepath}
%    \begin{macrocode}
\newcommand*\ifcurrfilepath{\begingroup\currfile@if\currfilepath}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifcurrfile}[1]{currfile macro or text}
% Expands and sanitizes the first argument and then calls the internal if-macro
% with the result.
%    \begin{macrocode}
\newcommand*\ifcurrfile[1]{%
    \begingroup
    \edef\@tempb{#1}%
    \@onelevel@sanitize\@tempb
    \currfile@if\@tempb
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\currfile@if}[2]{currfile macro to compare}{compare text}
% Expands the text and sanitize it to ensure correct neutral catcodes.
% Then it temp macro is compared to the given currfile macro.
%    \begin{macrocode}
\def\currfile@if#1#2{%
    \edef\@tempa{#2}%
    \@onelevel@sanitize\@tempa
    \ifx\@tempa#1%
        \endgroup
        \expandafter\@firstoftwo
    \else
        \endgroup
        \expandafter\@secondoftwo
    \fi
}
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{Fink Macros}
%
% The \pkg{fink} option defines all \pkg{fink} package macros to use the ones provided
% by this package. If the \pkg{fink} package was loaded beforehand the restoration
% of these macros must be avoided at the end of this file
% (\pkg{fink}s \Macro\InputIfFileExists was then used to load this package).
% If the package was not loaded its version is set to a dummy value and its
% options to this package options. If \pkg{fink} is attempted to be loaded later
% it will trigger an package option clash if different option are used.
% Otherwise it will be taken as already loaded and not loaded ``again''.
%
%    \begin{macrocode}
\ifcurrfile@fink
    \def\finkfile{\currfilename}%
    \def\finkdir{\currfiledir}%
    \def\finkpath{\currfilepath}%
    \def\finkbase{\currfilebase}%
    \def\finkext{\currfileext}%
    \@ifpackageloaded{fink}{%
        \def\fink@restore#1{}%
    }{%
        \@namedef{ver@fink.sty}{2011/01/09}%
        \expandafter\edef\csname opt@fink.sty\endcsname{%
            maindir=\currfile@maindir,mainext=\currfile@mainext
        }%
    }%
\else
    \@ifpackageloaded{fink}{}{%
        \AtBeginOfPackageFile{fink}{%
            \PackageError{currfile}{The 'fink' package is now deprecated. %
             Load 'currfile' with the 'fink' option or see the upgrade guide in the manual}{}%
        }%
    }%
\fi
%    \end{macrocode}
%
% \iffalse
%</package>
% \fi
% \Finale
\endinput
