move pipadoc plugin loading behind plaintext file handling
[nobug.git] / pipadoc
blob96f0bdc560098eeaa611e75810562a6a130bac32
1 #!/bin/sh
3 #TIT pipadoc - Documentation extractor
4 #TIT =================================
5 #TIT Christian Thaeter <ct@pipapo.org>
6 #TIT
7 #LIC Copyright (C) Pipapo Project
8 #LIC 2009, Christian Thaeter <ct@pipapo.org>
9 #LIC
10 #LIC This program is free software; you can redistribute it and/or modify
11 #LIC it under the terms of the GNU General Public License as published by
12 #LIC the Free Software Foundation; either version 2, or (at your option)
13 #LIC any later version.
14 #LIC
15 #LIC This program is distributed in the hope that it will be useful,
16 #LIC but WITHOUT ANY WARRANTY; without even the implied warranty of
17 #LIC MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 #LIC GNU General Public License for more details.
19 #LIC
20 #LIC You should have received a copy of the GNU General Public License
21 #LIC along with this program; if not, contact Christian Thaeter <ct@pipapo.org>.
22 #LIC
24 #INT Embedding documentation in program source files often yields the problem that the
25 #INT structure of a program is most often not the optimal structure for the associated documentation.
26 #INT Still there are good reasons to maintain documentation together with the source right at the code
27 #INT which defines the documented functionality. Pipadoc addresses this problem by extracting
28 #INT special comments out of a source file and let one define rules how to bring the
29 #INT documentation into proper order.
30 #INT
31 #INT Pipadoc only extracts and reorders the text from it special comments, it never ever looks at the
32 #INT sourcecode or the text it extracts.
33 #INT
34 #INT This is somewhat similar to ``Literate Programming'' but it puts the emphasis back to the code.
35 #INT There is no need to extract the source from a literate source and in contrast to ``Literate Programming''
36 #INT the order of source and text is defined by the programmer and programming language constraints.
37 #INT
38 #INT Pipadoc is programming language and documentation system agnostic, all it requires is that
39 #INT the programming language has some line comments or block comments where one places doc statements
40 #INT on each block line (see xref:c-example[Example for C]).
41 #INT
42 #BAS HEAD- Basic concepts; BAS; concepts
43 #BAS
44 #BAS NOTE: The following description uses the xref:ENV[default] settings for all examples.
45 #BAS
46 #BAS Pipadoc is controlled by special line comments.
47 #BAS
48 #DIR PARA Direct comments; DIR; low level control
49 #DIR
50 #DIR Line comments immediately followed by a special documentation character (the underscore `_` by default)
51 #DIR are treated as direct comments. They will appear in order of appearance in the generated output.
52 #DIR These can be used to do some boilerplate stuff. Usually one wants to define a controlling document and
53 #DIR use this direct comments only there, since using them in different files might yield unexpected results
54 #DIR since the order then depends on the load order of the files.
55 #DIR ----
56 #DIR //_ This is a direct comment,
57 #DIR //_ it will appear just verbatim in the generated output
58 #DIR ----
59 #DIR
60 #KEY PARA Keys; KEY; sectioning content
61 #KEY
62 #KEY A line comment immediately followed by a alphanumeric keyword (including the `_` underscore character)
63 #KEY is treated as key, all such keyed comments can later be placed in intended order with
64 #KEY a xref:SUB[substitution] comment.
65 #KEY ----
66 #KEY //example This text will later be inserted where one uses the `//=example` substitution.
67 #KEY //example All example lines are appended there in order even if they are defined at different
68 #KEY //example places or in different files
69 #KEY ----
70 #KEY
71 #SOR PARA Sorted Keys; SOR; sorted sections
72 #SOR A key can be appended with a dot `.` and a non-space string. This string will then be used to sort
73 #SOR these lines alphabetically. This can be used to create sorted indices and glossars, as well as reordering
74 #SOR paragraphs in stored under one primary key.
75 #SOR ----
76 #SOR //example.omega This is sorted after the next line
77 #SOR //example.alpha comes before the omega line above
78 #SOR ----
79 #SOR
80 #VAR PARA Variable Substitution; VAR; variable substitution
81 #VAR The strings `%%FILE%%` and `%%LINE%%` are substituted with the filename and line currently proccessed.
82 #VAR They can be used in the secondary sort key, as well as in documentation text directly. When one wants
83 #VAR to use this words verbatim then then percent signs must be doubled as in `%%%FILE%%%` or `%%%LINE%%%`.
84 #VAR
86 #SUB PARA Substitutions; SUB; paste sections
87 #SUB A line comment immediately followed by a special `substitution` character (the equal `=` sign by default)
88 #SUB followed by a xref:KEY[key] will be replaced by the text defined under that key. The rest of the line
89 #SUB is ignored and can be used as comment.
90 #SUB ----
91 #SUB //=example this will insert anything defined under `//example` here
92 #SUB ----
93 #SUB
95 #USE HEAD- Documenting Files; USE; usage
96 #USE
97 #USE Usually one wants to write documentation in more or less smaller blocks which later shall be
98 #USE brought into proper order. The xref:SUB[substitutions] feature is the key for this. One writes
99 #USE his documentation blocks with comments which later get replaced by the right sorting key and
100 #USE finally brought into (alphabetical) stable-sort order. You might take a look at the pipadoc
101 #USE source itself to see it in action.
102 #USE
104 #PLU HEAD- Plugins; PLU; extending pipadoc
105 #PLU Pipadoc can be extended with awk. This plugins are `awk` snippets which are included into
106 #PLU the processing stream. Take a look at the supplied plugins to figure out how it works.
107 #PLU
108 #PLU Supplied Plugins
109 #PLU ~~~~~~~~~~~~~~~~
110 #PLU
111 #PLU .asciidoc
112 #PLU Defines HEAD and PARA macros for headers and paragaphs with automatic index generation
113 #PLU in asciidoc
114 #PLU
115 #PLU .verbatim
116 #PLU Lets one include the code _before_ an pipadoc comment with the magic word `VERBATIM`.
117 #PLU Used to include code in the documentation.
118 #PLU
120 #ENV HEAD~ Environment Variables; ENV; configuration
121 #ENV
122 #ENV `COM`::
123 #ENV Defines the line-comment character used in the source file.
124 #ENV Defaults to `//` (C++/C99) if not set. Set this to `#` for shell
125 #ENV like languages.
126 test "$COM" || COM='//'
127 #ENV `DOC`::
128 #ENV The Documentation character which must follow a line comment to be recognized
129 #ENV by pipadoc as documentation. Either one for local definitions or two for global
130 #ENV definitions are used. Defaults to `_` and needs rarely to be changed.
131 test "$DOC" || DOC='_'
132 #ENV `SUB`::
133 #ENV Substitution character. Defaults to `=` and rarely needs to be changed.
134 #ENV See xref:SUB[substitutions] for details.
135 #ENV
136 test "$SUB" || SUB='='
137 #ENV [[ENVSXT]]
138 #ENV `SXT`::
139 #ENV Section eXTention. Defaults to `.txt`.
140 #ENV See xref:SXT[plaintext files] for details.
141 #ENV
142 test "$SXT" || SXT='.txt'
143 #ENV `PLG`::
144 #ENV Extension for xref:PLU[awk plugins] to implement generic text manipulations and macros.
145 #ENV Defaults to '.pawk'
146 #ENV
147 test "$PLG" || PLG='.pawk'
149 #SXT HEAD- Documentation Only Files; SXT; plain documentation
150 #SXT
151 #SXT One can write documentation without the need of pipadoc special comments in files
152 #SXT which have a configured extension (see the xref:ENVSXT[SXT] environment variable).
153 #SXT Each line in such a file which does not have a pipadoc special comment is then implicitly
154 #SXT prepended with the line comment sequence and the basename of that file, for example
155 #SXT lines in a file 'foo.txt' will be treated as if they where written with `//foo ` in front of
156 #SXT them. Later xref:SUB[substitutions] can be used to organize the document.
157 #SXT When such a file has an ordinary pipadoc special comment line then this takes precedence over
158 #SXT the implicit commenting.
159 #SXT
160 #INV HEAD- Invocation; INV; running pipadoc
161 #INV
162 #INV Pipadoc is called with a list of files from which the documentation shall be extracted.
163 #INV The extracted documentation is piped to stdout. No other command line options are available.
164 #INV
165 #INV There are few xref:ENV[environment variables] to do basic configuration.
166 #INV
169 sources=($(for element in "$@"; do [[ $element != *$PLG ]] && printf "%s " $element; done))
170 plugins=($(for element in "$@"; do [[ $element = *$PLG ]] && printf "%s " $element; done))
173 # here we go
174 gawk -f /dev/fd/3 ${COM:+-v com="$COM"} ${DOC:+-v doc="$DOC"} ${SUB:+-v subs="$SUB"} ${SXT:+-v sxt="$SXT"} "${sources[@]}" 3<<EOF
176 function append(idx, sort, text)
178 if (idx in maybe)
179 maybe[idx] = maybe[idx] "\n."sort" " text
180 else
181 maybe[idx] = "."sort" "text
184 # Plaintext file handling
185 FILENAME ~ sxt "\$" && \$0 !~ "^" com {
186 match(FILENAME, "/?([^/]*)" sxt "\$", p)
187 \$0 = com p[1] " " \$0
190 $([[ ${#plugins[*]} -gt 0 ]] && cat "${plugins[@]}")
192 # Substitution
193 match(\$0, com subs "([[:alpha:]][[:alnum:]_]*)", s) {
195 subst[n] = s[1]
196 next
199 # doc comment
200 match(\$0, com doc "([[:space:]](.*))?\$", s) {
202 output[n] = s[2]
203 next
206 # record all other comments which may be candidate comments
207 match(\$0, "(.*)" com "([[:alpha:]][[:alnum:]_]*)(([.]([^[:space:]]*)))?([[:space:]](.*))?", m) && m[1] !~ com {
208 gsub("%%FILE%%", " FILE%FILE ", m[5])
209 gsub("%%LINE%%", " LINE%LINE ", m[5])
210 gsub("%LINE%", FNR, m[5])
211 gsub("%FILE%", FILENAME, m[5])
212 gsub(" FILE%FILE ", "%FILE%", m[5])
213 gsub(" LINE%LINE ", "%LINE%", m[5])
215 gsub("%%FILE%%", " FILE%FILE ", m[7])
216 gsub("%%LINE%%", " LINE%LINE ", m[7])
217 gsub("%LINE%", FNR, m[7])
218 gsub("%FILE%", FILENAME, m[7])
219 gsub(" FILE%FILE ", "%FILE%", m[7])
220 gsub(" LINE%LINE ", "%LINE%", m[7])
222 append(m[2], m[5] , m[7])
223 next
226 # finally output
227 END {
228 for (i=1; i<=n; ++i)
230 if (i in output)
231 print output[i]
232 else
234 nelements = split(maybe[subst[i]], s, "\n")
235 delete tosort
236 #split("", tosort)
238 for (j=1; j <= nelements; ++j)
240 match(s[j], "[.]([^[:space:]]*) (.*)", entries)
242 if (entries[1] in tosort)
243 tosort[entries[1]] = tosort[entries[1]] "\n" entries[2]
244 else
245 tosort[entries[1]] = entries[2]
248 elements = asorti(tosort, sorted)
249 for (k = 1; k <= elements; ++k)
251 print tosort[sorted[k]]
258 #Document structure:
259 #=TIT Titles and stuff
260 #=INT Introduction
261 #=BAS Basics
262 #=DIR Direct comments
263 #=KEY Key comments
264 #=SOR sorted keys
265 #=VAR Variable substitutions
266 #=SUB Substitutions
267 #=INV Invocation
268 #=USE Real usage
269 #=SXT Plain Documentation
270 #=PLU Plugins
271 #_ Appendix
272 #_ --------
273 #=ENV Environment variables
274 #=APP Appendix
275 #_ License
276 #_ ~~~~~~~
277 #_ [[LIC]]
278 #_ ....
279 #=LIC
280 #_ ....
281 #_ Index
282 #_ -----
283 #=index
285 # Examples and appendixes:
286 #USE .A small C99 Program
287 #USE [source,c]
288 #USE ----
289 #USE //intro This is the well known ``Hello World'' example
290 #USE //glos.helloworld A common program to show examples for programming language and tools
291 #USE
292 #USE //depends Only the Standard C library is needed
293 #USE #include <stdio.h>
294 #USE
295 #USE int main(int argc, char* argv[])
296 #USE {
297 #USE //hello print the first commandline argument
298 #USE //glos.argument the text you pass to the programm when calling it from the shell
299 #USE //hello if no argument is given, then exit silently
300 #USE if (argc > 1)
301 #USE printf("Hello %s\n", argv[1]);
302 #USE return 0;
303 #USE }
304 #USE
305 #USE // Now the document structure with substitutions:
306 #USE //_ Yet another 'Hello' program
307 #USE //_
308 #USE //=intro introduction first right after the title
309 #USE //intro
310 #USE //=hello The main documentation
311 #USE //_
312 #USE //_ Appendix
313 #USE //_ Dependencies:
314 #USE //=depends
315 #USE //_ Glossary
316 #USE //=glos glossary will be sorted
317 #USE ----
318 #USE
319 #USE Runnning this through pipadoc gives following output:
320 #USE ----
321 #USE Yet another 'Hello' program
322 #USE
323 #USE This is the well known ``Hello World'' example
324 #USE
325 #USE print the first commandline argument
326 #USE if no argument is given, then exit silently
327 #USE
328 #USE Appendix
329 #USE Dependencies:
330 #USE Only the Standard C library is needed
331 #USE Glossary
332 #USE the text you pass to the programm when calling it from the shell
333 #USE A common program to show examples for programming language and tools
334 #USE ----
335 #USE
337 #APP [[c-example]]
338 #APP
339 #APP .Using C block comments with pipadoc: +example.c+
340 #APP ----
341 #APP /*
342 #APP //_ this is a documentation line
343 #APP */
344 #APP ----
345 #APP use `pipadoc example.c` to process the documentation.
346 #APP
347 #APP Creating this File
348 #APP ~~~~~~~~~~~~~~~~~~
349 #APP Pipadoc itself is documented with asciidoc, one can extract the asciidoc source with
350 #APP by:
351 #APP ----
352 #APP COM='#' ./pipadoc pipadoc asciidoc.pawk >pipadoc.txt
353 #APP ----
354 #APP And then further process the generated asciidoc.txt with the asciidoc toolchain.
355 #APP