1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
|
% \iffalse
%<*never>
\documentclass{ltxdoc}
\AtBeginDocument{\CodelineIndex\EnableCrossrefs}
\AtEndDocument{\PrintIndex}
\GetFileInfo{stack.cls}
\def\pack#1{\texttt{#1}}
\begin{document}
\def\docdate{2002/01/20}
\CheckSum{12}
\DocInput{stack.dtx}
\end{document}
%</never>
% \fi
% \iffalse
%
% (c) 2002 Benjamin BAYART. Freely redistributable under lppl.
%
% \fi
% \CheckSum{110}
% \DoNotIndex{\edef,\advance,\else,\csname,\endcsname,\expandafter}
% \DoNotIndex{\ifx,\fi,\input,\ifnum,\relax,\newcount,\romannumeral}
% \DoNotIndex{\the,\typeout,\xdef,\global,\newcommand,\RequirePackage}
% \DoNotIndex{\PackageError,\ProvidesPackage,\gdef}
%% \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 \~}
%
% \title{Using stacks independently from \TeX's one}
% \author{Benjamin \textsc{Bayart}}
% \date{\filedate}
% \maketitle
% \begin{abstract}
% This package is aimed to provide a new stack mechanisme independent
% from the \TeX\ stack itself. The first use was to have a system where
% |\input| become directory recursive. I.e.~to provide a kind of
% |\chdir| command: when you include a file ``\emph{a}'', it's directory become
% the current one, until the end of ``\emph{a}''. See the ``sample package''
% section for full explanation.
%
% This package by itself is of no use, except for some macro-developpers.
% \end{abstract}
% \tableofcontents
%
% \section{User's guide}
%
% \subsection{The \pack{stack} package}
%
% All of the macros provided by this package are supposed for
% package developpers (the is no meaning for a stack in a final
% document, only to be used in a package), so, all of those macros
% have capital letters in their names, following old guidelines
% for \LaTeX3 project.
%
% The first macro is the one to create a new stack:\newline
% \cs{NewStack}\marg{stack}\marg{default}\newline
% Well, it just initializes all the required data for the stack.
% \emph{default} is the value of the top of the stack if the stack is
% empty.
%
% The second one is the macro to push a new value on top of the
% stack:\newline
% \cs{Push}\marg{stack}\marg{value}\newline
%
% The third one is to remove the value on the top (i.e. to pop):\newline
% \cs{Pop}\marg{stack}
%
% Finally, the most usefull one is the command to obtain the value
% on the top of the stack:\newline
% \cs{Stack}\marg{stack}
%
% Another one is provided, but only for debugging purpose, it will
% |\typeout| the current value on the top of the stack:\newline
% \cs{ShowTop}\marg{stack}
%
% \subsection{The \pack{relinput} package}
%
% |relinput| provides only one macro which syntax is:\newline
% \cs{relinput}\marg{directory}\marg{file}.
%
% This will move the ``current directory'' into \emph{directory},
% from there include \emph{file}, and then go back to what was
% the current directory before you call the macro.
%
% A good way to understand it is to try to split a large document
% in a large number of files. Say a first level of directories
% for the parts, a second one for the chapters, a third one for
% the sections, and in each one a file per subsection.
%
% So, we will have this kind of directory tree:
% \begin{macrocode}
%<*never>
part-one/
part-one/thepart.tex
part-one/chapter-one/
part-one/chapter-one/thechapter.tex
part-one/chapter-one/section-one/
part-one/chapter-one/section-one/thesection.tex
part-one/chapter-one/section-one/subsec1.tex
part-one/chapter-one/section-one/subsec2.tex
part-one/chapter-one/section-two/
part-one/chapter-one/section-three/
part-one/chapter-two/
part-one/chapter-two/thechapter.tex
part-two/
part-two/thepart.tex
part-two/chapter-one/
part-two/chapter-one/thechapter.tex
% \end{macrocode}
%
% And so on.
%
% The main file only says:
% \begin{macrocode}
\relinput{part-one}{thepart.tex}
\relinput{part-two}{thepart.tex}
% \end{macrocode}
%
% The file |part-one/thepart.tex| states:
% \begin{macrocode}
\relinput{chapter-one}{thechapter.tex}
\relinput{chapter-two}{thechapter.tex}
% \end{macrocode}
%
% And so on for the other files, untill
% |part-one/chapter-one/section-one/thesection.tex| which says:
% \begin{macrocode}
\relinput{.}{subsec1.tex}
\relinput{.}{subsec2.tex}
%</never>
% \end{macrocode}
%
% With such a scheme, when you work on a chapter, you don't have to
% remember in which directory it is, and, even better, if you
% decide to rename the |chapter-one| directory to |introduction|
% you have only one file to modify.
%
% By using the usual \LaTeX\ mechanism you would have to edit the
% same file, plus all the files in this directory which include
% others (that's a rather large number of files).
%
% \section{Test file}
%
% The test application for |stack| is a ``relative dir input''. The basic
% macro is |\relinput| which takes two arguments: first a directory
% where to go (from the previous one) and then a file to include.
%
% In your main file (|./file.tex|) if you do |\relinput{dir}{file2.tex}|
% then \TeX\ will include |./dir/file2.tex|. If, in |file2|, you do
% |\relinput{dir2}{file3.tex}|, then, \TeX\ will include |./dir/dir2/file3.tex|.
%
% Really interesting if you have a large document with a lot of files
% in which case you can move a directory and have only minors corrections
% to do in a few files, and, anyway, no corrections in the files \emph{in}
% this directory, but only to files \emph{out} of the directory.
%
% This test file is provided as a small package |relinput|.
% \begin{macrocode}
%<*test>
\ProvidesPackage{relinput}[2002/01/20 v1.00 Relative input]
\RequirePackage{stack}
\NewStack{reldir}{.}
% \end{macrocode}
% \begin{macro}{\relinput}
% \begin{macrocode}
\newcommand\relinput[2]{%
\Push{reldir}{\Stack{reldir}/#1}%
\input{\Stack{reldir}/#2}%
\Pop{reldir}%
}
%</test>
% \end{macrocode}
% \end{macro}
%
% \StopEventually{}
%
% \section{Code for the \pack{stack} package}
%
% \subsection{Identification}
%
% \begin{macrocode}
%<*package>
\ProvidesPackage{stack}[2002/01/20 v1.0 Multi-stack system]
% \end{macrocode}
%
% \subsection{Macros by itself}
%
% In the following code, to use only one counter (in the \TeX\ meaning)
% we store the various values in macros, and use only the counter when
% we need to do computations.
%
% \begin{macro}{\tmp@stack}
% \begin{macrocode}
\newcount\tmp@stack
% \end{macrocode}
% \end{macro}
%
% Creating a new stack is, essentially, creating a new counter-like
% macro, initializing it to 0, and creating the macro for stack-top
% evaluation.
%
% \begin{macro}{\NewStack}
% This stack-top evaluation macro is required due to an ugly trick.
% During the push, we ``evaluate'' the value to push with an
% |\edef|, because one might want to push something which contain the
% previous top of the stack (see the example package provided).
% If the |\Stack| macro computes the real value on the top of the
% stack, then, the expanded definition in |\Push| will contain more
% or less the \emph{content} of |\Stack| and not the value.
%
% Another way would be to have a |\csname...\endcsname| pair within
% another one in an |\ifx| condition, which doesn't work.
%
% \begin{macrocode}
\newcommand\NewStack[2]{%
\expandafter\gdef\csname #1@count\endcsname{0}%
\expandafter\do@stack@macro\csname #1@count\endcsname{#1}{#2}%
}
\newcommand\do@stack@macro[3]{%
\expandafter\newcommand\expandafter*%
\csname stack@#2\endcsname{%
\expandafter\ifx\csname #2@\romannumeral#1\endcsname\relax
#3%
\else
\csname #2@\romannumeral#1\endcsname
\fi
}%
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\Stack}
% I'd rather remove the ``check'' code, but, well, it would suppose
% the end-user of the macro is a fair developper, which is not
% realistic.
%
% If the stack has been properly created, we call the top-stack evaluation
% macro.
%
% \begin{macrocode}
\newcommand\Stack[1]{%
\ifx\csname #1@count\endcsname\relax
\PackageError{stack}{Undefined stack #1}{You should first create the
stack with \NewStack}%
\else
\csname stack@#1\endcsname
\fi
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\Push}
% \begin{macro}{\Pop}
% The |\Push| macro is one of the most complex ones.
%
% First, we check if the stack is properly defined.
% \begin{macrocode}
\newcommand\Push[2]{%
\ifx\csname #1@count\endcsname\relax
\PackageError{stack}{Undefined stack #1}{You should first create the
stack with \NewStack}%
\else
% \end{macrocode}
%
% We store the new top-value in a macro, just because one might do
% |\Push{stack}{\Stack{stack}.ext}| in witch case the expansion of
% the value to push is something rather tricky.
%
% Then, we step the depth of the stack (put the depth in the scractch
% counter, advance this counter, have the value back in the macro).
%
% Only after that the value to be pushed is stored in the corresponding
% slot.
% \begin{macrocode}
\edef\stack@newtop{#2}%
\tmp@stack\csname #1@count\endcsname\relax
\global\advance\tmp@stack by 1\relax
\expandafter\xdef\csname #1@count\endcsname{\the\tmp@stack}%
\expandafter\xdef\csname #1@\romannumeral\tmp@stack\endcsname
{\stack@newtop}%
\fi
}
% \end{macrocode}
%
% The |\Pop| macro is more simple: if the stack is properly defined and
% the depth is more than zero, then down-step the depth.
% \begin{macrocode}
\newcommand\Pop[1]{%
\ifx\csname #1@count\endcsname\relax
\PackageError{stack}{Undefined stack #1}{You should first create the
stack with \NewStack}%
\else
\tmp@stack\csname #1@count\endcsname\relax
\ifnum\tmp@stack>0\relax
\advance\tmp@stack by -1\relax
\expandafter\xdef\csname #1@count\endcsname{\the\tmp@stack}%
\fi
\fi
}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% Now, a debug only macro.
% \begin{macro}{ShowTop}
% \begin{macrocode}
\newcommand\ShowTop[1]{%
{\edef\top{\Stack{#1}}%
\typeout{The top of #1: \top}}}
% \end{macrocode}
% \end{macro}
%
% That's all folks.
% \begin{macrocode}
%</package>
% \end{macrocode}
%
% \Finale
% \end{document}
|