aboutsummaryrefslogtreecommitdiff
path: root/lightroff.el
blob: ca49866c962daad05ad93f621c6d2344914e5bf5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
;;; lightroff.el --- major mode for lightroff  -*- lexical-binding: t; -*-

;; Copyright (C) 2022 John Ankarström

;; Author: John Ankarström <john@ankarstrom.se>
;; Created: 10 Jul 2022
;; Version: 0.1

;; Keywords: troff groff
;; URL: http://ankarstrom.se/~john/etc/lightroff

;; This file is not part of GNU Emacs.

;; Permission to use, copy, modify and/or distribute this software for
;; any purpose with or without fee is hereby granted.

;;; Commentary:

;; Major mode for lightroff, an alternative, XML-like syntax for troff.

;;; Code:

(defvar lightroff--request-regexp
  (rx "<"
      (group (+ (or "\\>" (not (in "> ")))))
      (group (* (or "\\>" (not ?>))))
      ">"))

(defvar lightroff--single-escape-regexp
  (rx "\\" any))

(defvar lightroff--identifier-escape-regexp
  (rx "\\"
      (any "FfgkmnOsYZ*$")
      (? (any "+-"))
      (or (not (any "([+-"))
	  (seq "(" any any)
	  (seq "[" (* (not "]")) "]"))))

(defvar lightroff--parameter-escape-regexp
  (rx "\\"
      (any "ABbCDHhLlMNoRSVvwXxz")
      "'" (* (not "'")) "'"))

(defconst lightroff-font-lock-keywords
  `(;; Comment.
    ("<!--.*-->"
     (0 font-lock-comment-face))
    ;; Request.
    (,(concat lightroff--request-regexp)
     (1 font-lock-keyword-face keep)
     (2 font-lock-string-face keep))
    (,(concat "\\\\" lightroff--request-regexp)
     (1 nil t)
     (2 nil t))
    ;; Parameter escape (e.g., \l'...').
    (,lightroff--parameter-escape-regexp
     (0 lightroff-escape-face))
    (,(concat "\\\\" lightroff--parameter-escape-regexp)
     (0 nil t))
    ;; Identifier escape (e.g., \n(PI).
    (,lightroff--identifier-escape-regexp
     (0 lightroff-escape-face))
    (,(concat "\\\\" lightroff--identifier-escape-regexp)
     (0 nil t))
    ;; Single escape (e.g., \%).
    (,lightroff--single-escape-regexp
     (0 lightroff-escape-face))
    (,(concat "\\\\" lightroff--single-escape-regexp)
     (0 nil t))
    ;; Escaped backslash.
    (,"\\\\\\\\"
     (0 lightroff-escape-face t))))

(defface lightroff-escape
  '((t (:foreground "gray")))
  "`lightroff-mode' face used to highlight backslash escapes."
  :group 'lightroff)
(defvar lightroff-escape-face 'lightroff-escape)

;;;###autoload
(define-derived-mode lightroff-mode text-mode "Lightroff"
  "Major mode for editing documents with lightroff syntax."
  ;; A start or end tag by itself on a line separates a paragraph.
  ;; This is desirable because SGML discards a newline that appears
  ;; immediately after a start tag or immediately before an end tag.
  (setq-local paragraph-start "<\\([^>]\\)+>")
  (setq-local paragraph-separate "$\\|\\]>")
  (setq-local adaptive-fill-regexp "[ \t]*")
  ;; (add-hook 'fill-nobreak-predicate 'sgml-fill-nobreak nil t)
  ;; (setq-local indent-line-function 'sgml-indent-line)
  (setq-local comment-start "<!-- ")
  (setq-local comment-end " -->")
  ;; (setq-local comment-indent-function 'sgml-comment-indent)
  ;; (setq-local comment-line-break-function 'sgml-comment-indent-new-line)
  (setq-local font-lock-defaults '((lightroff-font-lock-keywords)))
  ;; (setq-local font-lock-multiline t)
  (setq-local comment-start-skip "<!--[ \t]*")
  (setq-local comment-end-skip "[ \t]*--[ \t\n]*>")
  (visual-line-mode 1))

(provide 'lightroff)
;;; lightroff.el ends here