% \iffalse meta-comment % % esk.dtx - Encapsulated MetaPost for LaTeX(2e) % % Copyright (C) 2010 by Tom Kazimiers (tom@voodoo-arts.net) % % Esk is free software; you can redistribute it and/or modify it % under the terms of the GNU General Public License as published by % the Free Software Foundation; either version 2, or (at your option) % any later version. % % Esk is distributed in the hope that it will be useful, but % WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with this program; if not, write to the Free Software % Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. % % This project is greatly inspired and based on EMP. EMP is a LaTeX % package to provide a convenient way to work with metapost files and % code from inside LaTeX documents. % % \fi % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% \CheckSum{397} %% \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 \~} %% %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % \MakeShortVerb{\|} % % \title{% % \ESK: \\ % Encapsulated \SK{} for \LaTeX\thanks{% % This is \texttt{\filename}, version \fileversion, % revision \filerevision, date \filedate.}} % % \author{% % Tom Kazimiers\thanks{e-mail: % \texttt{tom@voodoo-arts.net}}} % % \maketitle % \begin{abstract} % The \ESK{} package allows to encapsulate \SK{} files in \LaTeX{} % sources. This is very useful for keeping illustrations in sync % with the text. It also frees the user from inventing descriptive % names for \LaTeX{} files that fit into the confines of file % system conventions. % \end{abstract} % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \vfill % \section*{Copying} % % \ESK{} is free software; you can redistribute it and/or modify it % under the terms of the GNU General Public License as published by % the Free Software Foundation; either version 2, or (at your option) % any later version. % % \ESK{} is distributed in the hope that it will be useful, but % \emph{without any warranty}; without even the implied warranty of % \emph{merchantability} or \emph{fitness for a particular purpose}. % See the GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with this program; if not, write to the Free Software % Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \newpage % \unitlength=1mm % \def\topfraction{0.9} % \def\bottomfraction{0.9} % \def\textfraction{0.1} % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \section{Introduction} % % When adding illustrations to documents, one faces two bookkeeping % problems: % \begin{itemize} % \item How to encourage oneself to keep the illustrations in sync % with the text, when the document is updated? % \item How to make sure that the illustrations appear on the right % spot? % \end{itemize} % For both problems, the best solution is to encapsulate the figures % in the \LaTeX{} source: % \begin{itemize} % \item It is much easier to remember to update an illustration if % one doesn't have to switch files in the editor. % \item One does not have to invent illustrative file names, if % the computer keeps track of them. % \end{itemize} % Therefore \ESK{} was written to allow to encapsulate % \SK{}~\cite{Sketch} into \LaTeX~\cite{LaTeX,Knuth}. It is based on % \texttt{emp}~\cite{emp} since it follows a similar approach for \MP{} % \cite{MP}. % Nevertheless, it is arguable that complex \SK{} figures may be easier % handled in a separate file. That is because it does not directly % improve readability for ones source code to have the \SK{} code mixed % with \LaTeX. But that's purely a matter of taste and complexity. To % have \SK{} code in separate files be included in your build process % you could do the following: % \begin{enumerate} % \item have your \SK{} code in a file, e.g. \emph{nice\_scene.sk} % \item include the file \emph{nice\_scene.sk.tex} in your document % source % \item configure your build in a way to automatically call \SK{} on all % \emph{\textasteriskcentered.sk} files, e.g in a Makefile:\newline % { |for i in `ls *.sk`; do sketch -o "$$i.tex" "$$i"; done| } % \end{enumerate} % At least for less complex graphics it is more convenient to use \ESK{} % and thus stay consistent more easily. % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \section{Usage} % % This chapter describes the different macros and environments provided % by the \ESK{} package. The |esk| environment is the one that actually % generates printable source code. Depending on what options have been % specified with |\eskglobals| and |\eskaddtoglobals| this is TikZ or % PSTricks code. If an |esk| environment is encountered, it gets % processed the following way: % \begin{enumerate} % \item \label{proc:gen_name}Create a file name for the current figure % out of the base name and a running figure number: % $\langle$\textit{name}$\rangle$.$\langle$\textit{number}$\rangle$.sk % (E. g. pyramid.1.sk) % \item \begin{enumerate} % \item \label{proc:tex_file_found} If a file exists that is named % like written in \ref{proc:gen_name} but with an additional % \textit{.tex} at the end (e.g. pyramid.1.sk.tex) it is % treated as a \SK{} processed result file. Thus, it is % included as a replacement for the environments content. % \item If such an item as in \ref{proc:tex_file_found} is not found % a \SK{} file with the contents of the environment is saved % to a file with the name generated in \ref{proc:gen_name}. % \end{enumerate} % \end{enumerate} % In contrast to \MP{} \SK{} can't produce different output files out of % one source file. This means every \SK{} figure has to be put into its % own \SK{} file. As a consequence one has to process all generated \SK % files with \SK and one can not have one generated file for the whole % document. A possible way of managing the build (within a Makefile) of % a document then could be: % \begin{enumerate} % \item Call |latex| on the document source % \item Process all \SK{} files and stick to naming convention:\newline % { |for i in `ls *.sk`; do sketch -o "$$i.tex" "$$i"; done| } % \item Call either |latex| and |dvips| or |pdflatex| on the document % source to actually see TikZ or PSTricks figures. % \end{enumerate} % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \subsection{Commands and Environments} % \label{sec:commands} % % \DescribeEnv{esk} % The |esk| environment contains the description of a single % figure that will be placed at the location of the environment. % The macro has two optional arguments. The first is the name of % the figure and defaults to |\jobname|. It is used as the base % name for file names. The second one consists of a comma separated % list of names previously defined with |\eskdef|. Note that the % names have to be put in parentheses (not brackets or braces). % Those definitions will be prepended to the \SK-commands. % \begin{quote} % \begin{flushleft} % |\begin{esk}[|\meta{name}|](|\meta{def 1}|,|\meta{def 2}|,...)|\\ % \qquad\meta{\SK-commands}\\ % |\end{esk}| % \end{flushleft} % \end{quote} % % \DescribeEnv{eskdef} % The |eskdef| environment acts as a container for \SK-commands. % In contrast to |esk| nothing is written to a file or drawn, but % kept in a token list register to recall it later on. Thus, % reoccurring patterns can be factored out and used as argument % in an |esk| environment. This is useful, because these % environments use the |verbatim| package and can therefore % \emph{not} be used directly as an argument to other macros. % \begin{quote} % \begin{flushleft} % |\begin{eskdef}{|\meta{name}|}|\\ % \qquad\meta{\SK-commands}\\ % |\end{eskdef}| % \end{flushleft} % \end{quote} % % \DescribeMacro{\eskprelude} % Define a \SK{} prelude to be written to the top of every \SK{} % file. The default is an empty prelude. Keep in mind that verbatim % arguments are not allowed. % % \DescribeMacro{\eskaddtoprelude} % Add to the \SK{} prelude. % E. g.~|\eskaddtoprelude{def O (0,0,0)}| makes sure the variable O % is available in all |esk| environments (and thus in every generated % \SK{} file). Of cause, this could also be achieved with |Eskimo|. % % \DescribeMacro{\eskglobals} % Define global \SK{} properties that get passed to the |global {...}| % method of \SK. This defaults to |language tikz|. % % \DescribeMacro{\eskaddtoglobals} % Add something to the global parameters of \SK. % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \subsection{Examples} % \label{sec:examples} % % For a simple example, let's draw a pyramid in a coordinate % system. Since our scene should be a composition of coordinate % axes and the geometry, we prepare definitions for the single % parts. In that way the parts will be reusable. First the % coordinate system: % \begin{macrocode} %<*sample> \begin{eskdef}{axes} def three_axes { % draw the axes def ax (dx,0,0) def ay (0,dy,0) def az (0,0,dz) line[arrows=<->,line width=.4pt](ax)(O)(ay) line[arrows=->,line width=.4pt](O)(az) % annotate axes special |\path #1 node[left] {$z$} #2 node[below] {$x$} #3 node[above] {$y$};|(az)(ax)(ay) } \end{eskdef} % \end{macrocode} %\begin{eskdef}{axes} def three_axes { % draw the axes def ax (dx,0,0) def ay (0,dy,0) def az (0,0,dz) line[arrows=<->,line width=.4pt](ax)(O)(ay) line[arrows=->,line width=.4pt](O)(az) % annotate axes special |\path #1 node[left] {$z$} #2 node[below] {$x$} #3 node[above] {$y$};|(az)(ax)(ay) } %\end{eskdef} % Now the pyramid: % \begin{macrocode} \begin{eskdef}{pyramid} def pyramid { def p0 (0,2) def p1 (1.5,0) def N 4 def seg_rot rotate(360 / N, [J]) % draw the pyramid by rotating a line about the J axis sweep[fill=red!20, fill opacity=0.5] { N<>, [[seg_rot]] } line[cull=false,fill=blue!20,fill opacity=0.5](p0)(p1) } \end{eskdef} % \end{macrocode} %\begin{eskdef}{pyramid} def pyramid { def p0 (0,2) def p1 (1.5,0) def N 4 def seg_rot rotate(360 / N, [J]) % draw the pyramid by rotating a line about the J axis sweep[fill=red!20, fill opacity=0.5] { N<>, [[seg_rot]] } line[cull=false,fill=blue!20,fill opacity=0.5](p0)(p1) } %\end{eskdef} % In the definitions some variable have been used that have % not been declared so far (|O|, |dx|, |dy|, |dz|, |J|). They have % been introduced to make the definitions more versatile. In % order to draw the scene their declaration has to be prepended % to our output: % \begin{macrocode} \eskaddtoprelude{def O (0,0,0)} \eskaddtoprelude{def dx 2.3} \eskaddtoprelude{def dy 2.5} \eskaddtoprelude{def dz dx} \eskaddtoprelude{def J [0,1,0]} % \end{macrocode} %\eskaddtoprelude{def O (0,0,0)} %\eskaddtoprelude{def dx 2.3} %\eskaddtoprelude{def dy 2.5} %\eskaddtoprelude{def dz dx} %\eskaddtoprelude{def J [0,1,0]} % % Now the previously created definitions can be used to do the % actual drawing. First, the coordinate system on its own: %\begin{center} %\begin{esk}(axes) def scene { {three_axes} } put { view((10,4,2)) } {scene} %\end{esk} %\end{center} % \begin{macrocode} \begin{esk}(axes) def scene { {three_axes} } put { view((10,4,2)) } {scene} \end{esk} % \end{macrocode} % Now the pyramid (note, the transparency effect will only be % visible in a pdf): %\begin{center} %\begin{esk}(pyramid) def scene { {pyramid} } put { view((10,4,2)) } {scene} %\end{esk} %\end{center} % \begin{macrocode} \begin{esk}(pyramid) def scene { {pyramid} } put { view((10,4,2)) } {scene} \end{esk} % \end{macrocode} % Finally both: %\begin{center} %\begin{esk}(axes,pyramid) def scene { {three_axes} {pyramid} } put { view((10,4,2)) } {scene} %\end{esk} %\end{center} % \begin{macrocode} \begin{esk}(axes,pyramid) def scene { {pyramid} {three_axes} } put { view((10,4,2)) } {scene} \end{esk} % % \end{macrocode} % With permission of Kjell Magne Fauske, the source code for this % example scene has been taken from \cite{Fauske}. % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \begin{thebibliography}{99} % \bibitem{Sketch} Eugene K. Ressler, Sketch, 2010/04/24, % http://www.frontiernet.net/~eugene.ressler/ % \bibitem{LaTeX} Leslie Lamport, \textit{\LaTeX{} --- A % Documentation Preparation System}, % Addison-Wesley, Reading MA, 1985. % \bibitem{Knuth} Donald E. Knuth, \textit{The \TeX book}, % Addison-Wesley, 1996 % \bibitem{emp} Thorsten Ohl, \texttt{emp},Encapsulated MetaPost, % 1997, available from CTAN % \bibitem{MP} John D.~Hobby, \textit{A User's Manual for % \MP}, Computer Science Report \#162, AT\&T Bell % Laboratories, April 1992. % \bibitem{Fauske} Kjell Magnus Fauske, An introduction to Sketch, % 2010/04/24, http://www.fauskes.net/nb/introduction-to-sketch/ % \end{thebibliography} % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \section*{Distribution} % \label{sec:distribution} % % \ESK{} is available by anonymous internet ftp from any of the % Comprehensive \TeX{} Archive Network (CTAN) hosts % \label{pg:CTAN} % \begin{quote} % |ftp.tex.ac.uk|, |ftp.dante.de| % \end{quote} % in the directory % \begin{quote} % |macros/latex/contrib/esk| % \end{quote} % It is available from host % \begin{quote} % |www.voodoo-arts.net| % \end{quote} % in the directory % \begin{quote} % |pub/tex/esk| % \end{quote} % A work in progress under git control is available from % \begin{quote} % |http://github.com/tomka/esk| % \end{quote} % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \StopEventually{\PrintIndex\PrintChanges} % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \section{Implementation} % \changes{v1.0}{2010/05/05}{Version 1.0 Release} % % This project is greatly inspired and based on EMP. EMP is a LaTeX package % to provide a convenient way to work with metapost files and code from % inside LaTeX documents. % % \iffalse meta-comment %% TeX hints: %% - @ is considered a normal letter in packages and classes %% - There are 256 32Bit \count registers (i.e. \count0=42), %% can be expanded with \the (i.e. \the\count0) %% - \relax ends scanning for tokens %% (i.e. \count0=\macro 42 <> \count0=\macro\relax 42) %% - A macro defined with can has a maximum of 9 arguments %% - \gdef is shortcut for \global\def %% \xdef is shortcut for \global\edef %% - \string<\macro> returns the "macro" (the name of a macro) %% Doc hints: %% - There must be _exactly_ four spaces between the "%" and the %% "\begin{macrocode}" or "\end{macrocode}. Otherwise, Doc %% won't detect the end of the code fragment. %% - The lines of code withen \begin{macrocode}...\end{macrocode} %% get written exactly as is to the .ins file, with no %-stripping. % \fi % % It's is good practice to identify this version of the document style % option. We do this by parsing an RCS |Id| string and storing the % result in the conventional \TeX{} control sequences. The parsing macro % is only visible locally (within the surrounding scope), but generated % control sequences like |\filename| are defined globally (due to the % use of |\gdef|): % \begin{macrocode} %<*style> \def\fileversion{v1.0} {\def\RCS#1#2\endRCS{% % is the first parameter a "$%? \ifx$#1% \@RCS $#2 \endRCS \else \@RCS $*: #1#2$ \endRCS \fi}% \def\@RCS $#1: #2,v #3 #4 #5 #6 #7$ \endRCS{% % global defines (independent of current scope) of file attributes \gdef\filename{#2}% \gdef\filerevision{#3}% \gdef\filedate{#4}% \gdef\filemaintainer{#6}}% \RCS $Id: esk.dtx,v 1.0 2010/05/05 01:23:42 kazimiers Exp $ \endRCS}% % \end{macrocode} % Make clear what LaTeX version is needed: % \begin{macrocode} \NeedsTeXFormat{LaTeX2e} % \end{macrocode} % And now the standard procedure: % \begin{macrocode} \ProvidesPackage{esk}[\filedate\space\fileversion\space Encapsulated Sketch LaTeX Package (\filemaintainer)] % \end{macrocode} % We do not declare options for this package, so we do not need to % invoke processing for found ones. Some other packages needed by % \ESK{}, partly of a minimum version, get specified. % \begin{macrocode} \RequirePackage{verbatim} \RequirePackage{kvsetkeys}[2007/09/29] % \end{macrocode} % The characters "\%", "\{" and "\}" are somewhat special to \TeX. More % precisely are they used for comments and grouping respectively. \SK{} % uses them as well, for the same purposes. To allow convenient code % generation by using macros to produce the symbols, three macros get % defined: % \begin{macro}{\p@rcent} % That macro is used for creating comments. The \% sign is locally % defined as a common letter (category code 11) and create a global macro % using it. The |@| in the name of the control sequence makes it only visible % from inside the % package\footnote{see http://de.wikibooks.org/wiki/LaTeX-Wörterbuch:\_\@}. % \begin{macrocode} {\catcode`\%=11\gdef\p@rcent{%}} % \end{macrocode} % \end{macro} % % \begin{macro}{\lc@rly} % \begin{macro}{\rc@rly} % Curly braces are used for scope and group definitions in \SK. Just like % with the |\p@rcent| macro, we need to make them a common letter. % Unfortunately we need the curly braces to define a local scope for \TeX. % To come around this the characters $>$ and $<$ are locally defined to % be grouping characters (category code 1). To allow normal scope closing % we finally make the curly braces grouping characters again. % \begin{macrocode} {\catcode`\>=1 \catcode`\<=2 \catcode`\{=11 \catcode`\}=11 \gdef\lc@rly>{< \gdef\rc@rly>}< \catcode`\{=1 \catcode`\}=2 } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\eskwrite} % Define a macro to write the contents of its first argument to a file. % If the Boolean toggle |@eskio| is set to true, the passed argument is % written\footnote{see http://www.tug.org/utilities/plain/cseq.html\#write-rp} % out to the file referenced in |@outesk|. Normally \TeX{} does the % actual writing during a |\shipout| operation, but we force it to do it % immediately\footnote{see http://www.tug.org/utilities/plain/cseq.html\#immediate-rp}. % All directly following spaces on the input will be % eaten\footnote{see http://en.wikibooks.org/wiki/TeX/ignorespaces}. % \begin{macrocode} \def\eskwrite#1{% \if@eskio \immediate\write\@outesk{#1}% \fi \ignorespaces} % \end{macrocode} % \end{macro} % % \begin{macro}{\eskwritetoken} % If a token list register should be put into a file, this macro should % be used. It will expand the token variable to its current contents. % \begin{macrocode} \def\eskwritetoken#1{ \eskwrite{\the#1}} % \end{macrocode} % \end{macro} % % Next a new private Boolean toggle is defined. It is used to reflect if % file writing is enabled and set it to true. % \begin{macrocode} \newif\if@eskio \@eskiotrue % \end{macrocode} % % The next free output file handle will be referenced by the private macro % |\@outesk|. At this point no file is opened, but just an output channel % defined\footnote{see \textit{A TEX primer for scientists} by Stanley % A. Sawyer,Steven George Krantz on p. 283}. An example file open could now % look like: |\openout\@outesk=TEXTFILE.TXT|. % \begin{macrocode} \newwrite\@outesk % \end{macrocode} % % \begin{macro}{\eskfile} % This environment encloses each \SK{} input file. The single optional % argument gives the name of the file and defaults to |\jobname|. This will % probably not be used explicitly when defining esk figures. It is invoked % automatically with an appropriate name for a figure. The macro |\theeskfile| % gets locally defined and stores the base name for a file. % \begin{macrocode} \newcommand{\eskfile}[1][\jobname]{% \def\theeskfile{#1}% % \end{macrocode} % Open the Sketch file. If output is enabled, check if we're running under % AMS-\LaTeX{} and if that is the case turn off I/O during the first pass over % equation environments. This is done by looking for |\ifmeasuring@| of % AMS-\LaTeX{} and, if found, replacing all |\if@eskio| checks with it. % \begin{macrocode} \if@eskio \@ifundefined{ifmeasuring@}% {}% {\def\if@eskio{\ifmeasuring@\else}}% % \end{macrocode} % A a new output file is linked to our |\@outesk| file number. The name of that % file is the content of |\theeskfile| with extension \textit{.sk}. Afterwards % a start comment is written to the new file. % \begin{macrocode} \immediate\openout\@outesk=\theeskfile.sk\relax \eskwrite{\p@rcent\p@rcent\p@rcent\space \theeskfile.sk -- % do not edit, generated automatically by \jobname.tex}% % \end{macrocode} % The |esk@prelude| token list register stores a prelude that should be put at % the beginning of the new file. If the register is empty, the expansion of it % (|\the\esk@prelude|) will be empty. This means the |\ifx| condition is met, % because the actual check is now if |*| equals |*|. Hence the |\else| branch % will \emph{not} be called. If the token register is not empty (and does not % start with an asterisk) the |\else| branch is used.. % \begin{macrocode} \expandafter\ifx\expandafter*\the\esk@prelude*\else \eskwrite{\the\esk@prelude}% \fi \fi} % \end{macrocode} % % Define |\theeskfile|, later redefined with the name of the currently opened % file, to be |\relax| (i.e. stop reading tokens). This should be the value % if no file is opened. % \begin{macrocode} \let\theeskfile\relax % \end{macrocode} % Define a new counter |\eskfig| to count the single esk figures. It is % initialized with 0. % \begin{macrocode} \newcounter{eskfig} % \end{macrocode} % % Let \TeX{} create a new token list register alias |\esk@prelude|. It stores % an optional prelude for the files written out. If the indirect alias % creation |\newtoks| is used, \TeX{} selects a free register and hides the % technical detail from us. % \begin{macrocode} \newtoks\esk@prelude % \end{macrocode} % \end{macro} % % \begin{macro}{\eskprelude} % \begin{macro}{\eskaddtoprelude} % Define a public |\eskprelude| macro that replaces the contents of the % internal token list register |\esk@prelude| with the argument passed. % \begin{macrocode} \def\eskprelude#1{\esk@prelude={#1}} % \end{macrocode} % Define a public macro that appends its argument to the internal % |\esk@prelude| token list register. The text is added on a new line. % This is accomplished by using |^^J|, a replacement ASCII representation % for LF (line feed)\footnote{e.g. see: http://www.torsten-horn.de/techdocs/ascii.htm}. % \begin{macrocode} \def\eskaddtoprelude#1{\esk@prelude=\expandafter{\the\esk@prelude^^J#1}} % \end{macrocode} % \end{macro} % \end{macro} % % The token list register storing the global settings of \SK{} is called % |\esk@globals| and defaults to \emph{language tikz}. % \begin{macrocode} \newtoks\esk@globals \esk@globals={language tikz} % \end{macrocode} % % \begin{macro}{\eskglobals} % \begin{macro}{\eskaddtoglobals} % The macros |\eskglobals| and |\eskaddtoglobals| are there to set and % modify the private token list register |\esk@globals|. With them one % has control over the general settings of \SK. On adding, new settings % will be delimited by a comma. % \begin{macrocode} \def\eskglobals#1{\esk@globals={#1}} \def\eskaddtoglobals#1{\esk@globals=\expandafter{\the\esk@globals,#1}} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\endeskfile} % And here is how the |empfile| environment is closed. If there are % global settings they are written out. The last line of the generated % file will be an end statement in form of a comment. followed by a line % break. As a convention the macro keeping the base name of the file, % |\theeskfile|, is set to |\relax|. That indicates that no file is open. % To make that true, the currently opened file (if any) is finally % closed. % \begin{macrocode} \def\endeskfile{% \expandafter\ifx\expandafter*\the\esk@globals*\else \eskwrite{global \lc@rly\the\esk@globals\rc@rly }% \fi \eskwrite{\p@rcent\p@rcent\p@rcent\space the end.^^J}% \let\theeskfile\relax \if@eskio \immediate\closeout\@outesk \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\esk} % The |esk| environment encloses \SK{} code that will be put into a file % for being later processed by \SK. First it (re-)defines the macro % |\esk@@name| with the environments argument. That argument is used as % the base name for the corresponding file and defaults to |\jobname|. % Then the internal macro |\esk@| produces a single esk graphic. % \begin{macrocode} \newcommand{\esk}[1][\jobname]{% \def\esk@@name{#1}% \esk@} % \end{macrocode} % \end{macro} % % Since the |esk| environment allows two optional parameters and only % one can have brackets, the second parameter is surrounded by parentheses. % A macro for an opening parenthesis is defined: % \begin{macrocode} \let\leftparanthesis=( % \end{macrocode} % % \begin{macro}{\esk@} % The private |\esk@| macro stores the immediately following token in % the macro |\next| and invokes |\esk@impl|. % \begin{macrocode} \def\esk@{ \futurelet\next\esk@impl} % \end{macrocode} % \end{macro} % % \begin{macro}{\esk@impl} % Now that the following token is known in |\next| it is checked % if the second optional argument got passed. This is done by testing % if the next token is an opening parenthesis and depending on its % occurrence |\esk@impl@Arg| or |\esk@impl@NoArg| is invoked. Since % we want to work with the content of the environment verbatim, we % have to get rid of |\else| and |\fi| in the input stream. This % can be achieved by just expanding them before calling the verbatim % handling macros with |\expandafter|. % \begin{macrocode} \def\esk@impl{% \ifx\next\leftparanthesis \expandafter\esk@impl@Arg \else \expandafter\esk@impl@NoArg \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\esk@impl@NoArg} % \begin{macro}{\esk@impl@Arg} % The macro |\esk@impl@NoArg| just calls |\esk@impl@Arg| with an % empty argument. It is mainly there for readability. % \begin{macrocode} \def\esk@impl@NoArg{\esk@impl@Arg()} % \end{macrocode} % The following macro, |\esk@impl@Arg|, expects one argument % surrounded by parentheses, namely a list of |eskdef| names. % It makes sure some preconditions are met by invoking |\esk@start|. % Afterwards |\esk@includegraphics| checks if a \SK{} file should % be generated or a \LaTeX{} file be included. Finally the argument % is parsed as a comma separated list to call |\esk@def@processor| % for each element found and the actual \SK{} code verbatim % processing is started with |\esk@cmds|. As the verbatim line % processing macro name "eskwritetoken" is passed as an argument. % \begin{macrocode} \def\esk@impl@Arg(#1){% \esk@start% \esk@includegraphics{\theeskfile}% \comma@parse{#1}{\esk@def@processor}% \esk@cmds{eskwritetoken}} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{esk@def@processor} % The macro |\esk@def@processor| gets expanded for every element % of the second optional argument of the |esk| environment. Here % every |eskdef| name of that list will be included in the current % file by invoking |\eskuse| for it. % \begin{macrocode} \def\esk@def@processor#1{ \esk@use{#1}} % \end{macrocode} % \end{macro} % % \begin{macro}{\esk@start} % A macro for preparing for a new \SK{} figure. % \begin{macrocode} \def\esk@start{% % \end{macrocode} % We can't use |\stepcounter| because of the |amstext| option of % AMS-\LaTeX{} disables it sometimes. Instead we globally advance % the eskfig counter manually by one. Afterwards we call % |\esk@checkfile| to make sure a file is open. Finally we invoke % |\esk@@def| with our previously defined temporary esk file name % to generate new |\theeskfile| and |\theeskfig| alias macros for % the current figure. % \begin{macrocode} \global\expandafter\advance\csname c@eskfig\endcsname \@ne \esk@checkfile \esk@@def{\esk@@name}} % \end{macrocode} % \end{macro} % % \begin{macro}{\esk@checkfile} % Make sure that a Sketch file is open, otherwise \emph{really} % obscure error messages are possible. This is done by checking % if |\theeskfile| is the same as |\relax| (as defined during % initialization and file closing). If so, try to open a file % (again) and do the test again. If it still fails print and % produce an error. % \begin{macrocode} \def\esk@checkfile{% \ifx\theeskfile\relax \eskfile[\esk@@name.\arabic{eskfig}] \fi \ifx\theeskfile\relax \errmessage{Could not open file "\esk@@name.\arabic{eskfig}.sk"!} \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\esk@includegraphics} % If a file having \emph{.sk.tex} added to the base name exists % this macro will include it. To start a new paragraph if we are % in vertical mode and switch to horizontal mode |\leaveemode| % is called at the beginning. Then, if the file exists, pass its % name as an argument to |\input| (which expects the file to end % with \emph{.tex}). If there is no such file a message is typed % out to tell the user that the sketch files might need the actual % processing. % \begin{macrocode} \def\esk@includegraphics#1{% \leavevmode \IfFileExists{#1.sk.tex}% {\input{#1.sk.tex}}% {\typeout{% esk: File #1.sk.tex\space not found:^^J% esk: Process #1.sk with Sketch (-o #1.sk.tex) and then % reprocess this file.}}} % \end{macrocode} % \end{macro} % % \begin{macro}{\esk@cmds} % The macro |\esk@cmds| gets the |esk| environments content by % using the verbatim package. Each line is processed by a macro % which name is passed as an argument. That is done to reuse % the macro for |esk| and |eskdef| environments. The macros % in use for the line processing are |eskwrite| and % |esk@def@verb@proc| respectively. Due to the use of % |\begingroup| \TeX{} enters a group that has to be terminated % by |\endgroup| and not by \}. % \begin{macrocode} \newcommand{\esk@cmds}[1]{% \begingroup % \end{macrocode} % The macros |\@bsphack| ... |\@esphack| are used by macros such as % |\index| and |\begin{@float}| ... |\end{@float}| that want to be % invisible -- i.e. not leave any extra space when used in the % middle of text. Such a macro should begin with |\@bsphack| and % end with |\@esphack|. The macro in question should not create any % text, nor change the mode. % \begin{macrocode} \@bsphack % \end{macrocode} % The next thing to do is to defuse \LaTeX{}' special characters: % |\dospeciels| expands to a list of special characters of the form % |\do\ \do\\ \do\{ \do\}|.... If one (re-)defines the "|\do|" macro % one can execute a macro on all of them. In our case we define % |\do| to be |\@makeother|. That assigns category code 12 % (non-letter) to all special characters, thus they get normal % characters without any special meaning. Due to the environment % those changes are local. % \begin{macrocode} \let\do\@makeother\dospecials % \end{macrocode} % |^^M| is the ASCII representation of CR (carriage return). With % the following line we make it an active character. Thus a macro % with the name |^^M| can now be defined. % \begin{macrocode} \catcode`\^^M\active % \end{macrocode} % Since we use the verbatim package |\verbatim@processline| is called % after each line. We redefine it to do what we would like it to do: % Process the line with the macro with the name passed as argument.. % The current line is available in |\verbatim@line|, a token register % \footnote{see: Latex hacks by Anselm Lingnau, p. 43 }. % \begin{macrocode} \def\verbatim@processline{\csname#1\endcsname{\verbatim@line}}% % \end{macrocode} % Enter the real verbatim mode. From here on \emph{all} characters % have lost their special meaning (if they had any). % \begin{macrocode} \verbatim@start}% % \end{macrocode} % \end{macro} % % \begin{macro}{\endesk@cmds} % To end the invisible environment and the group started by % |\esk@cmds|, this macro has to be used. % \begin{macrocode} \def\endesk@cmds{% \@esphack \endgroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\endesk} % This macro triggers the termination of the verbatim reading and % closes the current file. % \begin{macrocode} \def\endesk{% \endesk@cmds \endeskfile} % \end{macrocode} % \end{macro} % % \begin{macro}{\eskdef} % An |eskdef| environment allows to store blocks of \SK{} code in % token list registers for using them in |esk| environments. The % macro has one parameter, the name of the definition. First a % private and local name for the new block is defined. Then % |\esk@def| checks if the name is already there and does the % rest. %% \iffalse TODO: Make it more robust by remembering old name %% and setting it back afterwards (if any), so it can %% be used in esk environments \fi % \begin{macrocode} \newcommand{\eskdef}[1]{% %% Define a new name \def\esk@@def@name{esk@def:#1}% \esk@def} % \end{macrocode} % \end{macro} % % \begin{macro}{\esk@def} % The |\esk@def| macro relies on |\esk@@def@name| being defined % previously. At the beginning it checks if that name is already % registered by looking for a control sequence with the defined % name. If so, an error message is produced. % \begin{macrocode} \def\esk@def{% \expandafter\ifcsname\esk@@def@name\endcsname \errmessage{"\esk@@def@name" is already defined!} \fi % \end{macrocode} % If a new |eskdef| name is given a new token list register is % created and named like the expansion of |\esk@@def@name|. It % is not necessary to tell \TeX{} that the new register will be % global, because \emph{new...} tokens act always globally. % Unfortunately |\newtoks| is an |\outer| macro and we use the % wrapper |\tok@newtoks| (see below) to call it. % \begin{macrocode} \expandafter\tok@newtoks\csname\esk@@def@name\endcsname % \end{macrocode} % Create or override a global definition |\esk@@def@reg| % containing our new token register. Unfortunately, this works only % with a global definition. Afterwards the verbatim reading of the % environment is started with a different verbatim line processor as % before. Finally the macro ends with removing the previously % defined alias for the new token list register. % \begin{macrocode} \global\edef\esk@@def@reg{\csname\esk@@def@name\endcsname} \esk@cmds{esk@def@verb@proc}} \global\def\esk@@def@reg{} % \end{macrocode} % \end{macro} % % \begin{macro}{\esk@def@verb@proc} % The verbatim line processor for the |eskdef| environment first % creates a local alias for the new token list register. This is % done to make the code more readable. % \begin{macrocode} \def\esk@def@verb@proc#1{% \expandafter\let\expandafter\token@reg\esk@@def@reg % \end{macrocode} % If the token list register is empty it is filled with the % current verbatim line. % \begin{macrocode} \expandafter\ifx\expandafter*\the\token@reg* \global\esk@@def@reg=\expandafter{\the#1} % \end{macrocode} % If not, the verbatim line is appended on a new line. % \begin{macrocode} \else \global\esk@@def@reg=\expandafter{% \the\expandafter\token@reg\expandafter^^J\the#1} \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\endeskdef} % On ending an |eskdef| environment |\endeskdef| is expanded. Here, % its only purpose is to invoke the macro ending the verbatim % input environment. % \begin{macrocode} \def\endeskdef{ \endesk@cmds} % \end{macrocode} % \end{macro} % % \begin{macro}{\esk@@def} % A macro which takes a file name as argument to globally define % new macros |\esk@k:f:| and |\esk@k:c:| which expand % to |\theeskfile| and |\theeskfig| respectively. % \begin{macrocode} \def\esk@@def#1{% \global\e@namedef{esk@k:f:#1}{\theeskfile}% \global\e@namedef{esk@k:c:#1}{\theeskfig}} % \end{macrocode} % \end{macro} % % \begin{macro}{\e@namedef} % A macro which defines a new macro with the name of the % argument. This is done in use of |\expandafter| and % |\csname|...|\endcsname|. The new macro expands to the % following group, i.e. the new macros body. Due to the % use of |\edef| this happens dynamically. % \begin{macrocode} \def\e@namedef#1{% \expandafter\edef\csname #1\endcsname} % \end{macrocode} % \end{macro} % % \begin{macro}{\esk@use} % The |\esk@use| macro appends an \ESK{} \SK{} code definition % defined by |\eskdef|, into the currently defined file. After % creating an alias macro for the argument passed is is made % sure that the definition actually exists. If not an error % message is produced. If there is a token list register, named % like passed as argument, a short describing comment is written. % Further, the register is written as token to the file. The % file writing is finished with a new line. % \begin{macrocode} \def\esk@use#1{% \def\esk@@def@name{esk@def:#1}% \expandafter\ifcsname\esk@@def@name\endcsname \eskwrite{\p@rcent\p@rcent\space included definition: #1}% \expandafter\eskwritetoken\expandafter{% \expandafter\csname\esk@@def@name\endcsname} \eskwrite{^^J} \else \errmessage{esk: "#1" is undefined!} \fi } % \end{macrocode} % \end{macro} % % \begin{macro}{\tok@newtoks} % Since |\newtoks| is an |\outer| macro, it is not allowed in definitions. % Because we are in the need of creating token list registers on the % fly, we define a wrapper. It lets \TeX{} construct the |\newtoks| call: % \begin{macrocode} \def\tok@newtoks{ \csname newtoks\endcsname} % \end{macrocode} % \end{macro} % % % \begin{macro}{\futurespacelet} % A special version of the |\futurelet| macro. It is taken from Donald. E. % Knuths \emph{\TeX{}book} and behaves like |\futurelet|, but ignores spaces. % \begin{macrocode} \def\futurenospacelet#1{\def\cs{#1}% \afterassignment\stepone\let\nexttoken= } % \end{macrocode} % Let |\stoken| be a space token: % \begin{macrocode} \def\\{\let\stoken= } \\ % \end{macrocode} % And define the stepwise look-ahead macros: % \begin{macrocode} \def\stepone{\expandafter\futurelet\cs\steptwo} \def\steptwo{\expandafter\ifx\cs\stoken\let\next=\stepthree \else\let\next=\nexttoken\fi \next} \def\stepthree{\afterassignment\stepone\let\next= } % % \end{macrocode} % \end{macro} % \Finale % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \appendix % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \section{Driver File} % % \begin{macrocode} %<*driver> \documentclass[a4paper]{article} \usepackage{doc} \usepackage{amsmath} % \end{macrocode} % The logos would come out much nicer if |mflogo| would support some % more letters (i.e. k and K). We don't have that and so we define % the logos the following way: % \begin{macrocode} \def\ESK{\textsf{ESK}}% \def\SK{\textsf{Sketch}}% \def\MP{\textsf{META}\-\textsf{POST}}% % \end{macrocode} % Protect against certain outdated versions of the |kvsetkeys| package: % \begin{macrocode} \usepackage{kvsetkeys}[2007/09/29] \usepackage{tikz} \usepackage{esk} % \end{macrocode} % \begin{macrocode} \setlength{\parindent}{0pt} \def\manindex#1{\SortIndex{#1}{#1}} %\OnlyDescription \EnableCrossrefs \RecordChanges \CodelineIndex \DoNotIndex{\def,\gdef,\long,\let,\begin,\end,\if,\ifx,\else,\fi} \DoNotIndex{\immediate,\write,\newwrite,\openout,\closeout,\typeout} \DoNotIndex{\font,\jobname,\documentclass,\char,\catcode,\ } \DoNotIndex{\CodelineIndex,\DocInput,\DoNotIndex,\EnableCrossrefs} \DoNotIndex{\filedate,\filename,\fileversion,\logo,\manfnt} \DoNotIndex{\NeedsTeXFormat,\ProvidesPackage,\RecordChanges,\space} \DoNotIndex{\begingroup,\csname,\edef,\endcsname,\expandafter} \DoNotIndex{\usepackage,\@ifundefined,\ignorespaces,\item,\leavevmode} \DoNotIndex{\newcounter,\newif,\par,\parindent} \DoNotIndex{\relax,\setcounter,\stepcounter,\the,\advance} \DoNotIndex{\CurrentOption,\DeclareOption,\documentstyle} \DoNotIndex{\endgroup,\global,\hfuzz,\LaTeX,\LaTeXe} \DoNotIndex{\macrocode,\OnlyDescription,\PassOptionsToPackage} \DoNotIndex{\ProcessOptions,\RequirePackage,\string,\textsf,\unitlength} \DoNotIndex{\@bsphack,\@esphack,\@nameuse,\@ne,\active,\do,\dospecials} \DoNotIndex{\errhelp,\errmessage,\ifcase,\IfFileExists,\includegraphics} \DoNotIndex{\manindex,\SortIndex,\newcommand,\newtoks,\or,\origmacrocode} \DoNotIndex{\alpha,\displaystyle,\frac,\sin,\texttt} % \end{macrocode} % Cut the line breaking some slack for macro code which might contain % long lines (it doesn't really hurt if they stick out a bit). % \begin{macrocode} \let\origmacrocode\macrocode \def\macrocode{\hfuzz 5em\origmacrocode} \begin{document} \DocInput{esk.dtx} \end{document} % % \end{macrocode} % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \endinput Local Variables: mode:LaTeX fill-prefix:"% " indent-tabs-mode:nil change-log-default-name:"TODO" page-delimiter:"^% %%%%%%%%%*\n" End: