Automatically generate documentation from comments in R7RS Scheme code
git clone https://git.8pit.net/scmdoc.git
1## Demo 2 3A sample documentation for [chibi parse][chibi parse] is available: https://files.8pit.net/scmdoc-demo/ 4 5## Motivation 6 7Tooling for inline source code documentation of Scheme code is rare. 8Existing tools like [chibi-doc][chibi-doc source] actually interpret/load the code and thus do not work if, for example, some utilized libraries are not available for `chibi-scheme`. 9To overcome this limitation `scmdoc` takes a different approach were the code is not interpreted and only parsed. 10This allows `scmdoc` to be applicable to different R⁷RS implementations ([CHICKEN][chicken web], [Guile][guile web], [Gambit][gambit web], [Racket][racket r7rs], …) as long as the input is syntactically valid R⁷RS. 11Pattern matching is then performed on parsed S-expressions to format them nicely in the generated documentation (e.g. matching for procedure definitions, library definitions, …). 12In its essence, `scmdoc` is therefore a glorified pattern matcher for S-expressions. 13 14## Status 15 16This is currently a proof-of-concept. 17The R7RS parser should support the majority of the standard but is not well tested. 18A HTML generation backend is available and several R7RS expressions are formatted at the moment, including more complex ones like record type definitions. 19 20## Installation 21 22This software is known to compile with GHC 9.4.4 and can be installed by running the following commands inside the repository: 23 24 $ cabal install 25 26## Tests 27 28Unit tests are available and can be invoked using the following command: 29 30 $ cabal test 31 32Furthermore, integration tests are available. 33These tests require the `scmdoc` binary to be available in your `$PATH`. 34Furthermore, they require [Tidy][tidy web] to be installed. 35If these prerequisites are satisfied run the following command to execute these tests: 36 37 $ ./golden/run.sh 38 39## Approach 40 41The `scmdoc` tool is structured around R7RS Scheme libraries. 42For a given Scheme source file, it extracts all library declaration which are prefixed by a doc comment. 43Contrary to a normal Scheme comment, a doc comment has the form `;;>`. 44As such, `scmdoc` would for example recognize the following library declaration: 45 46 ;;> My awesome scheme library 47 (define-library (sample-library) 48 …) 49 50For each recognized library, `scmdoc` expands all includes in the declaration and then extracts all exported and documented expressions from the library. 51The recognized expressions are then further processed by high-level formatters which recognize S-expressions constituting Scheme procedure definitions et cetera. 52These formatters are available in `src/SchemeDoc/Format` and essentially perform pattern matching on arbitrary S-expressions. 53For example, the formatter for Scheme procedure definitions roughly looks as follows: 54 55 mkProcedure :: Sexp -> Maybe Procedure 56 mkProcedure (List ((Id "define"):(List ((Id defid):arglst)):bodylst)) = 57 -- Convert the S-expression into an algebraic data structure 58 -- which represents Scheme Procedure definitions and can be 59 -- formated. 60 mkProcedure _ = Nothing 61 62In the future, it should be possible to also supply custom formatters to, for example, to generate documentation for definitions defined using custom macros. 63Apart from formatters, `scmdoc` also has a WiP concept of "expanders" which perform primitive comment-preserving macro expansion. 64This feature is presently used to expand record type definitions (`define-record-type`) to primitive procedure definitions which are then formatted using the procedure formatter. 65 66## Usage 67 68The `scmdoc` tool generates HTML from a Scheme input defining a R7RS library. 69As described above, only documented S-expressions for which a documentation formatter is available are included in the generated documentation. 70In order to demonstrate generation of HTML documentation consider the following input file called `library.scm`: 71 72 ;;> This is my documented library. 73 (define-library (math arithmetic) 74 (export my-proc my-magic-constant) 75 76 ;; This is a normal comment which is not considered by scmdoc. 77 (begin 78 ;;> this is a hidden helper function which is not exported. 79 (define my-mult *) 80 81 ;;> my-proc multiplies the given value with two. 82 (define (my-proc x) 83 (my-mult x 2)) 84 85 ;;> A magic constant. 86 (define my-magic-constant 42))) 87 88In order to generate HTML documentation, using `scmdoc`, for this library run the following command: 89 90 $ scmdoc library.scm 91 92Within documentation comments, it is possible to use Markdown markup. 93 94### Section Comments 95 96Due to the lack of type information, it is difficult to meaningfully group Scheme program components. 97For this reason, `scmdoc` relies on manually inserted *section comments* for grouping. 98A section comment is a documentation comment which starts with a `|` character and is followed by an empty line and a normal documentation comment. 99The section comment corresponds to the section title, the documentation comment following it functions as the section description.100For example:101102 ;;>| Multiplication Procedures103 ;;>104 ;;> Procedures for performing multiplication.105106 ;;> Multiply two signed values.107 (define (multS x y) …)108109 ;;> Multiply two unsigned values.110 (define (multU x y) …)111112This will group the procedure `multS` and `multU` into the section *“Multiplication Procedures”*.113Every section comment consists of a section title (as indicated by `;;>|`) and a mandatory section description.114Each documented Scheme library *should* contain at least one section comment.115If the Scheme library doesn't contain any section comments, then everything is grouped under an arbitrary “Declarations” section.116117### Look and Feel118119The HTML generated by `scmdoc` should be compatible with any [classless CSS framework][cssbed web].120By default, the [water.css][water.css web] dark theme is used.121A custom CSS stylesheet can be specified using the `--stylesheet` command-line.122For more information on classless CSS frameworks refer to [this blog post][greenfield classless].123124## Related Work125126A loose, incomplete collection of similar work on the documentation of Scheme code:127128* [Scribble][scribble web]: The documentation tool used by the Racket programming language129* [chibi-doc][chibi-doc source]: The documentation tool used by chibi-scheme (inspired by Scribble)130* [SchemeDoc][schemedoc web]: Extract documentation from Scheme comments using [LAML][laml web]131* MOLE: [Scheme Program Source Code as a Semistructured Data][mole paper]132* [`l2t`][l2t web] (aka. LiSP2TeX): A literate programming utility for inserting Scheme into TeX files133* [schemeweb][schemeweb ctan]: Simple literate programming for Scheme with LaTeX134135## Development136137Please format all code with [fourmolu](https://github.com/fourmolu/fourmolu).138For convince, a pre-commit Git hook for checking if files are properly formated is provided in `.githooks`.139It can be activated using:140141 $ git config --local core.hooksPath .githooks142143## License144145This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation.146Furthermore, this code presently includes the Scheme number parser from [Husk Scheme][husk-scheme github] which is licensed under MIT.147148[chicken web]: https://call-cc.org149[guile web]: https://www.gnu.org/software/guile/150[gambit web]: https://www.gambitscheme.org/151[racket r7rs]: https://pkgs.racket-lang.org/package/r7rs152[chibi-doc source]: https://github.com/ashinn/chibi-scheme/blob/master/tools/chibi-doc153[husk-scheme github]: https://github.com/justinethier/husk-scheme154[schemedoc web]: https://people.cs.aau.dk/~normark/schemedoc/155[schemeweb ctan]: https://ctan.org/pkg/schemeweb156[mole paper]: http://www.schemeworkshop.org/2001/lisovsky.pdf157[laml web]: http://people.cs.aau.dk/~normark/laml-distributions/laml/158[l2t web]: https://christian.queinnec.org/WWW/l2t.html159[scribble web]: https://docs.racket-lang.org/scribble/index.html160[cssbed web]: https://www.cssbed.com/161[greenfield classless]: https://ubershmekel.medium.com/the-next-css-frontier-classless-5e66f3f25fdd162[water.css web]: https://watercss.kognise.dev/163[chibi parse]: https://synthcode.com/scheme/chibi/lib/chibi/parse.html164[tidy web]: https://www.html-tidy.org