diff --git a/doc/build.scm b/doc/build.scm index 8d5b58962a..c3d61f837b 100644 --- a/doc/build.scm +++ b/doc/build.scm @@ -220,8 +220,10 @@ (define build (syntax-highlight scheme) (syntax-highlight lexers) (guix build utils) + (srfi srfi-1) (ice-9 match) - (ice-9 threads)) + (ice-9 threads) + (ice-9 vlist)) (define (pair-open/close lst) ;; Pair 'open' and 'close' tags produced by 'highlights' and @@ -255,10 +257,11 @@ (define (pair-open/close lst) level (reverse result))) (values (reverse result) "" '()))))) - (define (highlights->sxml* highlights) + (define (highlights->sxml* highlights anchors) ;; Like 'highlights->sxml', but handle nested 'paren tags. This ;; allows for paren matching highlights via appropriate CSS - ;; "hover" properties. + ;; "hover" properties. When a symbol is encountered, look it up + ;; in ANCHORS, a vhash, and emit the corresponding href, if any. (define (tag->class tag) (string-append "syntax-" (symbol->string tag))) @@ -269,8 +272,16 @@ (define (tag->class tag) (number->string level)))) ,open (span (@ (class "syntax-symbol")) - ,@(highlights->sxml* body)) + ,@(highlights->sxml* body anchors)) ,close)) + (('symbol text) + ;; Check whether we can emit a hyperlink for TEXT. + (match (vhash-assoc text anchors) + (#f + `(span (@ (class ,(tag->class 'symbol))) ,text)) + ((_ . target) + `(a (@ (class ,(tag->class 'symbol)) (href ,target)) + ,text)))) ((tag text) `(span (@ (class ,(tag->class tag))) ,text))) highlights)) @@ -301,35 +312,95 @@ (define (concatenate-snippets pieces) (pk 'unsupported-code-snippet something) (primitive-exit 1))))) - (define (syntax-highlight sxml) + (define (syntax-highlight sxml anchors) ;; Recurse over SXML and syntax-highlight code snippets. - (match sxml - (('*TOP* decl body ...) - `(*TOP* ,decl ,@(map syntax-highlight body))) - (('head things ...) - `(head ,@things - (link (@ (rel "stylesheet") - (type "text/css") - (href #$syntax-css-url))))) - (('pre ('@ ('class "lisp")) code-snippet ...) - `(pre (@ (class "lisp")) - ,@(highlights->sxml* - (pair-open/close - (highlight lex-scheme - (concatenate-snippets code-snippet)))))) - ((tag ('@ attributes ...) body ...) - `(,tag (@ ,@attributes) ,@(map syntax-highlight body))) - ((tag body ...) - `(,tag ,@(map syntax-highlight body))) - ((? string? str) - str))) + (let loop ((sxml sxml)) + (match sxml + (('*TOP* decl body ...) + `(*TOP* ,decl ,@(map loop body))) + (('head things ...) + `(head ,@things + (link (@ (rel "stylesheet") + (type "text/css") + (href #$syntax-css-url))))) + (('pre ('@ ('class "lisp")) code-snippet ...) + `(pre (@ (class "lisp")) + ,@(highlights->sxml* + (pair-open/close + (highlight lex-scheme + (concatenate-snippets code-snippet))) + anchors))) + ((tag ('@ attributes ...) body ...) + `(,tag (@ ,@attributes) ,@(map loop body))) + ((tag body ...) + `(,tag ,@(map loop body))) + ((? string? str) + str)))) - (define (process-html file) + (define (underscore-decode str) + ;; Decode STR, an "underscore-encoded" string as produced by + ;; makeinfo for indexes, such as "_0025base_002dservices" for + ;; "%base-services". + (let loop ((str str) + (result '())) + (match (string-index str #\_) + (#f + (string-concatenate-reverse (cons str result))) + (index + (let ((char (string->number + (substring str (+ index 1) (+ index 5)) + 16))) + (loop (string-drop str (+ index 5)) + (append (list (string (integer->char char)) + (string-take str index)) + result))))))) + + (define (anchor-id->key id) + ;; Convert ID, an anchor ID such as + ;; "index-pam_002dlimits_002dservice" to the corresponding key, + ;; "pam-limits-service" in this example. + (underscore-decode + (string-drop id (string-length "index-")))) + + (define* (collect-anchors file #:optional (vhash vlist-null)) + ;; Collect the anchors that appear in FILE, a makeinfo-generated + ;; file. Grab those from
cups-configuration
parameter: …