master: sb-manual: automatically USE-PAX
melisgl via Sbcl-commits <[email protected]> Mon, 29 Jun 2026 12:19:59 +0000
| Newsgroups | gmane.lisp.steel-bank.cvs |
|---|---|
| Message-ID | <[email protected]> |
The branch "master" has been updated in SBCL:
via 4499dc643029f4a1ad7386937d5a245019251c1f (commit)
from 98d37dc3e3ac015e4e28747dbce279f137d78a6c (commit)
- Log -----------------------------------------------------------------
commit 4499dc643029f4a1ad7386937d5a245019251c1f
Author: Gabor Melis <[email protected]>
Date: Mon Jun 8 18:15:37 2026 +0200
sb-manual: automatically USE-PAX
Put a magic marker on the value of the variable holding the dummy
section. Variables with these markers are recognized by PAX (from
v0.4.12) as lazy sections. So, (DREF @FAKE 'SECTION) works. Then,
whenever such a reference is RESOLVEd, the function following the
magic marker is called. That function is USE-PAX in this case.
The net effect of this hack is that PAX:DOCUMENTing a fake section
will unfake it.
Export USE-PAX for the remaining cases.
---
contrib/sb-manual/TODO.md | 2 --
contrib/sb-manual/docstring.lisp | 1 +
contrib/sb-manual/manual.lisp | 45 +++++++++++++++++--------------
contrib/sb-manual/markdown.lisp | 3 ++-
contrib/sb-manual/package.lisp | 3 ++-
contrib/sb-manual/pax.lisp | 41 +++++++++++++++++++---------
contrib/sb-manual/sb-manual.texinfo | 53 +++++++++++++++++++++++++++----------
contrib/sb-manual/texinfo.lisp | 7 +++--
8 files changed, 103 insertions(+), 52 deletions(-)
diff --git a/contrib/sb-manual/TODO.md b/contrib/sb-manual/TODO.md
index 21037d0eb..0759ce6d1 100644
--- a/contrib/sb-manual/TODO.md
+++ b/contrib/sb-manual/TODO.md
@@ -16,8 +16,6 @@ image.
Alternatively, we could have `sb-bsd-sockets/manual.lisp` as a new
`SB-BSD-SOCKETS-MANUAL` module. Eh.
-# SWITCH-TO-PAX automatically?
-
# How to deal with repetitive package names?
For example, `SB-ALIEN` is `:USE`d by `SB-MANUAL` so that the section
diff --git a/contrib/sb-manual/docstring.lisp b/contrib/sb-manual/docstring.lisp
index 5ad06fb6d..455a38b53 100644
--- a/contrib/sb-manual/docstring.lisp
+++ b/contrib/sb-manual/docstring.lisp
@@ -85,6 +85,7 @@
("SB-GRAY" "SB-GRAY")
("SB-GROVEL" "SB-GROVEL")
("SB-INTROSPECT" "SB-INTROSPECT")
+ ("SB-MANUAL" "SB-MANUAL")
("SB-MD5" "SB-MD5")
("SB-POSIX" "SB-POSIX")
("SB-SEQUENCE" "SB-IMPL")
diff --git a/contrib/sb-manual/manual.lisp b/contrib/sb-manual/manual.lisp
index b3b023296..61e1f549d 100644
--- a/contrib/sb-manual/manual.lisp
+++ b/contrib/sb-manual/manual.lisp
@@ -1,36 +1,41 @@
(in-package :sb-manual)
(defsection @sb-manual (:title "sb-manual")
- "The `SB-MANUAL` module has the sections of the SBCL user manual in
- Lisp variables. The names of the variables (all start with the
- character `@`) are exported from the `SB-MANUAL` package. Sections
- are defined with the `DEFSECTION` macro:
+ "The `SB-MANUAL` module has the SBCL user manual in forms
+ mimicking `PAX:DEFSECTION`:
(defsection @example (:title \"Example\")
\"This is an example, but see the real @SB-MANUAL.\"
(print function)
(@subexample section))
- where `DEFSECTION` is a dummy implementation of
- `PAX:DEFSECTION` (see <https://github.com/melisgl/mgl-pax/>).
-
- In Slime, `\\\\M-.` on `\"@SB-MANUAL\"`, `\"print\"`, or on
- `\"@subexample\"` will take you to the respective definition. This
- makes it easy to navigate the documentation. Normal Lisp definition
- docstrings and section docstrings reference sections following the
- usual convention of uppercasing the name. Docstrings are in a subset
- of Markdown and use very little markup in general, so they are easy
- to read directly in the source.
+ The names of the variables holding the documentation are exported
+ from the `SB-MANUAL` package. Since sections are basically
+ variables, in Slime, `\\\\M-.` on `\"@SB-MANUAL\"`, `\"print\"`, or
+ on `\"@subexample\"` will take you to the respective definition.
+ This makes it easy to navigate the documentation. Normal Lisp
+ definition docstrings and section docstrings reference sections
+ following the usual convention of uppercasing the name. Docstrings
+ are in a subset of Markdown and use very little markup in general,
+ so they are easy to read directly in the source.
The official manual in Info, HTML and PDF formats is generated via
- Texinfo generated from these definitions.
-
- When \\PAX is loaded, the dummy `DEFSECTION` definitions are made
- real, so that \\PAX can work with them."
+ Texinfo generated from these definitions."
+ (@using-pax section)
(@browsing-live-with-pax section)
(@fancy-documentation-with-pax section))
-(defsection @browsing-live-with-pax (:title "Browsing Live with PAX")
+(defsection @using-pax (:title "Using \\PAX")
+ "However, `SB-MANUAL::DEFSECTION` is but a dummy implementation of
+ `PAX:DEFSECTION` to avoid a hard dependency on \\PAX.
+
+ See the `MGL-PAX` ASDF:SYSTEM or <https://github.com/melisgl/mgl-pax/>.
+
+ When \\PAX is loaded, the dummy `DEFSECTION` definitions are made
+ real, so that \\PAX can work with them."
+ (use-pax function))
+
+(defsection @browsing-live-with-pax (:title "Browsing Live with \\PAX")
"With \\PAX, you can browse the manual live. The documentation of this
feature is available at
<https://melisgl.github.io/mgl-pax-world/pax-manual.html#MGL-PAX:@BROWSING-LIVE-DOCUMENTATION%20MGL-PAX:SECTION>.
@@ -65,7 +70,7 @@
Loop, when working on documentation.")
(defsection @fancy-documentation-with-pax
- (:title "Fancy Documentation with PAX")
+ (:title "Fancy Documentation with \\PAX")
"\\PAX can generate dead documentation, too. In the SBCL sources,
`contrib/sb-manual/make-pax-docs.sh` generates the manual in plain
text, Markdown, PDF, and HTML formats. These differ from those
diff --git a/contrib/sb-manual/markdown.lisp b/contrib/sb-manual/markdown.lisp
index 34ae013a7..1959d1082 100644
--- a/contrib/sb-manual/markdown.lisp
+++ b/contrib/sb-manual/markdown.lisp
@@ -457,7 +457,8 @@
(typep (symbol-value symbol) (dummy 'section))
(let ((value (symbol-value symbol)))
(and (listp value)
- (eq (first value) 'defsection))))))
+ (listp (first value))
+ (eq (caar value) :%pax-lazy-section))))))
(when (and (not *using-pax*)
*downcase-uppercase-code*)
diff --git a/contrib/sb-manual/package.lisp b/contrib/sb-manual/package.lisp
index 200fdd96b..02a7fadc0 100644
--- a/contrib/sb-manual/package.lisp
+++ b/contrib/sb-manual/package.lisp
@@ -1,4 +1,5 @@
(locally (declare (sb-ext:muffle-conditions sb-int:package-at-variance))
(handler-bind ((sb-int:package-at-variance #'muffle-warning))
(defpackage :sb-manual
- (:use :cl :sb-alien))))
+ (:use :cl :sb-alien)
+ (:export #:use-pax))))
diff --git a/contrib/sb-manual/pax.lisp b/contrib/sb-manual/pax.lisp
index d7408632a..aaa292328 100644
--- a/contrib/sb-manual/pax.lisp
+++ b/contrib/sb-manual/pax.lisp
@@ -52,7 +52,24 @@
(defvar *definition-to-docstring-package*)
(defvar *package-to-docstring-package*)
+(defun resolve-lazy-section (&rest args)
+ (declare (ignore args))
+ (use-pax))
+
(defun use-pax ()
+ "Ensure that exported variables are `PAX:SECTION`s.
+ It is an error if the `MGL-PAX` library is not loaded.
+
+ Calling this function explicitly is rarely necessary because it is
+ called automatically:
+
+ - when `SB-MANUAL` is loaded, if PAX is present;
+
+ - when `PAX:DOCUMENT` (more precisely, `DREF:LOCATE`) is called on
+ an `SB-MANUAL` section.
+
+ The latter feature requires v0.4.12 of PAX. See the `MGL-PAX`
+ asdf:system."
(unless *using-pax*
(assert (find-package '#:mgl-pax))
;; Replace dummies with the real symbols.
@@ -75,13 +92,12 @@
(when (and (char= #\@ (aref (symbol-name symbol) 0))
(boundp symbol))
(let ((value (symbol-value symbol)))
- (assert (listp value))
- (assert (eq (first value) 'defsection))
- (assert (eq (second value) symbol))
+ (assert (and (consp value) (consp (car value ))
+ (eq (caar value) :%pax-lazy-section)))
(let ((source-location
(sb-int:info :source-location :variable symbol)))
(eval `(,(read-from-string "pax:defsection")
- ,@(subst-extras (rest value))))
+ ,@(subst-extras (rest (second value)))))
(setf (sb-int:info :source-location :variable symbol)
source-location)))))
(convert-docstring-package-overrides-to-pax)
@@ -127,26 +143,27 @@
(defmacro-dummy (defsection pax)
(name (&key (package *package*) (export t) title)
&body entries)
- (let ((defsection-form
- `(defsection ,name (:package ,package :export ,export :title ,title)
- ,@entries)))
+ (let ((value
+ `((:%pax-lazy-section ,name resolve-lazy-section)
+ (defsection ,name (:package ,package :export ,export :title ,title)
+ ,@entries))))
`(progn
- (defparameter ,name ',defsection-form)
+ (defparameter ,name ',value)
,@(when export
`((export ',name :sb-manual))))))
(defun-dummy (section-name :pax) (section)
- (second section))
+ (second (second section)))
(defun-dummy (section-title :pax) (section)
- (getf (third section) :title))
+ (getf (third (second section)) :title))
(defun-dummy (section-package :pax) (section)
- (find-package (getf (third section) :package)))
+ (find-package (getf (third (second section)) :package)))
;;; This is a list of (NAME LOCATIVE) elements with our dummy DEFSECTION.
(defun-dummy (section-entries :pax) (section)
- (nthcdr 3 section))
+ (nthcdr 3 (second section)))
(defun-dummy (xref-name :dref) (xref)
(first xref))
diff --git a/contrib/sb-manual/sb-manual.texinfo b/contrib/sb-manual/sb-manual.texinfo
index 278f90b04..dc0b27f8d 100644
--- a/contrib/sb-manual/sb-manual.texinfo
+++ b/contrib/sb-manual/sb-manual.texinfo
@@ -4,14 +4,13 @@
@section sb-manual
@menu
+* Using PAX: using pax.
* Browsing Live with PAX: browsing live with pax.
* Fancy Documentation with PAX: fancy documentation with pax.
@end menu
-The @code{sb-manual} module has the sections of the SBCL user manual in
-Lisp variables. The names of the variables (all start with the
-character @code{@@}) are exported from the @code{sb-manual} package. Sections
-are defined with the @code{defsection} macro:
+The @code{sb-manual} module has the SBCL user manual in forms
+mimicking @code{pax:defsection}:
@example
(defsection @@example (:title "Example")
@@ -20,23 +19,49 @@ are defined with the @code{defsection} macro:
(@@subexample section))
@end example
-where @code{defsection} is a dummy implementation of
-@code{pax:defsection} (see @url{https://github.com/melisgl/mgl-pax/}).
-
-In Slime, @code{M-.} on @code{"@@SB-MANUAL"}, @code{"print"}, or on
-@code{"@@subexample"} will take you to the respective definition. This
-makes it easy to navigate the documentation. Normal Lisp definition
-docstrings and section docstrings reference sections following the
-usual convention of uppercasing the name. Docstrings are in a subset
-of Markdown and use very little markup in general, so they are easy
-to read directly in the source.
+The names of the variables holding the documentation are exported
+from the @code{sb-manual} package. Since sections are basically
+variables, in Slime, @code{M-.} on @code{"@@SB-MANUAL"}, @code{"print"}, or
+on @code{"@@subexample"} will take you to the respective definition.
+This makes it easy to navigate the documentation. Normal Lisp
+definition docstrings and section docstrings reference sections
+following the usual convention of uppercasing the name. Docstrings
+are in a subset of Markdown and use very little markup in general,
+so they are easy to read directly in the source.
The official manual in Info, HTML and PDF formats is generated via
Texinfo generated from these definitions.
+@node using pax
+@subsection Using PAX
+
+However, @code{sb-manual::defsection} is but a dummy implementation of
+@code{pax:defsection} to avoid a hard dependency on PAX.
+
+See the @code{mgl-pax} @code{asdf:system} or @url{https://github.com/melisgl/mgl-pax/}.
+
When PAX is loaded, the dummy @code{defsection} definitions are made
real, so that PAX can work with them.
+@anchor{Function sb-manual use-pax}
+@ffindex @sortas{use-pax sb-manual} use-pax [sb-manual]
+@deffn{Function} sb-manual:use-pax
+Ensure that exported variables are @code{pax:section}s.
+It is an error if the @code{mgl-pax} library is not loaded.
+
+Calling this function explicitly is rarely necessary because it is
+called automatically:
+
+@itemize
+@item when @code{sb-manual} is loaded, if @code{pax} is present;
+
+@item when @code{pax:document} (more precisely, @code{dref:locate}) is called on
+ an @code{sb-manual} section.
+@end itemize
+
+The latter feature requires v0.4.12 of @code{pax}. See the @code{mgl-pax}
+asdf:system.
+@end deffn
@node browsing live with pax
@subsection Browsing Live with PAX
diff --git a/contrib/sb-manual/texinfo.lisp b/contrib/sb-manual/texinfo.lisp
index 0b782cf87..e4575d8de 100644
--- a/contrib/sb-manual/texinfo.lisp
+++ b/contrib/sb-manual/texinfo.lisp
@@ -116,13 +116,16 @@
(funcall fn))
(funcall fn)))
+(defun remove-markup (string)
+ (remove #\\ string))
+
;;; Write the Texinfo for SECTION to *STANDARD-OUTPUT*. When recursing
;;; into child sections, if a section is in PAGES, then emit an
;;; @include and open a new a file for output.
(defun emit-texinfo-for-section (section &key pages (depth 0)
top-level-menus-to-file
top-level-contents-to-file)
- (let ((title (section-title section))
+ (let ((title (remove-markup (section-title section)))
(entries (section-entries section)))
(format t "@node ~A~%" (texinfo-node-id section))
(format t "~A ~A~%~%"
@@ -144,7 +147,7 @@
(format t "@menu~%"))
(with-texinfo-to-file top-level-menus-to-file
(dolist (child-section child-sections)
- (format t "* ~A: ~A.~%" (section-title child-section)
+ (format t "* ~A: ~A.~%" (remove-markup (section-title child-section))
(texinfo-node-id child-section))))
(unless top-level-menus-to-file
(format t "@end menu~%~%"))))
-----------------------------------------------------------------------
hooks/post-receive
--
SBCL