;;; lightroff.el --- major mode for lightroff -*- lexical-binding: t; -*- ;; Copyright (C) 2022 John Ankarström ;; Author: John Ankarström ;; 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-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 "