summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/guile/skribilo/engine/info.scm57
1 files changed, 50 insertions, 7 deletions
diff --git a/src/guile/skribilo/engine/info.scm b/src/guile/skribilo/engine/info.scm
index 6a09b1c..364f2cf 100644
--- a/src/guile/skribilo/engine/info.scm
+++ b/src/guile/skribilo/engine/info.scm
@@ -436,7 +436,7 @@
;* info ::%reference ... */
;*---------------------------------------------------------------------*/
(markup-writer 'ref info-engine
- :options '(:text :page text kind
+ :options '(:text :page :text :kind
:chapter :section :subsection :subsubsection
:figure :mark :handle :ident)
@@ -444,12 +444,12 @@
(let ((target (handle-ast (markup-body n))))
(case (markup-markup target)
((chapter section subsection subsubsection)
- (info-block-ref target e))
+ (info-block-ref n target e))
((mark)
;; We can't refer directly to marks, so refer to the
;; enclosing section as an approximation.
(let ((parent (find1-up %block? target)))
- (info-block-ref parent e)))
+ (info-block-ref n parent e)))
(else
(skribe-warning/ast 1 target
"ref: don't know how to refer to target")
@@ -473,10 +473,53 @@
;*---------------------------------------------------------------------*/
;* info-block-ref ... */
;*---------------------------------------------------------------------*/
-(define (info-block-ref obj e)
- (output-justified "*Note ")
- (output (block-title obj e) e)
- (output-justified ":: "))
+(define (info-block-ref ref obj e)
+ ;; Emit a cross-reference from REF to chapter/section OBJ.
+
+ (define (next n)
+ ;; Return the markup or string that immediately follows N, or #f it there
+ ;; is none or it cannot be determined.
+ (let ((p (ast-parent n)))
+ (let loop ((body (markup-body p)))
+ (match body
+ (((sub-list ...) rest ...)
+ (or (loop sub-list) (loop rest)))
+ ((_ ...)
+ (match (memq n body)
+ ((_ next _ ...)
+ next)
+ (_ #f)))
+ (_ #f)))))
+
+ (define (next-char n)
+ ;; Return the character immediately following N or #f.
+ (let loop ((x (next n)))
+ (match x
+ ((? string? s)
+ (let ((s (string-trim s)))
+ (and (not (string-null? s))
+ (string-ref s 0))))
+ ((x _ ...)
+ (loop x))
+ (_ #f))))
+
+ (let ((text (markup-option ref :text)))
+ (output-justified "*Note ")
+ (if text
+ (begin
+ (output text e)
+ (output-justified ": ")))
+ (output (block-title obj e) e)
+
+ ;; Check whether REF is followed by a punctuation mark. If it is, we're
+ ;; fine; otherwise, we need to add either a space or a punctuation mark.
+ (let ((c (next-char ref)))
+ (if text
+ (or (memq c '(#\. #\,))
+ (output-justified ","))
+ (if (and c (char-set-contains? char-set:punctuation c))
+ (output-justified "::")
+ (output-justified ":: "))))))
;*---------------------------------------------------------------------*/
;* info ::%biblio-ref ... */