The currfile Package
Martin Scharrer
[email protected] http://www.ctan.org/pkg/currfile
Version v0.5 – 2011/09/18
Abstract
This small package provides the file name and path information of the current input file as LATEX macros. It properly supports file name with multiple dots and the\input@pathfeature used by some packages likeimport.
1 Usage
\currfiledir
\currfilebase
\currfileext
\currfilename
\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 (\ttfamily,\texttt{...}), but other fonts can be used using theurlpackage, e.g.:\urlstyle{rm}\expandafter\nolinkurl\expandafter{\currfilename}. Special care is taken to keep the file information of\includedfiles till the final
\clearpagecommand, 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\input,\include,
\InputIfFileExists,\usepackage,\RequirePackageand even\LoadClassand similar macros. Before v0.2 only\inputor\includeand the main file were taken into account.
This package uses thefilehookpackage written by the same author. See there for possible incompatibilities with classes or other packages.
More detailed information can be found in the implementation section4if re- quired.
\ifcurrfiledir{〈text〉}{〈true〉}{〈false〉}
\ifcurrfilebase{〈text〉}{〈true〉}{〈false〉}
\ifcurrfileext{〈text〉}{〈true〉}{〈false〉}
\ifcurrfilename{〈text〉}{〈true〉}{〈false〉}
\ifcurrfilepath{〈text〉}{〈true〉}{〈false〉}
This if-macros allow the comparison of〈text〉with the current file directory, base, ex- New in v0.4
from 2011/01/09
tension, name and path, respectively. The〈text〉is fully expanded and sanitized for the
comparison. Example:\ifcurrfileext{cfg}{I’m in a config file}{No config file!}
\ifcurrfile{〈currfile macro or text〉}{〈text〉}{〈true〉}{〈false〉}
Compares the given〈currfile macro or text〉with〈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,ifthenelse) might not do this.
Package Options
The package provides two optionsmainextandmaindirwhich 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.dtxfile) or is not located in the current directory. To provide support for the macros defined by thefinkpackage (see section3) afinkoption exists.
2 Usage inside file hooks
This package uses the ‘EveryFile’ hooks of thefilehookpackage 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 ‘AtEndOf- PackageFile’ and ‘AtEndOfClassFile’ hooks are executed after ‘AtEndOfEveryFile’ and therefore thecurrfilemacros will hold the values of the parent file, not of that package or class file.
3 Compatibility with the fink package
Thefinkpackage (filenamekeeper) 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 filenameafter the\clearpageof\include. The author offinkis now discontinuing it in favour of this package. Existing documents which usefinkshould either rename the related macros as shown by Table1or use thefinkoption ofcurrfilewhich defines the finkmacros to use thecurrfileones.
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 thefinkpackage author this package will undo most of thefinkcode if it was already loaded or prevent it from being loaded afterwards.
Table 1: Conversion fromfinkpackage tocurrfile.
fink currfile Example Result
\finkdir \currfiledir
\finkbase \currfilebase currfile
\finkext \currfileext dtx
\finkfile \currfilename currfile.dtx
\finkpath \currfilepath currfile.dtx
4 Implementation
4.1 Package header
1 \N e e d s T e X F o r m a t{ L a T e X 2 e } [ 1 9 9 9 / 1 2 / 0 1 ]
2 \ P r o v i d e s P a c k a g e { c u r r f i l e }[%
3 % <! DATE >
4 % <! VERSION >
5 % <* DRIVER >
6 2 0 9 9 / 0 1 / 0 1 d e v e l o p
7 % </ DRIVER >
8 y d o c p a c k a g e to d e s c r i b e macros , e n v i r o n m e n t s , .
o p t i o n s etc .]
4.2 Options
9 \ R e q u i r e P a c k a g e { k v o p t i o n s }
10 \ S e t u p K e y v a l O p t i o n s { f a m i l y = c u r r f i l e , p r e f i x = c u r r f i l e @ }
11
12 \ @ i f p a c k a g e l o a d e d { f i n k }{%
13 \ D e c l a r e S t r i n g O p t i o n [\ f n k @ m a i n e x t ]{ m a i n e x t }%
14 \ D e c l a r e S t r i n g O p t i o n [\ f n k @ m a i n d i r ]{ m a i n d i r }%
15 \ D e c l a r e B o o l O p t i o n [ t r u e ]{ f i n k }%
16 \ P a c k a g e W a r n i n g { c u r r f i l e }{ D e p r e c a t e d p a c k a g e ’.
fink ’ d e t e c t e d . %
17 The ’ fink ’ o p t i o n w i l l d e f a u l t to ’ true ’ . ^ ^ J%
18 If set to ’ false ’ no ’ fink ’ m a c r o s w i l l be .
c h a n g e d but t h e y w i l l s t o p
19 w o r k i n g c o r r e c t l y !}%
20 }{%
21 \ D e c l a r e S t r i n g O p t i o n [ tex ]{ m a i n e x t }%
22 \ D e c l a r e S t r i n g O p t i o n [\ @ c u r r d i r ]{ m a i n d i r }%
23 \ D e c l a r e B o o l O p t i o n [ f a l s e ]{ f i n k }%
24 }%
25 \ D e c l a r e V o i d O p t i o n { f o r c e }{\ P a s s O p t i o n s T o P a c k a g e { f o r c e.
}{ f i l e h o o k }}
26 \ R e q u i r e P a c k a g e { f i l e h o o k } [ 2 0 1 1 / 0 1 / 0 9 ]
27 \ P r o c e s s K e y v a l O p t i o n s *\r e l a x
28
29 \b e g i n g r o u p
30 \x d e f\ c u r r f i l e @ m a i n e x t {\ c u r r f i l e @ m a i n e x t }%
31 \x d e f\ c u r r f i l e @ m a i n d i r {\ c u r r f i l e @ m a i n d i r }%
32 \def\ @ t e m p a { . / }%
33 \ifx\ @ t e m p a \ c u r r f i l e @ m a i n d i r
34 \g l o b a l\let\ c u r r f i l e @ m a i n d i r \e m p t y
35 \fi
36 \e n d g r o u p
4.3 File Hooks
Thefilehookpackage is used to execute the macros at the correct places. However it must be loaded before the option processed because thefinkcompatibility code infilehook-finkwill 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.
37 \ f i l e h o o k @ p r e f i x w a r g \ f i l e h o o k @ e v e r y @ a t b e g i n {%
38 \ c u r r f i l e @ p u s h
39 \ c u r r f i l e @ s e t { # 1 }%
40 }
41 \ f i l e h o o k @ a p p e n d w a r g \ f i l e h o o k @ e v e r y @ a t e n d {%
42 \ c u r r f i l e @ p o p
43 }
4.4 Set Current Values
\currfile@set
Sets the file information which are parsed by LATEX’s\filename@parse.
44 \def\ c u r r f i l e @ s e t #1{%
45 \b e g i n g r o u p
46 \e d e f\ @ f i l e f @ u n d { # 1 }%
47 \ifx\ i n p u t @ p a t h \ @ u n d e f i n e d \e l s e
48 \ c u r r f i l e @ c h e c k p a t h
49 \fi
50 \ @ o n e l e v e l @ s a n i t i z e \ @ f i l e f @ u n d
51 \let\ f i l e n a m e @ s i m p l e \ c u r r f i l e @ p a r s e e x t
52 \let\ f i l e n a m e @ b a s e \ @ g o b b l e
53 \e x p a n d a f t e r\ f i l e n a m e @ p a r s e \e x p a n d a f t e r{\.
@ f i l e f @ u n d }%
54 \g l o b a l\let\ c u r r f i l e d i r \ f i l e n a m e @ a r e a
55 \g l o b a l\let\ c u r r f i l e b a s e \ f i l e n a m e @ b a s e
56 \g l o b a l\let\ c u r r f i l e e x t \ f i l e n a m e @ e x t
57 \x d e f\ c u r r f i l e n a m e {\ c u r r f i l e b a s e \ifx\ c u r r f i l e e x t \.
@ e m p t y \e l s e.\ c u r r f i l e e x t \fi}%
58 \x d e f\ c u r r f i l e p a t h {\ c u r r f i l e d i r \ c u r r f i l e n a m e }%
59 \e n d g r o u p
60 % < debug > \ e x p a n d a f t e r \ g d e f \ e x p a n d a f t e r \ d i n d e n t \.
e x p a n d a f t e r {\ d i n d e n t \ s p a c e }%
61 % < debug > \ m e s s a g e {^^ J D E B U G : \ d i n d e n t \ e m p t y E n t e r i n g .
f i l e ’\ c u r r f i l e n a m e ’ ^^ J }%
62 }
\currfile@checkpath
This loop is placed in an own macro for efficiency reasons. In the majority of cases it should not be needed and having it as a macro avoids the need to skip over this code as part of a conditional clause for every read file.
63 \def\ c u r r f i l e @ c h e c k p a t h {%
64 \o p e n i n\ @ i n p u t c h e c k \ @ f i l e f @ u n d \r e l a x
65 \i f e o f\ @ i n p u t c h e c k
66 \e x p a n d a f t e r\ @ t f o r
67 \e x p a n d a f t e r\ @ t e m p b
68 \e x p a n d a f t e r:\e x p a n d a f t e r=\ i n p u t @ p a t h \do{%
69 \o p e n i n\ @ i n p u t c h e c k \ @ t e m p b \ @ f i l e f @ u n d \.
r e l a x
70 \i f e o f\ @ i n p u t c h e c k \e l s e
71 \e d e f\ @ f i l e f @ u n d {\ @ t e m p b \ @ f i l e f @ u n d }%
72 \ @ b r e a k @ t f o r
73 \fi
74 }%
75 \fi
76 \c l o s e i n\ @ i n p u t c h e c k
77 }
\currfile@parseext
Replacement for\filename@simpleto allow multiple dots in a filename. This needs
\let\filename@base\@gobblebefore it is called.
78 \b e g i n g r o u p
79 \ @ m a k e o t h e r {.}
80 \g d e f\ c u r r f i l e @ p a r s e e x t # 1 . # 2 \ \ {%
81 \ifx\ \ # 2 \ \%
82 \ifx\ f i l e n a m e @ b a s e \ @ g o b b l e
83 \def\ f i l e n a m e @ b a s e { # 1 }%
84 \let\ f i l e n a m e @ e x t \ c u r r f i l e @ d e f a u l t e x t%
85 \e l s e
86 \def\ f i l e n a m e @ e x t { # 1 }%
87 \fi
88 \e l s e
89 \e d e f\ f i l e n a m e @ b a s e {\ f i l e n a m e @ b a s e . # 1 }%
90 \def\ @ t e m p a {\ c u r r f i l e @ p a r s e e x t # 2 \ \ }%
91 \e x p a n d a f t e r\ @ t e m p a
92 \fi
93 }
94 \e n d g r o u p
\currfile@defaultext
Holds the default extension ‘tex’ with catcodeotherlike\jobname.
95 \def\ c u r r f i l e @ d e f a u l t e x t { tex }
96 \ @ o n e l e v e l @ s a n i t i z e \ c u r r f i l e @ d e f a u l t e x t
4.5 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.
\currfile@push
97 \def\ c u r r f i l e @ p u s h {%
98 \x d e f\ c u r r f i l e @ s t a c k {%
99 {\ c u r r f i l e d i r }%
100 {\ c u r r f i l e b a s e }%
101 {\ c u r r f i l e e x t }%
102 \ c u r r f i l e @ s t a c k
103 }%
104 }
\currfile@pop
105 \def\ c u r r f i l e @ p o p {%
106 % < debug > \ m e s s a g e {^^ J D E B U G : \ d i n d e n t \ e m p t y L e a v i n g .
f i l e ’\ c u r r f i l e n a m e ’ ^^ J }%
107 \ifx\ c u r r f i l e @ s t a c k \e m p t y
108 \ P a c k a g e W a r n i n g { c u r r f i l e }{ F i l e s t a c k u n d e r f l o w !}%
109 \g l o b a l\let\ c u r r f i l e @ s t a c k \ c u r r f i l e @ s t a c k i n i t
110 \fi
111 \e x p a n d a f t e r\ c u r r f i l e @ p o p @ \ c u r r f i l e @ s t a c k \r e l a x
112 \r e l a x\r e l a x\r e l a x
113 % < debug > \ m e s s a g e {^^ J D E B U G : \ d i n d e n t \ e m p t y R e s t o r i n g .
f i l e ’\ c u r r f i l e n a m e ’ ^^ J }%
114 }
\currfile@pop@
115 \def\ c u r r f i l e @ p o p @ # 1 # 2 # 3 # 4 \r e l a x{%
116 \g d e f\ c u r r f i l e d i r { # 1 }%
117 \g d e f\ c u r r f i l e b a s e { # 2 }%
118 \g d e f\ c u r r f i l e e x t { # 3 }%
119 \x d e f\ c u r r f i l e n a m e {\ c u r r f i l e b a s e \ifx\ c u r r f i l e e x t \.
e m p t y\e l s e.\ c u r r f i l e e x t \fi}%
120 \x d e f\ c u r r f i l e p a t h {\ c u r r f i l e d i r \ c u r r f i l e n a m e }%
121 \g d e f\ c u r r f i l e @ s t a c k { # 4 }%
122 % < debug > \ e x p a n d a f t e r \ e x p a n d a f t e r \ e x p a n d a f t e r \ g d e f
123 % < debug > \ e x p a n d a f t e r \ e x p a n d a f t e r \ e x p a n d a f t e r \ d i n d e n t
124 % < debug > \ e x p a n d a f t e r \ e x p a n d a f t e r \ e x p a n d a f t e r {\.
e x p a n d a f t e r \ @ g o b b l e \ d i n d e n t }%
125 }
\currfile@stack
\currfile@stackinit
Place\jobnamevalues on stack and use this as init value.
126 \def\ c u r r f i l e @ s t a c k {}
127 \ c u r r f i l e @ s e t {\ c u r r f i l e @ m a i n d i r \j o b n a m e.\.
c u r r f i l e @ m a i n e x t }
128 \ c u r r f i l e @ p u s h
129 \let\ c u r r f i l e @ s t a c k i n i t \ c u r r f i l e @ s t a c k
4.6 If Macros
\ifcurrfilename
130 \n e w c o m m a n d*\ i f c u r r f i l e n a m e {\b e g i n g r o u p\ c u r r f i l e @ i f \.
c u r r f i l e n a m e }
\ifcurrfilebase
131 \n e w c o m m a n d*\ i f c u r r f i l e b a s e {\b e g i n g r o u p\ c u r r f i l e @ i f \.
c u r r f i l e b a s e }
\ifcurrfileext
132 \n e w c o m m a n d*\ i f c u r r f i l e e x t {\b e g i n g r o u p\ c u r r f i l e @ i f \.
c u r r f i l e e x t }
\ifcurrfiledir
133 \n e w c o m m a n d*\ i f c u r r f i l e d i r {\b e g i n g r o u p\ c u r r f i l e @ i f \.
c u r r f i l e d i r }
\ifcurrfilepath
134 \n e w c o m m a n d*\ i f c u r r f i l e p a t h {\b e g i n g r o u p\ c u r r f i l e @ i f \.
c u r r f i l e p a t h }
\ifcurrfile
#1: currfile macro or text
Expands and sanitizes the first argument and then calls the internal if-macro with the result.
135 \n e w c o m m a n d*\ i f c u r r f i l e [ 1 ] {%
136 \b e g i n g r o u p
137 \e d e f\ @ t e m p b { # 1 }%
138 \ @ o n e l e v e l @ s a n i t i z e \ @ t e m p b
139 \ c u r r f i l e @ i f \ @ t e m p b
140 }
\currfile@if
#1: currfile macro to compare
#2: compare text
Expands the text and sanitize it to ensure correct neutral catcodes. Then it temp macro is compared to the given currfile macro.
141 \def\ c u r r f i l e @ i f # 1 # 2 {%
142 \e d e f\ @ t e m p a { # 2 }%
143 \ @ o n e l e v e l @ s a n i t i z e \ @ t e m p a
144 \ifx\ @ t e m p a #1%
145 \e n d g r o u p
146 \e x p a n d a f t e r\ @ f i r s t o f t w o
147 \e l s e
148 \e n d g r o u p
149 \e x p a n d a f t e r\ @ s e c o n d o f t w o
150 \fi
151 }
4.7 Fink Macros
Thefinkoption defines allfinkpackage macros to use the ones provided by this package. If thefinkpackage was loaded beforehand the restoration of these macros must be avoided at the end of this file (finks\InputIfFileExistswas 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. Iffinkis 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”.
152 \ i f c u r r f i l e @ f i n k
153 \def\ f i n k f i l e {\ c u r r f i l e n a m e }%
154 \def\ f i n k d i r {\ c u r r f i l e d i r }%
155 \def\ f i n k p a t h {\ c u r r f i l e p a t h }%
156 \def\ f i n k b a s e {\ c u r r f i l e b a s e }%
157 \def\ f i n k e x t {\ c u r r f i l e e x t }%
158 \ @ i f p a c k a g e l o a d e d { f i n k }{%
159 \def\ f i n k @ r e s t o r e # 1 { }%
160 }{%
161 \ @ n a m e d e f { v e r @ f i n k . sty } { 2 0 1 1 / 0 1 / 0 9 }%
162 \e x p a n d a f t e r\e d e f\c s n a m e o p t @ f i n k . sty \.
e n d c s n a m e{%
163 m a i n d i r =\ c u r r f i l e @ m a i n d i r , m a i n e x t =\.
c u r r f i l e @ m a i n e x t
164 }%
165 }%
166 \e l s e
167 \ @ i f p a c k a g e l o a d e d { f i n k } { } {%
168 \ A t B e g i n O f P a c k a g e F i l e { f i n k }{%
169 \ P a c k a g e E r r o r { c u r r f i l e }{ The ’ fink ’ .
p a c k a g e is now d e p r e c a t e d . %
170 L o a d ’ c u r r f i l e ’ w i t h the ’ fink ’ o p t i o n .
or see the u p g r a d e g u i d e in the .
m a n u a l }{}%
171 }%
172 }%
173 \fi