master: sb-manual: add support for [label](uri) and [label][id]

melisgl via Sbcl-commits <[email protected]> Mon, 29 Jun 2026 12:20:04 +0000
Newsgroups gmane.lisp.steel-bank.cvs
Message-ID <[email protected]>
The branch "master" has been updated in SBCL:
       via  61e352d1058e9d170e70fe7779c5248572c9b74a (commit)
      from  79e63158c90e9af76c356381e7db0297ff88f3a0 (commit)

- Log -----------------------------------------------------------------
commit 61e352d1058e9d170e70fe7779c5248572c9b74a
Author: Gabor Melis <[email protected]>
Date:   Mon Jun 8 22:31:45 2026 +0200

    sb-manual: add support for [label](uri) and [label][id]
---
 contrib/sb-manual/README.md            | 38 ++++++++++++++++++++
 contrib/sb-manual/TODO.md              |  4 ---
 contrib/sb-manual/doc/beyond-ansi.lisp |  3 +-
 contrib/sb-manual/doc/intro.lisp       |  5 +--
 contrib/sb-manual/manual.lisp          |  2 +-
 contrib/sb-manual/markdown.lisp        | 65 +++++++++++++++++++++++++++++++---
 contrib/sb-manual/sb-manual.texinfo    |  2 +-
 doc/manual/beyond-ansi.texinfo         |  3 +-
 doc/manual/intro.texinfo               |  5 +--
 9 files changed, 110 insertions(+), 17 deletions(-)

diff --git a/contrib/sb-manual/README.md b/contrib/sb-manual/README.md
index 2202db34f..44f478b7e 100644
--- a/contrib/sb-manual/README.md
+++ b/contrib/sb-manual/README.md
@@ -124,6 +124,44 @@ Note how the code block is indented 8 spaces from the `-` character.
 The required indentation remains the same if the child paragraph above
 is not present.
 
+## Links
+
+### Plain Links
+
+For short links:
+
+    <http://x.y>
+
+### Explicit Links
+
+For overly long links:
+
+    [label](http://x.y/a?b=c)
+
+When generating Texinfo, this is translated to `@url`, which is
+rendered like a HTML link in HTML and PDF, but with `label (see
+<uri>)` in Info.
+
+PAX will generate a normal link except in plain text, where it simply
+drops the URI.
+
+### Reflinks
+
+In PAX-generated output only, `FUNCTION` is autolinked to its
+definitions. If there is more than one, you can dismambiguate:
+
+    [FUNCTION][type]
+
+PAX will produce a single link in this case. If `(FUNCTION CLASS)` is
+documented in some section, then the link will point to that
+documentation. Else, the link will go to the CLHS. The latter can be
+forced:
+
+    [FUNCTION][(clhs type)]
+
+Since we don't link to definitions in Texinfo (except to sections),
+the above examples are translated to `FUNCTION` there.
+
 ## Notes
 
 - In many cases, just write a sentence:
diff --git a/contrib/sb-manual/TODO.md b/contrib/sb-manual/TODO.md
index 0759ce6d1..e15a93b4b 100644
--- a/contrib/sb-manual/TODO.md
+++ b/contrib/sb-manual/TODO.md
@@ -24,7 +24,3 @@ In the generated Texinfo, this can be a tad confusing. In output
 formats with links (e.g. HTML from PAX), this is clearly preferable.
 
 Nicknames, maybe?
-
-# Implement PAX reflinks, e.g. `[function][type]`
-
-See `PAX::@REFLINKS`.
diff --git a/contrib/sb-manual/doc/beyond-ansi.lisp b/contrib/sb-manual/doc/beyond-ansi.lisp
index 6eee21284..6ddb59adf 100644
--- a/contrib/sb-manual/doc/beyond-ansi.lisp
+++ b/contrib/sb-manual/doc/beyond-ansi.lisp
@@ -515,7 +515,8 @@
     it supports extensible sequences directly."
   (sb-sequence:emptyp generic-function)
   (sb-sequence:dosequence macro)
-  "The remaining list parallels the _Sequence Dictionary_, `17.3` CLHS."
+  "The remaining list parallels the _Sequence Dictionary_, see
+  [17.3][clhs] in the ANSI spec."
   (sb-sequence:copy-seq generic-function)
   (sb-sequence:fill generic-function)
   (sb-sequence:subseq generic-function)
diff --git a/contrib/sb-manual/doc/intro.lisp b/contrib/sb-manual/doc/intro.lisp
index 46dac049f..cbebc2c00 100644
--- a/contrib/sb-manual/doc/intro.lisp
+++ b/contrib/sb-manual/doc/intro.lisp
@@ -24,8 +24,9 @@
     specified in the _Description_.
 
   - The STRING type is considered to be the union of all types
-    `(ARRAY C (SIZE))` for all non-`NIL` subtypes `C` of CHARACTER,
-     excluding arrays specialized to the empty type.
+    `(ARRAY C (SIZE))` for all non-`NIL` subtypes `C` of
+     [CHARACTER][type], excluding arrays specialized to the empty
+     type.
 
   - The `:ORDER` long form option in DEFINE-METHOD-COMBINATION method
     group specifiers accepts the value NIL as well as
diff --git a/contrib/sb-manual/manual.lisp b/contrib/sb-manual/manual.lisp
index 61e1f549d..38753eb3b 100644
--- a/contrib/sb-manual/manual.lisp
+++ b/contrib/sb-manual/manual.lisp
@@ -38,7 +38,7 @@
 (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>.
+  [online](https://melisgl.github.io/mgl-pax-world/pax-manual.html#MGL-PAX:@BROWSING-LIVE-DOCUMENTATION%20MGL-PAX:SECTION).
 
   If you are browsing this manual live right now, here is the
   equivalent live link: `PAX::@BROWSING-LIVE-DOCUMENTATION`.
diff --git a/contrib/sb-manual/markdown.lisp b/contrib/sb-manual/markdown.lisp
index 1959d1082..b55b6d9b3 100644
--- a/contrib/sb-manual/markdown.lisp
+++ b/contrib/sb-manual/markdown.lisp
@@ -26,8 +26,8 @@
 ;;;   opportunities for codification and linking.
 ;;;
 ;;;
-;;; Markdown Support
-;;; ----------------
+;;; Markdown Formatting
+;;; -------------------
 ;;;
 ;;; The supported Markdown constructs are:
 ;;;
@@ -37,8 +37,6 @@
 ;;;
 ;;; - Inline code: `monospace` -> @code{monospace}
 ;;;
-;;; - <http...> -> @url{http...}
-;;;
 ;;; - Itemized lists (like this one). List items can span multiple
 ;;;   lines.
 ;;;
@@ -122,6 +120,17 @@
 ;;;
 ;;; - Section references: @SECTION-NAME -> @ref{section name}
 ;;;
+;;; - <http...> -> @url{http...}
+;;;
+;;; - [label](uri) -> @uref{uri, label}
+;;;
+;;; - [label][id] -> label
+;;;
+;;;     This just strips Markdown reference links. These are used by
+;;;     PAX to disambiguate, e.g. "[FUNCTION][type]" links to the
+;;;     FUNCTION class only while FUNCTION links to both the class and
+;;;     macro.
+;;;
 ;;; FIXME:
 ;;;
 ;;; - Maybe implement glossary-terms (for books, "safe type", etc).
@@ -587,6 +596,47 @@
                           (out "}")
                           (setf i close-pos))
                         (buffer-codifiable-char char))))
+                 ;; Markdown explicit links: [label](url) -> @uref{url, label}
+                 ;;
+                 ;; Markdown reflinks: [label][id] -> label
+                 ((char= char #\[)
+                  (let* ((close-bracket (position #\] string :start (1+ i)))
+                         (next-char (when (and close-bracket
+                                               (< (1+ close-bracket) len))
+                                      (char string (1+ close-bracket))))
+                         (open-paren (when (eql next-char #\()
+                                       (1+ close-bracket)))
+                         (close-paren (when open-paren
+                                        (position #\) string
+                                                  :start (1+ open-paren))))
+                         (open-bracket2 (when (eql next-char #\[)
+                                          (1+ close-bracket)))
+                         (close-bracket2
+                           (when open-bracket2
+                             (position #\] string :start (1+ open-bracket2)))))
+                    (cond
+                      ;; Explicit link: [label](url)
+                      (close-paren
+                       (flush-codifiable-buffer)
+                       (out "@uref{")
+                       (out-escaped (subseq string (1+ open-paren)
+                                            close-paren))
+                       (out ", ")
+                       (out (process-inline-markdown
+                             (subseq string (1+ i) close-bracket)))
+                       (out "}")
+                       (setf i close-paren))
+                      ;; Reflink: [label][id]
+                      (close-bracket2
+                       (flush-codifiable-buffer)
+                       ;; Process the name, drop the id
+                       (out (process-inline-markdown
+                             (subseq string (1+ i) close-bracket)))
+                       (setf i close-bracket2))
+                      ;; Not a recognized link structure, treat as a
+                      ;; normal character
+                      (t
+                       (buffer-codifiable-char char)))))
                  (t
                   (buffer-codifiable-char char)))
                (incf i))
@@ -600,7 +650,12 @@
   (assert (equal (process-inline-markdown "_PRINT_") "@emph{@code{print}}"))
   (assert (equal (process-inline-markdown "<httpabc>") "@url{httpabc}"))
   (assert (equal (process-inline-markdown "`N`") "@code{n}"))
-  (assert (equal (process-inline-markdown "`N`th") "@code{n}th")))
+  (assert (equal (process-inline-markdown "`N`th") "@code{n}th"))
+  (assert (equal (process-inline-markdown "[x](uri)") "@uref{uri, x}"))
+  (assert (equal (process-inline-markdown "[`x`](uri)") "@uref{uri, @code{x}}"))
+  (assert (equal (process-inline-markdown "[function][type]") "function"))
+  (assert (equal (process-inline-markdown "[`function`][type]")
+                 "@code{function}")))
 
 
 ;;;; Processing Markdown block elements
diff --git a/contrib/sb-manual/sb-manual.texinfo b/contrib/sb-manual/sb-manual.texinfo
index dc0b27f8d..4f2b9cb6f 100644
--- a/contrib/sb-manual/sb-manual.texinfo
+++ b/contrib/sb-manual/sb-manual.texinfo
@@ -67,7 +67,7 @@ asdf:system.
 
 With PAX, you can browse the manual live. The documentation of this
 feature is available at
-@url{https://melisgl.github.io/mgl-pax-world/pax-manual.html#MGL-PAX:@@BROWSING-LIVE-DOCUMENTATION%20MGL-PAX:SECTION}.
+@uref{https://melisgl.github.io/mgl-pax-world/pax-manual.html#MGL-PAX:@@BROWSING-LIVE-DOCUMENTATION%20MGL-PAX:SECTION, online}.
 
 If you are browsing this manual live right now, here is the
 equivalent live link: @code{pax::@@browsing-live-documentation}.
diff --git a/doc/manual/beyond-ansi.texinfo b/doc/manual/beyond-ansi.texinfo
index 1ea9acbed..9204ae772 100644
--- a/doc/manual/beyond-ansi.texinfo
+++ b/doc/manual/beyond-ansi.texinfo
@@ -1008,7 +1008,8 @@ otherwise. Signals an error if @code{sequence} is not a sequence.
 Executes @code{body} with @code{element} subsequently bound to each element of
 @code{sequence}, then returns @code{return}.
 @end deffn
-The remaining list parallels the @emph{Sequence Dictionary}, @code{17.3} @code{clhs}.
+The remaining list parallels the @emph{Sequence Dictionary}, see
+17.3 in the ANSI spec.
 
 @anchor{Generic function sb-sequence copy-seq}
 @ffindex @sortas{copy-seq sb-sequence} copy-seq [sb-sequence]
diff --git a/doc/manual/intro.texinfo b/doc/manual/intro.texinfo
index 576318783..0cb76cf86 100644
--- a/doc/manual/intro.texinfo
+++ b/doc/manual/intro.texinfo
@@ -32,8 +32,9 @@ exceptions involve internal inconsistencies in the standard.) See
   specified in the @emph{Description}.
 
 @item The @code{string} type is considered to be the union of all types
-  @code{(array c (size))} for all non-@code{nil} subtypes @code{c} of @code{character},
-   excluding arrays specialized to the empty type.
+  @code{(array c (size))} for all non-@code{nil} subtypes @code{c} of
+   @code{character}, excluding arrays specialized to the empty
+   type.
 
 @item The @code{:order} long form option in @code{define-method-combination} method
   group specifiers accepts the value @code{nil} as well as

-----------------------------------------------------------------------


hooks/post-receive
-- 
SBCL