-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathmoonscript.el
148 lines (118 loc) · 5.03 KB
/
moonscript.el
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
;;; moonscript.el --- Major mode for editing MoonScript code
;;;
;; Author: @GriffinSchneider, @k2052, @EmacsFodder
;; Version: 20140803-0.1.0
;; Package-Requires: ((cl-lib "0.5") (emacs "24"))
;;; Commentary:
;;
;; A basic major mode for editing MoonScript, a preprocessed language
;; for Lua which shares many similarities with CoffeeScript.
;;
;;; License: MIT Licence
;;
;;; Code:
(require 'cl-lib)
(defgroup moonscript nil
"MoonScript (for Lua) language support for Emacs."
:tag "MoonScript"
:group 'languages)
(defcustom moonscript-indent-offset 2
"How many spaces to indent MoonScript code per level of nesting."
:group 'moonscript
:type 'integer
:safe 'integerp)
(defcustom moonscript-comment-start "-- "
"Default value of `comment-start'."
:group 'moonscript
:type 'string
:safe 'stringp)
(defvar moonscript-statement
'("return" "break" "continue"))
(defvar moonscript-repeat
'("for" "while"))
(defvar moonscript-conditional
'("if" "else" "elseif" "then" "switch" "when" "unless"))
(defvar moonscript-keyword
'("export" "local" "import" "from" "with" "in" "and" "or" "not"
"class" "extends" "super" "using" "do"))
(defvar moonscript-keywords
(append moonscript-statement moonscript-repeat moonscript-conditional moonscript-keyword))
(defvar moonscript-constants
'("nil" "true" "false" "self"))
(defvar moonscript-keywords-regex (regexp-opt moonscript-keywords 'symbols))
(defvar moonscript-constants-regex (regexp-opt moonscript-constants 'symbols))
(defvar moonscript-class-name-regex "\\<[A-Z]\\w*\\>")
(defvar moonscript-function-keywords
'("->" "=>" "(" ")" "[" "]" "{" "}"))
(defvar moonscript-function-regex (regexp-opt moonscript-function-keywords))
(defvar moonscript-octal-number-regex
"\\_<0x[[:xdigit:]]+\\_>")
(defvar moonscript-table-key-regex
"\\_<\\w+:")
(defvar moonscript-ivar-regex
"@\\_<\\w+\\_>")
(defvar moonscript-assignment-regex
"\\([-+/*%]\\|\\.\\.\\)?=")
(defvar moonscript-number-regex
(mapconcat 'identity '("[0-9]+\\.[0-9]*" "[0-9]*\\.[0-9]+" "[0-9]+") "\\|"))
(defvar moonscript-assignment-var-regex
(concat "\\(\\_<\\w+\\) = "))
(defvar moonscript-font-lock-defaults
`((,moonscript-class-name-regex . font-lock-type-face)
(,moonscript-function-regex . font-lock-function-name-face)
(,moonscript-assignment-regex . font-lock-preprocessor-face)
(,moonscript-constants-regex . font-lock-constant-face)
(,moonscript-keywords-regex . font-lock-keyword-face)
(,moonscript-ivar-regex . font-lock-variable-name-face)
(,moonscript-assignment-var-regex . (1 font-lock-variable-name-face))
(,moonscript-octal-number-regex . font-lock-constant-face)
(,moonscript-number-regex . font-lock-constant-face)
(,moonscript-table-key-regex . font-lock-variable-name-face)
("!" . font-lock-warning-face)))
(defun moonscript-indent-level (&optional blankval)
"Return nesting depth of current line.
If BLANKVAL is non-nil, return that instead if the line is blank.
Upon return, regexp match data is set to the leading whitespace."
(cl-assert (= (point) (point-at-bol)))
(looking-at "^[ \t]*")
(if (and blankval (= (match-end 0) (point-at-eol)))
blankval
(floor (/ (- (match-end 0) (match-beginning 0))
moonscript-indent-offset))))
(defun moonscript-indent-line ()
"Cycle indentation levels for the current line of MoonScript code.
Looks at how deeply the previous non-blank line is nested. The
maximum indentation level for the current line is that level plus
one.
When computing indentation depth, one tab is currently considered
equal to one space. Tabs are currently replaced with spaces when
re-indenting a line."
(goto-char (point-at-bol))
(let ((curlinestart (point))
(prevlineindent -1))
;; Find indent level of previous non-blank line.
(while (and (< prevlineindent 0) (> (point) (point-min)))
(goto-char (1- (point)))
(goto-char (point-at-bol))
(setq prevlineindent (moonscript-indent-level -1)))
;; Re-indent current line based on what we know.
(goto-char curlinestart)
(let* ((oldindent (moonscript-indent-level))
(newindent (if (= oldindent 0) (1+ prevlineindent)
(1- oldindent))))
(replace-match (make-string (* newindent moonscript-indent-offset)
? )))))
;;;###autoload
(define-derived-mode moonscript-mode prog-mode "MoonScript"
"Major mode for editing MoonScript code."
(setq font-lock-defaults '(moonscript-font-lock-defaults))
(set (make-local-variable 'indent-line-function) 'moonscript-indent-line)
(set (make-local-variable 'electric-indent-inhibit) t)
(set (make-local-variable 'comment-start) moonscript-comment-start)
(modify-syntax-entry ?\- ". 12b" moonscript-mode-syntax-table)
(modify-syntax-entry ?\n "> b" moonscript-mode-syntax-table)
(modify-syntax-entry ?\_ "w" moonscript-mode-syntax-table))
;;;###autoload
(add-to-list 'auto-mode-alist '("\\.moon\\'" . moonscript-mode))
(provide 'moonscript)
;;; moonscript.el ends here