Repository files navigation

40ANTS-DOC Documentation Generator

About this fork

This system is a fork of MGL-PAX.

There are a few reasons, why I've created the fork.

The main goal is to extract a core features into the 40ants-doc system with as little dependencies as possible. This is important, because with MGL-PAX's style, you define documentation sections in your library's code, which makes it dependent on the documentation system. However, heavy weight dependencies like IRONCLAD, 3BMD or SWANK should not be required.

The seconds goal was to refactor a 3.5k lines of pax.lisp file into a smaller modules to make navigation easier. This will help any person who will decide to learn how the documentation builder works. Also, granular design will make it possible loading subsystems like SLIME or SLY integration.

The third goal was to make documentation processing more sequential and hackable. To introduce hooks for adding new markup languages, and HTML themes.

Why this fork is different

Here are features already implemented in this fork:

  • Core system 40ants-doc now has only two dependencies on NAMED-READTABLES and PYTHONIC-STRING-READER. If you want to compile a documentation, load 40ants-doc-full system which will download such dependencies as markdown parser and more.
  • Now you don't have to import any locative symbols into your package. Import only a defsection macro and it will be enough to define documentation for your library!
  • Added a warning mechanism, which will issue such warnings on words which looks like a symbol, but when real symbol or reference is absent:

WARNING: Unable to find target for reference #<XREF "FIND-SOURCE" GENERIC-FUNCTION> mentioned at 40Ants Doc Manual / Extension API / Reference Based Extensions

  • Documentation processing now uses CommonDoc as intermediate format, and markup languages other than Markdown can be supported.
  • Added a JS search index which will work when you are hosting pages on a static website like GitHub pages.
  • It is possible to render pages in multiple formats and having cross references between them. See Multiple Formats.

I'm planning to extend this fork even more. Read todo section to learn about proposed features or start a new discussion on the GitHub to suggest a new feature.

See full list of changes in the ChangeLog section.

Full Documentation

Read full documentation at site 40ants.com/doc/.

Tutorial

40ants-doc provides an extremely poor man's Explorable Programming environment. Narrative primarily lives in so called sections that mix markdown docstrings with references to functions, variables, etc, all of which should probably have their own docstrings.

The primary focus is on making code easily explorable by using SLIME's M-. (slime-edit-definition). See how to enable some fanciness in Emacs Integration. Generating documentation from sections and all the referenced items in Markdown or HTML format is also implemented.

With the simplistic tools provided, one may accomplish similar effects as with Literate Programming, but documentation is generated from code, not vice versa and there is no support for chunking yet. Code is first, code must look pretty, documentation is code.

When the code is loaded into the lisp, pressing M-. in SLIME on the name of the section will take you there. Sections can also refer to other sections, packages, functions, etc and you can keep exploring.

Here is an example of how it all works together:

(uiop:define-package #:foo-random
(:nicknames #:40ants-doc-full/tutorial)
(:documentation "This package provides various utilities for
random. See @FOO-RANDOM-MANUAL.")
(:use #:common-lisp
#:40ants-doc)
(:import-from #:40ants-doc/ignored-words
#:ignore-words-in-package)
(:export #:foo-random-state
#:state
#:*foo-state*
#:gaussian-random
#:uniform-random))
(in-package foo-random)
(defsection @foo-random-manual (:title "Foo Random manual"
:ignore-words ("FOO"))
"Here you describe what's common to all the referenced (and
exported) functions that follow. They work with *FOO-STATE*,
and have a :RANDOM-STATE keyword arg. Also explain when to
choose which."
(foo-random-state class)
(state (reader foo-random-state))
"Hey we can also print states!"
(print-object (method () (foo-random-state t)))
(*foo-state* variable)
(gaussian-random function)
(uniform-random function)
;; this is a subsection
(@foo-random-examples section))
(defclass foo-random-state ()
((state :reader state
:documentation "Returns random foo's state.")))
(defmethod print-object ((object foo-random-state) stream)
(print-unreadable-object (object stream :type t)))
(defvar *foo-state* (make-instance 'foo-random-state)
"Much like *RANDOM-STATE* but uses the FOO algorithm.")
(defun uniform-random (limit &key (random-state *foo-state*))
"Return a random number from the between 0 and LIMIT (exclusive)
uniform distribution."
(declare (ignore limit random-state))
nil)
(defun gaussian-random (stddev &key (random-state *foo-state*))
"Return not a random number from a zero mean normal distribution with
STDDEV."
(declare (ignore stddev random-state))
nil)
(defsection @foo-random-examples (:title "Examples")
"Let's see the transcript of a real session of someone working
with FOO:
```cl-transcript
(values (princ :hello) (list 1 2))
.. HELLO
=> :HELLO
=> (1 2)
(make-instance 'foo-random-state)
==> #<FOO-RANDOM-STATE >
```")

Generating documentation in a very stripped down markdown format is easy:

(40ants-doc-full/builder:render-to-string
@foo-random-manual
:format:markdown)

For this example, the generated markdown would look like this:

<aid="x-28FOO-RANDOM-3A-3A-40FOO-RANDOM-MANUAL-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29"></a>
# Foo Random manual
Here you describe what's common to all the referenced (and
exported) functions that follow. They work with [`*foo-state*`][2133],
and have a `:RANDOM-STATE` keyword arg. Also explain when to
choose which.
<aid="x-28FOO-RANDOM-3AFOO-RANDOM-STATE-20CLASS-29"></a>
## [class](ebf3)`foo-random:foo-random-state` ()
<aid="x-28FOO-RANDOM-3ASTATE-20-2840ANTS-DOC-2FLOCATIVES-3AREADER-20FOO-RANDOM-3AFOO-RANDOM-STATE-29-29"></a>
## [reader](01ce)`foo-random:state` (foo-random-state) ()
Returns random foo's state.
Hey we can also print states!
<aid="x-28PRINT-OBJECT-20-28METHOD-20NIL-20-28FOO-RANDOM-3AFOO-RANDOM-STATE-20T-29-29-29"></a>
## [method](7656)`common-lisp:print-object` (object foo-random-state) stream
<aid="x-28FOO-RANDOM-3A-2AFOO-STATE-2A-20-28VARIABLE-29-29"></a>
## [variable](1a03)`foo-random:*foo-state*` #<foo-random-state >
Much like `*RANDOM-STATE*` but uses the `FOO` algorithm.
<aid="x-28FOO-RANDOM-3AGAUSSIAN-RANDOM-20FUNCTION-29"></a>
## [function](19bc)`foo-random:gaussian-random` stddev &key (random-state \*foo-state\*)
Return not a random number from a zero mean normal distribution with
`STDDEV`.
<aid="x-28FOO-RANDOM-3AUNIFORM-RANDOM-20FUNCTION-29"></a>
## [function](2e1e)`foo-random:uniform-random` limit &key (random-state \*foo-state\*)
Return a random number from the between 0 and `LIMIT` (exclusive)
uniform distribution.
<aid="x-28FOO-RANDOM-3A-3A-40FOO-RANDOM-EXAMPLES-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29"></a>
## Examples
Let's see the transcript of a real session of someone working
with `FOO`:
```cl-transcript(values (princ :hello) (list 1 2)).. HELLO=> :HELLO=> (1 2)(make-instance 'foo-random-state)==> #<FOO-RANDOM-STATE >```[2133]: #x-28FOO-RANDOM-3A-2AFOO-STATE-2A-20-28VARIABLE-29-29[ebf3]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L35[01ce]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L36[7656]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L39[1a03]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L42[2e1e]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L45[19bc]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L51

MGL-PAX supported the plain text format which was more readble when viewed from a simple text editor, but I've dropped support for plain text in this fork because most time documentation are read in the browser these days.

To render into the files, use 40ants-doc-full/builder:render-to-files and 40ants-doc-full/builder:update-asdf-system-docs functions.

Last one can even generate documentation for different, but related libraries at the same time with the output going to different files, but with cross-page links being automatically added for symbols mentioned in docstrings. See Generating Documentation for some convenience functions to cover the most common cases.

Note how (*FOO-STATE* VARIABLE) in the defsection form includes its documentation in @FOO-RANDOM-MANUAL. The symbols variable and function are just two instances of 'locatives' which are used in defsection to refer to definitions tied to symbols. See Locative Types.

The transcript in the code block tagged with cl-transcript is automatically checked for up-to-dateness. See Transcripts.

TODO

  • Refactor code and make a core package with only a few dependencies.
  • Add warnings on UPPERCASED symbols in docstrings which aren't found in the package and can't be cross referenced.
  • Support SLY and make both SLIME and SLY integrations optional.
  • Add a search facility which will build an index for static file like Sphinx does.
  • Separate markup parsing and result rendering code to support markups other than Markdown and HTML.
  • Add a new section type to render ChangeLog.
  • Support custom HTML themes.
  • Generate RSS or Atom feed out of changelog items, defined with 40ants-doc/changelog:defchangelog macro.
  • Make some warnings compile-time for defsection and show them in the Emacs, if possible.

[generated by 40ANTS-DOC]

About

Flexible documentation generator for Common Lisp projects.

Topics

Resources

Stars

28 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

40ANTS-DOC Documentation Generator

About this fork

This system is a fork of MGL-PAX.

There are a few reasons, why I've created the fork.

The main goal is to extract a core features into the 40ants-doc system with as little dependencies as possible. This is important, because with MGL-PAX's style, you define documentation sections in your library's code, which makes it dependent on the documentation system. However, heavy weight dependencies like IRONCLAD, 3BMD or SWANK should not be required.

The seconds goal was to refactor a 3.5k lines of pax.lisp file into a smaller modules to make navigation easier. This will help any person who will decide to learn how the documentation builder works. Also, granular design will make it possible loading subsystems like SLIME or SLY integration.

The third goal was to make documentation processing more sequential and hackable. To introduce hooks for adding new markup languages, and HTML themes.

Why this fork is different

Here are features already implemented in this fork:

  • Core system 40ants-doc now has only two dependencies on NAMED-READTABLES and PYTHONIC-STRING-READER. If you want to compile a documentation, load 40ants-doc-full system which will download such dependencies as markdown parser and more.
  • Now you don't have to import any locative symbols into your package. Import only a defsection macro and it will be enough to define documentation for your library!
  • Added a warning mechanism, which will issue such warnings on words which looks like a symbol, but when real symbol or reference is absent:

WARNING: Unable to find target for reference #<XREF "FIND-SOURCE" GENERIC-FUNCTION> mentioned at 40Ants Doc Manual / Extension API / Reference Based Extensions

  • Documentation processing now uses CommonDoc as intermediate format, and markup languages other than Markdown can be supported.
  • Added a JS search index which will work when you are hosting pages on a static website like GitHub pages.
  • It is possible to render pages in multiple formats and having cross references between them. See Multiple Formats.

I'm planning to extend this fork even more. Read todo section to learn about proposed features or start a new discussion on the GitHub to suggest a new feature.

See full list of changes in the ChangeLog section.

Full Documentation

Read full documentation at site 40ants.com/doc/.

Tutorial

40ants-doc provides an extremely poor man's Explorable Programming environment. Narrative primarily lives in so called sections that mix markdown docstrings with references to functions, variables, etc, all of which should probably have their own docstrings.

The primary focus is on making code easily explorable by using SLIME's M-. (slime-edit-definition). See how to enable some fanciness in Emacs Integration. Generating documentation from sections and all the referenced items in Markdown or HTML format is also implemented.

With the simplistic tools provided, one may accomplish similar effects as with Literate Programming, but documentation is generated from code, not vice versa and there is no support for chunking yet. Code is first, code must look pretty, documentation is code.

When the code is loaded into the lisp, pressing M-. in SLIME on the name of the section will take you there. Sections can also refer to other sections, packages, functions, etc and you can keep exploring.

Here is an example of how it all works together:

(uiop:define-package #:foo-random
(:nicknames #:40ants-doc-full/tutorial)
(:documentation "This package provides various utilities for
random. See @FOO-RANDOM-MANUAL.")
(:use #:common-lisp
#:40ants-doc)
(:import-from #:40ants-doc/ignored-words
#:ignore-words-in-package)
(:export #:foo-random-state
#:state
#:*foo-state*
#:gaussian-random
#:uniform-random))
(in-package foo-random)
(defsection @foo-random-manual (:title "Foo Random manual"
:ignore-words ("FOO"))
"Here you describe what's common to all the referenced (and
exported) functions that follow. They work with *FOO-STATE*,
and have a :RANDOM-STATE keyword arg. Also explain when to
choose which."
(foo-random-state class)
(state (reader foo-random-state))
"Hey we can also print states!"
(print-object (method () (foo-random-state t)))
(*foo-state* variable)
(gaussian-random function)
(uniform-random function)
;; this is a subsection
(@foo-random-examples section))
(defclass foo-random-state ()
((state :reader state
:documentation "Returns random foo's state.")))
(defmethod print-object ((object foo-random-state) stream)
(print-unreadable-object (object stream :type t)))
(defvar *foo-state* (make-instance 'foo-random-state)
"Much like *RANDOM-STATE* but uses the FOO algorithm.")
(defun uniform-random (limit &key (random-state *foo-state*))
"Return a random number from the between 0 and LIMIT (exclusive)
uniform distribution."
(declare (ignore limit random-state))
nil)
(defun gaussian-random (stddev &key (random-state *foo-state*))
"Return not a random number from a zero mean normal distribution with
STDDEV."
(declare (ignore stddev random-state))
nil)
(defsection @foo-random-examples (:title "Examples")
"Let's see the transcript of a real session of someone working
with FOO:
```cl-transcript
(values (princ :hello) (list 1 2))
.. HELLO
=> :HELLO
=> (1 2)
(make-instance 'foo-random-state)
==> #<FOO-RANDOM-STATE >
```")

Generating documentation in a very stripped down markdown format is easy:

(40ants-doc-full/builder:render-to-string
@foo-random-manual
:format:markdown)

For this example, the generated markdown would look like this:

<aid="x-28FOO-RANDOM-3A-3A-40FOO-RANDOM-MANUAL-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29"></a>
# Foo Random manual
Here you describe what's common to all the referenced (and
exported) functions that follow. They work with [`*foo-state*`][2133],
and have a `:RANDOM-STATE` keyword arg. Also explain when to
choose which.
<aid="x-28FOO-RANDOM-3AFOO-RANDOM-STATE-20CLASS-29"></a>
## [class](ebf3)`foo-random:foo-random-state` ()
<aid="x-28FOO-RANDOM-3ASTATE-20-2840ANTS-DOC-2FLOCATIVES-3AREADER-20FOO-RANDOM-3AFOO-RANDOM-STATE-29-29"></a>
## [reader](01ce)`foo-random:state` (foo-random-state) ()
Returns random foo's state.
Hey we can also print states!
<aid="x-28PRINT-OBJECT-20-28METHOD-20NIL-20-28FOO-RANDOM-3AFOO-RANDOM-STATE-20T-29-29-29"></a>
## [method](7656)`common-lisp:print-object` (object foo-random-state) stream
<aid="x-28FOO-RANDOM-3A-2AFOO-STATE-2A-20-28VARIABLE-29-29"></a>
## [variable](1a03)`foo-random:*foo-state*` #<foo-random-state >
Much like `*RANDOM-STATE*` but uses the `FOO` algorithm.
<aid="x-28FOO-RANDOM-3AGAUSSIAN-RANDOM-20FUNCTION-29"></a>
## [function](19bc)`foo-random:gaussian-random` stddev &key (random-state \*foo-state\*)
Return not a random number from a zero mean normal distribution with
`STDDEV`.
<aid="x-28FOO-RANDOM-3AUNIFORM-RANDOM-20FUNCTION-29"></a>
## [function](2e1e)`foo-random:uniform-random` limit &key (random-state \*foo-state\*)
Return a random number from the between 0 and `LIMIT` (exclusive)
uniform distribution.
<aid="x-28FOO-RANDOM-3A-3A-40FOO-RANDOM-EXAMPLES-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29"></a>
## Examples
Let's see the transcript of a real session of someone working
with `FOO`:
```cl-transcript(values (princ :hello) (list 1 2)).. HELLO=> :HELLO=> (1 2)(make-instance 'foo-random-state)==> #<FOO-RANDOM-STATE >```[2133]: #x-28FOO-RANDOM-3A-2AFOO-STATE-2A-20-28VARIABLE-29-29[ebf3]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L35[01ce]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L36[7656]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L39[1a03]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L42[2e1e]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L45[19bc]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L51

MGL-PAX supported the plain text format which was more readble when viewed from a simple text editor, but I've dropped support for plain text in this fork because most time documentation are read in the browser these days.

To render into the files, use 40ants-doc-full/builder:render-to-files and 40ants-doc-full/builder:update-asdf-system-docs functions.

Last one can even generate documentation for different, but related libraries at the same time with the output going to different files, but with cross-page links being automatically added for symbols mentioned in docstrings. See Generating Documentation for some convenience functions to cover the most common cases.

Note how (*FOO-STATE* VARIABLE) in the defsection form includes its documentation in @FOO-RANDOM-MANUAL. The symbols variable and function are just two instances of 'locatives' which are used in defsection to refer to definitions tied to symbols. See Locative Types.

The transcript in the code block tagged with cl-transcript is automatically checked for up-to-dateness. See Transcripts.

TODO

  • Refactor code and make a core package with only a few dependencies.
  • Add warnings on UPPERCASED symbols in docstrings which aren't found in the package and can't be cross referenced.
  • Support SLY and make both SLIME and SLY integrations optional.
  • Add a search facility which will build an index for static file like Sphinx does.
  • Separate markup parsing and result rendering code to support markups other than Markdown and HTML.
  • Add a new section type to render ChangeLog.
  • Support custom HTML themes.
  • Generate RSS or Atom feed out of changelog items, defined with 40ants-doc/changelog:defchangelog macro.
  • Make some warnings compile-time for defsection and show them in the Emacs, if possible.

[generated by 40ANTS-DOC]

About

Flexible documentation generator for Common Lisp projects.

Topics

Resources

Stars

28 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

40ANTS-DOC Documentation Generator

About this fork

This system is a fork of MGL-PAX.

There are a few reasons, why I've created the fork.

The main goal is to extract a core features into the 40ants-doc system with as little dependencies as possible. This is important, because with MGL-PAX's style, you define documentation sections in your library's code, which makes it dependent on the documentation system. However, heavy weight dependencies like IRONCLAD, 3BMD or SWANK should not be required.

The seconds goal was to refactor a 3.5k lines of pax.lisp file into a smaller modules to make navigation easier. This will help any person who will decide to learn how the documentation builder works. Also, granular design will make it possible loading subsystems like SLIME or SLY integration.

The third goal was to make documentation processing more sequential and hackable. To introduce hooks for adding new markup languages, and HTML themes.

Why this fork is different

Here are features already implemented in this fork:

  • Core system 40ants-doc now has only two dependencies on NAMED-READTABLES and PYTHONIC-STRING-READER. If you want to compile a documentation, load 40ants-doc-full system which will download such dependencies as markdown parser and more.
  • Now you don't have to import any locative symbols into your package. Import only a defsection macro and it will be enough to define documentation for your library!
  • Added a warning mechanism, which will issue such warnings on words which looks like a symbol, but when real symbol or reference is absent:

WARNING: Unable to find target for reference #<XREF "FIND-SOURCE" GENERIC-FUNCTION> mentioned at 40Ants Doc Manual / Extension API / Reference Based Extensions

  • Documentation processing now uses CommonDoc as intermediate format, and markup languages other than Markdown can be supported.
  • Added a JS search index which will work when you are hosting pages on a static website like GitHub pages.
  • It is possible to render pages in multiple formats and having cross references between them. See Multiple Formats.

I'm planning to extend this fork even more. Read todo section to learn about proposed features or start a new discussion on the GitHub to suggest a new feature.

See full list of changes in the ChangeLog section.

Full Documentation

Read full documentation at site 40ants.com/doc/.

Tutorial

40ants-doc provides an extremely poor man's Explorable Programming environment. Narrative primarily lives in so called sections that mix markdown docstrings with references to functions, variables, etc, all of which should probably have their own docstrings.

The primary focus is on making code easily explorable by using SLIME's M-. (slime-edit-definition). See how to enable some fanciness in Emacs Integration. Generating documentation from sections and all the referenced items in Markdown or HTML format is also implemented.

With the simplistic tools provided, one may accomplish similar effects as with Literate Programming, but documentation is generated from code, not vice versa and there is no support for chunking yet. Code is first, code must look pretty, documentation is code.

When the code is loaded into the lisp, pressing M-. in SLIME on the name of the section will take you there. Sections can also refer to other sections, packages, functions, etc and you can keep exploring.

Here is an example of how it all works together:

(uiop:define-package #:foo-random
(:nicknames #:40ants-doc-full/tutorial)
(:documentation "This package provides various utilities for
random. See @FOO-RANDOM-MANUAL.")
(:use #:common-lisp
#:40ants-doc)
(:import-from #:40ants-doc/ignored-words
#:ignore-words-in-package)
(:export #:foo-random-state
#:state
#:*foo-state*
#:gaussian-random
#:uniform-random))
(in-package foo-random)
(defsection @foo-random-manual (:title "Foo Random manual"
:ignore-words ("FOO"))
"Here you describe what's common to all the referenced (and
exported) functions that follow. They work with *FOO-STATE*,
and have a :RANDOM-STATE keyword arg. Also explain when to
choose which."
(foo-random-state class)
(state (reader foo-random-state))
"Hey we can also print states!"
(print-object (method () (foo-random-state t)))
(*foo-state* variable)
(gaussian-random function)
(uniform-random function)
;; this is a subsection
(@foo-random-examples section))
(defclass foo-random-state ()
((state :reader state
:documentation "Returns random foo's state.")))
(defmethod print-object ((object foo-random-state) stream)
(print-unreadable-object (object stream :type t)))
(defvar *foo-state* (make-instance 'foo-random-state)
"Much like *RANDOM-STATE* but uses the FOO algorithm.")
(defun uniform-random (limit &key (random-state *foo-state*))
"Return a random number from the between 0 and LIMIT (exclusive)
uniform distribution."
(declare (ignore limit random-state))
nil)
(defun gaussian-random (stddev &key (random-state *foo-state*))
"Return not a random number from a zero mean normal distribution with
STDDEV."
(declare (ignore stddev random-state))
nil)
(defsection @foo-random-examples (:title "Examples")
"Let's see the transcript of a real session of someone working
with FOO:
```cl-transcript
(values (princ :hello) (list 1 2))
.. HELLO
=> :HELLO
=> (1 2)
(make-instance 'foo-random-state)
==> #<FOO-RANDOM-STATE >
```")

Generating documentation in a very stripped down markdown format is easy:

(40ants-doc-full/builder:render-to-string
@foo-random-manual
:format:markdown)

For this example, the generated markdown would look like this:

<aid="x-28FOO-RANDOM-3A-3A-40FOO-RANDOM-MANUAL-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29"></a>
# Foo Random manual
Here you describe what's common to all the referenced (and
exported) functions that follow. They work with [`*foo-state*`][2133],
and have a `:RANDOM-STATE` keyword arg. Also explain when to
choose which.
<aid="x-28FOO-RANDOM-3AFOO-RANDOM-STATE-20CLASS-29"></a>
## [class](ebf3)`foo-random:foo-random-state` ()
<aid="x-28FOO-RANDOM-3ASTATE-20-2840ANTS-DOC-2FLOCATIVES-3AREADER-20FOO-RANDOM-3AFOO-RANDOM-STATE-29-29"></a>
## [reader](01ce)`foo-random:state` (foo-random-state) ()
Returns random foo's state.
Hey we can also print states!
<aid="x-28PRINT-OBJECT-20-28METHOD-20NIL-20-28FOO-RANDOM-3AFOO-RANDOM-STATE-20T-29-29-29"></a>
## [method](7656)`common-lisp:print-object` (object foo-random-state) stream
<aid="x-28FOO-RANDOM-3A-2AFOO-STATE-2A-20-28VARIABLE-29-29"></a>
## [variable](1a03)`foo-random:*foo-state*` #<foo-random-state >
Much like `*RANDOM-STATE*` but uses the `FOO` algorithm.
<aid="x-28FOO-RANDOM-3AGAUSSIAN-RANDOM-20FUNCTION-29"></a>
## [function](19bc)`foo-random:gaussian-random` stddev &key (random-state \*foo-state\*)
Return not a random number from a zero mean normal distribution with
`STDDEV`.
<aid="x-28FOO-RANDOM-3AUNIFORM-RANDOM-20FUNCTION-29"></a>
## [function](2e1e)`foo-random:uniform-random` limit &key (random-state \*foo-state\*)
Return a random number from the between 0 and `LIMIT` (exclusive)
uniform distribution.
<aid="x-28FOO-RANDOM-3A-3A-40FOO-RANDOM-EXAMPLES-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29"></a>
## Examples
Let's see the transcript of a real session of someone working
with `FOO`:
```cl-transcript(values (princ :hello) (list 1 2)).. HELLO=> :HELLO=> (1 2)(make-instance 'foo-random-state)==> #<FOO-RANDOM-STATE >```[2133]: #x-28FOO-RANDOM-3A-2AFOO-STATE-2A-20-28VARIABLE-29-29[ebf3]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L35[01ce]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L36[7656]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L39[1a03]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L42[2e1e]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L45[19bc]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L51

MGL-PAX supported the plain text format which was more readble when viewed from a simple text editor, but I've dropped support for plain text in this fork because most time documentation are read in the browser these days.

To render into the files, use 40ants-doc-full/builder:render-to-files and 40ants-doc-full/builder:update-asdf-system-docs functions.

Last one can even generate documentation for different, but related libraries at the same time with the output going to different files, but with cross-page links being automatically added for symbols mentioned in docstrings. See Generating Documentation for some convenience functions to cover the most common cases.

Note how (*FOO-STATE* VARIABLE) in the defsection form includes its documentation in @FOO-RANDOM-MANUAL. The symbols variable and function are just two instances of 'locatives' which are used in defsection to refer to definitions tied to symbols. See Locative Types.

The transcript in the code block tagged with cl-transcript is automatically checked for up-to-dateness. See Transcripts.

TODO

  • Refactor code and make a core package with only a few dependencies.
  • Add warnings on UPPERCASED symbols in docstrings which aren't found in the package and can't be cross referenced.
  • Support SLY and make both SLIME and SLY integrations optional.
  • Add a search facility which will build an index for static file like Sphinx does.
  • Separate markup parsing and result rendering code to support markups other than Markdown and HTML.
  • Add a new section type to render ChangeLog.
  • Support custom HTML themes.
  • Generate RSS or Atom feed out of changelog items, defined with 40ants-doc/changelog:defchangelog macro.
  • Make some warnings compile-time for defsection and show them in the Emacs, if possible.

[generated by 40ANTS-DOC]

About

Flexible documentation generator for Common Lisp projects.

Topics

Resources

Stars

28 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

40ANTS-DOC Documentation Generator

About this fork

This system is a fork of MGL-PAX.

There are a few reasons, why I've created the fork.

The main goal is to extract a core features into the 40ants-doc system with as little dependencies as possible. This is important, because with MGL-PAX's style, you define documentation sections in your library's code, which makes it dependent on the documentation system. However, heavy weight dependencies like IRONCLAD, 3BMD or SWANK should not be required.

The seconds goal was to refactor a 3.5k lines of pax.lisp file into a smaller modules to make navigation easier. This will help any person who will decide to learn how the documentation builder works. Also, granular design will make it possible loading subsystems like SLIME or SLY integration.

The third goal was to make documentation processing more sequential and hackable. To introduce hooks for adding new markup languages, and HTML themes.

Why this fork is different

Here are features already implemented in this fork:

  • Core system 40ants-doc now has only two dependencies on NAMED-READTABLES and PYTHONIC-STRING-READER. If you want to compile a documentation, load 40ants-doc-full system which will download such dependencies as markdown parser and more.
  • Now you don't have to import any locative symbols into your package. Import only a defsection macro and it will be enough to define documentation for your library!
  • Added a warning mechanism, which will issue such warnings on words which looks like a symbol, but when real symbol or reference is absent:

WARNING: Unable to find target for reference #<XREF "FIND-SOURCE" GENERIC-FUNCTION> mentioned at 40Ants Doc Manual / Extension API / Reference Based Extensions

  • Documentation processing now uses CommonDoc as intermediate format, and markup languages other than Markdown can be supported.
  • Added a JS search index which will work when you are hosting pages on a static website like GitHub pages.
  • It is possible to render pages in multiple formats and having cross references between them. See Multiple Formats.

I'm planning to extend this fork even more. Read todo section to learn about proposed features or start a new discussion on the GitHub to suggest a new feature.

See full list of changes in the ChangeLog section.

Full Documentation

Read full documentation at site 40ants.com/doc/.

Tutorial

40ants-doc provides an extremely poor man's Explorable Programming environment. Narrative primarily lives in so called sections that mix markdown docstrings with references to functions, variables, etc, all of which should probably have their own docstrings.

The primary focus is on making code easily explorable by using SLIME's M-. (slime-edit-definition). See how to enable some fanciness in Emacs Integration. Generating documentation from sections and all the referenced items in Markdown or HTML format is also implemented.

With the simplistic tools provided, one may accomplish similar effects as with Literate Programming, but documentation is generated from code, not vice versa and there is no support for chunking yet. Code is first, code must look pretty, documentation is code.

When the code is loaded into the lisp, pressing M-. in SLIME on the name of the section will take you there. Sections can also refer to other sections, packages, functions, etc and you can keep exploring.

Here is an example of how it all works together:

(uiop:define-package #:foo-random
(:nicknames #:40ants-doc-full/tutorial)
(:documentation "This package provides various utilities for
random. See @FOO-RANDOM-MANUAL.")
(:use #:common-lisp
#:40ants-doc)
(:import-from #:40ants-doc/ignored-words
#:ignore-words-in-package)
(:export #:foo-random-state
#:state
#:*foo-state*
#:gaussian-random
#:uniform-random))
(in-package foo-random)
(defsection @foo-random-manual (:title "Foo Random manual"
:ignore-words ("FOO"))
"Here you describe what's common to all the referenced (and
exported) functions that follow. They work with *FOO-STATE*,
and have a :RANDOM-STATE keyword arg. Also explain when to
choose which."
(foo-random-state class)
(state (reader foo-random-state))
"Hey we can also print states!"
(print-object (method () (foo-random-state t)))
(*foo-state* variable)
(gaussian-random function)
(uniform-random function)
;; this is a subsection
(@foo-random-examples section))
(defclass foo-random-state ()
((state :reader state
:documentation "Returns random foo's state.")))
(defmethod print-object ((object foo-random-state) stream)
(print-unreadable-object (object stream :type t)))
(defvar *foo-state* (make-instance 'foo-random-state)
"Much like *RANDOM-STATE* but uses the FOO algorithm.")
(defun uniform-random (limit &key (random-state *foo-state*))
"Return a random number from the between 0 and LIMIT (exclusive)
uniform distribution."
(declare (ignore limit random-state))
nil)
(defun gaussian-random (stddev &key (random-state *foo-state*))
"Return not a random number from a zero mean normal distribution with
STDDEV."
(declare (ignore stddev random-state))
nil)
(defsection @foo-random-examples (:title "Examples")
"Let's see the transcript of a real session of someone working
with FOO:
```cl-transcript
(values (princ :hello) (list 1 2))
.. HELLO
=> :HELLO
=> (1 2)
(make-instance 'foo-random-state)
==> #<FOO-RANDOM-STATE >
```")

Generating documentation in a very stripped down markdown format is easy:

(40ants-doc-full/builder:render-to-string
@foo-random-manual
:format:markdown)

For this example, the generated markdown would look like this:

<aid="x-28FOO-RANDOM-3A-3A-40FOO-RANDOM-MANUAL-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29"></a>
# Foo Random manual
Here you describe what's common to all the referenced (and
exported) functions that follow. They work with [`*foo-state*`][2133],
and have a `:RANDOM-STATE` keyword arg. Also explain when to
choose which.
<aid="x-28FOO-RANDOM-3AFOO-RANDOM-STATE-20CLASS-29"></a>
## [class](ebf3)`foo-random:foo-random-state` ()
<aid="x-28FOO-RANDOM-3ASTATE-20-2840ANTS-DOC-2FLOCATIVES-3AREADER-20FOO-RANDOM-3AFOO-RANDOM-STATE-29-29"></a>
## [reader](01ce)`foo-random:state` (foo-random-state) ()
Returns random foo's state.
Hey we can also print states!
<aid="x-28PRINT-OBJECT-20-28METHOD-20NIL-20-28FOO-RANDOM-3AFOO-RANDOM-STATE-20T-29-29-29"></a>
## [method](7656)`common-lisp:print-object` (object foo-random-state) stream
<aid="x-28FOO-RANDOM-3A-2AFOO-STATE-2A-20-28VARIABLE-29-29"></a>
## [variable](1a03)`foo-random:*foo-state*` #<foo-random-state >
Much like `*RANDOM-STATE*` but uses the `FOO` algorithm.
<aid="x-28FOO-RANDOM-3AGAUSSIAN-RANDOM-20FUNCTION-29"></a>
## [function](19bc)`foo-random:gaussian-random` stddev &key (random-state \*foo-state\*)
Return not a random number from a zero mean normal distribution with
`STDDEV`.
<aid="x-28FOO-RANDOM-3AUNIFORM-RANDOM-20FUNCTION-29"></a>
## [function](2e1e)`foo-random:uniform-random` limit &key (random-state \*foo-state\*)
Return a random number from the between 0 and `LIMIT` (exclusive)
uniform distribution.
<aid="x-28FOO-RANDOM-3A-3A-40FOO-RANDOM-EXAMPLES-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29"></a>
## Examples
Let's see the transcript of a real session of someone working
with `FOO`:
```cl-transcript(values (princ :hello) (list 1 2)).. HELLO=> :HELLO=> (1 2)(make-instance 'foo-random-state)==> #<FOO-RANDOM-STATE >```[2133]: #x-28FOO-RANDOM-3A-2AFOO-STATE-2A-20-28VARIABLE-29-29[ebf3]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L35[01ce]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L36[7656]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L39[1a03]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L42[2e1e]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L45[19bc]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L51

MGL-PAX supported the plain text format which was more readble when viewed from a simple text editor, but I've dropped support for plain text in this fork because most time documentation are read in the browser these days.

To render into the files, use 40ants-doc-full/builder:render-to-files and 40ants-doc-full/builder:update-asdf-system-docs functions.

Last one can even generate documentation for different, but related libraries at the same time with the output going to different files, but with cross-page links being automatically added for symbols mentioned in docstrings. See Generating Documentation for some convenience functions to cover the most common cases.

Note how (*FOO-STATE* VARIABLE) in the defsection form includes its documentation in @FOO-RANDOM-MANUAL. The symbols variable and function are just two instances of 'locatives' which are used in defsection to refer to definitions tied to symbols. See Locative Types.

The transcript in the code block tagged with cl-transcript is automatically checked for up-to-dateness. See Transcripts.

TODO

  • Refactor code and make a core package with only a few dependencies.
  • Add warnings on UPPERCASED symbols in docstrings which aren't found in the package and can't be cross referenced.
  • Support SLY and make both SLIME and SLY integrations optional.
  • Add a search facility which will build an index for static file like Sphinx does.
  • Separate markup parsing and result rendering code to support markups other than Markdown and HTML.
  • Add a new section type to render ChangeLog.
  • Support custom HTML themes.
  • Generate RSS or Atom feed out of changelog items, defined with 40ants-doc/changelog:defchangelog macro.
  • Make some warnings compile-time for defsection and show them in the Emacs, if possible.

[generated by 40ANTS-DOC]

About

Flexible documentation generator for Common Lisp projects.

Topics

Resources

Stars

28 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

40ANTS-DOC Documentation Generator

About this fork

This system is a fork of MGL-PAX.

There are a few reasons, why I've created the fork.

The main goal is to extract a core features into the 40ants-doc system with as little dependencies as possible. This is important, because with MGL-PAX's style, you define documentation sections in your library's code, which makes it dependent on the documentation system. However, heavy weight dependencies like IRONCLAD, 3BMD or SWANK should not be required.

The seconds goal was to refactor a 3.5k lines of pax.lisp file into a smaller modules to make navigation easier. This will help any person who will decide to learn how the documentation builder works. Also, granular design will make it possible loading subsystems like SLIME or SLY integration.

The third goal was to make documentation processing more sequential and hackable. To introduce hooks for adding new markup languages, and HTML themes.

Why this fork is different

Here are features already implemented in this fork:

  • Core system 40ants-doc now has only two dependencies on NAMED-READTABLES and PYTHONIC-STRING-READER. If you want to compile a documentation, load 40ants-doc-full system which will download such dependencies as markdown parser and more.
  • Now you don't have to import any locative symbols into your package. Import only a defsection macro and it will be enough to define documentation for your library!
  • Added a warning mechanism, which will issue such warnings on words which looks like a symbol, but when real symbol or reference is absent:

WARNING: Unable to find target for reference #<XREF "FIND-SOURCE" GENERIC-FUNCTION> mentioned at 40Ants Doc Manual / Extension API / Reference Based Extensions

  • Documentation processing now uses CommonDoc as intermediate format, and markup languages other than Markdown can be supported.
  • Added a JS search index which will work when you are hosting pages on a static website like GitHub pages.
  • It is possible to render pages in multiple formats and having cross references between them. See Multiple Formats.

I'm planning to extend this fork even more. Read todo section to learn about proposed features or start a new discussion on the GitHub to suggest a new feature.

See full list of changes in the ChangeLog section.

Full Documentation

Read full documentation at site 40ants.com/doc/.

Tutorial

40ants-doc provides an extremely poor man's Explorable Programming environment. Narrative primarily lives in so called sections that mix markdown docstrings with references to functions, variables, etc, all of which should probably have their own docstrings.

The primary focus is on making code easily explorable by using SLIME's M-. (slime-edit-definition). See how to enable some fanciness in Emacs Integration. Generating documentation from sections and all the referenced items in Markdown or HTML format is also implemented.

With the simplistic tools provided, one may accomplish similar effects as with Literate Programming, but documentation is generated from code, not vice versa and there is no support for chunking yet. Code is first, code must look pretty, documentation is code.

When the code is loaded into the lisp, pressing M-. in SLIME on the name of the section will take you there. Sections can also refer to other sections, packages, functions, etc and you can keep exploring.

Here is an example of how it all works together:

(uiop:define-package #:foo-random
(:nicknames #:40ants-doc-full/tutorial)
(:documentation "This package provides various utilities for
random. See @FOO-RANDOM-MANUAL.")
(:use #:common-lisp
#:40ants-doc)
(:import-from #:40ants-doc/ignored-words
#:ignore-words-in-package)
(:export #:foo-random-state
#:state
#:*foo-state*
#:gaussian-random
#:uniform-random))
(in-package foo-random)
(defsection @foo-random-manual (:title "Foo Random manual"
:ignore-words ("FOO"))
"Here you describe what's common to all the referenced (and
exported) functions that follow. They work with *FOO-STATE*,
and have a :RANDOM-STATE keyword arg. Also explain when to
choose which."
(foo-random-state class)
(state (reader foo-random-state))
"Hey we can also print states!"
(print-object (method () (foo-random-state t)))
(*foo-state* variable)
(gaussian-random function)
(uniform-random function)
;; this is a subsection
(@foo-random-examples section))
(defclass foo-random-state ()
((state :reader state
:documentation "Returns random foo's state.")))
(defmethod print-object ((object foo-random-state) stream)
(print-unreadable-object (object stream :type t)))
(defvar *foo-state* (make-instance 'foo-random-state)
"Much like *RANDOM-STATE* but uses the FOO algorithm.")
(defun uniform-random (limit &key (random-state *foo-state*))
"Return a random number from the between 0 and LIMIT (exclusive)
uniform distribution."
(declare (ignore limit random-state))
nil)
(defun gaussian-random (stddev &key (random-state *foo-state*))
"Return not a random number from a zero mean normal distribution with
STDDEV."
(declare (ignore stddev random-state))
nil)
(defsection @foo-random-examples (:title "Examples")
"Let's see the transcript of a real session of someone working
with FOO:
```cl-transcript
(values (princ :hello) (list 1 2))
.. HELLO
=> :HELLO
=> (1 2)
(make-instance 'foo-random-state)
==> #<FOO-RANDOM-STATE >
```")

Generating documentation in a very stripped down markdown format is easy:

(40ants-doc-full/builder:render-to-string
@foo-random-manual
:format:markdown)

For this example, the generated markdown would look like this:

<aid="x-28FOO-RANDOM-3A-3A-40FOO-RANDOM-MANUAL-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29"></a>
# Foo Random manual
Here you describe what's common to all the referenced (and
exported) functions that follow. They work with [`*foo-state*`][2133],
and have a `:RANDOM-STATE` keyword arg. Also explain when to
choose which.
<aid="x-28FOO-RANDOM-3AFOO-RANDOM-STATE-20CLASS-29"></a>
## [class](ebf3)`foo-random:foo-random-state` ()
<aid="x-28FOO-RANDOM-3ASTATE-20-2840ANTS-DOC-2FLOCATIVES-3AREADER-20FOO-RANDOM-3AFOO-RANDOM-STATE-29-29"></a>
## [reader](01ce)`foo-random:state` (foo-random-state) ()
Returns random foo's state.
Hey we can also print states!
<aid="x-28PRINT-OBJECT-20-28METHOD-20NIL-20-28FOO-RANDOM-3AFOO-RANDOM-STATE-20T-29-29-29"></a>
## [method](7656)`common-lisp:print-object` (object foo-random-state) stream
<aid="x-28FOO-RANDOM-3A-2AFOO-STATE-2A-20-28VARIABLE-29-29"></a>
## [variable](1a03)`foo-random:*foo-state*` #<foo-random-state >
Much like `*RANDOM-STATE*` but uses the `FOO` algorithm.
<aid="x-28FOO-RANDOM-3AGAUSSIAN-RANDOM-20FUNCTION-29"></a>
## [function](19bc)`foo-random:gaussian-random` stddev &key (random-state \*foo-state\*)
Return not a random number from a zero mean normal distribution with
`STDDEV`.
<aid="x-28FOO-RANDOM-3AUNIFORM-RANDOM-20FUNCTION-29"></a>
## [function](2e1e)`foo-random:uniform-random` limit &key (random-state \*foo-state\*)
Return a random number from the between 0 and `LIMIT` (exclusive)
uniform distribution.
<aid="x-28FOO-RANDOM-3A-3A-40FOO-RANDOM-EXAMPLES-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29"></a>
## Examples
Let's see the transcript of a real session of someone working
with `FOO`:
```cl-transcript(values (princ :hello) (list 1 2)).. HELLO=> :HELLO=> (1 2)(make-instance 'foo-random-state)==> #<FOO-RANDOM-STATE >```[2133]: #x-28FOO-RANDOM-3A-2AFOO-STATE-2A-20-28VARIABLE-29-29[ebf3]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L35[01ce]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L36[7656]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L39[1a03]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L42[2e1e]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L45[19bc]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L51

MGL-PAX supported the plain text format which was more readble when viewed from a simple text editor, but I've dropped support for plain text in this fork because most time documentation are read in the browser these days.

To render into the files, use 40ants-doc-full/builder:render-to-files and 40ants-doc-full/builder:update-asdf-system-docs functions.

Last one can even generate documentation for different, but related libraries at the same time with the output going to different files, but with cross-page links being automatically added for symbols mentioned in docstrings. See Generating Documentation for some convenience functions to cover the most common cases.

Note how (*FOO-STATE* VARIABLE) in the defsection form includes its documentation in @FOO-RANDOM-MANUAL. The symbols variable and function are just two instances of 'locatives' which are used in defsection to refer to definitions tied to symbols. See Locative Types.

The transcript in the code block tagged with cl-transcript is automatically checked for up-to-dateness. See Transcripts.

TODO

  • Refactor code and make a core package with only a few dependencies.
  • Add warnings on UPPERCASED symbols in docstrings which aren't found in the package and can't be cross referenced.
  • Support SLY and make both SLIME and SLY integrations optional.
  • Add a search facility which will build an index for static file like Sphinx does.
  • Separate markup parsing and result rendering code to support markups other than Markdown and HTML.
  • Add a new section type to render ChangeLog.
  • Support custom HTML themes.
  • Generate RSS or Atom feed out of changelog items, defined with 40ants-doc/changelog:defchangelog macro.
  • Make some warnings compile-time for defsection and show them in the Emacs, if possible.

[generated by 40ANTS-DOC]

About

Flexible documentation generator for Common Lisp projects.

Topics

Resources

Stars

28 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

40ANTS-DOC Documentation Generator

About this fork

This system is a fork of MGL-PAX.

There are a few reasons, why I've created the fork.

The main goal is to extract a core features into the 40ants-doc system with as little dependencies as possible. This is important, because with MGL-PAX's style, you define documentation sections in your library's code, which makes it dependent on the documentation system. However, heavy weight dependencies like IRONCLAD, 3BMD or SWANK should not be required.

The seconds goal was to refactor a 3.5k lines of pax.lisp file into a smaller modules to make navigation easier. This will help any person who will decide to learn how the documentation builder works. Also, granular design will make it possible loading subsystems like SLIME or SLY integration.

The third goal was to make documentation processing more sequential and hackable. To introduce hooks for adding new markup languages, and HTML themes.

Why this fork is different

Here are features already implemented in this fork:

  • Core system 40ants-doc now has only two dependencies on NAMED-READTABLES and PYTHONIC-STRING-READER. If you want to compile a documentation, load 40ants-doc-full system which will download such dependencies as markdown parser and more.
  • Now you don't have to import any locative symbols into your package. Import only a defsection macro and it will be enough to define documentation for your library!
  • Added a warning mechanism, which will issue such warnings on words which looks like a symbol, but when real symbol or reference is absent:

WARNING: Unable to find target for reference #<XREF "FIND-SOURCE" GENERIC-FUNCTION> mentioned at 40Ants Doc Manual / Extension API / Reference Based Extensions

  • Documentation processing now uses CommonDoc as intermediate format, and markup languages other than Markdown can be supported.
  • Added a JS search index which will work when you are hosting pages on a static website like GitHub pages.
  • It is possible to render pages in multiple formats and having cross references between them. See Multiple Formats.

I'm planning to extend this fork even more. Read todo section to learn about proposed features or start a new discussion on the GitHub to suggest a new feature.

See full list of changes in the ChangeLog section.

Full Documentation

Read full documentation at site 40ants.com/doc/.

Tutorial

40ants-doc provides an extremely poor man's Explorable Programming environment. Narrative primarily lives in so called sections that mix markdown docstrings with references to functions, variables, etc, all of which should probably have their own docstrings.

The primary focus is on making code easily explorable by using SLIME's M-. (slime-edit-definition). See how to enable some fanciness in Emacs Integration. Generating documentation from sections and all the referenced items in Markdown or HTML format is also implemented.

With the simplistic tools provided, one may accomplish similar effects as with Literate Programming, but documentation is generated from code, not vice versa and there is no support for chunking yet. Code is first, code must look pretty, documentation is code.

When the code is loaded into the lisp, pressing M-. in SLIME on the name of the section will take you there. Sections can also refer to other sections, packages, functions, etc and you can keep exploring.

Here is an example of how it all works together:

(uiop:define-package #:foo-random
(:nicknames #:40ants-doc-full/tutorial)
(:documentation "This package provides various utilities for
random. See @FOO-RANDOM-MANUAL.")
(:use #:common-lisp
#:40ants-doc)
(:import-from #:40ants-doc/ignored-words
#:ignore-words-in-package)
(:export #:foo-random-state
#:state
#:*foo-state*
#:gaussian-random
#:uniform-random))
(in-package foo-random)
(defsection @foo-random-manual (:title "Foo Random manual"
:ignore-words ("FOO"))
"Here you describe what's common to all the referenced (and
exported) functions that follow. They work with *FOO-STATE*,
and have a :RANDOM-STATE keyword arg. Also explain when to
choose which."
(foo-random-state class)
(state (reader foo-random-state))
"Hey we can also print states!"
(print-object (method () (foo-random-state t)))
(*foo-state* variable)
(gaussian-random function)
(uniform-random function)
;; this is a subsection
(@foo-random-examples section))
(defclass foo-random-state ()
((state :reader state
:documentation "Returns random foo's state.")))
(defmethod print-object ((object foo-random-state) stream)
(print-unreadable-object (object stream :type t)))
(defvar *foo-state* (make-instance 'foo-random-state)
"Much like *RANDOM-STATE* but uses the FOO algorithm.")
(defun uniform-random (limit &key (random-state *foo-state*))
"Return a random number from the between 0 and LIMIT (exclusive)
uniform distribution."
(declare (ignore limit random-state))
nil)
(defun gaussian-random (stddev &key (random-state *foo-state*))
"Return not a random number from a zero mean normal distribution with
STDDEV."
(declare (ignore stddev random-state))
nil)
(defsection @foo-random-examples (:title "Examples")
"Let's see the transcript of a real session of someone working
with FOO:
```cl-transcript
(values (princ :hello) (list 1 2))
.. HELLO
=> :HELLO
=> (1 2)
(make-instance 'foo-random-state)
==> #<FOO-RANDOM-STATE >
```")

Generating documentation in a very stripped down markdown format is easy:

(40ants-doc-full/builder:render-to-string
@foo-random-manual
:format:markdown)

For this example, the generated markdown would look like this:

<aid="x-28FOO-RANDOM-3A-3A-40FOO-RANDOM-MANUAL-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29"></a>
# Foo Random manual
Here you describe what's common to all the referenced (and
exported) functions that follow. They work with [`*foo-state*`][2133],
and have a `:RANDOM-STATE` keyword arg. Also explain when to
choose which.
<aid="x-28FOO-RANDOM-3AFOO-RANDOM-STATE-20CLASS-29"></a>
## [class](ebf3)`foo-random:foo-random-state` ()
<aid="x-28FOO-RANDOM-3ASTATE-20-2840ANTS-DOC-2FLOCATIVES-3AREADER-20FOO-RANDOM-3AFOO-RANDOM-STATE-29-29"></a>
## [reader](01ce)`foo-random:state` (foo-random-state) ()
Returns random foo's state.
Hey we can also print states!
<aid="x-28PRINT-OBJECT-20-28METHOD-20NIL-20-28FOO-RANDOM-3AFOO-RANDOM-STATE-20T-29-29-29"></a>
## [method](7656)`common-lisp:print-object` (object foo-random-state) stream
<aid="x-28FOO-RANDOM-3A-2AFOO-STATE-2A-20-28VARIABLE-29-29"></a>
## [variable](1a03)`foo-random:*foo-state*` #<foo-random-state >
Much like `*RANDOM-STATE*` but uses the `FOO` algorithm.
<aid="x-28FOO-RANDOM-3AGAUSSIAN-RANDOM-20FUNCTION-29"></a>
## [function](19bc)`foo-random:gaussian-random` stddev &key (random-state \*foo-state\*)
Return not a random number from a zero mean normal distribution with
`STDDEV`.
<aid="x-28FOO-RANDOM-3AUNIFORM-RANDOM-20FUNCTION-29"></a>
## [function](2e1e)`foo-random:uniform-random` limit &key (random-state \*foo-state\*)
Return a random number from the between 0 and `LIMIT` (exclusive)
uniform distribution.
<aid="x-28FOO-RANDOM-3A-3A-40FOO-RANDOM-EXAMPLES-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29"></a>
## Examples
Let's see the transcript of a real session of someone working
with `FOO`:
```cl-transcript(values (princ :hello) (list 1 2)).. HELLO=> :HELLO=> (1 2)(make-instance 'foo-random-state)==> #<FOO-RANDOM-STATE >```[2133]: #x-28FOO-RANDOM-3A-2AFOO-STATE-2A-20-28VARIABLE-29-29[ebf3]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L35[01ce]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L36[7656]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L39[1a03]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L42[2e1e]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L45[19bc]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L51

MGL-PAX supported the plain text format which was more readble when viewed from a simple text editor, but I've dropped support for plain text in this fork because most time documentation are read in the browser these days.

To render into the files, use 40ants-doc-full/builder:render-to-files and 40ants-doc-full/builder:update-asdf-system-docs functions.

Last one can even generate documentation for different, but related libraries at the same time with the output going to different files, but with cross-page links being automatically added for symbols mentioned in docstrings. See Generating Documentation for some convenience functions to cover the most common cases.

Note how (*FOO-STATE* VARIABLE) in the defsection form includes its documentation in @FOO-RANDOM-MANUAL. The symbols variable and function are just two instances of 'locatives' which are used in defsection to refer to definitions tied to symbols. See Locative Types.

The transcript in the code block tagged with cl-transcript is automatically checked for up-to-dateness. See Transcripts.

TODO

  • Refactor code and make a core package with only a few dependencies.
  • Add warnings on UPPERCASED symbols in docstrings which aren't found in the package and can't be cross referenced.
  • Support SLY and make both SLIME and SLY integrations optional.
  • Add a search facility which will build an index for static file like Sphinx does.
  • Separate markup parsing and result rendering code to support markups other than Markdown and HTML.
  • Add a new section type to render ChangeLog.
  • Support custom HTML themes.
  • Generate RSS or Atom feed out of changelog items, defined with 40ants-doc/changelog:defchangelog macro.
  • Make some warnings compile-time for defsection and show them in the Emacs, if possible.

[generated by 40ANTS-DOC]

About

Flexible documentation generator for Common Lisp projects.

Topics

Resources

Stars

28 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

40ANTS-DOC Documentation Generator

About this fork

This system is a fork of MGL-PAX.

There are a few reasons, why I've created the fork.

The main goal is to extract a core features into the 40ants-doc system with as little dependencies as possible. This is important, because with MGL-PAX's style, you define documentation sections in your library's code, which makes it dependent on the documentation system. However, heavy weight dependencies like IRONCLAD, 3BMD or SWANK should not be required.

The seconds goal was to refactor a 3.5k lines of pax.lisp file into a smaller modules to make navigation easier. This will help any person who will decide to learn how the documentation builder works. Also, granular design will make it possible loading subsystems like SLIME or SLY integration.

The third goal was to make documentation processing more sequential and hackable. To introduce hooks for adding new markup languages, and HTML themes.

Why this fork is different

Here are features already implemented in this fork:

  • Core system 40ants-doc now has only two dependencies on NAMED-READTABLES and PYTHONIC-STRING-READER. If you want to compile a documentation, load 40ants-doc-full system which will download such dependencies as markdown parser and more.
  • Now you don't have to import any locative symbols into your package. Import only a defsection macro and it will be enough to define documentation for your library!
  • Added a warning mechanism, which will issue such warnings on words which looks like a symbol, but when real symbol or reference is absent:

WARNING: Unable to find target for reference #<XREF "FIND-SOURCE" GENERIC-FUNCTION> mentioned at 40Ants Doc Manual / Extension API / Reference Based Extensions

  • Documentation processing now uses CommonDoc as intermediate format, and markup languages other than Markdown can be supported.
  • Added a JS search index which will work when you are hosting pages on a static website like GitHub pages.
  • It is possible to render pages in multiple formats and having cross references between them. See Multiple Formats.

I'm planning to extend this fork even more. Read todo section to learn about proposed features or start a new discussion on the GitHub to suggest a new feature.

See full list of changes in the ChangeLog section.

Full Documentation

Read full documentation at site 40ants.com/doc/.

Tutorial

40ants-doc provides an extremely poor man's Explorable Programming environment. Narrative primarily lives in so called sections that mix markdown docstrings with references to functions, variables, etc, all of which should probably have their own docstrings.

The primary focus is on making code easily explorable by using SLIME's M-. (slime-edit-definition). See how to enable some fanciness in Emacs Integration. Generating documentation from sections and all the referenced items in Markdown or HTML format is also implemented.

With the simplistic tools provided, one may accomplish similar effects as with Literate Programming, but documentation is generated from code, not vice versa and there is no support for chunking yet. Code is first, code must look pretty, documentation is code.

When the code is loaded into the lisp, pressing M-. in SLIME on the name of the section will take you there. Sections can also refer to other sections, packages, functions, etc and you can keep exploring.

Here is an example of how it all works together:

(uiop:define-package #:foo-random
(:nicknames #:40ants-doc-full/tutorial)
(:documentation "This package provides various utilities for
random. See @FOO-RANDOM-MANUAL.")
(:use #:common-lisp
#:40ants-doc)
(:import-from #:40ants-doc/ignored-words
#:ignore-words-in-package)
(:export #:foo-random-state
#:state
#:*foo-state*
#:gaussian-random
#:uniform-random))
(in-package foo-random)
(defsection @foo-random-manual (:title "Foo Random manual"
:ignore-words ("FOO"))
"Here you describe what's common to all the referenced (and
exported) functions that follow. They work with *FOO-STATE*,
and have a :RANDOM-STATE keyword arg. Also explain when to
choose which."
(foo-random-state class)
(state (reader foo-random-state))
"Hey we can also print states!"
(print-object (method () (foo-random-state t)))
(*foo-state* variable)
(gaussian-random function)
(uniform-random function)
;; this is a subsection
(@foo-random-examples section))
(defclass foo-random-state ()
((state :reader state
:documentation "Returns random foo's state.")))
(defmethod print-object ((object foo-random-state) stream)
(print-unreadable-object (object stream :type t)))
(defvar *foo-state* (make-instance 'foo-random-state)
"Much like *RANDOM-STATE* but uses the FOO algorithm.")
(defun uniform-random (limit &key (random-state *foo-state*))
"Return a random number from the between 0 and LIMIT (exclusive)
uniform distribution."
(declare (ignore limit random-state))
nil)
(defun gaussian-random (stddev &key (random-state *foo-state*))
"Return not a random number from a zero mean normal distribution with
STDDEV."
(declare (ignore stddev random-state))
nil)
(defsection @foo-random-examples (:title "Examples")
"Let's see the transcript of a real session of someone working
with FOO:
```cl-transcript
(values (princ :hello) (list 1 2))
.. HELLO
=> :HELLO
=> (1 2)
(make-instance 'foo-random-state)
==> #<FOO-RANDOM-STATE >
```")

Generating documentation in a very stripped down markdown format is easy:

(40ants-doc-full/builder:render-to-string
@foo-random-manual
:format:markdown)

For this example, the generated markdown would look like this:

<aid="x-28FOO-RANDOM-3A-3A-40FOO-RANDOM-MANUAL-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29"></a>
# Foo Random manual
Here you describe what's common to all the referenced (and
exported) functions that follow. They work with [`*foo-state*`][2133],
and have a `:RANDOM-STATE` keyword arg. Also explain when to
choose which.
<aid="x-28FOO-RANDOM-3AFOO-RANDOM-STATE-20CLASS-29"></a>
## [class](ebf3)`foo-random:foo-random-state` ()
<aid="x-28FOO-RANDOM-3ASTATE-20-2840ANTS-DOC-2FLOCATIVES-3AREADER-20FOO-RANDOM-3AFOO-RANDOM-STATE-29-29"></a>
## [reader](01ce)`foo-random:state` (foo-random-state) ()
Returns random foo's state.
Hey we can also print states!
<aid="x-28PRINT-OBJECT-20-28METHOD-20NIL-20-28FOO-RANDOM-3AFOO-RANDOM-STATE-20T-29-29-29"></a>
## [method](7656)`common-lisp:print-object` (object foo-random-state) stream
<aid="x-28FOO-RANDOM-3A-2AFOO-STATE-2A-20-28VARIABLE-29-29"></a>
## [variable](1a03)`foo-random:*foo-state*` #<foo-random-state >
Much like `*RANDOM-STATE*` but uses the `FOO` algorithm.
<aid="x-28FOO-RANDOM-3AGAUSSIAN-RANDOM-20FUNCTION-29"></a>
## [function](19bc)`foo-random:gaussian-random` stddev &key (random-state \*foo-state\*)
Return not a random number from a zero mean normal distribution with
`STDDEV`.
<aid="x-28FOO-RANDOM-3AUNIFORM-RANDOM-20FUNCTION-29"></a>
## [function](2e1e)`foo-random:uniform-random` limit &key (random-state \*foo-state\*)
Return a random number from the between 0 and `LIMIT` (exclusive)
uniform distribution.
<aid="x-28FOO-RANDOM-3A-3A-40FOO-RANDOM-EXAMPLES-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29"></a>
## Examples
Let's see the transcript of a real session of someone working
with `FOO`:
```cl-transcript(values (princ :hello) (list 1 2)).. HELLO=> :HELLO=> (1 2)(make-instance 'foo-random-state)==> #<FOO-RANDOM-STATE >```[2133]: #x-28FOO-RANDOM-3A-2AFOO-STATE-2A-20-28VARIABLE-29-29[ebf3]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L35[01ce]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L36[7656]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L39[1a03]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L42[2e1e]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L45[19bc]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L51

MGL-PAX supported the plain text format which was more readble when viewed from a simple text editor, but I've dropped support for plain text in this fork because most time documentation are read in the browser these days.

To render into the files, use 40ants-doc-full/builder:render-to-files and 40ants-doc-full/builder:update-asdf-system-docs functions.

Last one can even generate documentation for different, but related libraries at the same time with the output going to different files, but with cross-page links being automatically added for symbols mentioned in docstrings. See Generating Documentation for some convenience functions to cover the most common cases.

Note how (*FOO-STATE* VARIABLE) in the defsection form includes its documentation in @FOO-RANDOM-MANUAL. The symbols variable and function are just two instances of 'locatives' which are used in defsection to refer to definitions tied to symbols. See Locative Types.

The transcript in the code block tagged with cl-transcript is automatically checked for up-to-dateness. See Transcripts.

TODO

  • Refactor code and make a core package with only a few dependencies.
  • Add warnings on UPPERCASED symbols in docstrings which aren't found in the package and can't be cross referenced.
  • Support SLY and make both SLIME and SLY integrations optional.
  • Add a search facility which will build an index for static file like Sphinx does.
  • Separate markup parsing and result rendering code to support markups other than Markdown and HTML.
  • Add a new section type to render ChangeLog.
  • Support custom HTML themes.
  • Generate RSS or Atom feed out of changelog items, defined with 40ants-doc/changelog:defchangelog macro.
  • Make some warnings compile-time for defsection and show them in the Emacs, if possible.

[generated by 40ANTS-DOC]

About

Flexible documentation generator for Common Lisp projects.

Topics

Resources

Stars

28 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

40ANTS-DOC Documentation Generator

About this fork

This system is a fork of MGL-PAX.

There are a few reasons, why I've created the fork.

The main goal is to extract a core features into the 40ants-doc system with as little dependencies as possible. This is important, because with MGL-PAX's style, you define documentation sections in your library's code, which makes it dependent on the documentation system. However, heavy weight dependencies like IRONCLAD, 3BMD or SWANK should not be required.

The seconds goal was to refactor a 3.5k lines of pax.lisp file into a smaller modules to make navigation easier. This will help any person who will decide to learn how the documentation builder works. Also, granular design will make it possible loading subsystems like SLIME or SLY integration.

The third goal was to make documentation processing more sequential and hackable. To introduce hooks for adding new markup languages, and HTML themes.

Why this fork is different

Here are features already implemented in this fork:

  • Core system 40ants-doc now has only two dependencies on NAMED-READTABLES and PYTHONIC-STRING-READER. If you want to compile a documentation, load 40ants-doc-full system which will download such dependencies as markdown parser and more.
  • Now you don't have to import any locative symbols into your package. Import only a defsection macro and it will be enough to define documentation for your library!
  • Added a warning mechanism, which will issue such warnings on words which looks like a symbol, but when real symbol or reference is absent:

WARNING: Unable to find target for reference #<XREF "FIND-SOURCE" GENERIC-FUNCTION> mentioned at 40Ants Doc Manual / Extension API / Reference Based Extensions

  • Documentation processing now uses CommonDoc as intermediate format, and markup languages other than Markdown can be supported.
  • Added a JS search index which will work when you are hosting pages on a static website like GitHub pages.
  • It is possible to render pages in multiple formats and having cross references between them. See Multiple Formats.

I'm planning to extend this fork even more. Read todo section to learn about proposed features or start a new discussion on the GitHub to suggest a new feature.

See full list of changes in the ChangeLog section.

Full Documentation

Read full documentation at site 40ants.com/doc/.

Tutorial

40ants-doc provides an extremely poor man's Explorable Programming environment. Narrative primarily lives in so called sections that mix markdown docstrings with references to functions, variables, etc, all of which should probably have their own docstrings.

The primary focus is on making code easily explorable by using SLIME's M-. (slime-edit-definition). See how to enable some fanciness in Emacs Integration. Generating documentation from sections and all the referenced items in Markdown or HTML format is also implemented.

With the simplistic tools provided, one may accomplish similar effects as with Literate Programming, but documentation is generated from code, not vice versa and there is no support for chunking yet. Code is first, code must look pretty, documentation is code.

When the code is loaded into the lisp, pressing M-. in SLIME on the name of the section will take you there. Sections can also refer to other sections, packages, functions, etc and you can keep exploring.

Here is an example of how it all works together:

(uiop:define-package #:foo-random
(:nicknames #:40ants-doc-full/tutorial)
(:documentation "This package provides various utilities for
random. See @FOO-RANDOM-MANUAL.")
(:use #:common-lisp
#:40ants-doc)
(:import-from #:40ants-doc/ignored-words
#:ignore-words-in-package)
(:export #:foo-random-state
#:state
#:*foo-state*
#:gaussian-random
#:uniform-random))
(in-package foo-random)
(defsection @foo-random-manual (:title "Foo Random manual"
:ignore-words ("FOO"))
"Here you describe what's common to all the referenced (and
exported) functions that follow. They work with *FOO-STATE*,
and have a :RANDOM-STATE keyword arg. Also explain when to
choose which."
(foo-random-state class)
(state (reader foo-random-state))
"Hey we can also print states!"
(print-object (method () (foo-random-state t)))
(*foo-state* variable)
(gaussian-random function)
(uniform-random function)
;; this is a subsection
(@foo-random-examples section))
(defclass foo-random-state ()
((state :reader state
:documentation "Returns random foo's state.")))
(defmethod print-object ((object foo-random-state) stream)
(print-unreadable-object (object stream :type t)))
(defvar *foo-state* (make-instance 'foo-random-state)
"Much like *RANDOM-STATE* but uses the FOO algorithm.")
(defun uniform-random (limit &key (random-state *foo-state*))
"Return a random number from the between 0 and LIMIT (exclusive)
uniform distribution."
(declare (ignore limit random-state))
nil)
(defun gaussian-random (stddev &key (random-state *foo-state*))
"Return not a random number from a zero mean normal distribution with
STDDEV."
(declare (ignore stddev random-state))
nil)
(defsection @foo-random-examples (:title "Examples")
"Let's see the transcript of a real session of someone working
with FOO:
```cl-transcript
(values (princ :hello) (list 1 2))
.. HELLO
=> :HELLO
=> (1 2)
(make-instance 'foo-random-state)
==> #<FOO-RANDOM-STATE >
```")

Generating documentation in a very stripped down markdown format is easy:

(40ants-doc-full/builder:render-to-string
@foo-random-manual
:format:markdown)

For this example, the generated markdown would look like this:

<aid="x-28FOO-RANDOM-3A-3A-40FOO-RANDOM-MANUAL-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29"></a>
# Foo Random manual
Here you describe what's common to all the referenced (and
exported) functions that follow. They work with [`*foo-state*`][2133],
and have a `:RANDOM-STATE` keyword arg. Also explain when to
choose which.
<aid="x-28FOO-RANDOM-3AFOO-RANDOM-STATE-20CLASS-29"></a>
## [class](ebf3)`foo-random:foo-random-state` ()
<aid="x-28FOO-RANDOM-3ASTATE-20-2840ANTS-DOC-2FLOCATIVES-3AREADER-20FOO-RANDOM-3AFOO-RANDOM-STATE-29-29"></a>
## [reader](01ce)`foo-random:state` (foo-random-state) ()
Returns random foo's state.
Hey we can also print states!
<aid="x-28PRINT-OBJECT-20-28METHOD-20NIL-20-28FOO-RANDOM-3AFOO-RANDOM-STATE-20T-29-29-29"></a>
## [method](7656)`common-lisp:print-object` (object foo-random-state) stream
<aid="x-28FOO-RANDOM-3A-2AFOO-STATE-2A-20-28VARIABLE-29-29"></a>
## [variable](1a03)`foo-random:*foo-state*` #<foo-random-state >
Much like `*RANDOM-STATE*` but uses the `FOO` algorithm.
<aid="x-28FOO-RANDOM-3AGAUSSIAN-RANDOM-20FUNCTION-29"></a>
## [function](19bc)`foo-random:gaussian-random` stddev &key (random-state \*foo-state\*)
Return not a random number from a zero mean normal distribution with
`STDDEV`.
<aid="x-28FOO-RANDOM-3AUNIFORM-RANDOM-20FUNCTION-29"></a>
## [function](2e1e)`foo-random:uniform-random` limit &key (random-state \*foo-state\*)
Return a random number from the between 0 and `LIMIT` (exclusive)
uniform distribution.
<aid="x-28FOO-RANDOM-3A-3A-40FOO-RANDOM-EXAMPLES-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29"></a>
## Examples
Let's see the transcript of a real session of someone working
with `FOO`:
```cl-transcript(values (princ :hello) (list 1 2)).. HELLO=> :HELLO=> (1 2)(make-instance 'foo-random-state)==> #<FOO-RANDOM-STATE >```[2133]: #x-28FOO-RANDOM-3A-2AFOO-STATE-2A-20-28VARIABLE-29-29[ebf3]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L35[01ce]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L36[7656]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L39[1a03]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L42[2e1e]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L45[19bc]: https://github.com/40ants/doc/blob/709d3f2b7ab67bc617bff93be5219465d2d096f2/full/tutorial.lisp#L51

MGL-PAX supported the plain text format which was more readble when viewed from a simple text editor, but I've dropped support for plain text in this fork because most time documentation are read in the browser these days.

To render into the files, use 40ants-doc-full/builder:render-to-files and 40ants-doc-full/builder:update-asdf-system-docs functions.

Last one can even generate documentation for different, but related libraries at the same time with the output going to different files, but with cross-page links being automatically added for symbols mentioned in docstrings. See Generating Documentation for some convenience functions to cover the most common cases.

Note how (*FOO-STATE* VARIABLE) in the defsection form includes its documentation in @FOO-RANDOM-MANUAL. The symbols variable and function are just two instances of 'locatives' which are used in defsection to refer to definitions tied to symbols. See Locative Types.

The transcript in the code block tagged with cl-transcript is automatically checked for up-to-dateness. See Transcripts.

TODO

  • Refactor code and make a core package with only a few dependencies.
  • Add warnings on UPPERCASED symbols in docstrings which aren't found in the package and can't be cross referenced.
  • Support SLY and make both SLIME and SLY integrations optional.
  • Add a search facility which will build an index for static file like Sphinx does.
  • Separate markup parsing and result rendering code to support markups other than Markdown and HTML.
  • Add a new section type to render ChangeLog.
  • Support custom HTML themes.
  • Generate RSS or Atom feed out of changelog items, defined with 40ants-doc/changelog:defchangelog macro.
  • Make some warnings compile-time for defsection and show them in the Emacs, if possible.

[generated by 40ANTS-DOC]

About

Flexible documentation generator for Common Lisp projects.

Topics

Resources

Stars

28 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages