Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 945 lines (770 sloc) 30.814 kb
4a11c70 @defunkt documentation
authored
1 ;;; coffee-mode.el --- Major mode to edit CoffeeScript files in Emacs
2
3 ;; Copyright (C) 2010 Chris Wanstrath
4
89203e8 @rrthomas Make version consistent and bump it to 0.4.1 (Fixes #61).
rrthomas authored
5 ;; Version: 0.4.1
4a11c70 @defunkt documentation
authored
6 ;; Keywords: CoffeeScript major mode
7 ;; Author: Chris Wanstrath <chris@ozmm.org>
1d2aed3 @defunkt Use correct URL. Fixes #71
authored
8 ;; URL: http://github.com/defunkt/coffee-mode
4a11c70 @defunkt documentation
authored
9
10 ;; This file is not part of GNU Emacs.
11
12 ;; This program is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; any later version.
16
17 ;; This program is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
21
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with this program; if not, write to the Free Software
24 ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25
26 ;;; Commentary
27
20c919a @rrthomas Change installation instructions to advise use of ELPA.
rrthomas authored
28 ;; Provides syntax highlighting, indentation support, imenu support,
29 ;; a menu bar, and a few cute commands.
4a11c70 @defunkt documentation
authored
30
20c919a @rrthomas Change installation instructions to advise use of ELPA.
rrthomas authored
31 ;; ## Indentation
4a11c70 @defunkt documentation
authored
32
20c919a @rrthomas Change installation instructions to advise use of ELPA.
rrthomas authored
33 ;; ### TAB Theory
4a11c70 @defunkt documentation
authored
34
20c919a @rrthomas Change installation instructions to advise use of ELPA.
rrthomas authored
35 ;; It goes like this: when you press `TAB`, we indent the line unless
36 ;; doing so would make the current line more than two indentation levels
37 ;; deepers than the previous line. If that's the case, remove all
38 ;; indentation.
4a11c70 @defunkt documentation
authored
39
20c919a @rrthomas Change installation instructions to advise use of ELPA.
rrthomas authored
40 ;; Consider this code, with point at the position indicated by the
41 ;; caret:
4a11c70 @defunkt documentation
authored
42
20c919a @rrthomas Change installation instructions to advise use of ELPA.
rrthomas authored
43 ;; line1()
44 ;; line2()
45 ;; line3()
46 ;; ^
4a11c70 @defunkt documentation
authored
47
20c919a @rrthomas Change installation instructions to advise use of ELPA.
rrthomas authored
48 ;; Pressing `TAB` will produce the following code:
4a11c70 @defunkt documentation
authored
49
20c919a @rrthomas Change installation instructions to advise use of ELPA.
rrthomas authored
50 ;; line1()
51 ;; line2()
52 ;; line3()
53 ;; ^
4a11c70 @defunkt documentation
authored
54
20c919a @rrthomas Change installation instructions to advise use of ELPA.
rrthomas authored
55 ;; Pressing `TAB` again will produce this code:
56
57 ;; line1()
58 ;; line2()
59 ;; line3()
60 ;; ^
61
62 ;; And so on. I think this is a pretty good way of getting decent
63 ;; indentation with a whitespace-sensitive language.
64
65 ;; ### Newline and Indent
66
67 ;; We all love hitting `RET` and having the next line indented
68 ;; properly. Given this code and cursor position:
69
70 ;; line1()
71 ;; line2()
72 ;; line3()
73 ;; ^
74
75 ;; Pressing `RET` would insert a newline and place our cursor at the
76 ;; following position:
77
78 ;; line1()
79 ;; line2()
80 ;; line3()
81
82 ;; ^
83
84 ;; In other words, the level of indentation is maintained. This
85 ;; applies to comments as well. Combined with the `TAB` you should be
86 ;; able to get things where you want them pretty easily.
87
88 ;; ### Indenters
89
90 ;; `class`, `for`, `if`, and possibly other keywords cause the next line
91 ;; to be indented a level deeper automatically.
92
93 ;; For example, given this code and cursor position::
94
95 ;; class Animal
96 ;; ^
97
98 ;; Pressing enter would produce the following:
99
100 ;; class Animal
101
102 ;; ^
103
104 ;; That is, indented a column deeper.
105
106 ;; This also applies to lines ending in `->`, `=>`, `{`, `[`, and
107 ;; possibly more characters.
108
109 ;; So this code and cursor position:
110
111 ;; $('#demo').click ->
112 ;; ^
113
114 ;; On enter would produce this:
115
116 ;; $('#demo').click ->
117
118 ;; ^
119
120 ;; Pretty slick.
121
122 ;; Thanks to Jeremy Ashkenas for CoffeeScript, and to
123 ;; http://xahlee.org/emacs/elisp_syntax_coloring.html, Jason
124 ;; Blevins's markdown-mode.el and Steve Yegge's js2-mode for guidance.
38ce8da @defunkt small tweaks
authored
125
12bd5d0 @defunkt todo
authored
126 ;; TODO:
127 ;; - Make prototype accessor assignments like `String::length: -> 10` pretty.
5b00ae2 @defunkt more todo
authored
128 ;; - mirror-mode - close brackets and parens automatically
12bd5d0 @defunkt todo
authored
129
130 ;;; Code:
131
6639c36 @mkhl Silence byte-compiler warnings.
mkhl authored
132 (require 'comint)
38ce8da @defunkt small tweaks
authored
133 (require 'easymenu)
134 (require 'font-lock)
6639c36 @mkhl Silence byte-compiler warnings.
mkhl authored
135
136 (eval-when-compile
137 (require 'cl))
0480381 @defunkt mini docs
authored
138
7557530 @defunkt compilation commands
authored
139 ;;
38ce8da @defunkt small tweaks
authored
140 ;; Customizable Variables
7557530 @defunkt compilation commands
authored
141 ;;
142
89203e8 @rrthomas Make version consistent and bump it to 0.4.1 (Fixes #61).
rrthomas authored
143 (defconst coffee-mode-version "0.4.1"
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
144 "The version of `coffee-mode'.")
5f14029 @defunkt Menu
authored
145
7976bc4 @defunkt Make config options available from `customize-group`, document in README
authored
146 (defgroup coffee nil
147 "A CoffeeScript major mode."
148 :group 'languages)
149
150 (defcustom coffee-tab-width tab-width
151 "The tab width to use when indenting."
152 :type 'integer
153 :group 'coffee)
154
155 (defcustom coffee-command "coffee"
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
156 "The CoffeeScript command used for evaluating code."
7976bc4 @defunkt Make config options available from `customize-group`, document in README
authored
157 :type 'string
158 :group 'coffee)
7557530 @defunkt compilation commands
authored
159
1561b47 Adds an option to move the output directory for the JavaScript files
Ivan Stoyanov Arabadzhiev authored
160 (defcustom coffee-js-directory ""
161 "The directory for compiled JavaScript files output"
162 :type 'string
163 :group 'coffee)
164
2c204ef @mizchi add coffee-js2coffee-replace-region
mizchi authored
165 (defcustom js2coffee-command "js2coffee"
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
166 "The js2coffee command used for evaluating code."
2c204ef @mizchi add coffee-js2coffee-replace-region
mizchi authored
167 :type 'string
168 :group 'coffee)
169
3b0962d @defunkt Rename `args` variables to be more consistent.
authored
170 (defcustom coffee-args-repl '("-i")
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
171 "The arguments to pass to `coffee-command' to start a REPL."
7976bc4 @defunkt Make config options available from `customize-group`, document in README
authored
172 :type 'list
173 :group 'coffee)
28485fa @defunkt `coffee-repl'
authored
174
227a360 @orlandohill Customize args for compiling files and display the first compiler error
orlandohill authored
175 (defcustom coffee-args-compile '("-c")
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
176 "The arguments to pass to `coffee-command' to compile a file."
7976bc4 @defunkt Make config options available from `customize-group`, document in README
authored
177 :type 'list
178 :group 'coffee)
5f14029 @defunkt Menu
authored
179
7976bc4 @defunkt Make config options available from `customize-group`, document in README
authored
180 (defcustom coffee-compiled-buffer-name "*coffee-compiled*"
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
181 "The name of the scratch buffer used for compiled CoffeeScript."
7976bc4 @defunkt Make config options available from `customize-group`, document in README
authored
182 :type 'string
183 :group 'coffee)
7557530 @defunkt compilation commands
authored
184
b90db10 @tmcgilchrist Refactor name of Coffee REPL buffer into variable.
tmcgilchrist authored
185 (defcustom coffee-repl-buffer "*CoffeeREPL*"
186 "The name of the CoffeeREPL buffer."
187 :type 'string
188 :group 'coffee)
189
14a0d56 @errge Added coffee-compile-jump-to-error.
errge authored
190 (defcustom coffee-compile-jump-to-error t
191 "Whether to jump to the first error if compilation fails.
e5f93e8 @rrthomas Improve the coffee-compile-jump-to-error docstring.
rrthomas authored
192 Since the coffee compiler does not always include a line number in
193 its error messages, this is not always possible."
14a0d56 @errge Added coffee-compile-jump-to-error.
errge authored
194 :type 'boolean
195 :group 'coffee)
196
0b06b86 @semperos Add support for coffee --watch, and in process also add function for run...
semperos authored
197 (defcustom coffee-watch-buffer-name "*coffee-watch*"
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
198 "The name of the scratch buffer used when using the --watch flag
199 with CoffeeScript."
0b06b86 @semperos Add support for coffee --watch, and in process also add function for run...
semperos authored
200 :type 'string
201 :group 'coffee)
202
6d1d92d @rrthomas Make coffee-mode-hook customizable.
rrthomas authored
203 (defcustom coffee-mode-hook nil
20c919a @rrthomas Change installation instructions to advise use of ELPA.
rrthomas authored
204 "Hook called by `coffee-mode'. Examples:
205
206 ;; CoffeeScript uses two spaces.
207 (make-local-variable 'tab-width)
208 (set 'tab-width 2)
209
210 ;; If you don't want your compiled files to be wrapped
211 (setq coffee-args-compile '(\"-c\" \"--bare\"))
212
213 ;; Emacs key binding
214 (define-key coffee-mode-map [(meta r)] 'coffee-compile-buffer)
215
216 ;; Bleeding edge.
217 (setq coffee-command \"~/dev/coffee\")
218
219 ;; Compile '.coffee' files on every save
220 (and (file-exists-p (buffer-file-name))
221 (file-exists-p (coffee-compiled-file-name))
222 (coffee-cos-mode t)))"
6d1d92d @rrthomas Make coffee-mode-hook customizable.
rrthomas authored
223 :type 'hook
224 :group 'coffee)
1b887a5 @defunkt clean whitespace on save
authored
225
677cf42 fix some really obnoxious indentation
Justine Tunney authored
226 (defvar coffee-mode-map
227 (let ((map (make-sparse-keymap)))
228 ;; key bindings
229 (define-key map (kbd "A-r") 'coffee-compile-buffer)
230 (define-key map (kbd "A-R") 'coffee-compile-region)
231 (define-key map (kbd "A-M-r") 'coffee-repl)
232 (define-key map [remap comment-dwim] 'coffee-comment-dwim)
233 (define-key map [remap newline-and-indent] 'coffee-newline-and-indent)
234 (define-key map "\C-m" 'coffee-newline-and-indent)
235 (define-key map "\C-c\C-o\C-s" 'coffee-cos-mode)
67e8727 backspace now de-indents instead of just going back a space.
Shawn Krisman authored
236 (define-key map "\177" 'coffee-dedent-line-backspace)
e45ce09 @akheron Add functions for shifting blocks of code left and right
akheron authored
237 (define-key map (kbd "C-c C-<") 'coffee-indent-shift-left)
238 (define-key map (kbd "C-c C->") 'coffee-indent-shift-right)
329302e @YaleHuang Added SHIFT-TAB .
YaleHuang authored
239 (define-key map (kbd "<backtab>") 'coffee-indent-shift-left)
677cf42 fix some really obnoxious indentation
Justine Tunney authored
240 map)
eee29e0 @defunkt defvar the keymap
authored
241 "Keymap for CoffeeScript major mode.")
242
38ce8da @defunkt small tweaks
authored
243 ;;
244 ;; Commands
245 ;;
28485fa @defunkt `coffee-repl'
authored
246 (defun coffee-repl ()
247 "Launch a CoffeeScript REPL using `coffee-command' as an inferior mode."
248 (interactive)
249
b90db10 @tmcgilchrist Refactor name of Coffee REPL buffer into variable.
tmcgilchrist authored
250 (unless (comint-check-proc coffee-repl-buffer)
28485fa @defunkt `coffee-repl'
authored
251 (set-buffer
17150cf @defunkt docs and starting to implement indenters
authored
252 (apply 'make-comint "CoffeeREPL"
d06825b @fred-o Workaround to avoid getting garbage chars in the comint buffer.
fred-o authored
253 "env"
254 nil (append (list "NODE_NO_READLINE=1" coffee-command) coffee-args-repl))))
28485fa @defunkt `coffee-repl'
authored
255
b90db10 @tmcgilchrist Refactor name of Coffee REPL buffer into variable.
tmcgilchrist authored
256 (pop-to-buffer coffee-repl-buffer))
38ce8da @defunkt small tweaks
authored
257
62c84fb @knu Add a function coffee-compiled-file-name for ease of scripting.
knu authored
258 (defun coffee-compiled-file-name (&optional filename)
7d0c394 @syohex Fix for bytecompiling warnings
syohex authored
259 (let ((working-on-file (expand-file-name (or filename (buffer-file-name)))))
260 (unless (string= coffee-js-directory "")
261 (setq working-on-file
262 (expand-file-name (concat (file-name-directory working-on-file)
263 coffee-js-directory
264 (file-name-nondirectory working-on-file)))))
265 ;; Returns the name of the JavaScript file compiled from a CoffeeScript file.
266 ;; If FILENAME is omitted, the current buffer's file name is used.
267 (concat (file-name-sans-extension working-on-file) ".js")))
62c84fb @knu Add a function coffee-compiled-file-name for ease of scripting.
knu authored
268
cbd31f9 @defunkt coffee-compile-file
authored
269 (defun coffee-compile-file ()
20c919a @rrthomas Change installation instructions to advise use of ELPA.
rrthomas authored
270 "Compiles and saves the current file to disk in a file of the same
271 base name, with extension `.js'. Subsequent runs will overwrite the
272 file.
273
274 If there are compilation errors, point is moved to the first
275 (see `coffee-compile-jump-to-error')."
cbd31f9 @defunkt coffee-compile-file
authored
276 (interactive)
227a360 @orlandohill Customize args for compiling files and display the first compiler error
orlandohill authored
277 (let ((compiler-output (shell-command-to-string (coffee-command-compile (buffer-file-name)))))
278 (if (string= compiler-output "")
62c84fb @knu Add a function coffee-compiled-file-name for ease of scripting.
knu authored
279 (message "Compiled and saved %s" (coffee-compiled-file-name))
14a0d56 @errge Added coffee-compile-jump-to-error.
errge authored
280 (let* ((msg (car (split-string compiler-output "[\n\r]+")))
66c326b @rrthomas Remove custom debug code; should use the standard Emacs debugging tools ...
rrthomas authored
281 (line (and (string-match "on line \\([0-9]+\\)" msg)
282 (string-to-number (match-string 1 msg)))))
283 (message msg)
284 (when (and coffee-compile-jump-to-error line (> line 0))
285 (goto-char (point-min))
286 (forward-line (1- line)))))))
cbd31f9 @defunkt coffee-compile-file
authored
287
7557530 @defunkt compilation commands
authored
288 (defun coffee-compile-buffer ()
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
289 "Compiles the current buffer and displays the JavaScript in a buffer
290 called `coffee-compiled-buffer-name'."
7557530 @defunkt compilation commands
authored
291 (interactive)
292 (save-excursion
293 (coffee-compile-region (point-min) (point-max))))
294
295 (defun coffee-compile-region (start end)
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
296 "Compiles a region and displays the JavaScript in a buffer called
297 `coffee-compiled-buffer-name'."
7557530 @defunkt compilation commands
authored
298 (interactive "r")
299
300 (let ((buffer (get-buffer coffee-compiled-buffer-name)))
301 (when buffer
af89c39 @lcoq coffee-compile-region does not give focus to the compiled buffer, and cl...
lcoq authored
302 (with-current-buffer buffer
303 (erase-buffer))))
7557530 @defunkt compilation commands
authored
304
b4270de @semperos Allow existing `coffee-args-compile` to be used for `coffee-compile-regi...
semperos authored
305 (apply (apply-partially 'call-process-region start end coffee-command nil
306 (get-buffer-create coffee-compiled-buffer-name)
307 nil)
308 (append coffee-args-compile (list "-s" "-p")))
af89c39 @lcoq coffee-compile-region does not give focus to the compiled buffer, and cl...
lcoq authored
309
310 (let ((buffer (get-buffer coffee-compiled-buffer-name)))
311 (display-buffer buffer)
312 (with-current-buffer buffer
313 (let ((buffer-file-name "tmp.js")) (set-auto-mode)))))
3a47b28 @defunkt docs
authored
314
6542c7b @tmcgilchrist Merge branch 'master' into inferior-coffee
tmcgilchrist authored
315 ;; TODO replace coffee-repl-buffer with function like this
316 (defun coffee-get-repl-proc ()
317 (unless (comint-check-proc coffee-repl-buffer)
318 (coffee-repl))
319 (get-buffer-process coffee-repl-buffer))
3a47b28 @defunkt docs
authored
320
075b1ce @tmcgilchrist Add functions to send buffer, region and line to the CoffeeREPL buffer.
tmcgilchrist authored
321 (defun coffee-send-line (start end)
d7c9ac8 @tmcgilchrist Add key mappings to run the new send functions. Followed convention used...
tmcgilchrist authored
322 "Send the current line to the inferior Coffee process."
075b1ce @tmcgilchrist Add functions to send buffer, region and line to the CoffeeREPL buffer.
tmcgilchrist authored
323 (interactive "r")
6542c7b @tmcgilchrist Merge branch 'master' into inferior-coffee
tmcgilchrist authored
324 (send-region coffee-get-repl-proc (line-beginning-position) (line-end-position))
325 (send-string coffee-get-repl-proc "\n"))
075b1ce @tmcgilchrist Add functions to send buffer, region and line to the CoffeeREPL buffer.
tmcgilchrist authored
326
327 (defun coffee-send-region (start end)
328 "Send the current region to the inferior Coffee process."
329 (interactive "r")
b90db10 @tmcgilchrist Refactor name of Coffee REPL buffer into variable.
tmcgilchrist authored
330 (send-region coffee-repl-buffer start end)
331 (send-string coffee-repl-buffer "\n"))
075b1ce @tmcgilchrist Add functions to send buffer, region and line to the CoffeeREPL buffer.
tmcgilchrist authored
332
333 (defun coffee-send-buffer ()
334 "Send the current buffer to the inferior Coffee process."
335 (interactive "r")
b90db10 @tmcgilchrist Refactor name of Coffee REPL buffer into variable.
tmcgilchrist authored
336 (send-region coffee-repl-buffer point-min point-max)
337 (send-string coffee-repl-buffer "\n"))
075b1ce @tmcgilchrist Add functions to send buffer, region and line to the CoffeeREPL buffer.
tmcgilchrist authored
338
2c204ef @mizchi add coffee-js2coffee-replace-region
mizchi authored
339 (defun coffee-js2coffee-replace-region (start end)
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
340 "Convert JavaScript in the region into CoffeeScript."
2c204ef @mizchi add coffee-js2coffee-replace-region
mizchi authored
341 (interactive "r")
342
343 (let ((buffer (get-buffer coffee-compiled-buffer-name)))
344 (when buffer
345 (kill-buffer buffer)))
346
66c326b @rrthomas Remove custom debug code; should use the standard Emacs debugging tools ...
rrthomas authored
347 (call-process-region start end
2c204ef @mizchi add coffee-js2coffee-replace-region
mizchi authored
348 js2coffee-command nil
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
349 (current-buffer))
350 (delete-region start end))
2c204ef @mizchi add coffee-js2coffee-replace-region
mizchi authored
351
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
352 (defun coffee-version ()
353 "Show the `coffee-mode' version in the echo area."
5f14029 @defunkt Menu
authored
354 (interactive)
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
355 (message (concat "coffee-mode version " coffee-mode-version)))
5f14029 @defunkt Menu
authored
356
0b06b86 @semperos Add support for coffee --watch, and in process also add function for run...
semperos authored
357 (defun coffee-watch (dir-or-file)
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
358 "Run `coffee-run-cmd' with the --watch flag on a directory or file."
0b06b86 @semperos Add support for coffee --watch, and in process also add function for run...
semperos authored
359 (interactive "fDirectory or File: ")
360 (let ((coffee-compiled-buffer-name coffee-watch-buffer-name)
66c326b @rrthomas Remove custom debug code; should use the standard Emacs debugging tools ...
rrthomas authored
361 (args (mapconcat 'identity (append coffee-args-compile (list "--watch" (expand-file-name dir-or-file))) " ")))
0b06b86 @semperos Add support for coffee --watch, and in process also add function for run...
semperos authored
362 (coffee-run-cmd args)))
363
5f14029 @defunkt Menu
authored
364 ;;
365 ;; Menubar
366 ;;
367
368 (easy-menu-define coffee-mode-menu coffee-mode-map
369 "Menu for CoffeeScript mode"
370 '("CoffeeScript"
cbd31f9 @defunkt coffee-compile-file
authored
371 ["Compile File" coffee-compile-file]
5f14029 @defunkt Menu
authored
372 ["Compile Buffer" coffee-compile-buffer]
373 ["Compile Region" coffee-compile-region]
5256afd @defunkt tweaks
authored
374 ["REPL" coffee-repl]
5f14029 @defunkt Menu
authored
375 "---"
a707d2d @jmcejuela Update coffee-mode.el
jmcejuela authored
376 ["Version" coffee-version]
5f14029 @defunkt Menu
authored
377 ))
378
3a47b28 @defunkt docs
authored
379 ;;
380 ;; Define Language Syntax
381 ;;
382
c5831bb @sstephenson Fix for string literals with escaped quotes
sstephenson authored
383 ;; String literals
384 (defvar coffee-string-regexp "\"\\([^\\]\\|\\\\.\\)*?\"\\|'\\([^\\]\\|\\\\.\\)*?'")
385
3a47b28 @defunkt docs
authored
386 ;; Instance variables (implicit this)
2bb69be Regex for "this" variable includes underscore.
Ryan Koopmans authored
387 (defvar coffee-this-regexp "@\\(\\w\\|_\\)*\\|this")
3a47b28 @defunkt docs
authored
388
dc85f42 @tav Added support for the shorthand::syntax for .prototype.
tav authored
389 ;; Prototype::access
390 (defvar coffee-prototype-regexp "\\(\\(\\w\\|\\.\\|_\\| \\|$\\)+?\\)::\\(\\(\\w\\|\\.\\|_\\| \\|$\\)+?\\):")
391
88e7b95 @defunkt better regexps, @blah: and {blah: true, blah2:true}
authored
392 ;; Assignment
37b481e @defunkt Better assignment highlighting for `:`
authored
393 (defvar coffee-assign-regexp "\\(\\(\\w\\|\\.\\|_\\|$\\)+?\s*\\):")
30d2af5 @defunkt Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
394
7c5b19b local variable assignment is now highlighted.
Shawn Krisman authored
395 ;; Local Assignment
279bd3c allow member assignment to be highlighted just like local vars.
Shawn Krisman authored
396 (defvar coffee-local-assign-regexp "\\(\\(_\\|\\w\\|\\$\\)+\\)\s+=")
7c5b19b local variable assignment is now highlighted.
Shawn Krisman authored
397
30d2af5 @defunkt Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
398 ;; Lambda
00c197b @defunkt elisp regexps are fun
authored
399 (defvar coffee-lambda-regexp "\\((.+)\\)?\\s *\\(->\\|=>\\)")
88e7b95 @defunkt better regexps, @blah: and {blah: true, blah2:true}
authored
400
76ed341 @defunkt class support in imenu
authored
401 ;; Namespaces
402 (defvar coffee-namespace-regexp "\\b\\(class\\s +\\(\\S +\\)\\)\\b")
403
af34f91 @defunkt Booleans, better colors
authored
404 ;; Booleans
3900a8c @Wilfred adding undefined to reserved words as part of coffee-boolean-regexp (not...
Wilfred authored
405 (defvar coffee-boolean-regexp "\\b\\(true\\|false\\|yes\\|no\\|on\\|off\\|null\\|undefined\\)\\b")
3a47b28 @defunkt docs
authored
406
dbb4ec5 @defunkt comment tweaks
authored
407 ;; Regular Expressions
1fb4956 @levskaya small fix of coffee-regexp-regexp so it doesn't cause massive hangs when...
levskaya authored
408 (defvar coffee-regexp-regexp "\\/\\(\\\\.\\|\\[\\(\\\\.\\|.\\)+?\\]\\|[^/
409 ]\\)+?\\/")
3a47b28 @defunkt docs
authored
410
cf028f8 @defunkt basics
authored
411 ;; JavaScript Keywords
d6b78ed @defunkt defvars and basic indentation
authored
412 (defvar coffee-js-keywords
af34f91 @defunkt Booleans, better colors
authored
413 '("if" "else" "new" "return" "try" "catch"
cf028f8 @defunkt basics
authored
414 "finally" "throw" "break" "continue" "for" "in" "while"
415 "delete" "instanceof" "typeof" "switch" "super" "extends"
7803688 Until and loop are keywords.
Ryan Koopmans authored
416 "class" "until" "loop"))
cf028f8 @defunkt basics
authored
417
418 ;; Reserved keywords either by JS or CS.
d6b78ed @defunkt defvars and basic indentation
authored
419 (defvar coffee-js-reserved
cf028f8 @defunkt basics
authored
420 '("case" "default" "do" "function" "var" "void" "with"
421 "const" "let" "debugger" "enum" "export" "import" "native"
422 "__extends" "__hasProp"))
423
424 ;; CoffeeScript keywords.
d6b78ed @defunkt defvars and basic indentation
authored
425 (defvar coffee-cs-keywords
0a39a40 add support for the "own" keyword (for own k, v of obj ...)
Justine Tunney authored
426 '("then" "unless" "and" "or" "is" "own"
134d8a8 "where" isn't a coffeescript keyword
Justine Tunney authored
427 "isnt" "not" "of" "by" "when"))
cf028f8 @defunkt basics
authored
428
80ebae6 Added support for iced coffeescript await and defer keywords.
Marius Kjeldahl authored
429 ;; Iced CoffeeScript keywords
430 (defvar iced-coffee-cs-keywords
431 '("await" "defer"))
cf028f8 @defunkt basics
authored
432
0480381 @defunkt mini docs
authored
433 ;; Regular expression combining the above three lists.
fad39cc keywords can now be member names.
Shawn Krisman authored
434 (defvar coffee-keywords-regexp
435 ;; keywords can be member names.
0686a8a only the keywords are highlighted instead of text before them.
Shawn Krisman authored
436 (concat "[^.]"
437 (regexp-opt (append coffee-js-reserved
438 coffee-js-keywords
439 coffee-cs-keywords
440 iced-coffee-cs-keywords) 'words)))
cf028f8 @defunkt basics
authored
441
442
ff61700 @defunkt that was bothering me
authored
443 ;; Create the list for font-lock. Each class of keyword is given a
444 ;; particular face.
5256afd @defunkt tweaks
authored
445 (defvar coffee-font-lock-keywords
ff61700 @defunkt that was bothering me
authored
446 ;; *Note*: order below matters. `coffee-keywords-regexp' goes last
447 ;; because otherwise the keyword "state" in the function
448 ;; "state_entry" would be highlighted.
c5831bb @sstephenson Fix for string literals with escaped quotes
sstephenson authored
449 `((,coffee-string-regexp . font-lock-string-face)
450 (,coffee-this-regexp . font-lock-variable-name-face)
dc85f42 @tav Added support for the shorthand::syntax for .prototype.
tav authored
451 (,coffee-prototype-regexp . font-lock-variable-name-face)
ff61700 @defunkt that was bothering me
authored
452 (,coffee-assign-regexp . font-lock-type-face)
279bd3c allow member assignment to be highlighted just like local vars.
Shawn Krisman authored
453 (,coffee-local-assign-regexp 1 font-lock-variable-name-face)
ff61700 @defunkt that was bothering me
authored
454 (,coffee-regexp-regexp . font-lock-constant-face)
455 (,coffee-boolean-regexp . font-lock-constant-face)
bdb258b color -> and => as functions.
Shawn Krisman authored
456 (,coffee-lambda-regexp . (2 font-lock-function-name-face))
0686a8a only the keywords are highlighted instead of text before them.
Shawn Krisman authored
457 (,coffee-keywords-regexp 1 font-lock-keyword-face)))
cf028f8 @defunkt basics
authored
458
3a47b28 @defunkt docs
authored
459 ;;
460 ;; Helper Functions
461 ;;
462
9ff612a @defunkt single quotes
authored
463 (defun coffee-comment-dwim (arg)
464 "Comment or uncomment current line or region in a smart way.
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
465 For details, see `comment-dwim'."
9ff612a @defunkt single quotes
authored
466 (interactive "*P")
467 (require 'newcomment)
468 (let ((deactivate-mark nil) (comment-start "#") (comment-end ""))
469 (comment-dwim arg)))
84ab684 @defunkt comments
authored
470
227a360 @orlandohill Customize args for compiling files and display the first compiler error
orlandohill authored
471 (defun coffee-command-compile (file-name)
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
472 "Run `coffee-command' to compile FILE."
1561b47 Adds an option to move the output directory for the JavaScript files
Ivan Stoyanov Arabadzhiev authored
473 (let (
474 (full-file-name
475 (expand-file-name file-name))
476 (output-directory
477 (concat " -o " (file-name-directory (expand-file-name file-name)) coffee-js-directory)))
478 (mapconcat 'identity (append (list coffee-command) coffee-args-compile (list output-directory) (list full-file-name)) " ")))
5b00ae2 @defunkt more todo
authored
479
0b06b86 @semperos Add support for coffee --watch, and in process also add function for run...
semperos authored
480 (defun coffee-run-cmd (args)
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
481 "Run `coffee-command' with the given arguments, and display the
482 output in a compilation buffer."
0b06b86 @semperos Add support for coffee --watch, and in process also add function for run...
semperos authored
483 (interactive "sArguments: ")
484 (let ((compilation-buffer-name-function (lambda (this-mode)
485 (generate-new-buffer-name coffee-compiled-buffer-name))))
486 (compile (concat coffee-command " " args))))
487
2504ebe @defunkt explain indentation plan
authored
488 ;;
30d2af5 @defunkt Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
489 ;; imenu support
490 ;;
491
492 ;; This is a pretty naive but workable way of doing it. First we look
493 ;; for any lines that starting with `coffee-assign-regexp' that include
494 ;; `coffee-lambda-regexp' then add those tokens to the list.
495 ;;
496 ;; Should cover cases like these:
497 ;;
498 ;; minus: (x, y) -> x - y
499 ;; String::length: -> 10
500 ;; block: ->
501 ;; print('potion')
502 ;;
503 ;; Next we look for any line that starts with `class' or
504 ;; `coffee-assign-regexp' followed by `{` and drop into a
505 ;; namespace. This means we search one indentation level deeper for
506 ;; more assignments and add them to the alist prefixed with the
507 ;; namespace name.
508 ;;
509 ;; Should cover cases like these:
510 ;;
511 ;; class Person
512 ;; print: ->
513 ;; print 'My name is ' + this.name + '.'
514 ;;
515 ;; class Policeman extends Person
516 ;; constructor: (rank) ->
517 ;; @rank: rank
518 ;; print: ->
519 ;; print 'My name is ' + this.name + " and I'm a " + this.rank + '.'
520 ;;
76ed341 @defunkt class support in imenu
authored
521 ;; TODO:
30d2af5 @defunkt Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
522 ;; app = {
523 ;; window: {width: 200, height: 200}
524 ;; para: -> 'Welcome.'
525 ;; button: -> 'OK'
526 ;; }
527
528 (defun coffee-imenu-create-index ()
529 "Create an imenu index of all methods in the buffer."
530 (interactive)
531
532 ;; This function is called within a `save-excursion' so we're safe.
6639c36 @mkhl Silence byte-compiler warnings.
mkhl authored
533 (goto-char (point-min))
30d2af5 @defunkt Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
534
76ed341 @defunkt class support in imenu
authored
535 (let ((index-alist '()) assign pos indent ns-name ns-indent)
30d2af5 @defunkt Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
536 ;; Go through every assignment that includes -> or => on the same
c6562af @defunkt Make `coffee-debug' a macro
authored
537 ;; line or starts with `class'.
30d2af5 @defunkt Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
538 (while (re-search-forward
76ed341 @defunkt class support in imenu
authored
539 (concat "^\\(\\s *\\)"
540 "\\("
541 coffee-assign-regexp
542 ".+?"
543 coffee-lambda-regexp
544 "\\|"
545 coffee-namespace-regexp
546 "\\)")
30d2af5 @defunkt Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
547 (point-max)
548 t)
549
76ed341 @defunkt class support in imenu
authored
550 ;; If this is the start of a new namespace, save the namespace's
551 ;; indentation level and name.
7f5e1b3 @defunkt Bugfix: Clear old namespace when a new one is found
authored
552 (when (match-string 8)
553 ;; Set the name.
554 (setq ns-name (match-string 8))
555
76ed341 @defunkt class support in imenu
authored
556 ;; If this is a class declaration, add :: to the namespace.
557 (setq ns-name (concat ns-name "::"))
558
559 ;; Save the indentation level.
66c326b @rrthomas Remove custom debug code; should use the standard Emacs debugging tools ...
rrthomas authored
560 (setq ns-indent (length (match-string 1))))
76ed341 @defunkt class support in imenu
authored
561
562 ;; If this is an assignment, save the token being
563 ;; assigned. `Please.print:` will be `Please.print`, `block:`
564 ;; will be `block`, etc.
565 (when (setq assign (match-string 3))
566 ;; The position of the match in the buffer.
567 (setq pos (match-beginning 3))
568
569 ;; The indent level of this match
570 (setq indent (length (match-string 1)))
571
572 ;; If we're within the context of a namespace, add that to the
573 ;; front of the assign, e.g.
574 ;; constructor: => Policeman::constructor
575 (when (and ns-name (> indent ns-indent))
576 (setq assign (concat ns-name assign)))
577
578 ;; Clear the namespace if we're no longer indented deeper
579 ;; than it.
580 (when (and ns-name (<= indent ns-indent))
581 (setq ns-name nil)
582 (setq ns-indent nil))
583
584 ;; Add this to the alist. Done.
585 (push (cons assign pos) index-alist)))
30d2af5 @defunkt Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
586
587 ;; Return the alist.
588 index-alist))
589
590 ;;
d6b78ed @defunkt defvars and basic indentation
authored
591 ;; Indentation
2504ebe @defunkt explain indentation plan
authored
592 ;;
593
dbb4ec5 @defunkt comment tweaks
authored
594 ;;; The theory is explained in the README.
97a1001 @defunkt basic indentation with TAB
authored
595
d6b78ed @defunkt defvars and basic indentation
authored
596 (defun coffee-indent-line ()
7b03a71 @defunkt indentation theory
authored
597 "Indent current line as CoffeeScript."
d6b78ed @defunkt defvars and basic indentation
authored
598 (interactive)
599
df7ae3b @defunkt Bugfix: Indenting blank lines with TAB
authored
600 (if (= (point) (point-at-bol))
601 (insert-tab)
602 (save-excursion
3f4271f @rrthomas Simplify coffee-indent-line and coffee-previous-indent.
rrthomas authored
603 (let ((prev-indent (coffee-previous-indent))
604 (cur-indent (current-indentation)))
df7ae3b @defunkt Bugfix: Indenting blank lines with TAB
authored
605 ;; Shift one column to the left
606 (beginning-of-line)
607 (insert-tab)
608
609 (when (= (point-at-bol) (point))
7976bc4 @defunkt Make config options available from `customize-group`, document in README
authored
610 (forward-char coffee-tab-width))
df7ae3b @defunkt Bugfix: Indenting blank lines with TAB
authored
611
612 ;; We're too far, remove all indentation.
7976bc4 @defunkt Make config options available from `customize-group`, document in README
authored
613 (when (> (- (current-indentation) prev-indent) coffee-tab-width)
df7ae3b @defunkt Bugfix: Indenting blank lines with TAB
authored
614 (backward-to-indentation 0)
615 (delete-region (point-at-bol) (point)))))))
b7ee8b8 @defunkt start cleaning up indentation code
authored
616
617 (defun coffee-previous-indent ()
618 "Return the indentation level of the previous non-blank line."
619 (save-excursion
620 (forward-line -1)
d063614 @superbobry Fix hanging of `coffee-previous-indent` at start of buffer.
superbobry authored
621 (if (bobp)
622 0
623 (progn
3f4271f @rrthomas Simplify coffee-indent-line and coffee-previous-indent.
rrthomas authored
624 (while (and (looking-at "^[ \t]*$") (not (bobp))) (forward-line -1))
d063614 @superbobry Fix hanging of `coffee-previous-indent` at start of buffer.
superbobry authored
625 (current-indentation)))))
b7ee8b8 @defunkt start cleaning up indentation code
authored
626
17150cf @defunkt docs and starting to implement indenters
authored
627 (defun coffee-newline-and-indent ()
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
628 "Insert a newline and indent it to the same level as the previous line."
17150cf @defunkt docs and starting to implement indenters
authored
629 (interactive)
630
631 ;; Remember the current line indentation level,
632 ;; insert a newline, and indent the newline to the same
633 ;; level as the previous line.
634 (let ((prev-indent (current-indentation)) (indent-next nil))
74a9135 @piranha do not leave trailing whitespaces on newline
piranha authored
635 (delete-horizontal-space t)
17150cf @defunkt docs and starting to implement indenters
authored
636 (newline)
7976bc4 @defunkt Make config options available from `customize-group`, document in README
authored
637 (insert-tab (/ prev-indent coffee-tab-width))
3a47b28 @defunkt docs
authored
638
17150cf @defunkt docs and starting to implement indenters
authored
639 ;; We need to insert an additional tab because the last line was special.
640 (when (coffee-line-wants-indent)
641 (insert-tab)))
642
643 ;; Last line was a comment so this one should probably be,
644 ;; too. Makes it easy to write multi-line comments (like the one I'm
645 ;; writing right now).
646 (when (coffee-previous-line-is-comment)
647 (insert "# ")))
648
fc4e054 dedent respects increments of `coffee-tab-width`
Le Wang authored
649 (defun coffee-dedent-line-backspace (arg)
650 "Unindent to increment of `coffee-tab-width' with ARG==1 when
651 called from first non-blank char of line.
652
653 Delete ARG spaces if ARG!=1."
654 (interactive "*p")
655 (if (and (= 1 arg)
656 (= (point) (save-excursion
657 (back-to-indentation)
658 (point)))
fed87e1 check bol properly
Le Wang authored
659 (not (bolp)))
fc4e054 dedent respects increments of `coffee-tab-width`
Le Wang authored
660 (let ((extra-space-count (% (current-column) coffee-tab-width)))
661 (backward-delete-char-untabify
662 (if (zerop extra-space-count)
663 coffee-tab-width
664 extra-space-count)))
665 (backward-delete-char-untabify arg)))
67e8727 backspace now de-indents instead of just going back a space.
Shawn Krisman authored
666
17150cf @defunkt docs and starting to implement indenters
authored
667 ;; Indenters help determine whether the current line should be
668 ;; indented further based on the content of the previous line. If a
669 ;; line starts with `class', for instance, you're probably going to
670 ;; want to indent the next line.
671
9eca4aa @theJohnnyBrown indent following while statement
theJohnnyBrown authored
672 (defvar coffee-indenters-bol '("class" "for" "if" "try" "while")
7d338d1 @defunkt coffee-indenters
authored
673 "Keywords or syntax whose presence at the start of a line means the
674 next line should probably be indented.")
675
676 (defun coffee-indenters-bol-regexp ()
677 "Builds a regexp out of `coffee-indenters-bol' words."
27df14a @defunkt Fix coffee-indenters-bol-regexp. Closes #36
authored
678 (regexp-opt coffee-indenters-bol 'words))
7d338d1 @defunkt coffee-indenters
authored
679
5e170be @defunkt get it working (with a fake function though)
authored
680 (defvar coffee-indenters-eol '(?> ?{ ?\[)
681 "Single characters at the end of a line that mean the next line
682 should probably be indented.")
7d338d1 @defunkt coffee-indenters
authored
683
17150cf @defunkt docs and starting to implement indenters
authored
684 (defun coffee-line-wants-indent ()
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
685 "Return t if the current line should be indented relative to the
686 previous line."
8bfb7ed @defunkt Keep same indentation of last line when creating a new line
authored
687 (interactive)
688
17150cf @defunkt docs and starting to implement indenters
authored
689 (save-excursion
690 (let ((indenter-at-bol) (indenter-at-eol))
691 ;; Go back a line and to the first character.
692 (forward-line -1)
693 (backward-to-indentation 0)
8bfb7ed @defunkt Keep same indentation of last line when creating a new line
authored
694
17150cf @defunkt docs and starting to implement indenters
authored
695 ;; If the next few characters match one of our magic indenter
696 ;; keywords, we want to indent the line we were on originally.
697 (when (looking-at (coffee-indenters-bol-regexp))
66c326b @rrthomas Remove custom debug code; should use the standard Emacs debugging tools ...
rrthomas authored
698 (setq indenter-at-bol t))
17150cf @defunkt docs and starting to implement indenters
authored
699
700 ;; If that didn't match, go to the back of the line and check to
5e170be @defunkt get it working (with a fake function though)
authored
701 ;; see if the last character matches one of our indenter
702 ;; characters.
17150cf @defunkt docs and starting to implement indenters
authored
703 (when (not indenter-at-bol)
704 (end-of-line)
705
5e170be @defunkt get it working (with a fake function though)
authored
706 ;; Optimized for speed - checks only the last character.
65797fa @jaeyeom Fix missing function `some' issue when loading compiled elisp.
jaeyeom authored
707 (let ((indenters coffee-indenters-eol))
708 (while indenters
df0dfbc resolved issue #63. Fixed inspired by tzeskimo 6c5eb29.
Keith Simmons authored
709 (if (and (char-before) (/= (char-before) (car indenters)))
65797fa @jaeyeom Fix missing function `some' issue when loading compiled elisp.
jaeyeom authored
710 (setq indenters (cdr indenters))
711 (setq indenter-at-eol t)
712 (setq indenters nil)))))
17150cf @defunkt docs and starting to implement indenters
authored
713
714 ;; If we found an indenter, return `t'.
715 (or indenter-at-bol indenter-at-eol))))
716
8bfb7ed @defunkt Keep same indentation of last line when creating a new line
authored
717 (defun coffee-previous-line-is-comment ()
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
718 "Return t if the previous line is a CoffeeScript comment."
8bfb7ed @defunkt Keep same indentation of last line when creating a new line
authored
719 (save-excursion
720 (forward-line -1)
721 (coffee-line-is-comment)))
722
723 (defun coffee-line-is-comment ()
579e270 @rrthomas Overhaul the docstrings.
rrthomas authored
724 "Return t if the current line is a CoffeeScript comment."
8bfb7ed @defunkt Keep same indentation of last line when creating a new line
authored
725 (save-excursion
726 (backward-to-indentation 0)
727 (= (char-after) (string-to-char "#"))))
728
168b32d @disnet fixing triple quoted strings issue with code from python-mode
disnet authored
729
c5fb056 remove triple quotes, seems to be doing strange things to python-mode
Justine Tunney authored
730 ;; (defun coffee-quote-syntax (n)
731 ;; "Put `syntax-table' property correctly on triple quote.
732 ;; Used for syntactic keywords. N is the match number (1, 2 or 3)."
733 ;; ;; From python-mode...
734 ;; ;;
735 ;; ;; Given a triple quote, we have to check the context to know
736 ;; ;; whether this is an opening or closing triple or whether it's
737 ;; ;; quoted anyhow, and should be ignored. (For that we need to do
738 ;; ;; the same job as `syntax-ppss' to be correct and it seems to be OK
739 ;; ;; to use it here despite initial worries.) We also have to sort
740 ;; ;; out a possible prefix -- well, we don't _have_ to, but I think it
741 ;; ;; should be treated as part of the string.
742
743 ;; ;; Test cases:
744 ;; ;; ur"""ar""" x='"' # """
745 ;; ;; x = ''' """ ' a
746 ;; ;; '''
747 ;; ;; x '"""' x """ \"""" x
748 ;; (save-excursion
749 ;; (goto-char (match-beginning 0))
750 ;; (cond
751 ;; ;; Consider property for the last char if in a fenced string.
752 ;; ((= n 3)
753 ;; (let* ((font-lock-syntactic-keywords nil)
754 ;; (syntax (syntax-ppss)))
755 ;; (when (eq t (nth 3 syntax)) ; after unclosed fence
756 ;; (goto-char (nth 8 syntax)) ; fence position
757 ;; ;; (skip-chars-forward "uUrR") ; skip any prefix
758 ;; ;; Is it a matching sequence?
759 ;; (if (eq (char-after) (char-after (match-beginning 2)))
760 ;; (eval-when-compile (string-to-syntax "|"))))))
761 ;; ;; Consider property for initial char, accounting for prefixes.
762 ;; ((or (and (= n 2) ; leading quote (not prefix)
763 ;; (not (match-end 1))) ; prefix is null
764 ;; (and (= n 1) ; prefix
765 ;; (match-end 1))) ; non-empty
766 ;; (let ((font-lock-syntactic-keywords nil))
767 ;; (unless (eq 'string (syntax-ppss-context (syntax-ppss)))
768 ;; (eval-when-compile (string-to-syntax "|")))))
769 ;; ;; Otherwise (we're in a non-matching string) the property is
770 ;; ;; nil, which is OK.
771 ;; )))
168b32d @disnet fixing triple quoted strings issue with code from python-mode
disnet authored
772
ae2875f @akheron coffee-indent-shift-*: Indent to the closest increment of coffee-tab-wid...
akheron authored
773 (defun coffee-indent-shift-amount (start end dir)
774 "Compute distance to the closest increment of `coffee-tab-width'."
775 (let ((min most-positive-fixnum) rem)
776 (save-excursion
777 (goto-char start)
778 (while (< (point) end)
779 (let ((current (current-indentation)))
780 (when (< current min) (setq min current)))
781 (forward-line))
782 (setq rem (% min coffee-tab-width))
783 (if (zerop rem)
784 coffee-tab-width
785 (cond ((eq dir 'left) rem)
786 ((eq dir 'right) (- coffee-tab-width rem))
787 (t 0))))))
788
e45ce09 @akheron Add functions for shifting blocks of code left and right
akheron authored
789 (defun coffee-indent-shift-left (start end &optional count)
790 "Shift lines contained in region START END by COUNT columns to the left.
ae2875f @akheron coffee-indent-shift-*: Indent to the closest increment of coffee-tab-wid...
akheron authored
791 If COUNT is not given, indents to the closest increment of
792 `coffee-tab-width'. If region isn't active, the current line is
793 shifted. The shifted region includes the lines in which START and
794 END lie. An error is signaled if any lines in the region are
795 indented less than COUNT columns."
e45ce09 @akheron Add functions for shifting blocks of code left and right
akheron authored
796 (interactive
797 (if mark-active
798 (list (region-beginning) (region-end) current-prefix-arg)
799 (list (line-beginning-position) (line-end-position) current-prefix-arg)))
ae2875f @akheron coffee-indent-shift-*: Indent to the closest increment of coffee-tab-wid...
akheron authored
800 (let ((amount (if count (prefix-numeric-value count)
801 (coffee-indent-shift-amount start end 'left))))
802 (when (> amount 0)
803 (let (deactivate-mark)
804 (save-excursion
805 (goto-char start)
806 ;; Check that all lines can be shifted enough
807 (while (< (point) end)
808 (if (and (< (current-indentation) amount)
809 (not (looking-at "[ \t]*$")))
810 (error "Can't shift all lines enough"))
811 (forward-line))
812 (indent-rigidly start end (- amount)))))))
e45ce09 @akheron Add functions for shifting blocks of code left and right
akheron authored
813
814 (add-to-list 'debug-ignored-errors "^Can't shift all lines enough")
815
816 (defun coffee-indent-shift-right (start end &optional count)
ae2875f @akheron coffee-indent-shift-*: Indent to the closest increment of coffee-tab-wid...
akheron authored
817 "Shift lines contained in region START END by COUNT columns to the right.
818 if COUNT is not given, indents to the closest increment of
819 `coffee-tab-width'. If region isn't active, the current line is
820 shifted. The shifted region includes the lines in which START and
821 END lie."
e45ce09 @akheron Add functions for shifting blocks of code left and right
akheron authored
822 (interactive
823 (if mark-active
824 (list (region-beginning) (region-end) current-prefix-arg)
825 (list (line-beginning-position) (line-end-position) current-prefix-arg)))
ae2875f @akheron coffee-indent-shift-*: Indent to the closest increment of coffee-tab-wid...
akheron authored
826 (let (deactivate-mark
827 (amount (if count (prefix-numeric-value count)
828 (coffee-indent-shift-amount start end 'right))))
829 (indent-rigidly start end amount)))
e45ce09 @akheron Add functions for shifting blocks of code left and right
akheron authored
830
3a47b28 @defunkt docs
authored
831 ;;
832 ;; Define Major Mode
833 ;;
834
099e94a @jvshahid woot, finally got the block comment working, i love emacs extensibility.
jvshahid authored
835 (defun coffee-block-comment-delimiter (match)
836 (progn
837 (goto-char match)
838 (beginning-of-line)
839 (add-text-properties (point) (+ (point) 1) `(syntax-table (14 . nil)))))
840
834ce20 @jvshahid it turns out that coffee script block comments are more complicated than...
jvshahid authored
841 ;; support coffescript block comments
842 ;; examples:
843 ;; at indent level 0
844 ;; ###
845 ;; foobar
846 ;; ###
847 ;; at indent level 0 with text following it
848 ;; ### foobar
849 ;; moretext
850 ;; ###
851 ;; at indent level > 0
852 ;; ###
853 ;; foobar
854 ;; ###
855 ;; examples of non-block comments:
856 ;; #### foobar
099e94a @jvshahid woot, finally got the block comment working, i love emacs extensibility.
jvshahid authored
857 (defun coffee-propertize-function (start end)
858 ;; return if we don't have anything to parse
859 (unless (>= start end)
860 (save-excursion
861 (progn
862 (goto-char start)
834ce20 @jvshahid it turns out that coffee script block comments are more complicated than...
jvshahid authored
863 (let ((match (re-search-forward "^[[:space:]]*###\\([[:space:]]+.*\\)?$" end t)))
099e94a @jvshahid woot, finally got the block comment working, i love emacs extensibility.
jvshahid authored
864 (if match
865 (progn
866 (coffee-block-comment-delimiter match)
867 (goto-char match)
7d0c394 @syohex Fix for bytecompiling warnings
syohex authored
868 (forward-line)
099e94a @jvshahid woot, finally got the block comment working, i love emacs extensibility.
jvshahid authored
869 (coffee-propertize-function (point) end))))))))
870
af021a5 @josh magic autoload comments
josh authored
871 ;;;###autoload
cf028f8 @defunkt basics
authored
872 (define-derived-mode coffee-mode fundamental-mode
4631aa1 Use "Coffee" as mode name rather than the idiosynchratic "coffee-mode".
Daniel Brockman authored
873 "Coffee"
874 "Major mode for editing CoffeeScript."
cf028f8 @defunkt basics
authored
875
876 ;; code for syntax highlighting
877 (setq font-lock-defaults '((coffee-font-lock-keywords)))
878
1c8aea3 @chellmuth Fix syntax highlighting for variables containing keywords bounded by
chellmuth authored
879 ;; treat "_" as part of a word
880 (modify-syntax-entry ?_ "w" coffee-mode-syntax-table)
881
84ab684 @defunkt comments
authored
882 ;; perl style comment: "# ..."
883 (modify-syntax-entry ?# "< b" coffee-mode-syntax-table)
884 (modify-syntax-entry ?\n "> b" coffee-mode-syntax-table)
3779064 @thomasf inline local variable assignment
thomasf authored
885
886 (set (make-local-variable 'comment-start) "#")
84ab684 @defunkt comments
authored
887
9ff612a @defunkt single quotes
authored
888 ;; single quote strings
889 (modify-syntax-entry ?' "\"" coffee-mode-syntax-table)
890
c5fb056 remove triple quotes, seems to be doing strange things to python-mode
Justine Tunney authored
891 ;; (setq font-lock-syntactic-keywords
892 ;; ;; Make outer chars of matching triple-quote sequences into generic
893 ;; ;; string delimiters.
894 ;; ;; First avoid a sequence preceded by an odd number of backslashes.
895 ;; `((,(concat "\\(?:^\\|[^\\]\\(?:\\\\.\\)*\\)" ;Prefix.
896 ;; "\\(?:\\('\\)\\('\\)\\('\\)\\|\\(?1:\"\\)\\(?2:\"\\)\\(?3:\"\\)\\)")
897 ;; (1 (coffee-quote-syntax 1) nil lax)
898 ;; (2 (coffee-quote-syntax 2))
899 ;; (3 (coffee-quote-syntax 3)))))
168b32d @disnet fixing triple quoted strings issue with code from python-mode
disnet authored
900
d6b78ed @defunkt defvars and basic indentation
authored
901 ;; indentation
3779064 @thomasf inline local variable assignment
thomasf authored
902 (set (make-local-variable 'indent-line-function) #'coffee-indent-line)
b4b2a53 @kelleyk Small patch to fix indentation behavior; before, the global tab-width se...
kelleyk authored
903 (set (make-local-variable 'tab-width) coffee-tab-width)
3779064 @thomasf inline local variable assignment
thomasf authored
904 (set (make-local-variable 'syntax-propertize-function) #'coffee-propertize-function)
d6b78ed @defunkt defvars and basic indentation
authored
905
30d2af5 @defunkt Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
906 ;; imenu
3779064 @thomasf inline local variable assignment
thomasf authored
907 (set (make-local-variable 'imenu-create-index-function) #'coffee-imenu-create-index)
30d2af5 @defunkt Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
908
d6b78ed @defunkt defvars and basic indentation
authored
909 ;; no tabs
be2305f @rrthomas Remove support for removing trailing whitespace: whitepace-mode does tha...
rrthomas authored
910 (setq indent-tabs-mode nil))
eaf28ab @defunkt register as .coffee handler
authored
911
6eb6d99 @knu Introduce a minor mode `coffee-cos-mode'.
knu authored
912 ;;
913 ;; Compile-on-Save minor mode
914 ;;
915
916 (defvar coffee-cos-mode-line " CoS")
917 (make-variable-buffer-local 'coffee-cos-mode-line)
918
919 (define-minor-mode coffee-cos-mode
20c919a @rrthomas Change installation instructions to advise use of ELPA.
rrthomas authored
920 "Toggle compile-on-save for coffee-mode.
921
922 Add `'(lambda () (coffee-cos-mode t))' to `coffee-mode-hook' to turn
923 it on by default."
6eb6d99 @knu Introduce a minor mode `coffee-cos-mode'.
knu authored
924 :group 'coffee-cos :lighter coffee-cos-mode-line
925 (cond
926 (coffee-cos-mode
927 (add-hook 'after-save-hook 'coffee-compile-file nil t))
928 (t
929 (remove-hook 'after-save-hook 'coffee-compile-file t))))
930
27ffada @defunkt provide something
authored
931 (provide 'coffee-mode)
932
eaf28ab @defunkt register as .coffee handler
authored
933 ;;
934 ;; On Load
935 ;;
936
937 ;; Run coffee-mode for files ending in .coffee.
af021a5 @josh magic autoload comments
josh authored
938 ;;;###autoload
2e68bfb @thomasf fix auto-mode regular expressions
thomasf authored
939 (add-to-list 'auto-mode-alist '("\\.coffee\\'" . coffee-mode))
af021a5 @josh magic autoload comments
josh authored
940 ;;;###autoload
2e68bfb @thomasf fix auto-mode regular expressions
thomasf authored
941 (add-to-list 'auto-mode-alist '("\\.iced\\'" . coffee-mode))
af021a5 @josh magic autoload comments
josh authored
942 ;;;###autoload
2e68bfb @thomasf fix auto-mode regular expressions
thomasf authored
943 (add-to-list 'auto-mode-alist '("Cakefile\\'" . coffee-mode))
a9c8f48 Formatting changes for complians with elp/Marmalade
Scott Barron authored
944 ;;; coffee-mode.el ends here
Something went wrong with that request. Please try again.