Blame


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