% \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} % % \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} % % \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}% } % % \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} % % \end{macrocode} % % \Finale % \end{document}