% \iffalse meta-comment % Copyright (C) 2006-2007 by Martin Scharrer % http://www.scharrer-online.de/latex/ % ----------------------------------------------------------------- % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3 or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Martin Scharrer. % % This work consists of the files svn-multi.dtx and svn-multi.ins % and the derived files svn-multi.sty and svnkw.sty. % $Id: svn-multi.dtx 628 2007-07-10 20:32:06Z martin $ % \fi % \iffalse %<*driver> \ProvidesFile{svn-multi.dtx} % %%% DTX Id: $Id: svn-multi.dtx 628 2007-07-10 20:32:06Z martin $ %\NeedsTeXFormat{LaTeX2e}[1999/12/01] %\ProvidesPackage{svn-multi} %<*package|driver> [2009/02/27 v1.4 SVN Keywords for multi-file LaTeX documents] % %\NeedsTeXFormat{LaTeX2e}[1999/12/01] %\ProvidesPackage{svnkw} % [2009/02/27 v1.4 Backward compatibility wrapper for svn-multi] %\RequirePackage{svn-multi}[2009/02/27] % %<*driver> \documentclass{ltxdoc} \usepackage{svn-multi} \usepackage{ifpdf} \ifpdf % use hypdoc if you have it, hyperref else %\usepackage[hyperfootnotes=false]{hyperref} \usepackage{hypdoc} \else\let\url=\texttt\fi \usepackage{xspace} \newcommand{\ie}{i.e.\@\xspace} \newcommand{\eg}{e.g.\@\xspace} \iffalse % crossreference of macros in documentation \begingroup \catcode`\*=0 \catcode`\\=12 *gdef*removeslash\#1 #2END{#1#2} *endgroup \makeatletter % link \cs to macro definitions \let\origmacro\macro \let\origendmacro\endmacro \let\origStopEventually\StopEventually \let\origPrintDescribeMacro\PrintDescribeMacro \renewenvironment{macro}[1]{% \edef\macroname{\expandafter\removeslash\detokenize{#1}END} \hypertarget{\macroname}{} \origmacro#1} {\origendmacro} \DeclareRobustCommand{\cs}[1]{\hyperlink{Desc@#1}{\texttt{\textbackslash#1}}} \def\StopEventually#1{\origStopEventually{#1}% \DeclareRobustCommand{\cs}[1]{\hyperlink{##1}{\texttt{\textbackslash##1}}} } \def\PrintDescribeMacro#1{% \edef\macroname{\expandafter\removeslash\detokenize{#1}END}% \raisebox{11pt}[11pt]{\hypertarget{Desc@\macroname}{}} \origPrintDescribeMacro{#1} } \fi \EnableCrossrefs %\DisableCrossrefs \CodelineIndex %\PageIndex \RecordChanges %\OnlyDescription \begin{document} \DocInput{svn-multi.dtx} \PrintChanges \PrintIndex \end{document} % %<*package> % \fi % % \CheckSum{617} % % {\makeatother % \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 \~} % } % \changes{v1.0}{2006/05/27}{Initial version} % \changes{v1.1}{2006/06/08}{Added macros to extract and typeset date/time % informations. Added macros to set and typeset main URL or filename.} % \changes{v1.2}{2007/06/22}{Renamed packet from \texttt{svnkw} to % \texttt{svn-multi} to match CTAN directory. Wrapper file % \texttt{svnkw.sty} is provided for backward compatibility.} % \changes{v1.3}{2007/07/01}{Added verbatim support. Keywords can now contain % special character like \texttt{\_ \^{} \$ \% \& \textbackslash}. Rewrote % keyword check macros to work with verbatim code. \texttt{\textbackslash % nofiles} is now obeyed.} % \changes{v1.3a}{2007/07/10}{Fixed issue with unwanted spaces generated by % \cs{svnid}, \cs{svnidlong} and \cs{svnkwsave}, \eg when used in a file which is % included with \cs{input}} % \changes{v1.3b}{2008/12/03}{Changed the way catcodes are modified to be compatible % with the french option of the babel package or other packages which modify the % list of special characters.} % \changes{v1.4}{2009/02/27}{Added support for timezones with non-zero minute % part, \eg +0530.} % % \GetFileInfo{svn-multi.sty} % % \DoNotIndex{\newcommand,\newenvironment,\AtBeginDocument,\AtEndDocument} % \DoNotIndex{\def,\let,\edef,\xdef,\item,\space,\write,\jobname,\relax,\!} % \DoNotIndex{\closeout,\csname,\DeclareRobustCommand,\else,\empty,\newwrite} % \DoNotIndex{\endcsname,\expandafter,\fi,\Hurl,\hyper@normalise,\@ifnextchar} % \DoNotIndex{\ifnum,\@ifundefined,\ifx,\immediate,\InputIfFileExists,\ } % \DoNotIndex{\newcount,\noexpand,\openout,\PackageWarning,\@percentchar} % \DoNotIndex{\@sanitize,\@makeother,\@iwsvn,\%,\_,\&,\^,\$,\#,\ ,\\,\if@filesw} % \DoNotIndex{\gdef,\begingroup,\endgroup,\catcode} % % % \title{The \textsf{svn-multi} package\thanks{This document % corresponds to \textsf{svn-multi}~\fileversion, dated \filedate.} % \\also known as \textsf{svnkw}} % \author{Martin Scharrer \\ \url{martin@scharrer-online.de} \\ % \url{http://www.scharrer-online.de/latex/svn-multi}} % % \ifpdf % \hypersetup{ % pdfauthor={Martin Scharrer }, % pdftitle={The svn-multi package also known as svnkw}, % pdfsubject={Documentation of LaTeX package svn-multi which allows the % typesetting of Subversion keywords in multi-file LaTeX documents}, % pdfkeywords={svn-multi, svnkw, LaTeX, Subversion, keywords, Version % Control, Id} % } % \fi % \maketitle % % \section{Package naming} % The authors first choice for this package was |svnkw| but the CTAN % maintainer suggested a more descriptive name and put the package in the % |svn-multi|\footnote{CTAN: % \url{http://www.ctan.org/tex-archive/macros/latex/contrib/svn-multi/}} % directory. Therefore the style file got renamed to |svn-multi|, but a % |svnkw| dummy style file is still provided for backward compatibility. % % \section{Introduction} % This package lets you typeset keywords of the version control system Subversion\footnote % {Subversion homepage: \url{http://subversion.tigris.org/}} (svn), which is the successor of the popular CVS, % inside your \LaTeX{} files anywhere you like. % Unlike the very similar package % |svn|\footnote{CTAN: % \url{http://www.ctan.org/tex-archive/macros/latex/contrib/svn/}} the usage of % multiple files for one \LaTeX{} document is well supported. The package % acquires the keywords of the last changed file and provides them to the user % through macros. The package has to read all keywords of all files first and % writes the most recent values in an auxiliary file with an `.svn' % extention. This file is read back at the next \LaTeX{} run which introduces a % delay like by the table of contents. The standard \LaTeX{} switch |\nofiles| % can be used to suppress the file generation. Macros to typeset the keywords % of the current |include|d or |input|ed \LaTeX{} file are also provided. % % % \section{Usage} % % \subsection{Including of the Subversion keywords} % To include your Subversion Id keywords use \cs{svnid} or \cs{svnidlong}. % This macros should be written very % early in each file, \ie in the preamble of the main document soon after % |\documentclass| and |\usepackage{svn-multi}| (or, outdated, % |\usepackage{svnkw}|) and as first in \emph{every} |\include|d % subfile before the |\chapter| macro. They do not create any output. % See section~\ref{sec:kwaccess} to learn how to typeset the keyword values. % % \DescribeMacro{\svnid} % Macro for the svn Id keyword. % Write the macro as |\svnid{$||Id$}| into your \LaTeX{} files. A trailing colon % with spaces after the |Id| is also valid but \textbf{everything else} except % a valid Subversion string will cause a \TeX{} parse error. % Don't forget to set the subversion property |svn:keywords| of the files % to at least `|Id|'. Subversion will expand it at the next commit. % Please note that because the value is read verbatim the macro should exactly be % written like above. Spaces, newlines or comments between |\svnid| and % the \{ will lead to \TeX{} parse errors. % % \DescribeMacro{\svnidlong} % Macro for a ``long Id''. % Saves similar values like in `|Id|' but from the keywords % |HeadURL|, |LastChangedDate|, |LastChangedRevision| and |LastChangedBy|. % The usage of \cs{svnid} or \cs{svnidlong} is a matter of taste. The second is % more readable inside the code and results in a nicer date and a full URL, % not only the filename. Both can also be used together. % % Write this macro like this (order of arguments not meaningfull)\\[2ex] % |\svnidlong|\\ % |{$||HeadURL$}|\\ % |{$||LastChangedDate$}|\\ % |{$||LastChangedRevision$}|\\ % |{$||LastChangedBy$}|\\[2ex] % in your files and set the subversion % property |svn:keywords| of them % to\\`|HeadURL LastChangedDate LastChangedRevision LastChangedBy|'. % % Please note that the arguments are read verbatim. Special precaution are % taken to allow spaces, newlines and comments direct after the |\svnidlong| % and after each of the four arguments, just in case someone need this. % In fact everything not inside braces \{ \} is ignored. % % The two macros above are sufficient for the operation of |svn-multi| but % the following macros are provided for additional or alternative keyword % handling. % % \DescribeMacro{\svn} % \DescribeMacro{\svn*} % This macro let you typeset svn keywords directly. The only argument is % the svn keyword in the usual dollars. The dollars will be stripped % and the rest is typeset as normal text. The star version strips also the % space before the last dollar. % This macro alone was the very first version of |svnkw| and is still included % for fast and simple keyword typesetting. % % \DescribeMacro{\svnkwsave} % This macro lets you include and save any keyword you like. The syntax is % |\svnkwsave|\{\$\meta{keyword}\$\}. The keyword can be already expanded or % not (no value and only ``|:|'' or nothing after the key name). This macro is % also used internally and does not create any output. % Please note that the argument is read verbatim and that there should be no % space between the macro and the argument's left brace. % % \subsection{Typesetting the keyword values}\label{sec:kwaccess} % The following macros can be used to typeset the keyword values anywhere in % the document. Please note that note all \LaTeX{} fonts have all special % characters, \eg `\_' is not provided in the standard roman font. To proper % typeset filename and URL containing these letters you can use either % texttyper font (|\texttt|) or use |{\urlstyle{rm}\svnnolinkurl{...}}| which % needs the |hyperref| package. % % Like already mentioned |svn-multi| knows two groups of keywords. The first % group contains of the keywords for the whole document which hold the values % of the most recent committed file, the second contains of the \emph{current} % or \emph{file local} keywords, \eg the keywords of the current file. % % \DescribeMacro{\svnrev} % \DescribeMacro{\svndate} % \DescribeMacro{\svnauthor} % These macros hold the keyword values of the whole document, \ie of the % most recent revision. They can be used everywhere in every file of the % \LaTeX{} document, after |\usepackage{svn}| of course. Please see % section~\ref{sec:date} how to typeset parts of the date. % % \DescribeMacro{\svnfilerev} % \DescribeMacro{\svnfiledate} % \DescribeMacro{\svnfileauthor} % These macros hold the keyword values of the current \LaTeX{} file, but % only if it contains a \cs{svnid} or \cs{svnidlong} macro. Otherwise % the macros hold still the values of the last file. Please see % section~\ref{sec:date} how to typeset parts of the date. See \cs{svnkw} below % for all other keywords. % % \DescribeMacro{\svnmainurl} % \DescribeMacro{\svnmainfilename} % The macro |\svnmainurl| and |\svnmainfilename| hold the URL and the filename % of the main \LaTeX{file} as long the keywords |HeadURL| or |Id| were used in % it, respectively. % These can be used to typeset this information anywhere in the document % which might be more descriptive as the name of the current file (which can % be typeset with |\svnkw{HeadURL}| or |\svnkw{Filename}| after \cs{svnid} or % \cs{svnidlong}, respectively). % % \DescribeMacro{\svnsetmainfile} % This will declare the current file as the main LaTeX % file by defining the above macros. It will automatically be called at the % end of the preamble so the user normally doesn't have to use it by him- or % herself as long it isn't needed in the preamble. \par % Please note that this macro changes the definition of |\svnmainurl| and % |\svnmainfilename| directly without going over the auxiliary file. Calling % it in several files will make this two macros inconsistent. % % \DescribeMacro{\svnkw} % All keywords saved with \cs{svnid}, \cs{svnidlong} or \cs{svnkwsave} can be typeset % by this macro which is a holdover of pare-multi-file times of this package. % It takes one argument which must be a subversion keyword name. It % then returns the current value of this keyword or nothing (|\relax|) when % the keyword was not set yet. % Examples:\\ % \indent\indent |\textsl{Revision: \svnkw{Revision}}|\\ % \indent\indent |URL: \url{\svnkw{HeadURL}}|\\ % In the second example |\url| (|hyperref| package) is used to add a % hyperlink and to avoid problems with underscores (|_|) inside the URL. % |svn-multi| is also providing a macro \cs{svnnolinkurl} which works like |\url| % but doesn't adds an hyperlink. See the description of this macro for more % details. % % If the given keyword doesn't exists a package warning is given to allow % spelling errors to be tracked down. This doesn't work well when \cs{svnkw} % is used inside |\url|. In this case the % warning code will be typeset(!) verbatim into the document by |\url|. % % \DescribeMacro{\svnkwdef} % This macro is used to define the keyword values, \ie % \cs{svnkwdef}\marg{keyword}\marg{value}. This is normally only % called internally but could be used by the user to override single keywords. % The values can then be typeset by \cs{svnkw}. % Note that this macro has no influence on the calculation of the latest % revision. % % Note that for \cs{svnkw} and \cs{svnkwdef} all different names for one keyword % are valid and result in the access of the same variable. So \eg subversion % treats |Rev|, |Revision| and |LastChangedRev| the same way and so does this % macros. You can \eg say |\svnkwdef{Rev}{123}| and then typeset it with % |\svnkw{Revision}| or |\svnkw{LastChangedRev}| if you like. % % \subsubsection{Accessing Date Values}\label{sec:date} % \DescribeMacro{\svnfileyear} % \DescribeMacro{\svnfilemonth} % \DescribeMacro{\svnfileday} % \DescribeMacro{\svnfilehour} % Whenever the date information is read, \ie by |\svnkwsave{LastChangedDate}| % |\svnkwsave{Date}|, \cs{svnidlong} or \cs{svnid}, the following macros are % set to the appropriate date parts for the current file (the |\svnfile...| % versions) and for the whole document. % % \iffalse Put here and not above to avoid 'to many floats' error. \fi % \DescribeMacro{\svnfileminute} % \DescribeMacro{\svnfilesecond} % \DescribeMacro{\svnfiletimezone} % \DescribeMacro{\svnfiletimezonehour} % \DescribeMacro{\svnfiletimezoneminute} % Please note that the hour and timezone are dependend on the keyword which % defines the date informations. The hour will be in UTC aka Zulu-time, \ie % timezone +0000, when the date comes from the |Id| keyword. % \iffalse Put here and not above to avoid 'to many floats' error. \fi % \DescribeMacro{\svnyear} % \DescribeMacro{\svnmonth} % \DescribeMacro{\svnday} % \DescribeMacro{\svnhour} % Otherwise the hour and timezone will be in local time. % To avoid confusion the |Id| and |Date|/|LastChangedDate| keywords, \eg % \cs{svnid} and \cs{svnidlong}, should not be intermixed and/or the timezone % should always be typeset together with the time. % % \iffalse Put here and not above to avoid 'to many floats' error. \fi % \DescribeMacro{\svnminute} % \DescribeMacro{\svnsecond} % \DescribeMacro{\svntimezone} % \DescribeMacro{\svntimezonehour} % \DescribeMacro{\svntimezoneminute} % Starting with v1.4 of |svn-multi| the timezone macros return the full % timezone, \ie sign, hour and minute part, \eg |+0100|, not only the sign and % hour. The new macros % |\svntimezonehour|/|\svnfiletimezonehour| and % |\svntimezoneminute|/\linebreak[3]|\svnfiletimezoneminute| can be used to access only the % hour including sign or the minute part, respectively. % % Older versions of this manual assumed the minute part as always |00| and % suggested to add it manually if needed: |\svnfiletimezone00| or |\svntimezone00|. % In order not to ``break'' documents which followed this suggestion this two % macros now remove a trailing |00| if present. % However, this can be a problem when they are used inside an argument of % another macro. One solution for this is to redefine them without the |00| % removal part:\\ % \begingroup\small % |\renewcommand{\svntimezone}{\svntimezonehour\svntimezoneminute}|\\ % |\renewcommand{\svnfiletimezone}{\svnfiletimezonehour\svnfiletimezoneminute}| % \endgroup\par % To revert to the old (pre-v1.4) definition use:\\ % \begingroup\small % |\renewcommand{\svntimezone}{\svntimezonehour}|\\ % |\renewcommand{\svnfiletimezone}{\svnfiletimezonehour}| % \endgroup % \vspace{1ex} % % \DescribeMacro{\svnpdfdate} % Returns the last changed date of the whole document in a format needed for % |\pdfinfo|. Can be used like this:\\ % \hbox{}\hfill|\pdfinfo{ /CreationDate (D:\svnpdfdate) }|\hfill\hbox{}\\ % to set the PDF creation date to % the last changed date if you use |pdflatex| to compile your \LaTeX{} document. % % \subsection{Using full author names} % If you like to have the full author\footnote{This means subversion authors, % \eg the persons who commit changes into the svn repository.} % names, not only the usernames, in your % document you can use the following macros. First you have to register all % authors of the document with \cs{svnRegisterAuthor} and then you can write % \eg |\svnFullAuthor{\svnauthor}| or |\svnFullAuthor{\svnfileauthor}|. % % \DescribeMacro{\svnRegisterAuthor} % The usage is \cs{svnRegisterAuthor}\marg{username}\marg{full name} which % registers \meta{full name} as full name for \meta{username}. % % \DescribeMacro{\svnFullAuthor} % \DescribeMacro{\svnFullAuthor*} % Takes the username as argument and returns the full name if it was % registered first with \cs{svnRegisterAuthor}, otherwise it returns the given % username. The star version returns the username in parentheses after the % full name. % % \subsection{Using full revision names} % Like the author's also revision names/tags can be registered and used later. % This macros were implemented on user request and have the drawback % that you have to guess the next revision number of your document in order % to get correct results when you like to tag the to-be-checked-in revision. % Please note that this has nothing to do with the normal subversion tagging. % % \DescribeMacro{\svnRegisterRevision} % The usage is \cs{svnRegisterRevision}\marg{revision number}\marg{tag name} % which registers \meta{tag name} as tag name for \meta{revision number}. % % \DescribeMacro{\svnFullRevision} % \DescribeMacro{\svnFullRevision*} % Takes a \marg{revision number} (\ie |\svnrev|, |\svnfilerev| or a number) % as argument and returns the full name if it was registered first with % \cs{svnRegisterRevision}, otherwise it returns ``Revision \meta{revision % number}''. % The star version returns also the revision number leaded by `r' in parentheses % after the tag name, \eg |Name (r123)|. % % \subsection{Verbatim URLs with and without hyperlinks} % \DescribeMacro{\svnnolinkurl} % This macro allows you to write |\svnnolinkurl{\svnkw{HeadURL}}| and get % the Head URL typeset verbatim. However |\url{\svnkw{HeadURL}}| (|hyperref| % package) gives you the same result with hyperlinked. Both macros require % the |hyperref| package which is not automatically loaded by |svn-multi|. % Please load it manually when you like to use \cs{svnnolinkurl}. % % Since v1.3 all keywords are read and typeset verbatim so this macro isn't % this important anymore. However together with |hyperref|s |\urlstyle| macro % it can be used to have keyword values with special characters in roman font, % which normaly doesn't hold letters like `\_'. % % Please note that you can't use |hyperref|s |\nolinkurl| because it won't % expand \cs{svnkw}. % % \section{Further Reading} % The \textsf{svn-multi} package and its usage got discussed in the following % articles: % % \begin{itemize} % \item[{[1]}] Martin Scharrer, ``Version Control of LaTeX Documents with % svn-multi'', The Prac\TeX\ Journal, (3), 2007. % URL: \url{http://www.tug.org/pracjourn/2007-3/scharrer/} % \item[{[2]}] Mark Eli Kalderon, ``LaTeX and Subversion'', % The Prac\TeX\ Journal, (3), 2007. % URL: \url{http://www.tug.org/pracjourn/2007-3/kalderon-svnmulti/} % \item[{[3]}] Uwe Ziegenhagen , ``LaTeX Document Management with Subversion'', % The Prac\TeX\ Journal, (3), 2007. % URL: \url{http://www.tug.org/pracjourn/2007-3/ziegenhagen/} % \end{itemize} % % \StopEventually{} % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \section{Implementation} % \begin{macro}{\svn} % \begin{macro}{\svn*} % After *-testing, the intermediate macros |\svn@s| and |\svn@n| are called to % strip the |{ }| from |\svn|[|*|]|{$...$}| and to remove the |*|. Then the % actual macros are called to strip the dollars with or without the space % before the last dollar. % \changes{v1.2}{2007/06/22}{Added star version. Normal version was not % changed to not break existing documents with user defined keywords without % leading space.} % \begin{macrocode} \newcommand{\svn}{\@ifnextchar{*}{\svn@s}{\svn@n}} \def\svn@n#1{\@svn@n#1} \def\svn@s*#1{\@svn@s#1} \def\@svn@n$#1${#1} \def\@svn@s$#1 ${#1} % \end{macrocode} % \end{macro} % \end{macro} % \subsection{Definition of init values} % \begin{macrocode} % Init values \def\svnrev{0} \def\svnfilerev{0} \def\@svn@rev{0} \def\svndate{} \def\svnfiledate{} \def\@svn@date{} \def\svnauthor{} \def\svnfileauthor{} \def\@svn@author{} \def\svnyear{0} \def\svnfileyear{0} \def\@svn@year{0} \def\svnmonth{0} \def\svnfilemonth{0} \def\@svn@month{0} \def\svnday{0} \def\svnfileday{0} \def\@svn@day{0} \def\svnhour{0} \def\svnfilehour{0} \def\@svn@hour{0} \def\svnminute{0} \def\svnfileminute{0} \def\@svn@minute{0} \def\svnsecond{0} \def\svnfilesecond{0} \def\@svn@second{0} \def\svntimezonehour{+00} \def\svnfiletimezonehour{+00} \def\@svn@timezonehour{+00} \def\svntimezoneminute{00} \def\svnfiletimezoneminute{00} \def\@svn@timezoneminute{00} \def\svnmainurl{NOT SET}\def\svnmainfilename{NOT SET} % \end{macrocode} % % \subsection{Timezone macros} % \begin{macro}{\svnfiletimezone} % \begin{macro}{\svntimezone} % This macros return the global and local time zones. Since v1.4 the minute part % is returned as well and the macro removes manually added |00| after it to % support older documents. % \changes{v1.4}{2009/02/27}{Return now full timezone (hour + minute part). % Manually added 00 minutes are removed.} % \begin{macrocode} \def\svntimezone{\svntimezonehour\svntimezoneminute\svn@gobblezeros} \def\svnfiletimezone{\svnfiletimezonehour\svnfiletimezoneminute\svn@gobblezeros} % \end{macrocode} % \end{macro} % \end{macro} % \begin{macro}{\svn@gobblezeros} % \begin{macro}{\svn@gobblezeros@} % This two cascaded macros remove a trailing |00| and are used by % |\svnfiletimezone| and |\svntimezone|. % \begin{macrocode} \def\svn@gobblezeros{% \futurelet\svn@nextchar\svn@gobblezeros@ } \def\svn@gobblezeros@{% \let\@tempa=\relax \def\@tempb{0}% \ifx0\svn@nextchar \let\@tempa=\@gobbletwo \fi \@tempa } % \end{macrocode} % \end{macro} % \end{macro} % \subsection{Id macros} % \subsubsection{Normal Id} % \begin{macro}{\svnid} % Calls \cs{svnkwsave} with |\@svnidswtrue| so that the Id keyword will be % parsed at the end of \cs{svnkwsave}. % \begin{macrocode} \newcommand*{\svnid}{% \@svnidswtrue \svnkwsave } \newif\if@svnidsw \@svnidswfalse % \end{macrocode} % \end{macro} % % \begin{macro}{\svn@scanId} % Scans svn Id (after it got parsed by \cs{svnkwsave}). % Awaits only Id value without leading `|Id:|' and a trailing |\relax| as end % marker. % It calls \cs{@svn@scandate} to extract the date informations and % \cs{@svn@updateid} to update global Id values and also sets the appropriate % keywords. % \begin{macrocode} \def\svn@scanId#1 #2 #3 #4 #5\relax{% % #1 is filename, #2 is revision, #3 is date (JJJJ-MM-DD), % #4 is time (HH:MM:SST), #5 is author (username) \@svn@scandate{#3 #4}% \@svn@updateid{#2}{#3 #4}{#5}% \svnkwdef{Filename}{#1}% \svnkwdef{Date}{#3 #4}% \svnkwdef{Revision}{#2}% \svnkwdef{Author}{#5}% } % \end{macrocode} % \end{macro} % % \begin{macro}{\@svn@updateid} % We first define the expanded arguments to variables for the user. % The expansion is needed because the arguments content is mostly generic like % |\svn@key| and |\svn@value| which can change very soon after this macro. % \begin{macrocode} \def\@svn@updateid#1#2#3{% #1 = rev, #2 date, #3 author (username) \xdef\svnfilerev{#1}% \xdef\svnfiledate{#2}% \xdef\svnfileauthor{#3}% % \end{macrocode} % Then we check if the revision is non-empty (not yet expanded by % subversion?) and larger then the current maximum value |\@svn@rev|. % If yes we save all value to save them in the .svn-file later. % \begin{macrocode} \ifx\svnfilerev\empty\else \ifnum\@svn@rev<\svnfilerev \xdef\@svn@rev{#1}% \xdef\@svn@date{#2}% \xdef\@svn@author{#3}% \xdef\@svn@year{\svnfileyear}% \xdef\@svn@month{\svnfilemonth}% \xdef\@svn@day{\svnfileday}% \xdef\@svn@hour{\svnfilehour}% \xdef\@svn@minute{\svnfileminute}% \xdef\@svn@second{\svnfilesecond}% \xdef\@svn@timezonehour{\svnfiletimezonehour}% \xdef\@svn@timezoneminute{\svnfiletimezoneminute}% \else\fi \fi } % \end{macrocode} % \end{macro} % % \subsubsection{Long Id} % \begin{macro}{\svnidlong} % We clear the keyword value first to reduce the risk though bad user input. % \begin{macrocode} \newcommand{\svnidlong}{% \svnkwdef{HeadURL}{}% \svnkwdef{LastChangedDate}{}% \svnkwdef{LastChangedRevision}{0}% \svnkwdef{LastChangedBy}{}% % \end{macrocode} % The catcodes are changed by \cs{svn@catcodes} to allow \TeX-special characters % inside the keywords. % The braces \{ \} are changed to allow comments between the arguments. % \cs{svnidlong@readargsfull} is called to read the arguments. % \begin{macrocode} \begingroup \svn@catcodes \catcode`\{=12 \catcode`\}=12 \svnidlong@readargsfull } % \end{macrocode} % \end{macro} % \begin{macro}{\svn@catcodes} % Changes all \TeX-special character to category ``other''. The newline aka % return is changed to category ``ignore'' so line breaks are not taken as % part of the verbatim arguments. % \begin{macrocode} \def\svn@catcodes{% \let\do\@makeother \dospecials \catcode`\^^M9 \catcode`\ 10 \catcode`\{1 \catcode`\}2 } % \end{macrocode} % \end{macro} % \begin{macro}{\svnidlong@readargsfull} % Reads all four arguments of \cs{svnidlong} and passes them to % \cs{svnidlong@readargs}. The normal argument braces are changed to category % ``other'' and put into the macros parameter text to remove all code between % them. This is done to avoid problems with comments direct after one of the % arguments. Because the braces are now non-special the parentheses are made % to a local replacement. % % \begin{macrocode} \begingroup \catcode`\{=12\catcode`\}=12 \catcode`\(=1\catcode`\)=2 \gdef\svnidlong@readargsfull#1{#2}#3{#4}#5{#6}#7{#8}(% \svnidlong@readargs(#2)(#4)(#6)(#8)% ) \endgroup % \end{macrocode} % \end{macro} % \begin{macro}{\svnidlong@readargs} % Calls sub macro for all four arguments and ends the catcode changes made % by \cs{svnidlong}. % \begin{macrocode} \def\svnidlong@readargs#1#2#3#4{% \svnkwsave@read #1\relax \svnkwsave@read #2\relax \svnkwsave@read #3\relax \svnkwsave@read #4\relax \endgroup % \end{macrocode} % Now the update macros for date and id are called. % \begin{macrocode} \ifx\svnkwLastChangedDate\empty \else\@svn@scanlongdate{\svnkwLastChangedDate}\fi \@svn@updateid{\svnkw{LastChangedRevision}}{\svnkw{LastChangedDate}} {\svnkw{LastChangedBy}}% \ignorespaces }% % \end{macrocode} % \end{macro} % \subsection{KeyWord Macros} % \begin{macro}{\svnkwsave} % Save macro. Takes a dollar wrapped keyword string, reads it though % \cs{svn@readkw} and saves it using \cs{svnkwdef}. % \begin{macrocode} \def\svnkwsave{% \begingroup \svn@catcodes \svnkwsave@readargs } % \end{macrocode} % \end{macro} % \begin{macro}{\svnkwsave@readargs} % Reads full argument, calls parse submacro and ends catcode changes. % If \cs{svnkwsave} was called by \cs{svnid} scans the id keyword by calling the % scan macro. % \begin{macrocode} \gdef\svnkwsave@readargs#1{% \svnkwsave@read#1\relax \endgroup \if@svnidsw \ifx\svnkwId\empty \else \expandafter \svn@scanId\svnkwId\relax \@svnidswfalse \fi \fi \ignorespaces } % \end{macrocode} % \end{macro} % \begin{macro}{\svnkwsave@read} % Reads the full keyword and strips the dollars. % \begin{macrocode} \begingroup \catcode`\$=12 \gdef\svnkwsave@read $#1$\relax{% \svn@checkcolon#1:\relax } \endgroup % \end{macrocode} % \end{macro} % \begin{macro}{\svnkwsave@parse} % Parse the keyword and save it away. % \begin{macrocode} \begingroup \catcode`\$=11 \gdef\svnkwsave@parse$#1:#2${% \expandafter\xdef\csname svnkw#1\endcsname{#2}} \endgroup % \end{macrocode} % \end{macro} % \begin{macro}{\svnkwdef} % First we check if there is a `setter'-macro for the keyword called % \cs{svnkwdef@}\meta{keyword}. % \begin{macrocode} \newcommand{\svnkwdef}[2]{% \@ifundefined{svnkwdef@#1} % \end{macrocode} % If not we call the general macro \cs{svnkwdef@}. % \begin{macrocode} {\svnkwdef@{#1}{#2}} % \end{macrocode} % If yes we just call it with the value as argument. % \begin{macrocode} {\csname svnkwdef@#1\endcsname{#2}}% } % \end{macrocode} % \end{macro} % \begin{macro}{\svnkwdef@} % This macro defines the second argument under \cs{svnkw}\meta{1st argument}. % The |\xdef| is used to expand the content first (needed for internal use) % and make the definition globally. % \begin{macrocode} \newcommand{\svnkwdef@}[2] {\expandafter\xdef\csname svnkw#1\endcsname{#2}} % \end{macrocode} % Example: |\svnkwdef{Revision}{23}| will define |\svnkwRevision| as 23. % \end{macro} % \begin{macro}{\svnkwdef@Rev} % \begin{macro}{\svnkwdef@Author} % \begin{macro}{\svnkwdef@Date} % `Setter'-macros for single keywords, used by \cs{svnkwdef}.\\ % These are needed to have have a common value for all alternative keyword % names ala |Rev|, |Revision|, |LastChangedRevision|. % % The keywords |Rev|, |Author| and |Date| % are just calling \cs{svnkwdef@} with a fixed first argument. % \begin{macrocode} \def\svnkwdef@Rev#1{\svnkwdef@{Rev}{#1}} \def\svnkwdef@Author#1{\svnkwdef@{Author}{#1}} \def\svnkwdef@Date#1{\svnkwdef@{Date}{#1}} % \end{macrocode} % The long keywords are defined then as aliases of the short,\\ % first for writing % \begin{macrocode} \let\svnkwdef@Revision=\svnkwdef@Rev \let\svnkwdef@LastChangedRevision=\svnkwdef@Rev \let\svnkwdef@LastChangedBy=\svnkwdef@Author \let\svnkwdef@LastChangedAt=\svnkwdef@Date % \end{macrocode} % and then for reading. % \begin{macrocode} \def\svnkwRevision{\svnkwRev} \def\svnkwLastChangedRevision{\svnkwRev} \def\svnkwLastChangedBy{\svnkwAuthor} \def\svnkwLastChangedAt{\svnkwDate} % \end{macrocode} % So \eg |\svnkw{LastChangedRevision}| is always be the % same as |\svnkw{Rev}|. % \end{macro} % \end{macro} % \end{macro} % We define default values for normal keywords. Keyword |Filename| is the name % given by |Id| and not a real keyword. % \begin{macrocode} \svnkwdef{Rev}{0} \svnkwdef{Date}{} \svnkwdef{Author}{} \svnkwdef{Filename}{} \svnkwdef{HeadURL}{} % \end{macrocode} % \begin{macro}{\svnkw} % Macro to get keyword value. Just calls \cs{svnkw}\meta{ARGUMENT} where % the argument interpreted as text. So \eg |\svnkw{Date}| is the same as % |\svnkwDate| but this could be changed later so always use this interface % to get the keyword values. % % \changes{v1.2}{2007/06/22}{Added warning when a wrong, maybe % misspelled, keyword is given.} % \begin{macrocode} \newcommand{\svnkw}[1]{% \@ifundefined{svnkw#1} {\PackageWarning{svn-multi}{SVN keyword '#1' not defined (typo?)}} {\csname svnkw#1\endcsname}}% % \end{macrocode} % \end{macro} % % \subsection{Keyword check and strip macros} % The following macros are used to test whether the given keywords are fully % expanded or not. % Subversion supports unexpanded keywords as input with or without colon and % with or without trailing space(s), \ie a:~|$KW$|, b:~|$KW:$| or c:~|$KW: $|. % To avoid \LaTeX{} syntax errors in this pre-commit state the keyword is % checked by the following macros. Unexpanded keywords result in an empty value. % Also leading and trailing spaces are removed. % % \begin{macro}{\svn@checkcolon} % Checks if the keyword contains a colon. It is called by \cs{svnkwsave@read} % with a trailing |:\relax| so that \#2 will be empty if there is no earlier % colon or will hold the value with this trailing colon otherwise. % The first case means that the keyword is unexpanded without colon (case a) % which leads to an empty value. In the second case \cs{svn@stripcolon} is % called to strip the colon and surrounding spaces. The final value is % returned by |\svn@value|. % \begin{macrocode} \def\svn@checkcolon#1:#2\relax{% \def\svn@test{#2}% \ifx\svn@test\empty \svnkwdef{#1}{}% \else \svn@stripcolon#2\relax \svnkwdef{#1}{\svn@value}% \fi } % \end{macrocode} % \end{macro} % \begin{macro}{\svn@stripcolon} % Strips the previous added colon (for \cs{svn@checkcolon}). % The remaining argument is checked if it's empty (case b) or only a space % (case c). Otherwise the keyword is expanded and \cs{svn@stripspace} is % called to strip the spaces. % \begin{macrocode} \def\svn@stripcolon#1:\relax{% \def\svn@test{#1}% \ifx\svn@test\empty \gdef\svn@value{}% \else \ifx\svn@test\svn@spaceonly \gdef\svn@value{}% \else \svn@stripspace#1\relax\relax \fi\fi } \def\svn@spaceonly{ } % \end{macrocode} % \end{macro} % \begin{macro}{\svn@stripspace} % Strips leading space if present and calls \cs{svn@striptrailingspace} to % strip the trailing space. % \begin{macrocode} \def\svn@stripspace#1#2\relax{% \def\svn@test{#1}% \ifx\svn@test\svn@spaceonly \gdef\svn@value{#2}% \else \svn@striptrailingspace#1#2\relax \fi } % \end{macrocode} % \end{macro} % \begin{macro}{\svn@striptrailingspace} % Strips trailing space using the macros parameter text. Must be called with % |\relax| as end marker. % \begin{macrocode} \def\svn@striptrailingspace#1 \relax{% \gdef\svn@value{#1}% } % \end{macrocode} % \end{macro} % \subsection{Date Macros} % \begin{macro}{\@svn@scandate} % Scans data informations in Id keyword and saves them in macros. % \begin{macrocode} \def\@svn@scandate#1{\@svn@scandate@#1\relax} \def\@svn@scandate@#1-#2-#3 #4:#5:#6#7#8\relax{% \gdef\svnfileyear{#1}% \gdef\svnfilemonth{#2}% \gdef\svnfileday{#3}% \gdef\svnfilehour{#4}% \gdef\svnfileminute{#5}% \gdef\svnfilesecond{#6#7}% \gdef\svnfiletimezonehour{+00}% \gdef\svnfiletimezoneminute{00}% #8 always 'Z' for Zulu-time (UTC) } % \end{macrocode} % \end{macro} % \begin{macro}{\@svn@scanlongdate} % Scans data informations in Date keyword and saves them in macros. % \begin{macrocode} \def\@svn@scanlongdate#1{\expandafter\@svn@scanlongdate@#1\relax} % \def\@svn@scanlongdate@#1-#2-#3 #4:#5:#6 #7 #8\relax{% \gdef\svnfileyear{#1}% \gdef\svnfilemonth{#2}% \gdef\svnfileday{#3}% \gdef\svnfilehour{#4}% \gdef\svnfileminute{#5}% \gdef\svnfilesecond{#6}% \@svn@parsetimezone#7\relax% } % \end{macrocode} % \end{macro} % \begin{macro}{\@svn@parsetimezone} % Scans timezone and splits hour and minute part. % \begin{macrocode} \def\@svn@parsetimezone#1#2#3#4#5\relax{% \gdef\svnfiletimezonehour{#1#2#3}% \gdef\svnfiletimezoneminute{#4#5}% } % \end{macrocode} % \end{macro} % \begin{macro}{\svnpdfdate} % Returns date in a format needed for |\pdfinfo|. % \begin{macrocode} \def\svnpdfdate{\svnyear\svnmonth\svnday \svnhour\svnminute\svnsecond\svntimezonehour'\svntimezoneminute'} % \end{macrocode} % \end{macro} % \subsection{Mainfile Makros} % \begin{macro}{\svnsetmainfile} % Saves the current |HeadURL| and |Filename| keywords to macros. % Will be called automatically in the preamble. % \changes{v1.2}{2007/06/22}{New macro} % \begin{macrocode} \newcommand{\svnsetmainfile} {\edef\svnmainurl{\svnkw{HeadURL}} \edef\svnmainfilename{\svnkw{Filename}}} \AtBeginDocument{\svnsetmainfile} % \end{macrocode} % \end{macro} % \subsection{Register and FullName Macros} % \begin{macro}{\svnRegisterAuthor} % Saves the author's name by defining % |\svn@author@|\meta{username} to it. % \begin{macrocode} \newcommand{\svnRegisterAuthor}[2]{% \expandafter\def\csname svn@author@#1\endcsname{#2}% } % \end{macrocode} % \end{macro} % \begin{macro}{\svnFullAuthor} % \begin{macro}{\svnFullAuthor*} % We test if the starred or the normal version is used and call the % appropriate submacro |\svnFullAuthor@star| or |\svnFullAuthor@normal|. % \changes{v1.2}{2007/06/22}{Macro now returns the username if the full name % was not registered.} % \begin{macrocode} \newcommand{\svnFullAuthor}{% \@ifnextchar{*} {\svnFullAuthor@star} {\svnFullAuthor@normal} } % \end{macrocode} % Both submacros are calling |\svnFullAuthor@| but with different arguments. % The star macro also removes the star of course. % \begin{macrocode} \def\svnFullAuthor@star*#1{\svnFullAuthor@{#1}{~(#1)}} \def\svnFullAuthor@normal#1{\svnFullAuthor@{#1}{}} % \end{macrocode} % |\svnFullAuthor@| now sets the author's full name. Note that |#2| is empty % when the normal version is called. % \begin{macrocode} \def\svnFullAuthor@#1#2{% \@ifundefined{svn@author@#1} {#1} {\csname svn@author@#1\endcsname #2}% } % \end{macrocode} % \end{macro} % \end{macro} % \begin{macro}{\svnRegisterRevision} % Saves the revision's name or tag by defining % |\svn@revision@|\meta{revisionnumber} to it. % \changes{v1.2}{2007/06/22}{New macro} % \begin{macrocode} \newcommand{\svnRegisterRevision}[2]{% \expandafter\def\csname svn@revision@#1\endcsname{#2} } % \end{macrocode} % \end{macro} % \begin{macro}{\svnFullRevision} % \begin{macro}{\svnFullRevision*} % We test if the starred or the normal version is used and call the % appropriate submacro |\svnFullRevision@star| or |\svnFullRevision@normal|. % \changes{v1.2}{2007/06/22}{New macro} % \begin{macrocode} \newcommand{\svnFullRevision}{% \@ifnextchar{*} {\svnFullRevision@star} {\svnFullRevision@normal} } % \end{macrocode} % Both submacros are calling |\svnFullRevision@| but with different arguments. % The star macro also removes the star of course. % \begin{macrocode} \def\svnFullRevision@star*#1{\svnFullRevision@{#1}{~(r#1)}} \def\svnFullRevision@normal#1{\svnFullRevision@{#1}{}} % \end{macrocode} % |\svnFullRevision@| now sets the revision name. Note that |#2| is empty % when the normal version is called. % \begin{macrocode} \def\svnFullRevision@#1#2{% \@ifundefined{svn@revision@#1} {Revision #1} {\csname svn@revision@#1\endcsname #2}% } % \end{macrocode} % \end{macro} % \end{macro} % \begin{macro}{\svnnolinkurl} % This code is taken from the |hyperref| package and is the definition of % |\url| just without the part which creates the actual hyperlink. This needs % of course the |hyperref| package. A warning is given if it isn't loaded. % \changes{v1.2}{2007/06/22}{New macro} % \begin{macrocode} \DeclareRobustCommand*{\svnnolinkurl}{% \@ifundefined{hyper@normalise} {\PackageWarning{svn-multi}{Package hyperref is needed for \noexpand \svnnolinkurl.}} {\hyper@normalise\svnnolinkurl@}}% \def\svnnolinkurl@#1{\Hurl{#1}} % \end{macrocode} % \end{macro} % \subsection{Auxiliary file generation and read-back} % At the end of document we write the values to an auxiliary file. % \begin{macrocode} \AtEndDocument{% % \end{macrocode} % We first check if we have something to save. Revision, date and author must be % non-empty. This suppresses the auxiliary file if the user doesn't use the % appropriate macros but other provided by this package. % \begin{macrocode} \if@filesw \ifx\@svn@rev\empty\else \ifnum\@svn@rev=0\else \ifx\@svn@date\empty\else \ifx\@svn@author\empty\else % \end{macrocode} % Open outfile to write project keywords. % \begin{macrocode} \newwrite\svn@write \immediate\openout\svn@write=\jobname.svn \immediate\write\svn@write{% \@percentchar\space SVN cache^^J% \noexpand\def\noexpand\svnrev{\@svn@rev}^^J% \noexpand\def\noexpand\svndate{\@svn@date}^^J% \noexpand\def\noexpand\svnauthor{\@svn@author}^^J% \noexpand\def\noexpand\svnyear{\@svn@year}^^J% \noexpand\def\noexpand\svnmonth{\@svn@month}^^J% \noexpand\def\noexpand\svnday{\@svn@day}^^J% \noexpand\def\noexpand\svnhour{\@svn@hour}^^J% \noexpand\def\noexpand\svnminute{\@svn@minute}^^J% \noexpand\def\noexpand\svnsecond{\@svn@second}^^J% \noexpand\def\noexpand\svntimezonehour{\@svn@timezonehour}^^J% \noexpand\def\noexpand\svntimezoneminute{\@svn@timezoneminute}^^J% } \immediate\closeout\svn@write% \fi\fi\fi\fi\fi% } % \end{macrocode} % Reread output from last compile run if it exists. % \begin{macrocode} \InputIfFileExists{\jobname.svn}{}{} % \end{macrocode} % % \Finale \endinput