summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/stack
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/stack
Initial commit
Diffstat (limited to 'macros/latex/contrib/stack')
-rw-r--r--macros/latex/contrib/stack/stack.dtx332
-rw-r--r--macros/latex/contrib/stack/stack.ins5
2 files changed, 337 insertions, 0 deletions
diff --git a/macros/latex/contrib/stack/stack.dtx b/macros/latex/contrib/stack/stack.dtx
new file mode 100644
index 0000000000..0cc0858073
--- /dev/null
+++ b/macros/latex/contrib/stack/stack.dtx
@@ -0,0 +1,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}
diff --git a/macros/latex/contrib/stack/stack.ins b/macros/latex/contrib/stack/stack.ins
new file mode 100644
index 0000000000..186e1432a3
--- /dev/null
+++ b/macros/latex/contrib/stack/stack.ins
@@ -0,0 +1,5 @@
+\input docstrip
+\keepsilent
+\generate{\file{stack.sty}{\from{stack.dtx}{package}}
+ \file{relinput.sty}{\from{stack.dtx}{test}}}
+\endbatchfile