Blob


1 ;;; 9ps-mode.el --- major mode for editing ninepscripts -*- lexical-binding: t; -*-
3 ;; Copyright (C) 2021 Omar Polo
5 ;; Author: Omar Polo <op@omarpolo.com>
6 ;; Keywords: languages
8 ;; Permission to use, copy, modify, and distribute this software for any
9 ;; purpose with or without fee is hereby granted, provided that the above
10 ;; copyright notice and this permission notice appear in all copies.
12 ;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 ;; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 ;; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 ;; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 ;; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ;; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 ;; OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 ;;; Commentary:
22 ;; Major mode for editing ninepscripts, the kamid regression tests.
24 ;;; Code:
25 (eval-when-compile
26 (require 'rx))
28 (defconst 9ps-keywords
29 '("assert" "const" "dir" "include" "proc" "str" "testing"
30 "u8" "u16" "u32"))
32 (defconst 9ps--font-lock-keywords
33 (list
34 (rx-to-string
35 `(: (or ,@9ps-keywords))))
36 "`9ps-mode' constant keywords.")
38 (defvar 9ps-mode-syntax-table
39 (let ((st (make-syntax-table)))
40 (modify-syntax-entry ?\{ "(}" st)
41 (modify-syntax-entry ?\} "){" st)
42 (modify-syntax-entry ?\( "()" st)
43 ;; - and _ are word constituent
44 (modify-syntax-entry ?_ "w" st)
45 (modify-syntax-entry ?- "w" st)
46 ;; both single and double quotes makes strings
47 (modify-syntax-entry ?\" "\"" st)
48 (modify-syntax-entry ?' "'" st)
49 ;; one day we'll have escaping (maybe)
50 (modify-syntax-entry ?\\ "\\" st)
51 ;; add comments. is this the correct way?
52 (modify-syntax-entry ?# "<" st)
53 (modify-syntax-entry ?\n ">" st)
54 st))
56 (defun 9ps-indent-line ()
57 "Indent current line."
58 (let (indent
59 boi-p ;begin of indent
60 move-eol-p
61 (point (point)))
62 (save-excursion
63 (back-to-indentation)
64 (setq indent (car (syntax-ppss))
65 boi-p (= point (point)))
66 ;; don't indent empty lines, but only when they don't have the
67 ;; cursor in it.
68 (when (and (eq (char-after) ?\n)
69 (not boi-p))
70 (setq indent 0))
71 ;; check whether we want to move to the end of line
72 (when (and (eq (char-after) ?\n)
73 boi-p)
74 (setq move-eol-p t))
75 ;; decrement the indent if the first character on the line is a
76 ;; closer.
77 (when (or (eq (char-after) ?\))
78 (eq (char-after) ?\}))
79 (setq indent (1- indent)))
80 ;; indent the line
81 (delete-region (line-beginning-position)
82 (point))
83 (indent-to (* tab-width indent)))
84 (when move-eol-p
85 (move-end-of-line nil))))
87 ;;;###autoload
88 (define-derived-mode 9ps-mode prog-mode "9ps"
89 "Major mode for ninepscript files."
90 (setq font-lock-defaults '((9ps--font-lock-keywords)))
91 (setq-local comment-start "#")
92 (setq-local comment-start-skip "#+[\t ]*")
93 (setq-local indent-line-function #'9ps-indent-line))
95 ;;;###autoload
96 (add-to-list 'auto-mode-alist '("\\.9ps" . 9ps-mode))
98 (provide '9ps-mode)
99 ;;; 9ps-mode.el ends here