;;; sisu-spine-mode.el --- Major mode for SiSU (spine parser) markup text ;; Copyright (C) 2011, 2021 Free Software Foundation, Inc. ;; Author: Ralph Amissah & Ambrose Kofi Laing ;; Maintainer: Ralph Amissah <ralph.amissah@gmail.com> ;; Keywords: text, syntax, processes, tools ;; Version: 8.0.0 ;; URL: https://www.sisudoc.org/ ;; originally looked at (based on) doc-mode, with kind permission of the author ;; Author: SUN, Tong <suntong001@users.sf.net>, (c)2001-6, all right reserved ;; Version: $Date: 2006/01/19 03:13:41 $ $Revision: 1.14 $ ;; Home URL: https://xpt.sourceforge.net/ ;; with contributions from Kevin Ryde and Stefan Monnier ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see <https://www.gnu.org/licenses/>. ;; Viva Software Libre! ;; Support the free software movement! ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Commentary: ;; SiSU (https://www.sisudoc.org/) is a document structuring and ;; publishing framework. This package provides an Emacs major mode ;; for SiSU markup, as used by the spine parser (in D) which has a different ;; header (based on yaml) from the original sisu parser (in Ruby) which has ;; bespoke headers. ;; When this package is installed, files ending in ".sst" are automatically ;; associated with sisu-spine-mode. If a file doesn't have a ;; .sst extension, add a first line: ;; # -*- sisuSpine -*- ;; The documentation for the "Structure Of The Hierarchy Text" can be ;; found in the sisustring for the sisu-spine-mode function. ;;; Code: ;; Variables: (defgroup sisu-faces nil "AsciiSisu highlighting" :group 'sisus) ;; == Colors ; color n is more prominent than color n+1 (defface sisu-title-1-face `((((class color) (background dark)) (:foreground "brown3" :bold t :height 1.2 :inherit variable-pitch)) (((class color) (background light)) (:foreground "brown3" :bold t :height 1.2 :inherit variable-pitch)) (t (:weight bold :inherit variable-pitch))) "Face for AsciiSisu titles at level 1." :group 'sisu-faces) (defface sisu-title-2-face `((((class color) (background dark)) (:foreground "yellow4" :bold t :height 1.1 :inherit variable-pitch)) (((class color) (background light)) (:foreground "yellow4" :bold t :height 1.1 :inherit variable-pitch)) (t (:weight bold :inherit variable-pitch))) "Face for AsciiSisu titles at level 2." :group 'sisu-faces) (defface sisu-title-3-face `((((class color) (background dark)) (:foreground "sienna3" :bold t)) (((class color) (background light)) (:foreground "sienna3" :bold t)) (t (:weight bold))) "Face for AsciiSisu titles at level 3." :group 'sisu-faces) (defface sisu-title-4-face `((((class color) (background dark)) (:foreground "burlywood3")) (((class color) (background light)) (:foreground "burlywood3")) (t ())) "Face for AsciiSisu titles at level 4." :group 'sisu-faces) (defface info-node '((((class color) (background light)) (:foreground "brown" :bold t :italic t)) (((class color) (background dark)) (:foreground "white" :bold t :italic t)) (t (:bold t :italic t))) "Face for Info node names." :group 'sisu-faces) (defvar sisu-title-1 'sisu-title-1-face) (defvar sisu-title-2 'sisu-title-2-face) (defvar sisu-title-3 'sisu-title-3-face) (defvar sisu-title-4 'sisu-title-4-face) (defvar sisu-general-font-lock-red1 font-lock-warning-face) (defvar sisu-general-font-lock-red2 font-lock-comment-face) (defvar sisu-general-font-lock-red3 font-lock-string-face) (defvar sisu-general-font-lock-green1 font-lock-type-face) (defvar sisu-general-font-lock-green2 font-lock-constant-face) (defvar sisu-general-font-lock-blue1 font-lock-keyword-face) (defvar sisu-general-font-lock-blue2 font-lock-function-name-face) (defvar sisu-general-font-lock-blue3 font-lock-builtin-face) (defvar sisu-general-font-lock-yellow1 font-lock-variable-name-face) (defvar sisu-general-font-lock-yellow2 font-lock-comment-face) ;; == sisu-spine-mode settings (defvar sisu-spine-mode-hook nil "Normal hook run when entering Sisu Text mode.") (defvar sisu-spine-mode-abbrev-table nil "Abbrev table in use in Sisu-spine-mode buffers.") (define-abbrev-table 'sisu-spine-mode-abbrev-table ()) (defconst sisu-font-lock-keywords (eval-when-compile (list ;;grouped text --------- ;(cons "^```[ ]code\\(.\\|\n\\)+?\n```\n" 'sisu-general-font-lock-red2) (cons "^```[ ]+code.*?$\\|^```$" 'sisu-general-font-lock-red2) (cons "^```[ ]+table.*?$\\|^```$" 'sisu-general-font-lock-red2) (cons "^```[ ]+group$\\|^```$" 'sisu-general-font-lock-red2) (cons "^```[ ]+block$\\|^```$" 'sisu-general-font-lock-red2) (cons "^```[ ]+poem$\\|^```$" 'sisu-general-font-lock-red2) (cons "^```[ ]+alt$\\|^```$" 'sisu-general-font-lock-red2) ;;grouped text --------- (cons "^group{\\|^}group" 'sisu-general-font-lock-red2) (cons "^block{\\|^}block" 'sisu-general-font-lock-red2) (cons "^code{\\|^}code" 'sisu-general-font-lock-red2) (cons "^poem{\\|^}poem" 'sisu-general-font-lock-red2) (cons "^alt{\\|^}alt" 'sisu-general-font-lock-red2) (cons "^table{.+\\|^}table" 'sisu-general-font-lock-red2) (cons "^{table[^}]+}" 'sisu-general-font-lock-red2) (list (concat "^\`\\{3\\}[ ]+code.*?$" "\\(.\\|\n\\)+?" "\`\\{3\\}$" ) '(1 sisu-general-font-lock-red2 t) '(2 nil t) '(3 sisu-general-font-lock-red2 t) ) (list (concat "^\`\\{3\\}[ ]+table.*?$" "\\(.\\|\n\\)+?" "\`\\{3\\}$" ) '(1 sisu-general-font-lock-red2 t) '(2 nil t) '(3 sisu-general-font-lock-red2 t) ) (list (concat "^\`\\{3\\}[ ]+\\(group\\|block\\|alt\\|poem\\)$" "\\(.\\|\n\\)+?" "^\`\\{3\\}$" ) '(1 sisu-general-font-lock-red2 t) '(2 nil t) '(3 sisu-general-font-lock-red2 t) ) ;; footnote/endnote ---- ;(cons "\~{.+?}\~" 'sisu-general-font-lock-green1) (cons "\~{\\*\\*\\|\~{\\*\\|\~{\\|}\~" 'sisu-general-font-lock-red2) (cons "\~\\[\\+\\|\~\\[\\*\\|\~\\[\\|\\]\~" 'sisu-general-font-lock-red2) (cons "\~\\^ \\|^\\^\~ " 'sisu-general-font-lock-red2) (list (concat "\\(\*\~\\)" "\\([^ \r\t\n]+\\)" ) '(1 sisu-general-font-lock-red1 t) '(2 sisu-general-font-lock-blue2 t) ) ;; emphasis (can be program configured to be bold italics or underscore) (list (concat "\\([*]{\\)" "\\([^}]+\\)" "\\(}[*]\\)" ) '(1 sisu-general-font-lock-red1 t) '(2 sisu-general-font-lock-red1 t) '(3 sisu-general-font-lock-red1 t) ) ;; bold ---------------- (list (concat "\\([!]{\\)" "\\([^}]+\\)" "\\(}[!]\\)" ) '(1 sisu-general-font-lock-red1 t) '(2 sisu-general-font-lock-red1 t) '(3 sisu-general-font-lock-red1 t) ) (cons "\\*[^ ]+\\*" 'sisu-general-font-lock-red1) (cons "^!_ .+" 'sisu-general-font-lock-red1) ;; italics ------------- (list (concat "\\([/]{\\)" "\\([^}]+\\)" "\\(}[/]\\)" ) '(1 sisu-general-font-lock-red1 t) '(2 sisu-general-font-lock-blue1 t) '(3 sisu-general-font-lock-red1 t) ) ;; underscore ---------- (list (concat "\\([_]{\\)" "\\([^}]+\\)" "\\(\}[_]\\)" ) '(1 sisu-general-font-lock-red1 t) '(2 sisu-general-font-lock-red1 t) '(3 sisu-general-font-lock-red1 t) ) ;; monospace ----------- (list (concat "\\([#]{\\)" "\\([^}]+\\)" "\\(}[#]\\)" ) '(1 sisu-general-font-lock-red1 t) '(2 sisu-general-font-lock-red1 t) '(3 sisu-general-font-lock-red1 t) ) ;; citation ------------ (list (concat "\\([\"]{\\)" "\\([^}]+\\)" "\\(}[\"]\\)" ) '(1 sisu-general-font-lock-red1 t) '(2 sisu-general-font-lock-red1 t) '(3 sisu-general-font-lock-red1 t) ) ;; inserted text ------- (list (concat "\\([\+]{\\)" "\\([^}]+\\)" "\\(}[\+]\\)" ) '(1 sisu-general-font-lock-red1 t) '(2 sisu-general-font-lock-red1 t) '(3 sisu-general-font-lock-red1 t) ) ;; strike through ------ (list (concat "\\(\\-{\\)" "\\([^}]+\\)" "\\(}\\-\\)" ) '(1 sisu-general-font-lock-red1 t) '(2 sisu-general-font-lock-red1 t) '(3 sisu-general-font-lock-red1 t) ) ;; superscript --------- (list (concat "\\(\\^{\\)" "\\([^}]+\\)" "\\(}\\^\\)" ) '(1 sisu-general-font-lock-red1 t) '(2 sisu-general-font-lock-red1 t) '(3 sisu-general-font-lock-red1 t) ) ;; subscript ----------- (list (concat "\\([,]{\\)" "\\([^}]+\\)" "\\(}[,]\\)" ) '(1 sisu-general-font-lock-red1 t) '(2 sisu-general-font-lock-red1 t) '(3 sisu-general-font-lock-red1 t) ) ;; numbered list (cons "^# \\|^_# " 'sisu-general-font-lock-red1) ;; bullet text (cons "^_\\*[1-9] \\|^_\\* " 'sisu-general-font-lock-red1) ;; indented text (cons "^_[1-9] " 'sisu-general-font-lock-red1) (cons "^_[1-9]! " 'sisu-general-font-lock-red1) ;; hanging indented text [proposed enable when implemented] (cons "^__[1-9] " 'sisu-general-font-lock-red1) (cons "^_[0-9]_[0-9] " 'sisu-general-font-lock-red1) (cons "^__[1-9]! " 'sisu-general-font-lock-red1) (cons "^_[0-9]_[0-9]! " 'sisu-general-font-lock-red1) ;; url (cons "\\(^\\|[ ]\\)https?:[/][/][^ \t\n\r<]+" 'sisu-general-font-lock-blue2) ;; Comment Lines (cons "^% .*" 'sisu-general-font-lock-blue1) ;; page break (cons "^\\(-\\\\\\\\-\\|=\\\\\\\\=\\|-\\.\\.-\\)" 'sisu-general-font-lock-red2) ;; line break (cons " \\\\\\\\ " 'sisu-general-font-lock-red1) ;; line break (depreciated) (cons "<br>" 'sisu-general-font-lock-red1) ;; Section titles (list "^\\(\\([1-4]\\|:?[A-D]\\)\\~\\)\\(.*\\)" '(1 sisu-title-1 t) '(3 sisu-title-2 t) ) ;; hyper-links (list (concat "\\({~^\\|{\\)" "\\([^}{]+\\)" "\\(}https?:[/][/][^ \r\n\t<]+\\)" ) '(1 sisu-general-font-lock-blue2 t) '(2 sisu-general-font-lock-red1 t) '(3 sisu-general-font-lock-blue2 t) ) ;; book index (list (concat "^\\(\={\\)" "\\([^}{]+\\)" "\\(}\\)$" ) '(1 sisu-general-font-lock-green1 t) '(2 nil t) '(3 sisu-general-font-lock-green1 t) ) ;(cons "^\={.+}" 'sisu-general-font-lock-green1) ;; numbers (cons "\\<[.0-9]+\\>" 'sisu-general-font-lock-green2) ;; bullets sisu_normal (nearly copied regexp) (cons "^_\\([1-9*]\\|[1-9]\\*\\) " 'sisu-general-font-lock-blue2) ;; image links (list (concat "\\({\\)" "\\([^}{]+\\)" "\\(}image\\)" ) '(1 sisu-general-font-lock-blue2 t) '(2 sisu-general-font-lock-red1 t) '(3 sisu-general-font-lock-blue2 t) ) ;; insert file links (list (concat "\\(<< \\)" "\\([^ \r\t\n]+\\.ss\\)" "\\(i\\|t\\)" ) '(1 sisu-general-font-lock-blue2 t) '(2 sisu-general-font-lock-blue2 t) '(3 sisu-general-font-lock-blue2 t) ) ;; raw keywords (list (concat "^\\(\\(" "creator\\|" "title\\|" "date\\|" "rights\\|" "publisher\\|" "classify\\|" "identifier\\|" "original\\|" "notes\\|" "links\\|" "make\\|" "\\):\\)\\(.*\\)" ) '(1 sisu-title-2 keep) '(3 sisu-title-3 keep) ) ) ) "Default expressions to highlight in AsciiSisu mode." ) ;; outline mode evil "folding" if available ;; (define-key evil-normal-state-map ",0" 'show-all) ;; (define-key evil-normal-state-map ",-" 'hide-body) ;; (define-key evil-normal-state-map ",+" 'show-subtree) ;; (define-key evil-normal-state-map ",=" 'show-subtree) ;; ;; Sisu & Autoload: ;;;###autoload (define-derived-mode sisu-spine-mode text-mode "SiSU" "Major mode for editing SiSU files. SiSU document structuring, publishing in multiple formats and search. URL `https://www.sisudoc.org/'" (modify-syntax-entry ?\' ".") ;;(flyspell-mode nil) (make-local-variable 'paragraph-start) (setq paragraph-start (concat "$\\|>" page-delimiter)) (make-local-variable 'paragraph-separate) (setq paragraph-separate paragraph-start) (make-local-variable 'paragraph-ignore-fill-prefix) (setq paragraph-ignore-fill-prefix t) (set (make-local-variable 'outline-regexp) "^\\(\\([1-4]\\|:?[A-D]\\)\\~\\|\\@[a-z]+:\\( \\|$\\)\\)") (make-local-variable 'require-final-newline) (setq require-final-newline t) (make-local-variable 'font-lock-defaults) (setq font-lock-defaults '(sisu-font-lock-keywords nil ; KEYWORDS-ONLY: no nil ; CASE-FOLD: no ((?_ . "w")) ; SYNTAX-ALIST )) ;; Enable outlining. ;; TODO with outlining make sure linum (line numbering) is off, ;; else performance penalty, sucks bigtime (outline-minor-mode 1)) ;;;###autoload (add-to-list 'auto-mode-alist '("\\.ss[imt]\\'" . sisu-spine-mode)) (provide 'sisu-spine-mode) ;; ;;; sisu-spine-mode.el ends here