]> code.delx.au - gnu-emacs-elpa/blob - coffee-mode.el
basic indentation with TAB
[gnu-emacs-elpa] / coffee-mode.el
1 ;; Major thanks to http://xahlee.org/emacs/elisp_syntax_coloring.html
2 ;; the instructions.
3
4
5 ;;
6 ;; Define Language Syntax
7 ;;
8
9 ;; Assignment
10 (defvar coffee-type-regexp ".+?:")
11
12 ;; Instance variables (implicit this)
13 (defvar coffee-constant-regexp "@\\w*\\|this")
14
15 ;; Booleans
16 (defvar coffee-functions-regexp "\\b\\(true\\|false\\|yes\\|no\\|on\\|off\\)\\b")
17
18 ;; Unused
19 (defvar coffee-event-regexp "")
20
21 ;; JavaScript Keywords
22 (defvar coffee-js-keywords
23 '("if" "else" "new" "return" "try" "catch"
24 "finally" "throw" "break" "continue" "for" "in" "while"
25 "delete" "instanceof" "typeof" "switch" "super" "extends"
26 "class"))
27
28 ;; Reserved keywords either by JS or CS.
29 (defvar coffee-js-reserved
30 '("case" "default" "do" "function" "var" "void" "with"
31 "const" "let" "debugger" "enum" "export" "import" "native"
32 "__extends" "__hasProp"))
33
34 ;; CoffeeScript keywords.
35 (defvar coffee-cs-keywords
36 '("then" "unless" "and" "or" "is"
37 "isnt" "not" "of" "by" "where" "when"))
38
39 ;; Regular expression combining the above three lists.
40 (defvar coffee-keywords-regexp (regexp-opt
41 (append
42 coffee-js-reserved
43 coffee-js-keywords
44 coffee-cs-keywords) 'words))
45
46
47 ;; Create the list for font-lock.
48 ;; Each class of keyword is given a particular face
49 (defvar coffee-font-lock-keywords
50 `(
51 (,coffee-type-regexp . font-lock-type-face)
52 (,coffee-constant-regexp . font-lock-variable-name-face)
53 (,coffee-event-regexp . font-lock-builtin-face)
54 (,coffee-functions-regexp . font-lock-constant-face)
55 (,coffee-keywords-regexp . font-lock-keyword-face)
56
57 ;; note: order above matters. `coffee-keywords-regexp' goes last because
58 ;; otherwise the keyword "state" in the function "state_entry"
59 ;; would be highlighted.
60 ))
61
62
63 ;;
64 ;; Helper Functions
65 ;;
66
67 ;; The command to comment/uncomment text
68 (defun coffee-comment-dwim (arg)
69 "Comment or uncomment current line or region in a smart way.
70 For detail, see `comment-dwim'."
71 (interactive "*P")
72 (require 'newcomment)
73 (let ((deactivate-mark nil) (comment-start "#") (comment-end ""))
74 (comment-dwim arg)))
75
76 ;;
77 ;; Indentation
78 ;;
79
80 ;; The theory here is simple:
81 ;; When you press TAB, indent the line unless doing so would make the
82 ;; current line more than two indentation levels deepers than the
83 ;; previous line. If that's the case, remove all indentation.
84 ;;
85 ;; Consider this code, with point at the position indicated by the
86 ;; carot:
87 ;;
88 ;; line1()
89 ;; line2()
90 ;; line3()
91 ;; ^
92 ;; Pressing TAB will produce the following code:
93 ;;
94 ;; line1()
95 ;; line2()
96 ;; line3()
97 ;; ^
98 ;;
99 ;; Pressing TAB again will produce this code:
100 ;;
101 ;; line1()
102 ;; line2()
103 ;; line3()
104 ;; ^
105 ;;
106 ;; And so on.
107
108 (defun coffee-indent-line ()
109 "Indent current line as CoffeeScript"
110 (interactive)
111
112 (save-excursion
113 (let ((prev-indent 0) (cur-indent 0))
114 ;; Figure out the indentation of the previous line
115 (forward-line -1)
116 (setq prev-indent (current-indentation))
117
118 ;; Figure out the current line's indentation
119 (forward-line 1)
120 (setq cur-indent (current-indentation))
121
122 ;; Shift one column to the left
123 (backward-to-indentation 0)
124 (insert-tab)
125
126 ;; We're too far, remove all indentation.
127 (when (> (- (current-indentation) prev-indent) tab-width)
128 (backward-to-indentation 0)
129 (delete-region (point-at-bol) (point))))))
130
131 ;;
132 ;; Define Major Mode
133 ;;
134
135 (define-derived-mode coffee-mode fundamental-mode
136 "coffee-mode"
137 "Major mode for editing CoffeeScript..."
138
139 ;; code for syntax highlighting
140 (setq font-lock-defaults '((coffee-font-lock-keywords)))
141
142 ;; modify the keymap
143 (define-key coffee-mode-map [remap comment-dwim] 'coffee-comment-dwim)
144
145 ;; perl style comment: "# ..."
146 (modify-syntax-entry ?# "< b" coffee-mode-syntax-table)
147 (modify-syntax-entry ?\n "> b" coffee-mode-syntax-table)
148 (setq comment-start "#")
149
150 ;; single quote strings
151 (modify-syntax-entry ?' "\"" coffee-mode-syntax-table)
152 (modify-syntax-entry ?' "\"" coffee-mode-syntax-table)
153
154 ;; regular expressions
155 (modify-syntax-entry ?/ "\"" coffee-mode-syntax-table)
156 (modify-syntax-entry ?/ "\"" coffee-mode-syntax-table)
157
158 ;; indentation
159 (make-local-variable 'indent-line-function)
160 (setq indent-line-function 'coffee-indent-line)
161
162 ;; no tabs
163 (setq indent-tabs-mode nil)
164
165 ;; clear memory
166 (setq coffee-keywords-regexp nil)
167 (setq coffee-types-regexp nil)
168 (setq coffee-constants-regexp nil)
169 (setq coffee-events-regexp nil)
170 (setq coffee-functions-regexp nil))