% \iffalse meta-comment % $Id: svn-prov.dtx 1049 2009-05-03 00:24:49Z martin $ % % Copyright (C) 2009 by Martin Scharrer % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c % 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.3c or later is part of all distributions of LaTeX % version 2008/05/04 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-prov.dtx, svn-prov.ins % and the derived file svn-prov.sty. % % \fi % % \iffalse %<*driver> \RequirePackage{svn-prov} \makeatletter % %<*driver|package> \def\svnprov@version{v1.\rev} % %<*driver> \ProvidesFileSVN{$Id: svn-prov.dtx 1049 2009-05-03 00:24:49Z martin $} [\svnprov@version\space DTX for \filebase.sty] \DefineFileInfoSVN[svnprov] \DefineFileInfoSVN \makeatother \documentclass{ltxdoc} \usepackage[hyperfootnotes=false]{hyperref} \makeatletter %%% Examples %%% \RequirePackage{fancyvrb} \RequirePackage{listings} \newenvironment{example} {\begingroup\VerbatimOut[gobble=4]{\jobname.exa}} {\endVerbatimOut\endgroup\formatexample} \newsavebox{\examplecodebox} \newsavebox{\exampleresultbox} \usepackage{ifthen,calc} \def\examplebeforetext{The following code:} \def\exampleaftertext{is equivalent to:} \def\formatexample{% \par\noindent\examplebeforetext \lstinputlisting{\jobname.exa}\medskip \exampleaftertext\\[\medskipamount]% {\catcode`\%=14% \input{\jobname.exa}}% \par\bigskip } \lstset{% %numbers=left, numberstyle=\scriptsize\sffamily, basicstyle=\ttfamily, stepnumber=1, language=[latex]tex, }% \usepackage{xspace} \newcommand*{\pkg}[1]{% \href{http://tug.ctan.org/pkg/#1}{\texttt{#1}}% % URL footnote (for print-out) on first appearance: \@ifundefined{seen@package@#1}{% \footnote{CTAN: \url{http://tug.ctan.org/pkg/#1}}% \@namedef{seen@package@#1}{1}% }{}% \xspace } \def\darg#1{\texttt{\frenchspacing\char`\{\$#1\$\char`\}}} \makeatother \EnableCrossrefs \CodelineIndex \RecordChanges \let\manualnewpage\newpage \listfiles \begin{document} \DocInput{svn-prov.dtx} \PrintChanges \manualnewpage \PrintIndex \end{document} % % \fi % % \CheckSum{246} % % \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{v0.922}{2009/04/26}{Initial version} % \changes{v1.}{2009/05/03}{Added \cs{DefineFileInfoSVN} macro.} % % ^^A \GetFileInfo{\jobname.dtx} % % \DoNotIndex{\newcommand,\newenvironment,\def,\edef,\gdef,\xdef,\let,\@tempa} % \DoNotIndex{\g@tempa,\textbackslash,\ifx,\if,\ifnum,\else,\fi,\relax,\space} % \DoNotIndex{\@ifnextchar,\@gobble,\@undefined,\begingroup,\endgroup,\empty} % \DoNotIndex{\expandafter,\NeedsTeXFormat} % % \title{The \textsf{svn-prov} package\\\large Use SVN Id keywords for package, % class and file header} % \author{Martin Scharrer \\ \url{martin@scharrer-online.de}} % \makeatletter % \date{Version~\svnprov@version\ - \svnprov@date} % \makeatother % % \maketitle % % \section{Introduction} % This package is directed to authors of \LaTeX\ packages and classes which use % the version control software % \href{http://subversion.tigris.org/}{Subversion}\footnote % {WWW: \url{http://subversion.tigris.org/}} (SVN) for their source files. It % introduces three macros which are Subversion variants of the standard \LaTeX\ % header macros \cs{ProvidesPackage}, \cs{ProvidesClass} and \cs{ProvidesFile} % which are used to identify package, class and other files, respectively. % Instead of providing the package/class/file name and date manually they are % extracted from a Subversion Id keywords string which % is updated automatically by every time the source file is committed to the % repository. % % A similar package exists for RCS, the pre-predecessor of Subversion, in the % \pkg{pgf} bundle which is called \texttt{pgfrcs}. % For further support for Subversion keywords see the author's other package % \pkg{svn-multi}. % % \section{Usage} % ^^A\subsection{Subversion Id Keyword} % The following macros need an Id keyword which can initially be written as % `|$||Id:$|' and will be expanded by Subversion into the following format at % the next commit:\\[\smallskipamount] % \texttt{\frenchspacing\${}Id: \meta{filename} \meta{revision} \meta{date} % \meta{time} \meta{author} \$}\\[\smallskipamount] % e.g. for the source file of this document:\\*[\smallskipamount] % |$Id: svn-prov.dtx 1049 2009-05-03 00:24:49Z martin $| % \par\smallskip % For this to work the Subversion \emph{property} \texttt{svn:keywords} must be % set to (at least) `|Id|' for the source file(s). e.g.\ using the command % line:\\[\smallskipamount] % \texttt{svn propset 'svn:keyword' 'Id' \meta{filename(s)}} % \par\smallskip % \nopagebreak[3] % More information about using Subversion in the \LaTeX\ workflow can be found in the % Prac\TeX{} Journal issue 2007-3\footnote % {URL: % \ttfamily\url{http://www.tug.org/pracjourn/2007-3/}\char`\{\href % {http://www.tug.org/pracjourn/2007-3/skiadas-svn}{skiadas-svn}\char`\|\href % {http://www.tug.org/pracjourn/2007-3/ziegenhagen}{ziegenhagen}\char`\|\href % {http://www.tug.org/pracjourn/2007-3/scharrer}{scharrer}\char`\}}. % % ^^A\subsection{Main Macros} % \manualnewpage%% % \DescribeMacro{\ProvidesPackageSVN} % \DescribeMacro{\ProvidesClassSVN} % \DescribeMacro{\ProvidesFileSVN} % \hspace*{-\parindent}\hspace{-\marginparsep} % {\oarg % {file name}\darg{Id: \ldots\ }\oarg % {Package Information (version, description)}\\* % \hspace*{-\marginparsep} % \oarg{file name}\darg{Id: \ldots\ }\oarg % {Class Information (version, description)}\\* % \hspace*{-\marginparsep} % \oarg{file name}\darg{Id: \ldots\ }\oarg % {File Information (version, description)}}. % % All of these macros await a valid Subversion Id keyword string as a mandatory % argument. The file name and date is extracted from this string. For cases when % the file source is not stored in the correct file but packed inside a % different one, like a |.dtx| file, the correct file name can be provided by an % optional argument. Because the file extension of package and class files is % predefined and therefore ignored this is not needed for them when they are % packed inside a corresponding |.dtx| file, i.e. one with the same base name. % % As with the standard macros mentioned above an optional argument can be given % afterwards which contains additional information (date, version, description) % of the package, class or file. However, the SVN macros automatically insert % the date, so only a version number and a short description should be given. If % this argument is not given a default information string is used which is shown % below as \cs{revinfo}. % % Both optional arguments can include the following macros which are only valid % inside them, but not afterwards: % \begin{description} % \item[\cs{rev}] File revision. % \item[\cs{Rev}] File revision followed by a space. % \item[\cs{revinfo}] The default information used: % ``\texttt{\frenchspacing(SVN Rev: \meta{revision})}''. % \item[\cs{filebase}] File base name (file name without extension). % \item[\cs{fileext}] File extension (without leading dot). % \item[\cs{filename}] File name. % \item[\cs{filedate}] File date (in the format YYYY/MM/DD). % \item[\cs{filerev}] File revision, like \cs{rev}. % \end{description} % % ^^A\subsection{Other Macros} % \par\medskip % \DescribeMacro{\GetFileInfoSVN}\hspace*{-\parindent}\hspace{-\marginparsep}|*| % \\[-\baselineskip]\hspace*{\parindent}The star version of this macro provides % the file information of the last file which called one of the % \cs{Provides\ldots SVN} macros. It is meant to be used inside a |.dtx| file % directly after the provide macro so that the file information can be typeset % inside the documentation. % % A `normal', non-star version is not yet implemented. % % The provided information macros are \cs{filebase}, \cs{fileext}, % \cs{filename}, \cs{filedate}, \cs{filerev} and \cs{fileinfo}. The last one % contains the file description, e.g.\ the content of the optional argument % without date and version. The other macros were already described earlier. % % \par\medskip % \DescribeMacro{\DefineFileInfoSVN}\hspace*{-\parindent}\hspace{-\marginparsep}\oarg{name} % \marginpar{\it New in v1. 2009/05/03}\\ % Defines a set of macros which provide the information collected by a previous % \cs{Provides\ldots} macro. The macros have the form % |\|\meta{name}|@|\meta{data} where \meta{name} is by default the filename % either with the file extension (general files) or without (packages and % classes). This default can be overwritten by the optional argument. % The \meta{data} stands for |version|, |rev| (revision), |date| and |info| (the % information part without the version number). % % \noindent % \textit{Example:} Applied to the |.dtx| file of this very package the % following macros are defined:\par % \begingroup % \makeatletter\centering % \begin{tabular}{ll} % Macro & Definition \\ % \hline % \cs{svn-prov.dtx@version} & \@nameuse{svn-prov.dtx@version} \\ % \cs{svn-prov.dtx@rev} & \@nameuse{svn-prov.dtx@rev} \\ % \cs{svn-prov.dtx@date} & \@nameuse{svn-prov.dtx@date} \\ % \cs{svn-prov.dtx@info} & \@nameuse{svn-prov.dtx@info} \\ % \end{tabular} % \\[\medskipamount] % The style file however would get macros like \cs{svn-prov@version}. % Because `|-|' is not a letter the macros can only be accessed using |\csname|. % Therefore the optional argument |[svnprov]| is used to name the macros % \cs{svnprov@version} etc.. % \endgroup % % % \section{Examples} % \begingroup % \def\{{\texttt{\char`\{}}% % \def\}{\texttt{\char`\}}}% % \def\ProvidesPackage#1[#2]{\texttt{\cs{ProvidesPackage}\{#1\}[#2]}\\}% % \def\ProvidesClass#1[#2]{\texttt{\cs{ProvidesClass}\{#1\}[#2]}\\}% % \def\ProvidesFile#1[#2]{\texttt{\cs{ProvidesFile}\{#1\}[#2]}\\}% % % The following examples illustrate the usage of the provided macros and how % they call the equivalent standard macros internally. The example % \emph{results} are produced by expanding the corresponding example \emph{code} % while the standard provide macros are locally redefined to typeset their own % name and arguments in verbatim style. This does not only simplifies the % generation of this document but makes this examples also test cases which % allow the package author to test the result of the defined macros. % % While mostly the package macro is used here the usage is identical to the % class and file macros. Of course before this macros are used it must be made % sure that the \texttt{svn-prov} package is loaded which is done by using the % following code direct before them:\\[\smallskipamount] % |\RequirePackage{svn-prov}|\\ % % \frenchspacing % \subsubsection*{Minimal usage} % \begin{example} % \ProvidesPackageSVN % {$Id: svn-prov.dtx 1049 2009-05-03 00:24:49Z martin $} % \end{example} % \begin{example} % \ProvidesClassSVN % {$Id: svn-prov.dtx 1049 2009-05-03 00:24:49Z martin $} % \end{example} % \begin{example} % \ProvidesFileSVN % {$Id: svn-prov.dtx 1049 2009-05-03 00:24:49Z martin $} % \end{example} % % \subsubsection*{Normal Usage} % \begin{example} % \ProvidesPackageSVN % {$Id: svn-prov.dtx 1049 2009-05-03 00:24:49Z martin $} % [v1.0 Example Description] % \end{example} % \begin{example} % \ProvidesClassSVN % {$Id: svn-prov.dtx 1049 2009-05-03 00:24:49Z martin $} % [v1.0 Example Description] % \end{example} % \begin{example} % \ProvidesFileSVN % {$Id: svn-prov.dtx 1049 2009-05-03 00:24:49Z martin $} % [v1.0 Example Description] % \end{example} % % \subsubsection*{Overwriting Name} % \begin{example} % \ProvidesPackageSVN[othername] % {$Id: svn-prov.dtx 1049 2009-05-03 00:24:49Z martin $} % [v1.0 Example Description] % \end{example} % % \subsubsection*{Overwriting Name including unneeded Extension} % \begin{example} % \ProvidesPackageSVN[othername.sty] % {$Id: svn-prov.dtx 1049 2009-05-03 00:24:49Z martin $} % [v1.0 Example Description] % \end{example} % % \subsubsection*{Overwriting Name using Macros} % \begin{example} % \ProvidesFileSVN[\filebase.cfg] % {$Id: svn-prov.dtx 1049 2009-05-03 00:24:49Z martin $} % [v1.0 Example Description] % \end{example} % % \subsubsection*{Using Macros in File Information String} % \begin{example} % \ProvidesPackageSVN % {$Id: svn-prov.dtx 1049 2009-05-03 00:24:49Z martin $} % [v1.\Rev Example Description] % \end{example} % % \subsubsection*{Adding Text to Default Information} % \begin{example} % \ProvidesPackageSVN % {$Id: svn-prov.dtx 1049 2009-05-03 00:24:49Z martin $} % [v1.\Rev Extra Text \revinfo] % \end{example} % % \subsection*{Getting the File Information} % \def\exampleaftertext{results in:} % \def\ProvidesPackage#1[#2]{}% % % \begin{example} % \ProvidesPackageSVN % {$Id: svn-prov.dtx 1049 2009-05-03 00:24:49Z martin $} % [v1.\Rev Extra Text \revinfo] % \GetFileInfoSVN* % % ... % \begin{tabular}{l@{\ :\ \ }l} % File Name & \filename \\ % File Base Name & \filebase \\ % File Extension & \fileext \\ % File Date & \filedate \\ % File Revision & \filerev \\ % File Version & \fileversion \\ % File Info & \fileinfo \\ % \end{tabular} % \end{example} % \noindent % The correct package file extension `|.sty|' for \cs{fileext} can be forced by % using |[\filebase.sty]| as a first optional argument. % % \endgroup % \StopEventually{} % \manualnewpage % \section{Implementation} % \begin{macrocode} \NeedsTeXFormat{LaTeX2e}[1999/12/01] % \end{macrocode} % % \begin{macro}{\ProvidesClassSVN} % Calls the generic macro with the original LaTeX macro and the string to be % used as filename. % \begin{macrocode} \def\ProvidesClassSVN{% \svnprov@generic\ProvidesClass{\svnprov@filebase}% } % \end{macrocode} % \end{macro} % % \begin{macro}{\ProvidesFileSVN} % Calls the generic macro with the original LaTeX macro and the string to be % used as filename. % \begin{macrocode} \def\ProvidesFileSVN{% \svnprov@generic\ProvidesFile{\svnprov@filebase.\svnprov@fileext}% } % \end{macrocode} % \end{macro} % % \begin{macro}{\ProvidesPackageSVN} % Calls the generic macro with the original LaTeX macro and the string to be % used as filename. % \begin{macrocode} \def\ProvidesPackageSVN{% \svnprov@generic\ProvidesPackage{\svnprov@filebase}% } % \end{macrocode} % \end{macro} % % \begin{macro}{\svnprov@generic} % Stores the arguments (1: original macro, 2: file mask (full filename of only % base is used?)). Then tests if a explicit file name was given as optional % argument. If not the file name from the SVN Id string is used. % \begin{macrocode} \def\svnprov@generic#1#2{% \def\svnprov@ltxprov{#1}% \def\svnprov@filemask{#2}% \@ifnextchar{[}% {\svnprov@getid}% {\svnprov@getid[\svnprov@svnfilename]}% } % \end{macrocode} % \end{macro} % % \begin{macro}{\svnprov@generic} % Saves first argument as filename and calls the scan macro with the second. % A fall-back string is provided to avoid \TeX\ parsing errors. % \begin{macrocode} \def\svnprov@getid[#1]#2{% \def\svnprov@filename{#1}% \svnprov@scanid #2\relax $% Id: unknown.xxx 0 0000-00-00 00:00:00Z user $\svnprov@endmarker } % \end{macrocode} % \end{macro} % % \begin{macro}{\svnprov@scanid} % Parses the Id string and tests if it is correct (\#1=empty, \#8=\cs{relax}). % If correct the values are stored in macros and the next macro is called. % Otherwise a warning message is printed. In both cases any remaining text of % the parsing procedure is gobbled before the next step. % \begin{macrocode} \def\svnprov@scanid#1$% Id: #2 #3 #4-#5-#6 #7 $#8{% \def\next{% \PackageWarning{svn-prov}{Did not found valid SVN Id line in file '#2'.}{}{}{}% \svnprov@gobbleopt }% \ifx\relax#1\relax \ifx\relax#8\empty \def\svnprov@svnfilename{#2}% \svnprov@splitfilename{#2}% \def\svnprov@filerev{#3}% \def\svnprov@filedate{#4/#5/#6}% \def\next{\svnprov@buildstring}% \fi \fi \expandafter\next\svnprov@gobblerest }% $ % \end{macrocode} % \end{macro} % % \begin{macro}{\svnprov@splitfilename} % Expands the argument and initialises the file base macro before it calls the % next macro with the expanded argument and a dot to protect for \TeX\ parsing % errors. The \cs{relax} is used as end marker. % \begin{macrocode} \def\svnprov@splitfilename#1{% \edef\g@tempa{#1}% \let\svnprov@filebase\@gobble \expandafter \svnprov@splitfilename@\g@tempa.\relax } % \end{macrocode} % \end{macro} % % \begin{macro}{\svnprov@splitfilename@} % The second argument is tested if it is empty (end of file name reached). If % not empty the first argument is concatenated to the file base macro and the % macro calls itself on the second argument. This ensures correct handling of % file name which contain multiple dots. % % If the second argument was empty it is tested if the file base name is still % in its initialised state which means that there is no file extension. Then the % file base is defined to the first argument and the extension as empty. % Otherwise the file extension is defined to the first argument and the file % base macro is unchanged because it is already correct. % \begin{macrocode} \def\svnprov@splitfilename@#1.#2\relax{% \if& \ifx\svnprov@filebase\@gobble \gdef\svnprov@filebase{#1}% \gdef\svnprov@fileext{}% \else \gdef\svnprov@fileext{#1}% \fi \let\next\relax \else \xdef\svnprov@filebase{\svnprov@filebase.#1}% \def\next{\svnprov@splitfilename@#2\relax}% \fi \next } % \end{macrocode} % \end{macro} % % \begin{macro}{\svnprov@gobblerest} % Simply gobbles everything up to the next endmarker. % \begin{macrocode} \def\svnprov@gobblerest#1\svnprov@endmarker{} % \end{macrocode} % \end{macro} % % \begin{macro}{\svnprov@endmarker} % This is the end marker which should never be expanded. However it gets defined % and set to an unique definition which will gobble itself if ever expanded. % \begin{macrocode} \def\svnprov@endmarker{\@gobble{svn-prov endmarker}} % \end{macrocode} % \end{macro} % % \begin{macro}{\svnprov@gobbleopt} % Gobbles an optional argument if present. % \begin{macrocode} \newcommand*\svnprov@gobbleopt[1][]{} % \end{macrocode} % \end{macro} % % \begin{macro}{\svnprov@defaultdesc} % Default description text to be used. Does not include the file date which is % prepended later. % \begin{macrocode} \def\svnprov@defaultdesc{% (SVN Rev:\space\svnprov@filerev)% } % \end{macrocode} % \end{macro} % % \begin{macro}{\svnprov@buildstring} % First aliases the internal macro to user-friendly names and then builds the % info string. Finally the stored original LaTeX macro is called with the % filename and information. % \begin{macrocode} \newcommand*\svnprov@buildstring[1][\svnprov@defaultdesc]{% \begingroup \let\rev\svnprov@filerev \let\filerev\svnprov@filerev \def\Rev{\rev\space}% \let\revinfo\svnprov@defaultdesc \let\filebase\svnprov@filebase \let\fileext\svnprov@fileext \ifx\fileversion\@undefined \def\fileversion{v0.0}% \fi \edef\filename{\filebase.\fileext}% \xdef\svnprov@filename{\svnprov@filename}% \ifx\svnprov@filename\filename\else \svnprov@splitfilename{\svnprov@filename}% \fi \let\filename\svnprov@filename \xdef\svnprov@fileinfo{#1}% \endgroup \svnprov@ltxprov{\svnprov@filemask}[\svnprov@filedate\space\svnprov@fileinfo]% } % \end{macrocode} % \end{macro} % % \begin{macro}{\GetFileInfoSVN} % At the moment this macro \textbf{must} be called with a star `|*|' which % indicated that the current file is to be used. Other arguments are not % implemented yet. % % The macro provides the file information of ``the current file'', i.e.\ the % last file which called one of the above \cs{Provides\ldots} macros. For this % the internal macros are simply copied to user-friendly names. % % This macro is inspired by the macro \cs{GetFileInfo}\marg{file name} from the % \texttt{doc} package. % \begin{macrocode} \def\GetFileInfoSVN#1{% \ifx*#1\relax \let\filebase\svnprov@filebase \let\fileext\svnprov@fileext \let\filename\svnprov@filename \let\filedate\svnprov@filedate \let\filerev\svnprov@filerev \expandafter\svnprov@getversion \svnprov@fileinfo\relax{} \relax\svnprov@endmarker \let\fileversion\svnprov@fileversion \let\fileinfo\svnprov@fileinfoonly \else \PackageError{svn-prov}{Macro \textbackslash GetFileInfoSVN without '*' is not implemented yet.}{}{}{}% \fi } % \end{macrocode} % \end{macro} % % \begin{macro}{\DefineFileInfoSVN} % Defines macros in the form |\|\meta{filename}|@|\meta{xxx}, where \meta{xxx} % is date, version, rev(ision) and info. % \begin{macrocode} \newcommand*\DefineFileInfoSVN[1][\svnprov@filemask]{% \expandafter\svnprov@getversion \svnprov@fileinfo\relax{} \relax\svnprov@endmarker \expandafter \let\csname#1@date\endcsname\svnprov@filedate \expandafter \let\csname#1@version\endcsname\svnprov@fileversion \expandafter \let\csname#1@rev\endcsname\svnprov@filerev \expandafter \let\csname#1@info\endcsname\svnprov@fileinfoonly } % \end{macrocode} % \end{macro} % % \begin{macro}{\svnprov@getversion} % Splits the string at the first space into arguments \#1 (version) and \#2 % (info). Argument \#3 will be empty if there was no space in the string. % \begin{macrocode} \def\svnprov@getversion#1 #2\relax#3\svnprov@endmarker{% \if&% \def\svnprov@fileversion{??}% \else \def\svnprov@fileversion{#1}% \def\svnprov@fileinfoonly{#2}% \fi } % \end{macrocode} % \end{macro} % % Finally, call the macro for this package itself. % \begin{macrocode} \ProvidesPackageSVN{$Id: svn-prov.dtx 1049 2009-05-03 00:24:49Z martin $}% [\svnprov@version\space Package Date/Version from SVN Keywords] % \end{macrocode} % % \Finale