summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/svn-multi/svnkw.dtx
blob: bd41645643709aef509e86b5301a2286bef74557 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
% \iffalse meta-comment
%
% Copyright (C) 2006 by Martin Scharrer <martin@scharrer-online.de>
% -----------------------------------------------------------------
% 
% This file may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.2
% 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.2 or later is part of all distributions of LaTeX 
% version 1999/12/01 or later.
%
% \fi
%
% \iffalse
%<*driver>
\ProvidesFile{svnkw.dtx}
%</driver>
%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%<package>\ProvidesPackage{svnkw}
%<*package>
    [2006/05/27 v1.0 SVN Keywords]
%</package>
%
%<*driver>
\documentclass{ltxdoc}
\usepackage{svnkw}[2004/11/05]
\EnableCrossrefs         
\CodelineIndex
\RecordChanges
\begin{document}
  \DocInput{svnkw.dtx}
  \PrintChanges
  \PrintIndex
\end{document}
%</driver>
% \fi
%
% \CheckSum{0}
%
% \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}
%
% \GetFileInfo{svnkw.dtx}
%
% \DoNotIndex{\newcommand,\newenvironment}
% 
%
% \title{The \textsf{svnkw} package\thanks{This document
%   corresponds to \textsf{svnkw}~\fileversion, dated \filedate.}}
% \author{Martin Scharrer \\ \texttt{martin@scharrer-online.de}}
%
% \maketitle
%
% \section{Introduction}
% This package lets you typeset keywords of the version control system Subversion\footnote
% {Subversion homepage: 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:
% 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 axiliary 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 special date features of the |svn| package are not (yet?) supported. If
% you need them you can try to use both packages together which should work
% but is not tested by the author.
%
% \section{Usage}
%
% \subsection{Including of the Subversion keywords}
% To include your Subversion Id keywords use |\svnid| or |\svnidlong|. 
% This macros should be written very
% early in each file, i.e.\ in the preamble of the main document soon after
% |\documentclass| and |\usepackage{svnkw}| and as first in every |\include|d
% subfile before the |\chapter| macro. They do not create any output.
%
% \DescribeMacro{\svnid}
% Macro for the svn Id keyword. 
% Write the macro as |\svnid{$||Id$}| into your files and set the subversion
% property |svn:keywords| of them
% to at least '|Id|'. Subversion will expand it. A trailing colon
% with spaces after the |Id| is also valid but \textbf{everything else} will
% cause a \TeX\ parse error.
%
% The keyword content will be interpreted and
% saved in the variables (ah, macros) |\svnfilerev|, |\svnfiledate| and
% |\svnfileauthor|. The most recent values (i.e.\ with the highest revision)
% are written as |\svnrev|, |\svndate| and |\svnauthor| in a .svn-file which
% is read back at the next \LaTeX\ run. The idea is that the first variables
% holding the local values for the current file and the otheris the values for 
% the complete document.
% Nevertheless all keywords can also be typeset with |\svnkw|\marg{keyword}
% which returns the latest saved value. This macro is used internally.
%
% \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 |\svnid| or |\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 be used together.
%
% Write this as (order of arguments not meaningfull)\\
% |\svnidlong|\\
% |{$||HeadURL$}|\\
% |{$||LastChangedDate$}|\\
% |{$||LastChangedRevision$}|\\
% |{$||LastChangedBy$}|\\
% in your files and set the subversion
% property |svn:keywords| of them
% to\\'|HeadURL LastChangedDate LastChangedRevision LastChangedBy|'.
%
% \DescribeMacro{\svn}
% This macro lets you set svn keywords directly. The only argument is
% the svn keyword in the usual dollars. The dollars will be stripped
% by the macro and the rest is typeset as normal text. 
% 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 only argument
% is the keyword wrapped in dollars. 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. 
%
% \subsection{Access to the keyword values}
%
% \DescribeMacro{\svnkw}
% Keyword values can be typeset by this macro.
% 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:\\|\textsl{Revision: \svnkw{Revision}}|\\
% |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. 
%
% \DescribeMacro{\svnkwdef}
% This macro is used to define the keyword values. This is normally only
% called internally but could be used by the user to override single keywords.
% The values can then be typeset by |\svnkw|.
% Note that |\svnid| and |\svnidlong| both sets some keywords to new values
% using this macro.
%
% Note that for |\svnkw| and |\svnkwdef| all different names for one keyword
% are valid and result in the access of the same variable. So e.g.\ subversion
% treats |Rev|, |Revision| and |LastChangedRev| the same way and so does this
% macros. You can e.g.\ say |\svnkwdef{Rev}| and then typeset it with
% |\svnkw{Revision}| or |\svnkw{LastChangedRev}| if you like.
%
% \subsection{Using full author names}
% If you like to have the full author\footnote{This means subversion authors,
% e.g.\ the persons who commit changes into the svn reprository.}
% 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 |\svnRegisterAuthor| and then you can write
% e.g.\ |\svnFullAuthor{\svnauthor}| or |\svnFullAuthor{\svnfileauthor}|.
%
% \DescribeMacro{\svnRegisterAuthor}
% The usage is |\svnRegisterAuthor|\marg{username}\marg{full name} which
% registers \meta{full name} as full name for \meta{username}.
%
% \DescribeMacro{\svnFullAuthor}
% Takes the username as argument and returns the full name if it was
% registered first with |\svnRegisterAuthor| or nothing (|\relax|) else. There is
% also a star version |\svnFullAuthor*| which also returns the username in
% parentheses after the full name.

% \StopEventually{}
%
% \section{Implementation}
%
% \begin{macro}{\svn}
% Just calls TeX macro |\@svn| to strip the dollars.
%    \begin{macrocode}
\newcommand{\svn}[1]{\@svn#1}
\def\@svn$#1${#1}
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\svnkwdef}
% First we check if there is a 'setter'-macro for the keyword called
% |\svnkwdef@|\meta{keyword}. 
%    \begin{macrocode}
\newcommand{\svnkwdef}[2]{%
\@ifundefined{svnkwdef@#1}
%    \end{macrocode}
% If not we call the general macro |\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 |\svnkw|\meta{2nd 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@...}
% 'Setter'-macros for single keywords, used by |\svnkwdef|.\\The keywords |Rev|, |Author| and |Date|
% are just calling |\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 writting
%    \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 e.g. |\svnkw{LastChangedRevision}| is always be the
% same as |\svnkw{Rev}|.
% \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} % must always be numerical
\svnkwdef{Date}{}
\svnkwdef{Author}{}
\svnkwdef{Filename}{}
\svnkwdef{HeadURL}{}
%    \end{macrocode}

% \begin{macro}{\svnkw}
% Macro to get keyword value. Just calls |\svnkwARGUMENT| where |ARGUMENT| is
% the argument interpreted as text. So e.g. |\svnkw{Date}| is the same as
% |\svnkwDate| but this could be changed later so always use this interface
% to get the keyword values.
%    \begin{macrocode}
\newcommand{\svnkw}[1]{\csname svnkw#1\endcsname}
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\svn@scanId}
% Scans svn Id (after it got parsed by |\svn@readkw|). 
% Awaits only Id value without leading '|Id:|' and a trailing dollar as end
% marker. It calls
% |\@svn@updateid| to update global Id values and also sets the approbriate
% keywords. 
%    \begin{macrocode}
\def\svn@scanId#1 #2 #3 #4 #5${%
% #1 is filename, #2 is revision, #3 is date (JJJJ-MM-DD), 
% #4 is time (HH:MM:SST), #5 is author (username)
\@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@readkw}
% General macro to read keywords.
% Saves key in |\svn@key| and the value in |\svn@value|.
% We have to analyse the argument but need it in full later. So we use the submacro
% |\svn@readkw@sub| to do the scan job. Sets |\svn@case| to one of three
% cases, where the first two cases result in identical code.
%    \begin{macrocode}
\def\svn@readkw$#1${%
\svn@readkw@sub$#1: $ % call submacro to get case
\ifnum\svn@case<3
%    \end{macrocode}
% If there is no value set |\svn@value| to empty and define |\svn@key| to the
% full argument.
%    \begin{macrocode}
\def\svn@key{#1}
\let\svn@value=\svn@empty
\svn@checkkeyforcolon$#1:$ % needed for case '$kw:$'
\relax
\else
%    \end{macrocode}
% If there is a value split the argument again by calling |\svn@readkw@def|.
%    \begin{macrocode}
\svn@readkw@def$#1$ % needed to remove leading space
\fi
}

\newcount\svn@case
\let\svn@empty=\empty
%    \end{macrocode}
%
% The submacro |\svn@readkw@sub| checks if the argument ends with '|: |'. In
% order to mach always we add a '|: |' at the macro call and then test here if
% |#2| is empty. This is the case if there was no '|: |' before. We return 1
% if there was no colon which means the keyword is not yet expanded by
% Subversion.
%    \begin{macrocode}
\def\svn@readkw@sub$#1: #2${%
\def\svn@temp{#2}
\ifx\svn@temp\empty
\svn@case=1
\else
%    \end{macrocode}
% If there was an tailing '|: |' we check if |#2| is now just '|: |'
% which would be the '|: |' we added at the macro call.
%    \begin{macrocode}
\svn@checkcolon$#2$
\ifx\svn@temp\empty
%    \end{macrocode}
% If we have nothing (empty value) in |#2| return 2.
%    \begin{macrocode}
\svn@case=2
\else
%    \end{macrocode}
% If we have something in |#2| return 3.
%    \begin{macrocode}
\svn@case=3
\fi\fi
}
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\svn@readkw@def}
% Submacro for |\svn@readkw| to split argument and to save the parts.
%    \begin{macrocode}
\def\svn@readkw@def$#1: #2 ${%
\def\svn@key{#1}
\def\svn@value{#2}
}
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\svn@checkcolon}
% Checks whether value is just '|: |',
% if yes |\svn@temp| is empty.
%    \begin{macrocode}
\def\svn@checkcolon$#1: ${%
\def\svn@temp{#1}
}
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\svn@checkkeyforcolon}
% Checks whether key includes a trailing '|:|'
% and removes it. Must be called with an trailing '|:|' to always mach! So its
% check actually for tow trailing '|:|'.
%    \begin{macrocode}
\def\svn@checkkeyforcolon$#1:#2${%
\def\svn@temp{#2}
\ifx\svn@temp\empty
\else
\def\svn@key{#1}
\fi
}
%    \end{macrocode}
% \end{macro}

% Definition of  init values.
%    \begin{macrocode}
% Init values
\def\svnrev{0}  % \
\def\svndate{}  %  > Values for whole project
\def\svnauthor{}  % /
\def\svnfilerev{0} % \
\def\svnfiledate{} %  > Values for current file
\def\svnfileauthor{} % /
\def\@svn@rev{0} % \
\def\@svn@date{} %  > Values for packet internal use
\def\@svn@author{} % /
%    \end{macrocode}

% \begin{macro}{\svnid}
% We read the argument with |\svn@readkw| and provide the value to
% |\svn@scanId|.
%    \begin{macrocode}
\newcommand{\svnid}[1]{%
\svn@readkw#1 % Read keyword
\ifx\svn@value\empty % Check if value is empty
\else
\expandafter\svn@scanId\svn@value$ % Scan Id 
\fi
}
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\svnidlong}
% We clear the keyword value first to reduce the risk though bad user input.
%    \begin{macrocode}
\newcommand{\svnidlong}[4]{
\svnkwdef{HeadURL}{}%
\svnkwdef{LastChangedDate}{}%
\svnkwdef{LastChangedRevision}{0}%
\svnkwdef{LastChangedBy}{}%
%    \end{macrocode}
% Then we save the four keywords/arguments using |\svnkwsave|.
%    \begin{macrocode}
\svnkwsave{#1}\svnkwsave{#2}
\svnkwsave{#3}\svnkwsave{#4}
%    \end{macrocode}
% And update the latest values.
%    \begin{macrocode}
\@svn@updateid{\svnkw{LastChangedRevision}}{\svnkw{LastChangedDate}}%
{\svnkw{LastChangedBy}}
}
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\svnkwsave}
% Save macro. Takes a dollar wrapped keyword string, reads it though
% |\svn@readkw| and saves it using |\svnkwdef|.
%    \begin{macrocode}
\newcommand{\svnkwsave}[1]{%
\def\svn@temp{#1}
\ifx\svn@temp\empty
%% skip at empty argument
\else
\svn@readkw#1% read keyword
\svnkwdef{\svn@key}{\svn@value}
\fi
}
%    \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)
\edef\svnfilerev{#1}
\edef\svnfiledate{#2}
\edef\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 % skip rest if rev is empty
\ifnum\@svn@rev<\svnfilerev%
\edef\@svn@rev{#1}
\edef\@svn@date{#2}
\edef\@svn@author{#3}
\else\fi
\fi
}
%    \end{macrocode}
% \end{macro}

% \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}
% We test if the starred or the normal version is used and call the
% appropriate submacro |\svnFullAuthor@star| or |\svnFullAuthor@normal|.
%    \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{%
\csname svn@author@#1\endcsname #2
}
%    \end{macrocode}
% \end{macro}

%
% At the end of document we write the values to an auxiliary file.
%    \begin{macrocode}
\AtEndDocument{
%    \end{macrocode}
% We first check if we have somthing 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}
 \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\svnwrite
 \immediate\openout\svnwrite=\jobname.svn
 \immediate\write\svnwrite{\@percentchar\space SVN cache}
 \immediate\write\svnwrite{\noexpand\def\noexpand\svnrev{\@svn@rev}}
 \immediate\write\svnwrite{\noexpand\def\noexpand\svndate{\@svn@date}}
 \immediate\write\svnwrite{\noexpand\def\noexpand\svnauthor{\@svn@author}}
 \immediate\closeout\svnwrite
 \fi\fi\fi\fi
}

%    \end{macrocode}
% Reread output from last compile run if it exists.
%    \begin{macrocode}
\InputIfFileExists{\jobname.svn}{}{}
%    \end{macrocode}
%
% \Finale
\endinput