1;; This file implements an engine for creating mdoc(7) manual2;; pages using Skribilo. Semantic mdoc(7) markup is supported3;; through a custom Skribilo markup package.4;;5;; See https://man.openbsd.org/mdoc.767(define-module (skribilo engine mdoc)8 #:use-module (skribilo evaluator)9 #:use-module (skribilo lib)10 #:use-module (skribilo ast)11 #:use-module (skribilo engine)12 #:use-module (skribilo writer)13 #:use-module (skribilo utils syntax)14 #:use-module (skribilo utils strings)15 #:use-module (skribilo package base)16 #:use-module (skribilo output)17 #:autoload (skribilo parameters) (*destination-file*)1819 #:use-module (mdoc utils markup)20 #:use-module (mdoc utils output)2122 #:export (mdoc-engine))2324(skribilo-module-syntax)2526;; State to detect empty lines in filter function.27(define filter-prev-empty? #t)2829(define mdoc-engine30 (default-engine-set!31 (make-engine 'mdoc32 :version 0.133 :format "mdoc"34 :delegate (find-engine 'base)35 ;; TODO: Remove the newline filtering code at some point.36 :filter (lambda (str)37 (let* ((is-empty? (equal? str "\n"))38 (ret-value (if (and is-empty? filter-prev-empty?)39 ""40 (string-trim str char-set:blank))))41 (set! filter-prev-empty? is-empty?)42 ret-value))43 :custom '())))4445(make-ornament 'bold 'Sy)46;; TODO: 'code47(make-ornament 'emph 'Em)48(make-ornament 'it 'Em)49;; TODO: 'kbd50(make-ornament 'roman 'No)51;; TODO: 'sc52;; TODO: 'underline53;; TODO: 'sf54;; TODO: 'sub55;; TODO: 'sup56;; TODO: 'tt57;; TODO: 'underline58(make-ornament 'var 'Va)5960(make-block 'blockquote '(Bd "-literal" "-offset indent") '(Ed))61(make-block 'center '(Bd "-centered") '(Ed))62(make-block 'pre '(Bd "-literal") '(Ed))63;; TODO: flush6465(markup-writer 'document66 :options '(:title :author :ending :mdoc-desc :mdoc-date :mdoc-section :mdoc-system)67 :action (lambda (doc e)68 (set-port-encoding! (current-output-port) "UTF-8")69 (let ((title (markup-option doc :title))70 (desc (markup-option doc :mdoc-desc))71 (section (markup-option doc :mdoc-section))72 (date (markup-option doc :mdoc-date))73 (system (markup-option doc :mdoc-system))74 (body (markup-body doc)))75 (output-preamble e76 (if (string? title)77 title78 (ast->string title))79 (or date "$Mdocdate$")80 (or section81 (begin82 (skribe-warning 1 "mdoc section not defined, defaulting to '1'")83 1))84 system)8586 (output-section e "name")87 (output-macro e 'Nm title)88 (if desc89 (output-macro e 'Nd desc)90 (skribe-warning 1 "mdoc one-line description is missing"))9192 (output body e)93 (output-newline e))))9495(markup-writer 'paragraph96 :before (lambda (n e)97 (output-macro e 'Pp))98 :after (lambda (n e)99 (output-newline e)))100101(markup-writer 'section102 :options '(:title :number :file :toc)103 :action (lambda (n e)104 (let ((body (markup-body n))105 (title (markup-option n :title)))106 (output-section e (ast->string title))107 (output body e))))108109(make-listing 'itemize "-tag" "-width Ds")110(make-listing 'enumerate "-enum")111;; TODO: description112113(markup-writer 'item114 :options '(:key)115 :action (lambda (n e)116 (let ((k (markup-option n :key)))117 (if k118 (with-parsed-macro (e 'It)119 (evaluate-document k e))120 (output-macro e 'It)))121 (evaluate-document (markup-body n) e)))122123(make-macro 'mark 'Tg)124(make-macro 'mailto 'Mt '(:text))125126;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;127128(markup-writer 'man-name129 :action (lambda (n e)130 (output-macro e 'Nm)))131132(make-parsed-macro 'man-arg 'Ar)133(make-parsed-macro 'man-flags 'Fl)134(make-parsed-macro 'man-opt 'Op)