;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Muse Publishing Using groff -mom -mwww
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require 'muse-publish)
(defgroup muse-groff nil
"Rules for marking up a Muse file with groff -mom -mwww macros."
:group 'muse-publish)
(defcustom muse-groff-extension ".groff"
"Default file extension for publishing groff -mom -mwww files."
:type 'string
:group 'muse-groff)
(defcustom muse-groff-pdf-extension ".pdf"
"Default file extension for publishing groff -mom -mwww files to PDF."
:type 'string
:group 'muse-groff)
(defcustom muse-groff-header
".TITLE \"(muse-publishing-directive \"title\")\"
.SUBTITLE \"(muse-publishing-directive \"date\")\"
.AUTHOR \"(muse-publishing-directive \"author\")\"
.PRINTSTYLE TYPESET
.de para
'PP
'ne 2
..
.blm para
.START
(and muse-publish-generate-contents \".TOC\n\")\n"
"Header used for publishing groff -mom -mwww files."
:type '(choice string file)
:group 'muse-groff)
(defcustom muse-groff-footer " "
"Footer used for publishing groff -mom -mwww files."
:type '(choice string file)
:group 'muse-groff)
(defcustom muse-groff-markup-regexps
`()
"List of markup regexps for identifying regions in a Muse page.
For more on the structure of this list, see `muse-publish-markup-regexps'."
:type '(repeat (choice
(list :tag "Markup rule"
integer
(choice regexp symbol)
integer
(choice string function symbol))
function))
:group 'muse-groff)
(defcustom muse-groff-markup-functions
'((table . muse-groff-markup-table))
"An alist of style types to custom functions for that kind of text.
For more on the structure of this list, see
`muse-publish-markup-functions'."
:type '(alist :key-type symbol :value-type function)
:group 'muse-groff)
(defcustom muse-groff-markup-strings
'((image-with-desc . "\n.MPIMG -R %s\n")
(image-link . "\n.MPIMG -R %s\n")
(url-with-image . "\n.\\\" %s\n.MPIMG -R %s")
(url-link . "\n.URL %s %s\n")
(email-addr . "\f[C]%s\f[]")
(emdash . "\\(em")
(rule . "\n.RULE\n")
(enddots . "....")
(dots . "...")
;; (part . "\\part{")
;; (part-end . "}")
;; (chapter . "\\chapter{")
;; (chapter-end . "}")
(section . ".HEAD \"")
(section-end . "\"")
(subsection . ".SUBHEAD \"")
(subsection-end . "\"")
(subsubsection . ".PARAHEAD \"")
(subsubsection-end . "\"")
;; (footnote . "\\c\n.FOOTNOTE\n")
;; (footnote-end . "\n.FOOTNOTE OFF\n")
;; (footnotemark . "\\footnotemark[%d]")
;; (footnotetext . "\\footnotetext[%d]{")
;; (footnotetext-end . "}")
(begin-underline . "\n.UNDERSCORE \"")
(end-underline . "\"\n")
(begin-literal . "\\fC")
(end-literal . "\\fP")
(begin-emph . "\\fI")
(end-emph . "\\fP")
(begin-more-emph . "\\fB")
(end-more-emph . "\\fP")
(begin-most-emph . "\\f(BI")
(end-most-emph . "\\fP")
(begin-verse . ".QUOTE")
(end-verse-line . "")
(last-stanza-end . "")
(end-verse . ".QUOTE OFF")
(begin-example . (concat
".QUOTE_FONT CR\n.QUOTE_INDENT 1\n.QUOTE_SIZE -2\n"
".UNDERLINE_QUOTES OFF\n.QUOTE"))
(end-example . ".QUOTE OFF")
(begin-center . "\n.CENTER\n")
(end-center . "\n.QUAD L\n")
(begin-quote . ".BLOCKQUOTE")
(end-quote . ".BLOCKQUOTE OFF")
(begin-uli . ".LIST BULLET\n.ITEM\n")
(end-uli . "\n.LIST OFF")
(begin-oli . ".LIST DIGIT\n.ITEM\n")
(end-oli . "\n.LIST OFF")
(begin-ddt . "\\fB")
(start-dde . "\\fP\n.IR 4P\n")
(end-ddt . ".IRX CLEAR"))
"Strings used for marking up text.
These cover the most basic kinds of markup, the handling of which
differs little between the various styles."
:type '(alist :key-type symbol :value-type string)
:group 'muse-groff)
(defcustom muse-groff-markup-specials
'((?\\ . "\\e"))
"A table of characters which must be represented specially."
:type '(alist :key-type character :value-type string)
:group 'muse-groff)
;; (defun muse-latex-markup-table ()
;; (let* ((str (prog1
;; (match-string 1)
;; (delete-region (match-beginning 0) (match-end 0))))
;; (fields (split-string str "\\s-*|+\\s-*"))
;; (type (and (string-match "\\s-*\\(|+\\)\\s-*" str)
;; (length (match-string 1 str)))))
;; (insert "\\begin{tabular}{" (make-string (length fields) ?l) "}\n")
;; (insert (mapconcat 'identity fields " & "))
;; (insert " \\\\\n\\end{tabular}")))
(defun muse-groff-protect-leading-chars ()
"Protect leading periods and apostrophes from being interpreted as
command characters."
(while (re-search-forward "^[.']" nil t)
(replace-match "\\\\&\\&" t)))
(defun muse-groff-concat-lists ()
"Join like lists."
(let (arg begin)
(while (re-search-forward "^\.LIST[ \t]+\\(.*\\)\n" nil t)
(setq arg (match-string 1))
(if (string= arg "OFF")
(setq begin (match-beginning 0))
(if (and begin (string= type arg))
(delete-region begin (match-end 0))
(setq type arg
begin 0))))))
(defun muse-groff-fixup-dquotes ()
"Fixup double quotes."
(let ((open t))
(while (search-forward "\"" nil t)
(unless (get-text-property (match-beginning 0) 'read-only)
(if (and (bolp) (eq (char-before) ?\n))
(setq open t))
(if open
(progn
(replace-match "``")
(setq open nil))
(replace-match "''")
(setq open t))))))
(defun muse-groff-prepare-buffer ()
(goto-char (point-min))
(muse-groff-protect-leading-chars))
(defun muse-groff-finalize-buffer ()
(goto-char (point-min))
(muse-groff-concat-lists))
(defun muse-groff-pdf-browse-file (file)
(shell-command (concat "open " file)))
(defun muse-groff-pdf-generate (file output-path final-target)
(muse-publish-transform-output
file output-path final-target "PDF"
(function
(lambda (file output-path)
(let ((command
(format
(concat "file=%s; ext=%s; cd %s && cp $file$ext $file.ref && "
"groff -mom -mwww -t $file$ext > $file.ps && "
"ps2pdf12 $file.ps")
(file-name-sans-extension file)
muse-groff-extension
(file-name-directory output-path))))
(shell-command command))))
".ps"))
(unless (assoc "groff" muse-publishing-styles)
(muse-define-style "groff"
:suffix 'muse-groff-extension
:regexps 'muse-groff-markup-regexps
:functions 'muse-groff-markup-functions
:strings 'muse-groff-markup-strings
:specials 'muse-groff-markup-specials
:before 'muse-groff-prepare-buffer
:after 'muse-groff-finalize-buffer
:header 'muse-groff-header
:footer 'muse-groff-footer
:browser 'find-file)
(muse-derive-style "pdf" "groff"
:final 'muse-groff-pdf-generate
:browser 'muse-groff-pdf-browse-file
:osuffix 'muse-groff-pdf-extension))
(provide 'muse-groff)
;;; muse-groff.el ends here