Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 578 lines (454 sloc) 17.798 kb
4a11c70 Chris Wanstrath documentation
authored
1 ;;; coffee-mode.el --- Major mode to edit CoffeeScript files in Emacs
2
3 ;; Copyright (C) 2010 Chris Wanstrath
4
199b771 Chris Wanstrath 0.2.0
authored
5 ;; Version 0.2.0
4a11c70 Chris Wanstrath documentation
authored
6 ;; Keywords: CoffeeScript major mode
7 ;; Author: Chris Wanstrath <chris@ozmm.org>
8 ;; URL: http://github.com/defunkt/coffee-script
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
28 ;; For commentary please see the README.md or
29 ;; http://github.com/defunkt/coffee-mode#readme
30
31 ;;; Installation
32
33 ;; In your shell:
34
35 ;; $ cd ~/.emacs.d/vendor
36 ;; $ git clone git://github.com/defunkt/coffee-mode.git
37
38 ;; In your emacs config:
39
40 ;; (add-to-list 'load-path "~/.emacs.d/vendor/coffee-mode")
41 ;; (require 'coffee-mode)
42
43 ;;; Thanks
44
0480381 Chris Wanstrath mini docs
authored
45 ;; Major thanks to http://xahlee.org/emacs/elisp_syntax_coloring.html
46 ;; the instructions.
4a11c70 Chris Wanstrath documentation
authored
47
a6c6911 Chris Wanstrath tweaks
authored
48 ;; Also thanks to Jason Blevins's markdown-mode.el and Steve Yegge's
49 ;; js2-mode for guidance.
38ce8da Chris Wanstrath small tweaks
authored
50
12bd5d0 Chris Wanstrath todo
authored
51 ;; TODO:
52 ;; - Fix indentation toggling on blank (pure whitespace) lines
a6c6911 Chris Wanstrath tweaks
authored
53 ;; - Execute {buffer,region,line} and show output in new buffer
12bd5d0 Chris Wanstrath todo
authored
54 ;; - Make prototype accessor assignments like `String::length: -> 10` pretty.
5b00ae2 Chris Wanstrath more todo
authored
55 ;; - mirror-mode - close brackets and parens automatically
12bd5d0 Chris Wanstrath todo
authored
56
57 ;;; Code:
58
38ce8da Chris Wanstrath small tweaks
authored
59 (require 'easymenu)
60 (require 'font-lock)
14ab5a0 Chris Wanstrath Use Common Lisp's `some` despite its inferior API.
authored
61 (require 'cl)
0480381 Chris Wanstrath mini docs
authored
62
7557530 Chris Wanstrath compilation commands
authored
63 ;;
38ce8da Chris Wanstrath small tweaks
authored
64 ;; Customizable Variables
7557530 Chris Wanstrath compilation commands
authored
65 ;;
66
199b771 Chris Wanstrath 0.2.0
authored
67 (defconst coffee-mode-version "0.2.0"
5f14029 Chris Wanstrath Menu
authored
68 "The version of this `coffee-mode'.")
69
c063681 Chris Wanstrath no more debug mode
authored
70 (defvar coffee-debug-mode nil
ce05b32 Chris Wanstrath debug mode, t for now
authored
71 "Whether to run in debug mode or not. Logs to `*Messages*'.")
72
1b887a5 Chris Wanstrath clean whitespace on save
authored
73 (defvar coffee-js-mode 'js2-mode
74 "The mode to use when viewing compiled JavaScript.")
75
76 (defvar coffee-cleanup-whitespace t
77 "Should we `delete-trailing-whitespace' on save? Probably.")
38ce8da Chris Wanstrath small tweaks
authored
78
7557530 Chris Wanstrath compilation commands
authored
79 (defvar coffee-command "coffee"
80 "The CoffeeScript command used for evaluating code. Must be in your
81 path.")
82
28485fa Chris Wanstrath `coffee-repl'
authored
83 (defvar coffee-repl-args '("-i")
84 "The command line arguments to pass to `coffee-command' to start a REPL.")
85
5f14029 Chris Wanstrath Menu
authored
86 (defvar coffee-command-args '("-s" "-p" "--no-wrap")
87 "The command line arguments to pass to `coffee-command' to get it to
88 print the compiled JavaScript.")
89
7557530 Chris Wanstrath compilation commands
authored
90 (defvar coffee-compiled-buffer-name "*coffee-compiled*"
91 "The name of the scratch buffer used when compiling CoffeeScript.")
92
1b887a5 Chris Wanstrath clean whitespace on save
authored
93 (defvar coffee-mode-hook nil
94 "A hook for you to run your own code when the mode is loaded.")
95
eee29e0 Chris Wanstrath defvar the keymap
authored
96 (defvar coffee-mode-map (make-keymap)
97 "Keymap for CoffeeScript major mode.")
98
38ce8da Chris Wanstrath small tweaks
authored
99 ;;
c5ffe04 Chris Wanstrath setd macro for logging variable values when setting them
authored
100 ;; Macros
5b00ae2 Chris Wanstrath more todo
authored
101 ;;
102
c5ffe04 Chris Wanstrath setd macro for logging variable values when setting them
authored
103 (defmacro setd (var val)
104 "Like setq but optionally logs the variable's value using `coffee-debug'."
21ce2da Chris Wanstrath The kind of optimization that turns on every Lisp hacker: macro-time.
authored
105 (if coffee-debug-mode
c6562af Chris Wanstrath Make `coffee-debug' a macro
authored
106 `(progn
107 (coffee-debug "%s: %s" ',var ,val)
108 (setq ,var ,val))
109 `(setq ,var ,val)))
110
2799609 Chris Wanstrath back out that macro change for now, something is funny
authored
111 (defun coffee-debug (string &rest args)
c6562af Chris Wanstrath Make `coffee-debug' a macro
authored
112 "Print a message when in debug mode."
113 (when coffee-debug-mode
2799609 Chris Wanstrath back out that macro change for now, something is funny
authored
114 (apply 'message (append (list string) args))))
c5ffe04 Chris Wanstrath setd macro for logging variable values when setting them
authored
115
b7ee8b8 Chris Wanstrath start cleaning up indentation code
authored
116 (defmacro coffee-line-as-string ()
117 "Returns the current line as a string."
118 `(buffer-substring (point-at-bol) (point-at-eol)))
119
5b00ae2 Chris Wanstrath more todo
authored
120 ;;
38ce8da Chris Wanstrath small tweaks
authored
121 ;; Commands
122 ;;
123
28485fa Chris Wanstrath `coffee-repl'
authored
124 (defun coffee-repl ()
125 "Launch a CoffeeScript REPL using `coffee-command' as an inferior mode."
126 (interactive)
127
17150cf Chris Wanstrath docs and starting to implement indenters
authored
128 (unless (comint-check-proc "*CoffeeREPL*")
28485fa Chris Wanstrath `coffee-repl'
authored
129 (set-buffer
17150cf Chris Wanstrath docs and starting to implement indenters
authored
130 (apply 'make-comint "CoffeeREPL"
28485fa Chris Wanstrath `coffee-repl'
authored
131 coffee-command nil coffee-repl-args)))
132
133 (pop-to-buffer "*CoffeeScript*"))
38ce8da Chris Wanstrath small tweaks
authored
134
cbd31f9 Chris Wanstrath coffee-compile-file
authored
135 (defun coffee-compile-file ()
136 "Compiles and saves the current file to disk. Doesn't open in a buffer.."
137 (interactive)
138 (shell-command (concat coffee-command " -c " (buffer-file-name)))
139 (message "Compiled and saved %s"
140 (concat
141 (substring (buffer-file-name) 0 -6)
142 "js")))
143
7557530 Chris Wanstrath compilation commands
authored
144 (defun coffee-compile-buffer ()
17150cf Chris Wanstrath docs and starting to implement indenters
authored
145 "Compiles the current buffer and displays the JS in another buffer."
7557530 Chris Wanstrath compilation commands
authored
146 (interactive)
147 (save-excursion
148 (coffee-compile-region (point-min) (point-max))))
149
150 (defun coffee-compile-region (start end)
17150cf Chris Wanstrath docs and starting to implement indenters
authored
151 "Compiles a region and displays the JS in another buffer."
7557530 Chris Wanstrath compilation commands
authored
152 (interactive "r")
153
154 (let ((buffer (get-buffer coffee-compiled-buffer-name)))
155 (when buffer
156 (kill-buffer buffer)))
157
158 (call-process-region start end coffee-command nil
159 (get-buffer-create coffee-compiled-buffer-name)
160 nil
161 "-s" "-p" "--no-wrap")
162 (switch-to-buffer-other-frame (get-buffer coffee-compiled-buffer-name))
163 (funcall coffee-js-mode)
164 (beginning-of-buffer))
3a47b28 Chris Wanstrath docs
authored
165
5f14029 Chris Wanstrath Menu
authored
166 (defun coffee-show-version ()
167 "Prints the `coffee-mode' version."
168 (interactive)
169 (message (concat "coffee-mode v" coffee-mode-version)))
170
fd314cc Chris Wanstrath menu tweaks
authored
171 (defun coffee-open-reference ()
172 "Open browser to CoffeeScript reference."
173 (interactive)
174 (browse-url "http://jashkenas.github.com/coffee-script/"))
175
48c36c1 Chris Wanstrath open node.js api in browser
authored
176 (defun coffee-open-node-reference ()
177 "Open browser to node.js reference."
178 (interactive)
179 (browse-url "http://nodejs.org/api.html"))
180
5f14029 Chris Wanstrath Menu
authored
181 (defun coffee-open-github ()
fd314cc Chris Wanstrath menu tweaks
authored
182 "Open browser to `coffee-mode' project on GithHub."
5f14029 Chris Wanstrath Menu
authored
183 (interactive)
184 (browse-url "http://github.com/defunkt/coffee-mode"))
185
186 ;;
187 ;; Menubar
188 ;;
189
190 (easy-menu-define coffee-mode-menu coffee-mode-map
191 "Menu for CoffeeScript mode"
192 '("CoffeeScript"
cbd31f9 Chris Wanstrath coffee-compile-file
authored
193 ["Compile File" coffee-compile-file]
5f14029 Chris Wanstrath Menu
authored
194 ["Compile Buffer" coffee-compile-buffer]
195 ["Compile Region" coffee-compile-region]
5256afd Chris Wanstrath tweaks
authored
196 ["REPL" coffee-repl]
5f14029 Chris Wanstrath Menu
authored
197 "---"
48c36c1 Chris Wanstrath open node.js api in browser
authored
198 ["CoffeeScript Reference" coffee-open-reference]
199 ["node.js Reference" coffee-open-node-reference]
fd314cc Chris Wanstrath menu tweaks
authored
200 ["coffee-mode on GitHub" coffee-open-github]
5f14029 Chris Wanstrath Menu
authored
201 ["Version" coffee-show-version]
202 ))
203
3a47b28 Chris Wanstrath docs
authored
204 ;;
205 ;; Define Language Syntax
206 ;;
207
208 ;; Instance variables (implicit this)
5256afd Chris Wanstrath tweaks
authored
209 (defvar coffee-this-regexp "@\\w*\\|this")
3a47b28 Chris Wanstrath docs
authored
210
88e7b95 Chris Wanstrath better regexps, @blah: and {blah: true, blah2:true}
authored
211 ;; Assignment
30d2af5 Chris Wanstrath Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
212 (defvar coffee-assign-regexp "\\(\\(\\w\\|\\.\\|_\\| \\|$\\)+?\\):")
213
214 ;; Lambda
00c197b Chris Wanstrath elisp regexps are fun
authored
215 (defvar coffee-lambda-regexp "\\((.+)\\)?\\s *\\(->\\|=>\\)")
88e7b95 Chris Wanstrath better regexps, @blah: and {blah: true, blah2:true}
authored
216
76ed341 Chris Wanstrath class support in imenu
authored
217 ;; Namespaces
218 (defvar coffee-namespace-regexp "\\b\\(class\\s +\\(\\S +\\)\\)\\b")
219
af34f91 Chris Wanstrath Booleans, better colors
authored
220 ;; Booleans
5256afd Chris Wanstrath tweaks
authored
221 (defvar coffee-boolean-regexp "\\b\\(true\\|false\\|yes\\|no\\|on\\|off\\)\\b")
3a47b28 Chris Wanstrath docs
authored
222
dbb4ec5 Chris Wanstrath comment tweaks
authored
223 ;; Regular Expressions
5256afd Chris Wanstrath tweaks
authored
224 (defvar coffee-regexp-regexp "\\/.+?\\/")
3a47b28 Chris Wanstrath docs
authored
225
cf028f8 Chris Wanstrath basics
authored
226 ;; JavaScript Keywords
d6b78ed Chris Wanstrath defvars and basic indentation
authored
227 (defvar coffee-js-keywords
af34f91 Chris Wanstrath Booleans, better colors
authored
228 '("if" "else" "new" "return" "try" "catch"
cf028f8 Chris Wanstrath basics
authored
229 "finally" "throw" "break" "continue" "for" "in" "while"
230 "delete" "instanceof" "typeof" "switch" "super" "extends"
231 "class"))
232
233 ;; Reserved keywords either by JS or CS.
d6b78ed Chris Wanstrath defvars and basic indentation
authored
234 (defvar coffee-js-reserved
cf028f8 Chris Wanstrath basics
authored
235 '("case" "default" "do" "function" "var" "void" "with"
236 "const" "let" "debugger" "enum" "export" "import" "native"
237 "__extends" "__hasProp"))
238
239 ;; CoffeeScript keywords.
d6b78ed Chris Wanstrath defvars and basic indentation
authored
240 (defvar coffee-cs-keywords
af34f91 Chris Wanstrath Booleans, better colors
authored
241 '("then" "unless" "and" "or" "is"
cf028f8 Chris Wanstrath basics
authored
242 "isnt" "not" "of" "by" "where" "when"))
243
0480381 Chris Wanstrath mini docs
authored
244 ;; Regular expression combining the above three lists.
d6b78ed Chris Wanstrath defvars and basic indentation
authored
245 (defvar coffee-keywords-regexp (regexp-opt
cf028f8 Chris Wanstrath basics
authored
246 (append
247 coffee-js-reserved
248 coffee-js-keywords
249 coffee-cs-keywords) 'words))
250
251
ff61700 Chris Wanstrath that was bothering me
authored
252 ;; Create the list for font-lock. Each class of keyword is given a
253 ;; particular face.
5256afd Chris Wanstrath tweaks
authored
254 (defvar coffee-font-lock-keywords
ff61700 Chris Wanstrath that was bothering me
authored
255 ;; *Note*: order below matters. `coffee-keywords-regexp' goes last
256 ;; because otherwise the keyword "state" in the function
257 ;; "state_entry" would be highlighted.
258 `((,coffee-this-regexp . font-lock-variable-name-face)
259 (,coffee-assign-regexp . font-lock-type-face)
260 (,coffee-regexp-regexp . font-lock-constant-face)
261 (,coffee-boolean-regexp . font-lock-constant-face)
262 (,coffee-keywords-regexp . font-lock-keyword-face)))
cf028f8 Chris Wanstrath basics
authored
263
3a47b28 Chris Wanstrath docs
authored
264 ;;
265 ;; Helper Functions
266 ;;
267
1b887a5 Chris Wanstrath clean whitespace on save
authored
268 (defun coffee-before-save ()
269 "Hook run before file is saved. Deletes whitespace if
270 `coffee-cleanup-whitespace' is non-nil."
271 (when coffee-cleanup-whitespace
272 (delete-trailing-whitespace)))
273
9ff612a Chris Wanstrath single quotes
authored
274 (defun coffee-comment-dwim (arg)
275 "Comment or uncomment current line or region in a smart way.
276 For detail, see `comment-dwim'."
277 (interactive "*P")
278 (require 'newcomment)
279 (let ((deactivate-mark nil) (comment-start "#") (comment-end ""))
280 (comment-dwim arg)))
84ab684 Chris Wanstrath comments
authored
281
5b00ae2 Chris Wanstrath more todo
authored
282 (defun coffee-command-full ()
283 "The full `coffee-command' complete with args."
284 (mapconcat 'identity (append (list coffee-command) coffee-command-args) " "))
285
2504ebe Chris Wanstrath explain indentation plan
authored
286 ;;
30d2af5 Chris Wanstrath Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
287 ;; imenu support
288 ;;
289
290 ;; This is a pretty naive but workable way of doing it. First we look
291 ;; for any lines that starting with `coffee-assign-regexp' that include
292 ;; `coffee-lambda-regexp' then add those tokens to the list.
293 ;;
294 ;; Should cover cases like these:
295 ;;
296 ;; minus: (x, y) -> x - y
297 ;; String::length: -> 10
298 ;; block: ->
299 ;; print('potion')
300 ;;
301 ;; Next we look for any line that starts with `class' or
302 ;; `coffee-assign-regexp' followed by `{` and drop into a
303 ;; namespace. This means we search one indentation level deeper for
304 ;; more assignments and add them to the alist prefixed with the
305 ;; namespace name.
306 ;;
307 ;; Should cover cases like these:
308 ;;
309 ;; class Person
310 ;; print: ->
311 ;; print 'My name is ' + this.name + '.'
312 ;;
313 ;; class Policeman extends Person
314 ;; constructor: (rank) ->
315 ;; @rank: rank
316 ;; print: ->
317 ;; print 'My name is ' + this.name + " and I'm a " + this.rank + '.'
318 ;;
76ed341 Chris Wanstrath class support in imenu
authored
319 ;; TODO:
30d2af5 Chris Wanstrath Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
320 ;; app = {
321 ;; window: {width: 200, height: 200}
322 ;; para: -> 'Welcome.'
323 ;; button: -> 'OK'
324 ;; }
325
326 (defun coffee-imenu-create-index ()
327 "Create an imenu index of all methods in the buffer."
328 (interactive)
329
330 ;; This function is called within a `save-excursion' so we're safe.
331 (beginning-of-buffer)
332
76ed341 Chris Wanstrath class support in imenu
authored
333 (let ((index-alist '()) assign pos indent ns-name ns-indent)
30d2af5 Chris Wanstrath Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
334 ;; Go through every assignment that includes -> or => on the same
c6562af Chris Wanstrath Make `coffee-debug' a macro
authored
335 ;; line or starts with `class'.
30d2af5 Chris Wanstrath Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
336 (while (re-search-forward
76ed341 Chris Wanstrath class support in imenu
authored
337 (concat "^\\(\\s *\\)"
338 "\\("
339 coffee-assign-regexp
340 ".+?"
341 coffee-lambda-regexp
342 "\\|"
343 coffee-namespace-regexp
344 "\\)")
30d2af5 Chris Wanstrath Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
345 (point-max)
346 t)
347
e1b9c83 Chris Wanstrath print full match to debug
authored
348 (coffee-debug "Match: %s" (match-string 0))
349
76ed341 Chris Wanstrath class support in imenu
authored
350 ;; If this is the start of a new namespace, save the namespace's
351 ;; indentation level and name.
7f5e1b3 Chris Wanstrath Bugfix: Clear old namespace when a new one is found
authored
352 (when (match-string 8)
353 ;; Set the name.
354 (setq ns-name (match-string 8))
355
76ed341 Chris Wanstrath class support in imenu
authored
356 ;; If this is a class declaration, add :: to the namespace.
357 (setq ns-name (concat ns-name "::"))
358
359 ;; Save the indentation level.
360 (setq ns-indent (length (match-string 1)))
361
362 ;; Debug
363 (coffee-debug "ns: Found %s with indent %s" ns-name ns-indent))
364
365 ;; If this is an assignment, save the token being
366 ;; assigned. `Please.print:` will be `Please.print`, `block:`
367 ;; will be `block`, etc.
368 (when (setq assign (match-string 3))
369 ;; The position of the match in the buffer.
370 (setq pos (match-beginning 3))
371
372 ;; The indent level of this match
373 (setq indent (length (match-string 1)))
374
375 ;; If we're within the context of a namespace, add that to the
376 ;; front of the assign, e.g.
377 ;; constructor: => Policeman::constructor
378 (when (and ns-name (> indent ns-indent))
379 (setq assign (concat ns-name assign)))
380
381 (coffee-debug "=: Found %s with indent %s" assign indent)
382
383 ;; Clear the namespace if we're no longer indented deeper
384 ;; than it.
385 (when (and ns-name (<= indent ns-indent))
386 (coffee-debug "ns: Clearing %s" ns-name)
387 (setq ns-name nil)
388 (setq ns-indent nil))
389
390 ;; Add this to the alist. Done.
391 (push (cons assign pos) index-alist)))
30d2af5 Chris Wanstrath Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
392
393 ;; Return the alist.
394 index-alist))
395
396 ;;
d6b78ed Chris Wanstrath defvars and basic indentation
authored
397 ;; Indentation
2504ebe Chris Wanstrath explain indentation plan
authored
398 ;;
399
dbb4ec5 Chris Wanstrath comment tweaks
authored
400 ;;; The theory is explained in the README.
97a1001 Chris Wanstrath basic indentation with TAB
authored
401
d6b78ed Chris Wanstrath defvars and basic indentation
authored
402 (defun coffee-indent-line ()
7b03a71 Chris Wanstrath indentation theory
authored
403 "Indent current line as CoffeeScript."
d6b78ed Chris Wanstrath defvars and basic indentation
authored
404 (interactive)
405
b7ee8b8 Chris Wanstrath start cleaning up indentation code
authored
406 (save-excursion
407 (let ((prev-indent 0) (cur-indent 0))
408 ;; Figure out the indentation of the previous line
409 (setd prev-indent (coffee-previous-indent))
97ef92b Chris Wanstrath Bugfix: Indentation works when point is at beginning of the line
authored
410
b7ee8b8 Chris Wanstrath start cleaning up indentation code
authored
411 ;; Figure out the current line's indentation
412 (setd cur-indent (current-indentation))
97ef92b Chris Wanstrath Bugfix: Indentation works when point is at beginning of the line
authored
413
b7ee8b8 Chris Wanstrath start cleaning up indentation code
authored
414 ;; Shift one column to the left
415 (backward-to-indentation 0)
416 (insert-tab)
417
418 ;; We're too far, remove all indentation.
419 (when (> (- (current-indentation) prev-indent) tab-width)
97a1001 Chris Wanstrath basic indentation with TAB
authored
420 (backward-to-indentation 0)
b7ee8b8 Chris Wanstrath start cleaning up indentation code
authored
421 (delete-region (point-at-bol) (point))))))
422
423 (defun coffee-previous-indent ()
424 "Return the indentation level of the previous non-blank line."
97ef92b Chris Wanstrath Bugfix: Indentation works when point is at beginning of the line
authored
425
b7ee8b8 Chris Wanstrath start cleaning up indentation code
authored
426 (save-excursion
427 (forward-line -1)
428 (while (coffee-line-empty-p) (forward-line -1))
429 (current-indentation)))
430
431 (defun coffee-line-empty-p ()
432 "Is this line empty? Returns non-nil if so, nil if not."
433 (or (bobp)
434 (string-match "^\\s *$" (coffee-line-as-string))))
df08186 Chris Wanstrath indenters
authored
435
17150cf Chris Wanstrath docs and starting to implement indenters
authored
436 (defun coffee-newline-and-indent ()
437 "Inserts a newline and indents it to the same level as the previous line."
438 (interactive)
439
440 ;; Remember the current line indentation level,
441 ;; insert a newline, and indent the newline to the same
442 ;; level as the previous line.
443 (let ((prev-indent (current-indentation)) (indent-next nil))
444 (newline)
445 (insert-tab (/ prev-indent tab-width))
3a47b28 Chris Wanstrath docs
authored
446
17150cf Chris Wanstrath docs and starting to implement indenters
authored
447 ;; We need to insert an additional tab because the last line was special.
448 (when (coffee-line-wants-indent)
449 (insert-tab)))
450
451 ;; Last line was a comment so this one should probably be,
452 ;; too. Makes it easy to write multi-line comments (like the one I'm
453 ;; writing right now).
454 (when (coffee-previous-line-is-comment)
455 (insert "# ")))
456
457 ;; Indenters help determine whether the current line should be
458 ;; indented further based on the content of the previous line. If a
459 ;; line starts with `class', for instance, you're probably going to
460 ;; want to indent the next line.
461
462 (defvar coffee-indenters-bol '("class" "for" "if" "try")
7d338d1 Chris Wanstrath coffee-indenters
authored
463 "Keywords or syntax whose presence at the start of a line means the
464 next line should probably be indented.")
465
466 (defun coffee-indenters-bol-regexp ()
467 "Builds a regexp out of `coffee-indenters-bol' words."
468 (concat "^" (regexp-opt coffee-indenters-bol 'words)))
469
5e170be Chris Wanstrath get it working (with a fake function though)
authored
470 (defvar coffee-indenters-eol '(?> ?{ ?\[)
471 "Single characters at the end of a line that mean the next line
472 should probably be indented.")
7d338d1 Chris Wanstrath coffee-indenters
authored
473
17150cf Chris Wanstrath docs and starting to implement indenters
authored
474 (defun coffee-line-wants-indent ()
475 "Does the current line want to be indented deeper than the previous
df08186 Chris Wanstrath indenters
authored
476 line? Returns `t' or `nil'. See the README for more details."
8bfb7ed Chris Wanstrath Keep same indentation of last line when creating a new line
authored
477 (interactive)
478
17150cf Chris Wanstrath docs and starting to implement indenters
authored
479 (save-excursion
480 (let ((indenter-at-bol) (indenter-at-eol))
481 ;; Go back a line and to the first character.
482 (forward-line -1)
483 (backward-to-indentation 0)
8bfb7ed Chris Wanstrath Keep same indentation of last line when creating a new line
authored
484
17150cf Chris Wanstrath docs and starting to implement indenters
authored
485 ;; If the next few characters match one of our magic indenter
486 ;; keywords, we want to indent the line we were on originally.
487 (when (looking-at (coffee-indenters-bol-regexp))
c5ffe04 Chris Wanstrath setd macro for logging variable values when setting them
authored
488 (setd indenter-at-bol t))
17150cf Chris Wanstrath docs and starting to implement indenters
authored
489
490 ;; If that didn't match, go to the back of the line and check to
5e170be Chris Wanstrath get it working (with a fake function though)
authored
491 ;; see if the last character matches one of our indenter
492 ;; characters.
17150cf Chris Wanstrath docs and starting to implement indenters
authored
493 (when (not indenter-at-bol)
494 (end-of-line)
495
5e170be Chris Wanstrath get it working (with a fake function though)
authored
496 ;; Optimized for speed - checks only the last character.
14ab5a0 Chris Wanstrath Use Common Lisp's `some` despite its inferior API.
authored
497 (when (some (lambda (char)
498 (= (char-before) char))
499 coffee-indenters-eol)
c5ffe04 Chris Wanstrath setd macro for logging variable values when setting them
authored
500 (setd indenter-at-eol t)))
17150cf Chris Wanstrath docs and starting to implement indenters
authored
501
502 ;; If we found an indenter, return `t'.
503 (or indenter-at-bol indenter-at-eol))))
504
8bfb7ed Chris Wanstrath Keep same indentation of last line when creating a new line
authored
505 (defun coffee-previous-line-is-comment ()
506 "Returns `t' if the previous line is a CoffeeScript comment."
507 (save-excursion
508 (forward-line -1)
509 (coffee-line-is-comment)))
510
511 (defun coffee-line-is-comment ()
512 "Returns `t' if the current line is a CoffeeScript comment."
513 (save-excursion
514 (backward-to-indentation 0)
515 (= (char-after) (string-to-char "#"))))
516
3a47b28 Chris Wanstrath docs
authored
517 ;;
518 ;; Define Major Mode
519 ;;
520
af021a5 Joshua Peek magic autoload comments
josh authored
521 ;;;###autoload
cf028f8 Chris Wanstrath basics
authored
522 (define-derived-mode coffee-mode fundamental-mode
523 "coffee-mode"
524 "Major mode for editing CoffeeScript..."
525
1b887a5 Chris Wanstrath clean whitespace on save
authored
526 ;; key bindings
7557530 Chris Wanstrath compilation commands
authored
527 (define-key coffee-mode-map (kbd "A-r") 'coffee-compile-buffer)
79333bf Chris Wanstrath Bugfix: Bad binding
authored
528 (define-key coffee-mode-map (kbd "A-R") 'coffee-compile-region)
eee29e0 Chris Wanstrath defvar the keymap
authored
529 (define-key coffee-mode-map (kbd "A-M-r") 'coffee-repl)
7557530 Chris Wanstrath compilation commands
authored
530 (define-key coffee-mode-map [remap comment-dwim] 'coffee-comment-dwim)
8bfb7ed Chris Wanstrath Keep same indentation of last line when creating a new line
authored
531 (define-key coffee-mode-map "\C-m" 'coffee-newline-and-indent)
7557530 Chris Wanstrath compilation commands
authored
532
cf028f8 Chris Wanstrath basics
authored
533 ;; code for syntax highlighting
534 (setq font-lock-defaults '((coffee-font-lock-keywords)))
535
84ab684 Chris Wanstrath comments
authored
536 ;; perl style comment: "# ..."
537 (modify-syntax-entry ?# "< b" coffee-mode-syntax-table)
538 (modify-syntax-entry ?\n "> b" coffee-mode-syntax-table)
0480381 Chris Wanstrath mini docs
authored
539 (setq comment-start "#")
84ab684 Chris Wanstrath comments
authored
540
9ff612a Chris Wanstrath single quotes
authored
541 ;; single quote strings
542 (modify-syntax-entry ?' "\"" coffee-mode-syntax-table)
543 (modify-syntax-entry ?' "\"" coffee-mode-syntax-table)
544
d6b78ed Chris Wanstrath defvars and basic indentation
authored
545 ;; indentation
546 (make-local-variable 'indent-line-function)
547 (setq indent-line-function 'coffee-indent-line)
548
30d2af5 Chris Wanstrath Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
549 ;; imenu
550 (make-local-variable 'imenu-create-index-function)
551 (setq imenu-create-index-function 'coffee-imenu-create-index)
552
d6b78ed Chris Wanstrath defvars and basic indentation
authored
553 ;; no tabs
554 (setq indent-tabs-mode nil)
555
1b887a5 Chris Wanstrath clean whitespace on save
authored
556 ;; hooks
557 (set (make-local-variable 'before-save-hook) 'coffee-before-save)
558
cf028f8 Chris Wanstrath basics
authored
559 ;; clear memory
30d2af5 Chris Wanstrath Basic imenu support - makes things like `textmate-goto-symbol' work!
authored
560 ;; TODO: make these accurate
cf028f8 Chris Wanstrath basics
authored
561 (setq coffee-keywords-regexp nil)
562 (setq coffee-types-regexp nil)
563 (setq coffee-constants-regexp nil)
564 (setq coffee-events-regexp nil)
565 (setq coffee-functions-regexp nil))
eaf28ab Chris Wanstrath register as .coffee handler
authored
566
27ffada Chris Wanstrath provide something
authored
567 (provide 'coffee-mode)
568
eaf28ab Chris Wanstrath register as .coffee handler
authored
569 ;;
570 ;; On Load
571 ;;
572
573 ;; Run coffee-mode for files ending in .coffee.
af021a5 Joshua Peek magic autoload comments
josh authored
574 ;;;###autoload
eaf28ab Chris Wanstrath register as .coffee handler
authored
575 (add-to-list 'auto-mode-alist '("\\.coffee$" . coffee-mode))
af021a5 Joshua Peek magic autoload comments
josh authored
576 ;;;###autoload
605a330 Chris Wanstrath highlight Cakefile too
authored
577 (add-to-list 'auto-mode-alist '("Cakefile" . coffee-mode))
Something went wrong with that request. Please try again.