jochu / clojure-mode

A mode for emacs that handles clojure

This URL has Read+Write access

technomancy (author)
Tue May 05 15:18:43 -0700 2009
jochu (committer)
Thu May 21 11:45:58 -0700 2009
clojure-mode / clojure-mode.el
aebf4dda » technomancy 2008-12-27 Remove README and expand he... 1 ;;; clojure-mode.el --- Major mode for Clojure code
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 2
627ae650 » technomancy 2009-02-01 Improve clojure-install ins... 3 ;; Copyright (C) 2007, 2008, 2009 Jeffrey Chu and Lennart Staflin
bcacc766 » jochu 2008-03-07 add author information 4 ;;
aebf4dda » technomancy 2008-12-27 Remove README and expand he... 5 ;; Authors: Jeffrey Chu <jochu0@gmail.com>
6 ;; Lennart Staflin <lenst@lysator.liu.se>
7 ;; URL: http://www.emacswiki.org/cgi-bin/wiki/ClojureMode
299eb2db » technomancy 2009-03-12 Preparation for ELPA submis... 8 ;; Version: 1.1
aebf4dda » technomancy 2008-12-27 Remove README and expand he... 9 ;; Keywords: languages, lisp
10
11 ;; This file is not part of GNU Emacs.
12
13 ;;; Commentary:
14
15 ;; Provides font-lock, indentation, and functions for communication
299eb2db » technomancy 2009-03-12 Preparation for ELPA submis... 16 ;; with subprocesses for the Clojure language. (http://clojure.org)
aebf4dda » technomancy 2008-12-27 Remove README and expand he... 17
18 ;;; Installation:
19
299eb2db » technomancy 2009-03-12 Preparation for ELPA submis... 20 ;; If you use ELPA, you can install via the M-x package-list-packages
21 ;; interface. This is preferrable as you will have access to updates
22 ;; automatically.
23
24 ;; If you need to install by hand for some reason:
25
60daec40 » technomancy 2009-02-04 Expand clojure-src-root; sh... 26 ;; (0) Add this file to your load-path, usually the ~/.emacs.d directory.
aebf4dda » technomancy 2008-12-27 Remove README and expand he... 27 ;; (1) Either:
28 ;; Add these lines to your .emacs:
29 ;; (autoload 'clojure-mode "clojure-mode" "A major mode for Clojure" t)
30 ;; (add-to-list 'auto-mode-alist '("\\.clj$" . clojure-mode))
31 ;; Or generate autoloads with the `update-directory-autoloads' function.
32
e359e311 » jochu 2009-01-23 better handling of paredit,... 33 ;; Paredit users:
34
4ec68c21 » jochu 2009-01-23 tested and works with pared... 35 ;; Download paredit v21 or greater
36 ;; http://mumble.net/~campbell/emacs/paredit.el
e359e311 » jochu 2009-01-23 better handling of paredit,... 37
627ae650 » technomancy 2009-02-01 Improve clojure-install ins... 38 ;; Use paredit as you normally would with any other mode; for instance:
39 ;;
0a90e587 » jochu 2009-01-23 get rid of useless comment,... 40 ;; ;; require or autoload paredit-mode
e359e311 » jochu 2009-01-23 better handling of paredit,... 41 ;; (defun lisp-enable-paredit-hook () (paredit-mode 1))
42 ;; (add-hook 'clojure-mode-hook 'lisp-enable-paredit-hook)
43
627ae650 » technomancy 2009-02-01 Improve clojure-install ins... 44 ;; The clojure-install function can check out and configure all the
45 ;; dependencies get going with Clojure, including SLIME integration.
a2c942ab » technomancy 2009-02-17 Doc updates, git updates. 46 ;; To use this function, you may have to manually load clojure-mode.el
47 ;; using M-x load-file or M-x eval-buffer.
627ae650 » technomancy 2009-02-01 Improve clojure-install ins... 48
60d975b2 » technomancy 2009-01-21 Imenu support. 49 ;;; Todo:
50
3bb58f31 » technomancy 2009-02-26 Call swank-clojure-slime-mo... 51 ;; * installer doesn't work when git port is blocked
52 ;; * updater/installer should know "last known good" sha1s?
60d975b2 » technomancy 2009-01-21 Imenu support. 53 ;; * hashbang is also a valid comment character
627ae650 » technomancy 2009-02-01 Improve clojure-install ins... 54 ;; * do the inferior-lisp functions work without SLIME? needs documentation
60d975b2 » technomancy 2009-01-21 Imenu support. 55
aebf4dda » technomancy 2008-12-27 Remove README and expand he... 56 ;;; License:
57
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 58 ;; This program is free software; you can redistribute it and/or
59 ;; modify it under the terms of the GNU General Public License
60 ;; as published by the Free Software Foundation; either version 3
61 ;; of the License, or (at your option) any later version.
62 ;;
63 ;; This program is distributed in the hope that it will be useful,
64 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
65 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
66 ;; GNU General Public License for more details.
67 ;;
68 ;; You should have received a copy of the GNU General Public License
69 ;; along with GNU Emacs; see the file COPYING. If not, write to the
70 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
71 ;; Boston, MA 02110-1301, USA.
72
c8118668 » technomancy 2009-01-17 Render io! in font-lock-war... 73 ;;; Code:
74
6615bc96 » jochu 2008-03-06 required cl 75 (require 'cl)
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 76
989d7ed9 » jochu 2008-03-07 clean up, use custom vars, ... 77 (defgroup clojure-mode nil
78 "A mode for Clojure"
79 :prefix "clojure-mode-"
80 :group 'applications)
81
c08f8024 » jochu 2008-03-09 rename typo multine to mult... 82 (defcustom clojure-mode-font-lock-multiline-def t
8d9d0e7a » jochu 2008-03-08 add note to font-lock custo... 83 "Set to non-nil in order to enable font-lock of
84 multi-line (def...) forms. Changing this will require a
85 restart (ie. M-x clojure-mode) of existing clojure mode buffers."
989d7ed9 » jochu 2008-03-07 clean up, use custom vars, ... 86 :type 'boolean
87 :group 'clojure-mode)
88
89 (defcustom clojure-mode-font-lock-comment-sexp nil
90 "Set to non-nil in order to enable font-lock of (comment...)
8d9d0e7a » jochu 2008-03-08 add note to font-lock custo... 91 forms. This option is experimental. Changing this will require a
92 restart (ie. M-x clojure-mode) of existing clojure mode buffers."
989d7ed9 » jochu 2008-03-07 clean up, use custom vars, ... 93 :type 'boolean
94 :group 'clojure-mode)
95
3bb58f31 » technomancy 2009-02-26 Call swank-clojure-slime-mo... 96 (defcustom clojure-mode-load-command "(clojure.core/load-file \"%s\")\n"
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 97 "*Format-string for building a Clojure expression to load a file.
98 This format string should use `%s' to substitute a file name
99 and should result in a Clojure expression that will command the inferior Clojure
100 to load that file."
989d7ed9 » jochu 2008-03-07 clean up, use custom vars, ... 101 :type 'string
102 :group 'clojure-mode)
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 103
9859c93c » jochu 2008-03-08 starting experimental backt... 104 (defcustom clojure-mode-use-backtracking-indent nil
105 "Set to non-nil to enable backtracking/context sensitive
106 indentation."
107 :type 'boolean
108 :group 'clojure-mode)
109
110 (defcustom clojure-max-backtracking 3
111 "Maximum amount to backtrack up a list to check for context."
112 :type 'integer
113 :group 'clojure-mode)
114
60daec40 » technomancy 2009-02-04 Expand clojure-src-root; sh... 115 (defcustom clojure-src-root (expand-file-name "~/src")
1db8b4c3 » technomancy 2009-02-02 Move clojure-src-root to a ... 116 "Directory that contains checkouts for clojure, clojure-contrib,
117 slime, and swank-clojure. This value is used by `clojure-install'
118 and `clojure-slime-config'."
119 :type 'string
120 :group 'clojure-mode)
121
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 122 (defvar clojure-mode-map
123 (let ((map (make-sparse-keymap)))
124 (set-keymap-parent map lisp-mode-shared-map)
125 (define-key map "\e\C-x" 'lisp-eval-defun)
126 (define-key map "\C-x\C-e" 'lisp-eval-last-sexp)
127 (define-key map "\C-c\C-e" 'lisp-eval-last-sexp)
128 (define-key map "\C-c\C-l" 'clojure-load-file)
129 (define-key map "\C-c\C-r" 'lisp-eval-region)
130 (define-key map "\C-c\C-z" 'run-lisp)
131 map)
132 "Keymap for ordinary Clojure mode.
133 All commands in `lisp-mode-shared-map' are inherited by this map.")
134
135
136 (easy-menu-define clojure-menu clojure-mode-map "Menu used in `clojure-mode'."
3ddc9701 » jochu 2008-03-07 fix lisp-eval-region-and-go... 137 '("Clojure"
138 ["Eval defun" lisp-eval-defun t]
139 ["Eval defun and go" lisp-eval-defun-and-go t]
140 ["Eval last sexp" lisp-eval-last-sexp t]
141 ["Eval region" lisp-eval-region t]
142 ["Eval region and go" lisp-eval-region-and-go t]
143 ["Load file..." clojure-load-file t]
144 ["Run Lisp" run-lisp t]))
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 145
146
147 (defvar clojure-mode-syntax-table
148 (let ((table (copy-syntax-table emacs-lisp-mode-syntax-table)))
149 (modify-syntax-entry ?~ "' " table)
150 (modify-syntax-entry ?, " " table)
c7d04736 » jochu 2008-02-12 support for other brackets ... 151 (modify-syntax-entry ?\{ "(}" table)
152 (modify-syntax-entry ?\} "){" table)
153 (modify-syntax-entry ?\[ "(]" table)
154 (modify-syntax-entry ?\] ")[" table)
e2b7090f » jochu 2008-03-06 properly treat ^ as prefix ... 155 (modify-syntax-entry ?^ "'" table)
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 156 table))
157
158
159 (defvar clojure-prev-l/c-dir/file nil
160 "Record last directory and file used in loading or compiling.
161 This holds a cons cell of the form `(DIRECTORY . FILE)'
162 describing the last `clojure-load-file' or `clojure-compile-file' command.")
163
60d975b2 » technomancy 2009-01-21 Imenu support. 164 (defvar clojure-def-regexp "^\\s *\\((def\\S *\\s +\\(\\S +\\)\\)"
165 "A regular expression to match any top-level definitions.")
166
93ad64c0 » technomancy 2008-12-27 Put appropriate autoloads i... 167 ;;;###autoload
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 168 (defun clojure-mode ()
169 "Major mode for editing Clojure code - similar to Lisp mode..
170 Commands:
171 Delete converts tabs to spaces as it moves back.
172 Blank lines separate paragraphs. Semicolons start comments.
173 \\{clojure-mode-map}
174 Note that `run-lisp' may be used either to start an inferior Lisp job
175 or to switch back to an existing one.
176
177 Entry to this mode calls the value of `clojure-mode-hook'
178 if that value is non-nil."
179 (interactive)
180 (kill-all-local-variables)
181 (use-local-map clojure-mode-map)
182 (setq major-mode 'clojure-mode)
183 (setq mode-name "Clojure")
b4e84830 » jochu 2008-03-08 provide arg for lisp-mode-v... 184 (lisp-mode-variables nil)
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 185 (set-syntax-table clojure-mode-syntax-table)
989d7ed9 » jochu 2008-03-07 clean up, use custom vars, ... 186
187 (set (make-local-variable 'comment-start-skip)
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 188 "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\)\\(;+\\|#|\\) *")
989d7ed9 » jochu 2008-03-07 clean up, use custom vars, ... 189 (set (make-local-variable 'lisp-indent-function)
190 'clojure-indent-function)
dfb0cf89 » jochu 2008-02-17 add support for multiline m... 191 (set (make-local-variable 'font-lock-multiline) t)
989d7ed9 » jochu 2008-03-07 clean up, use custom vars, ... 192
60d975b2 » technomancy 2009-01-21 Imenu support. 193 (setq lisp-imenu-generic-expression
194 `((nil ,clojure-def-regexp 2)))
195 (setq imenu-create-index-function
196 (lambda ()
197 (imenu--generic-function lisp-imenu-generic-expression)))
198
c09fe239 » jochu 2008-03-09 emacs 21 compat: disable fo... 199 (if (and (not (boundp 'font-lock-extend-region-functions))
200 (or clojure-mode-font-lock-multiline-def
201 clojure-mode-font-lock-comment-sexp))
202 (message "Clojure mode font lock extras are unavailable, please upgrade to atleast version 22 ")
203
b2e2e3f1 » jochu 2009-02-06 add emacs 21 compatibility ... 204 (when clojure-mode-font-lock-multiline-def
205 (add-to-list 'font-lock-extend-region-functions 'clojure-font-lock-extend-region-def t))
206
207 (when clojure-mode-font-lock-comment-sexp
208 (add-to-list 'font-lock-extend-region-functions 'clojure-font-lock-extend-region-comment t)
209 (make-local-variable 'clojure-font-lock-keywords)
210 (add-to-list 'clojure-font-lock-keywords 'clojure-font-lock-mark-comment t)
211 (set (make-local-variable 'open-paren-in-column-0-is-defun-start) nil)))
989d7ed9 » jochu 2008-03-07 clean up, use custom vars, ... 212
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 213 (setq font-lock-defaults
b2e2e3f1 » jochu 2009-02-06 add emacs 21 compatibility ... 214 '(clojure-font-lock-keywords ; keywords
215 nil nil
dfb0cf89 » jochu 2008-02-17 add support for multiline m... 216 (("+-*/.<>=!?$%_&~^:@" . "w")) ; syntax alist
217 nil
b2e2e3f1 » jochu 2009-02-06 add emacs 21 compatibility ... 218 (font-lock-mark-block-function . mark-defun)
219 (font-lock-syntactic-face-function . lisp-font-lock-syntactic-face-function)))
220
221 (if (fboundp 'run-mode-hooks)
222 (run-mode-hooks 'clojure-mode-hook)
223 (run-hooks 'clojure-mode-hook))
224
e359e311 » jochu 2009-01-23 better handling of paredit,... 225 ;; Enable curly braces when paredit is enabled in clojure-mode-hook
4ec68c21 » jochu 2009-01-23 tested and works with pared... 226 (when (and (featurep 'paredit) paredit-mode (>= paredit-version 21))
e359e311 » jochu 2009-01-23 better handling of paredit,... 227 (define-key clojure-mode-map "{" 'paredit-open-curly)
228 (define-key clojure-mode-map "}" 'paredit-close-curly)))
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 229
3bb58f31 » technomancy 2009-02-26 Call swank-clojure-slime-mo... 230 ;; (define-key clojure-mode-map "{" 'self-insert-command)
231 ;; (define-key clojure-mode-map "}" 'self-insert-command)
232
dfb0cf89 » jochu 2008-02-17 add support for multiline m... 233 (defun clojure-font-lock-def-at-point (point)
234 "Find the position range between the top-most def* and the
235 fourth element afterwards. Note that this means there's no
236 gaurantee of proper font locking in def* forms that are not at
237 top-level."
238 (goto-char point)
239 (condition-case nil
240 (beginning-of-defun)
241 (error nil))
242
243 (let ((beg-def (point)))
244 (when (and (not (= point beg-def))
7c7ab32a » jochu 2008-02-20 use looking-at instead of s... 245 (looking-at "(def"))
dfb0cf89 » jochu 2008-02-17 add support for multiline m... 246 (condition-case nil
247 (progn
248 ;; move forward as much as possible until failure (or success)
249 (forward-char)
250 (dotimes (i 4)
251 (forward-sexp)))
252 (error nil))
253 (cons beg-def (point)))))
254
6bc1f736 » jochu 2008-03-07 rename extend-region-list t... 255 (defun clojure-font-lock-extend-region-def ()
dfb0cf89 » jochu 2008-02-17 add support for multiline m... 256 "Move fontification boundaries to always include the first four
257 elements of a def* forms."
258 (let ((changed nil))
259 (let ((def (clojure-font-lock-def-at-point font-lock-beg)))
260 (when def
261 (destructuring-bind (def-beg . def-end) def
262 (when (and (< def-beg font-lock-beg)
263 (< font-lock-beg def-end))
264 (setq font-lock-beg def-beg
265 changed t)))))
266
267 (let ((def (clojure-font-lock-def-at-point font-lock-end)))
268 (when def
269 (destructuring-bind (def-beg . def-end) def
270 (when (and (< def-beg font-lock-end)
271 (< font-lock-end def-end))
272 (setq font-lock-end def-end
6bc1f736 » jochu 2008-03-07 rename extend-region-list t... 273 changed t)))))
274 changed))
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 275
989d7ed9 » jochu 2008-03-07 clean up, use custom vars, ... 276 (defun clojure-font-lock-extend-region-comment ()
277 "Move fontification boundaries to always contain
278 entire (comment ..) sexp. Does not work if you have a
279 white-space between ( and comment, but that is omitted to make
280 this run faster."
281 (let ((changed nil))
282 (goto-char font-lock-beg)
283 (condition-case nil (beginning-of-defun) (error nil))
cbcba57c » jochu 2008-04-19 Make sure only (comment ..)... 284 (let ((pos (re-search-forward "(comment\\>" font-lock-end t)))
989d7ed9 » jochu 2008-03-07 clean up, use custom vars, ... 285 (when pos
286 (forward-char -8)
287 (when (< (point) font-lock-beg)
288 (setq font-lock-beg (point)
289 changed t))
290 (condition-case nil (forward-sexp) (error nil))
291 (when (> (point) font-lock-end)
292 (setq font-lock-end (point)
293 changed t))))
294 changed))
295
296
297 (defun clojure-font-lock-mark-comment (limit)
298 "Marks all (comment ..) forms with font-lock-comment-face."
299 (let (pos)
300 (while (and (< (point) limit)
cbcba57c » jochu 2008-04-19 Make sure only (comment ..)... 301 (setq pos (re-search-forward "(comment\\>" limit t)))
989d7ed9 » jochu 2008-03-07 clean up, use custom vars, ... 302 (when pos
303 (forward-char -8)
304 (condition-case nil
305 (add-text-properties (1+ (point)) (progn (forward-sexp) (1- (point)))
306 '(face font-lock-comment-face multiline t))
307 (error (forward-char 8))))))
308 nil)
309
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 310 (defconst clojure-font-lock-keywords
311 (eval-when-compile
312 `( ;; Definitions.
c6302e91 » jochu 2008-04-29 add support for namespace c... 313 (,(concat "(\\(?:clojure/\\)?\\(def"
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 314 ;; Function declarations.
a2c942ab » technomancy 2009-02-17 Doc updates, git updates. 315 "\\(n-?\\|multi\\|macro\\|method\\|test\\|"
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 316 ;; Variable declarations.
876bac71 » mattrepl 2008-08-30 Added syntax highlighting f... 317 "struct\\|once\\|"
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 318 "\\)\\)\\>"
319 ;; Any whitespace
dfb0cf89 » jochu 2008-02-17 add support for multiline m... 320 "[ \r\n\t]*"
321 ;; Possibly type or metadata
322 "\\(?:#^\\(?:{[^}]*}\\|\\sw+\\)[ \r\n\t]*\\)?"
323
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 324 "\\(\\sw+\\)?")
325 (1 font-lock-keyword-face)
326 (3 font-lock-function-name-face nil t))
327 ;; Control structures
328 (,(concat
329 "(\\(?:clojure/\\)?"
330 (regexp-opt
a51f8ff2 » jochu 2009-03-05 add letfn highlight 331 '("let" "letfn" "do"
142c8c3b » jochu 2009-01-06 be a little more discrimina... 332 "cond" "condp"
333 "for" "loop" "recur"
334 "when" "when-not" "when-let" "when-first"
335 "if" "if-let" "if-not"
336 "." ".." "->" "doto"
337 "and" "or"
338 "dosync" "doseq" "dotimes" "dorun" "doall"
339 "load" "import" "unimport" "ns" "in-ns" "refer"
340 "try" "catch" "finally" "throw"
341 "with-open" "with-local-vars" "binding"
342 "gen-class" "gen-and-load-class" "gen-and-save-class") t)
343 "\\>")
344 . 1)
345 ;; Built-ins
346 (,(concat
347 "(\\(?:clojure/\\)?"
348 (regexp-opt
349 '(
350 "implement" "proxy" "lazy-cons" "with-meta"
351 "struct" "struct-map" "delay" "locking" "sync" "time" "apply"
0e11dd06 » Lau-of-DK 2008-12-27 Added all sequence/function... 352 "remove" "merge" "interleave" "interpose" "distinct" "for"
353 "cons" "concat" "lazy-cat" "cycle" "rest" "frest" "drop" "drop-while"
354 "nthrest" "take" "take-while" "take-nth" "butlast" "drop-last"
355 "reverse" "sort" "sort-by" "split-at" "partition" "split-with"
356 "first" "ffirst" "rfirst" "when-first" "zipmap" "into" "set" "vec" "into-array"
357 "to-array-2d" "not-empty" "seq?" "not-every?" "every?" "not-any?" "empty?"
142c8c3b » jochu 2009-01-06 be a little more discrimina... 358 "map" "mapcat" "vector?" "list?" "hash-map" "reduce" "filter"
359 "vals" "keys" "rseq" "subseq" "rsubseq" "count"
0e11dd06 » Lau-of-DK 2008-12-27 Added all sequence/function... 360 "fnseq" "lazy-cons" "repeatedly" "iterate"
361 "repeat" "replicate" "range"
362 "line-seq" "resultset-seq" "re-seq" "re-find" "tree-seq" "file-seq" "xml-seq"
9b6841e7 » Lau-of-DK 2008-12-28 Added more keywords 363 "iterator-seq" "enumeration-seq"
364 "symbol?" "string?" "vector" "conj" "str"
365 "pos?" "neg?" "zero?" "nil?" "inc" "format"
366 "alter" "commute" "ref-set" "floor" "assoc" "send" "send-off" ) t)
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 367 "\\>")
142c8c3b » jochu 2009-01-06 be a little more discrimina... 368 1 font-lock-builtin-face)
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 369 ;; (fn name? args ...)
c6302e91 » jochu 2008-04-29 add support for namespace c... 370 (,(concat "(\\(?:clojure/\\)?\\(fn\\)[ \t]+"
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 371 ;; Possibly type
372 "\\(?:#^\\sw+[ \t]*\\)?"
373 ;; Possibly name
374 "\\(\\sw+\\)?" )
375 (1 font-lock-keyword-face)
376 (2 font-lock-function-name-face nil t))
377 ;; Constant values.
378 ("\\<:\\sw+\\>" 0 font-lock-builtin-face)
379 ;; Meta type annotation #^Type
380 ("#^\\sw+" 0 font-lock-type-face)
019c486f » technomancy 2009-01-22 Fix io! font-lock rule. 381 ("\\<io\\!\\>" 0 font-lock-warning-face)))
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 382 "Default expressions to highlight in Clojure mode.")
383
384
385 (defun clojure-load-file (file-name)
386 "Load a Lisp file into the inferior Lisp process."
387 (interactive (comint-get-source "Load Clojure file: " clojure-prev-l/c-dir/file
388 '(clojure-mode) t))
389 (comint-check-source file-name) ; Check to see if buffer needs saved.
390 (setq clojure-prev-l/c-dir/file (cons (file-name-directory file-name)
391 (file-name-nondirectory file-name)))
392 (comint-send-string (inferior-lisp-proc)
989d7ed9 » jochu 2008-03-07 clean up, use custom vars, ... 393 (format clojure-mode-load-command file-name))
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 394 (switch-to-lisp t))
395
396
397
398 (defun clojure-indent-function (indent-point state)
399 "This function is the normal value of the variable `lisp-indent-function'.
400 It is used when indenting a line within a function call, to see if the
401 called function says anything special about how to indent the line.
402
403 INDENT-POINT is the position where the user typed TAB, or equivalent.
404 Point is located at the point to indent under (for default indentation);
405 STATE is the `parse-partial-sexp' state for that position.
406
407 If the current line is in a call to a Lisp function
408 which has a non-nil property `lisp-indent-function',
409 that specifies how to do the indentation. The property value can be
410 * `defun', meaning indent `defun'-style;
411 * an integer N, meaning indent the first N arguments specially
412 like ordinary function arguments and then indent any further
413 arguments like a body;
414 * a function to call just as this function was called.
415 If that function returns nil, that means it doesn't specify
416 the indentation.
417
418 This function also returns nil meaning don't specify the indentation."
419 (let ((normal-indent (current-column)))
420 (goto-char (1+ (elt state 1)))
421 (parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t)
422 (if (and (elt state 2)
423 (not (looking-at "\\sw\\|\\s_")))
424 ;; car of form doesn't seem to be a symbol
425 (progn
426 (if (not (> (save-excursion (forward-line 1) (point))
427 calculate-lisp-indent-last-sexp))
428 (progn (goto-char calculate-lisp-indent-last-sexp)
429 (beginning-of-line)
430 (parse-partial-sexp (point)
431 calculate-lisp-indent-last-sexp 0 t)))
432 ;; Indent under the list or under the first sexp on the same
433 ;; line as calculate-lisp-indent-last-sexp. Note that first
434 ;; thing on that line has to be complete sexp since we are
435 ;; inside the innermost containing sexp.
436 (backward-prefix-chars)
ae5f46dd » jochu 2008-04-05 Ensure indent [] when insid... 437 (if (and (eq (char-after (point)) ?\[)
438 (eq (char-after (elt state 1)) ?\())
7c3a604a » jochu 2008-03-28 added a few keywords, chang... 439 (+ (current-column) 2) ;; this is probably inside a defn
440 (current-column)))
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 441 (let ((function (buffer-substring (point)
442 (progn (forward-sexp 1) (point))))
6162bd89 » jochu 2008-03-06 use less round about way to... 443 (open-paren (elt state 1))
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 444 method)
445 (setq method (get (intern-soft function) 'clojure-indent-function))
c6302e91 » jochu 2008-04-29 add support for namespace c... 446
fb85ade6 » jochu 2008-02-12 bracket indents are flush left 447 (cond ((member (char-after open-paren) '(?\[ ?\{))
6162bd89 » jochu 2008-03-06 use less round about way to... 448 (goto-char open-paren)
449 (1+ (current-column)))
fb85ade6 » jochu 2008-02-12 bracket indents are flush left 450 ((or (eq method 'defun)
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 451 (and (null method)
452 (> (length function) 3)
c6302e91 » jochu 2008-04-29 add support for namespace c... 453 (string-match "\\`\\(?:clojure/\\)?def" function)))
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 454 (lisp-indent-defform state indent-point))
7c3a604a » jochu 2008-03-28 added a few keywords, chang... 455
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 456 ((integerp method)
457 (lisp-indent-specform method state
458 indent-point normal-indent))
459 (method
9859c93c » jochu 2008-03-08 starting experimental backt... 460 (funcall method indent-point state))
461 (clojure-mode-use-backtracking-indent
462 (clojure-backtracking-indent indent-point state normal-indent)))))))
463
464 (defun clojure-backtracking-indent (indent-point state normal-indent)
465 "Experimental backtracking support. Will upwards in an sexp to
466 check for contextual indenting."
467 (let (indent (path) (depth 0))
468 (goto-char (elt state 1))
469 (while (and (not indent)
470 (< depth clojure-max-backtracking))
471 (let ((containing-sexp (point)))
472 (parse-partial-sexp (1+ containing-sexp) indent-point 1 t)
473 (when (looking-at "\\sw\\|\\s_")
474 (let* ((start (point))
475 (fn (buffer-substring start (progn (forward-sexp 1) (point))))
476 (meth (get (intern-soft fn) 'clojure-backtracking-indent)))
477 (let ((n 0))
478 (when (< (point) indent-point)
479 (condition-case ()
480 (progn
481 (forward-sexp 1)
482 (while (< (point) indent-point)
483 (parse-partial-sexp (point) indent-point 1 t)
484 (incf n)
485 (forward-sexp 1)))
486 (error nil)))
487 (push n path))
488 (when meth
489 (let ((def meth))
490 (dolist (p path)
ab5e0616 » jochu 2008-03-08 fix undefined deep backtrac... 491 (if (and (listp def)
492 (< p (length def)))
9859c93c » jochu 2008-03-08 starting experimental backt... 493 (setq def (nth p def))
ab5e0616 » jochu 2008-03-08 fix undefined deep backtrac... 494 (if (listp def)
495 (setq def (car (last def)))
496 (setq def nil))))
9859c93c » jochu 2008-03-08 starting experimental backt... 497 (goto-char (elt state 1))
ab5e0616 » jochu 2008-03-08 fix undefined deep backtrac... 498 (when def
499 (setq indent (+ (current-column) def)))))))
9859c93c » jochu 2008-03-08 starting experimental backt... 500 (goto-char containing-sexp)
501 (condition-case ()
502 (progn
503 (backward-up-list 1)
504 (incf depth))
505 (error (setq depth clojure-max-backtracking)))))
506 indent))
507
7c3a604a » jochu 2008-03-28 added a few keywords, chang... 508 ;; (defun clojure-indent-defn (indent-point state)
509 ;; "Indent by 2 if after a [] clause that's at the beginning of a
510 ;; line"
511 ;; (if (not (eq (char-after (elt state 2)) ?\[))
512 ;; (lisp-indent-defform state indent-point)
513 ;; (goto-char (elt state 2))
514 ;; (beginning-of-line)
515 ;; (skip-syntax-forward " ")
516 ;; (if (= (point) (elt state 2))
517 ;; (+ (current-column) 2)
518 ;; (lisp-indent-defform state indent-point))))
519
520 ;; (put 'defn 'clojure-indent-function 'clojure-indent-defn)
521 ;; (put 'defmacro 'clojure-indent-function 'clojure-indent-defn)
522
9859c93c » jochu 2008-03-08 starting experimental backt... 523 ;; clojure backtracking indent is experimental and the format for these
c6302e91 » jochu 2008-04-29 add support for namespace c... 524
9859c93c » jochu 2008-03-08 starting experimental backt... 525 ;; entries are subject to change
526 (put 'implement 'clojure-backtracking-indent '(4 (2)))
527 (put 'proxy 'clojure-backtracking-indent '(4 4 (2)))
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 528
c6302e91 » jochu 2008-04-29 add support for namespace c... 529
530 (defun put-clojure-indent (sym indent)
531 (put sym 'clojure-indent-function indent)
532 (put (intern (format "clojure/%s" (symbol-name sym))) 'clojure-indent-function indent))
533
534 (defmacro define-clojure-indent (&rest kvs)
535 `(progn
536 ,@(mapcar (lambda (x) `(put-clojure-indent (quote ,(first x)) ,(second x))) kvs)))
537
538 (define-clojure-indent
539 (catch 2)
540 (defmuti 1)
541 (do 0)
d587ea15 » jochu 2009-02-23 add if-not indentation 542 (for 1)
c6302e91 » jochu 2008-04-29 add support for namespace c... 543 (if 1)
d587ea15 » jochu 2009-02-23 add if-not indentation 544 (if-not 1)
c6302e91 » jochu 2008-04-29 add support for namespace c... 545 (let 1)
7f3de0bd » jochu 2009-03-05 add letfn indentation 546 (letfn 1)
c6302e91 » jochu 2008-04-29 add support for namespace c... 547 (loop 1)
548 (struct-map 1)
549 (assoc 1)
dd656296 » jochu 2009-02-23 add indentation for condp 550 (condp 2)
c6302e91 » jochu 2008-04-29 add support for namespace c... 551
552 (fn 'defun))
553
fea3cab0 » jochu 2008-03-04 add a few more indent specs... 554 ;; built-ins
c6302e91 » jochu 2008-04-29 add support for namespace c... 555 (define-clojure-indent
374fa61d » jochu 2008-09-03 add support for (ns ... ) 556 (ns 1)
c6302e91 » jochu 2008-04-29 add support for namespace c... 557 (binding 1)
558 (comment 0)
559 (defstruct 1)
992724e8 » jochu 2008-11-13 update to latest bindings 560 (doseq 1)
561 (dotimes 1)
c6302e91 » jochu 2008-04-29 add support for namespace c... 562 (doto 1)
563 (implement 1)
564 (let 1)
992724e8 » jochu 2008-11-13 update to latest bindings 565 (when-let 1)
566 (if-let 1)
c6302e91 » jochu 2008-04-29 add support for namespace c... 567 (locking 1)
568 (proxy 2)
569 (sync 1)
570 (when 1)
992724e8 » jochu 2008-11-13 update to latest bindings 571 (when-first 1)
572 (when-let 1)
c6302e91 » jochu 2008-04-29 add support for namespace c... 573 (when-not 1)
574 (with-local-vars 1)
992724e8 » jochu 2008-11-13 update to latest bindings 575 (with-open 1)
374fa61d » jochu 2008-09-03 add support for (ns ... ) 576 (with-precision 1))
fea3cab0 » jochu 2008-03-04 add a few more indent specs... 577
733a4e49 » technomancy 2009-02-02 Bug fixes for clojure-install. 578 ;;; SLIME integration
579
9c36712c » technomancy 2009-02-03 Fix a typo. 580 ;;;###autoload
0f28b61d » technomancy 2009-01-22 Added clojure-install comma... 581 (defun clojure-slime-config ()
582 "Load Clojure SLIME support out of the `clojure-src-root' directory.
583
584 Since there's no single conventional place to keep Clojure, this
585 is bundled up as a function so that you can call it after you've set
586 `clojure-src-root' in your personal config."
587
588 (add-to-list 'load-path (concat clojure-src-root "/slime"))
589 (add-to-list 'load-path (concat clojure-src-root "/slime/contrib"))
590 (add-to-list 'load-path (concat clojure-src-root "/swank-clojure"))
591
592 (require 'slime-autoloads)
593 (require 'swank-clojure-autoload)
594
3bb58f31 » technomancy 2009-02-26 Call swank-clojure-slime-mo... 595 (slime-setup '(slime-fancy))
0f28b61d » technomancy 2009-01-22 Added clojure-install comma... 596
293e3968 » technomancy 2009-04-27 Don't overwrite swank-cloju... 597 (setq swank-clojure-jar-path (concat clojure-src-root "/clojure/clojure.jar"))
598 (add-to-list 'swank-clojure-extra-classpaths
599 (concat clojure-src-root "/clojure-contrib/src/")))
0f28b61d » technomancy 2009-01-22 Added clojure-install comma... 600
9c36712c » technomancy 2009-02-03 Fix a typo. 601 ;;;###autoload
0f28b61d » technomancy 2009-01-22 Added clojure-install comma... 602 (defun clojure-install (src-root)
603 "Perform the initial Clojure install along with Emacs support libs.
604
605 This requires git, a JVM, ant, and an active Internet connection."
606 (interactive (list
e1e641db » technomancy 2009-02-02 Use read-string instead. 607 (read-string (concat "Install Clojure in (default: "
608 clojure-src-root "): ")
609 nil nil clojure-src-root)))
733a4e49 » technomancy 2009-02-02 Bug fixes for clojure-install. 610
82357642 » technomancy 2009-02-02 Fix for emacs 22, use slime... 611 (make-directory src-root t)
0f28b61d » technomancy 2009-01-22 Added clojure-install comma... 612
613 (if (file-exists-p (concat src-root "/clojure"))
614 (error "Clojure is already installed at %s/clojure" src-root))
615
616 (message "Checking out source... this will take a while...")
617 (dolist (cmd '("git clone git://github.com/kevinoneill/clojure.git"
618 "git clone git://github.com/kevinoneill/clojure-contrib.git"
619 "git clone git://github.com/jochu/swank-clojure.git"
82357642 » technomancy 2009-02-02 Fix for emacs 22, use slime... 620 "git clone --depth 2 git://github.com/nablaone/slime.git"))
9219f13d » technomancy 2009-02-02 Fix calls to format and ins... 621 (unless (= 0 (shell-command (format "cd %s; %s" src-root cmd)))
0f28b61d » technomancy 2009-01-22 Added clojure-install comma... 622 (error "Clojure installation step failed: %s" cmd)))
623
624 (message "Compiling...")
9219f13d » technomancy 2009-02-02 Fix calls to format and ins... 625 (unless (= 0 (shell-command (format "cd %s/clojure; ant" src-root)))
733a4e49 » technomancy 2009-02-02 Bug fixes for clojure-install. 626 (error "Couldn't compile Clojure."))
0f28b61d » technomancy 2009-01-22 Added clojure-install comma... 627
9219f13d » technomancy 2009-02-02 Fix calls to format and ins... 628 (with-output-to-temp-buffer "clojure-install-note"
629 (princ
630 (if (equal src-root clojure-src-root)
293e3968 » technomancy 2009-04-27 Don't overwrite swank-cloju... 631 "Add a call to \"\(clojure-slime-config\)\"
0cf5eeb2 » technomancy 2009-02-04 Put clojure-slime-config in... 632 to your .emacs so you can use SLIME in future sessions."
9219f13d » technomancy 2009-02-02 Fix calls to format and ins... 633 (setq clojure-src-root src-root)
82357642 » technomancy 2009-02-02 Fix for emacs 22, use slime... 634 (format "You've installed clojure in a non-default location. If you want
635 to use this installation in the future, you will need to add the following
636 lines to your personal Emacs config somewhere:
0f28b61d » technomancy 2009-01-22 Added clojure-install comma... 637
627ae650 » technomancy 2009-02-01 Improve clojure-install ins... 638 \(setq clojure-src-root \"%s\"\)
293e3968 » technomancy 2009-04-27 Don't overwrite swank-cloju... 639 \(clojure-slime-config\)" src-root)))
9219f13d » technomancy 2009-02-02 Fix calls to format and ins... 640 (princ "\n\n Press M-x slime to launch Clojure."))
0f28b61d » technomancy 2009-01-22 Added clojure-install comma... 641
9219f13d » technomancy 2009-02-02 Fix calls to format and ins... 642 (clojure-slime-config))
0f28b61d » technomancy 2009-01-22 Added clojure-install comma... 643
43dfe592 » technomancy 2009-02-02 Added clojure-update functi... 644 (defun clojure-update ()
645 "Update clojure-related repositories and recompile clojure.
646
647 Works with clojure etc. installed via `clojure-install'. Code
648 should be checked out in the `clojure-src-root' directory."
649 (interactive)
650
651 (message "Updating...")
652 (dolist (repo '("clojure" "clojure-contrib" "swank-clojure" "slime"))
a2c942ab » technomancy 2009-02-17 Doc updates, git updates. 653 (unless (= 0 (shell-command (format "cd %s/%s; git pull origin master" clojure-src-root repo)))
43dfe592 » technomancy 2009-02-02 Added clojure-update functi... 654 (error "Clojure update failed: %s" repo)))
655
656 (message "Compiling...")
4506f07f » technomancy 2009-02-03 save-window-excursion aroun... 657 (save-window-excursion
658 (unless (= 0 (shell-command (format "cd %s/clojure; ant" clojure-src-root)))
659 (error "Couldn't compile Clojure.")))
43dfe592 » technomancy 2009-02-02 Added clojure-update functi... 660 (message "Finished updating Clojure."))
661
bbc939d8 » technomancy 2009-02-18 Enable SLIME for all clojur... 662 (defun clojure-enable-slime-on-existing-buffers ()
663 (interactive)
3bb58f31 » technomancy 2009-02-26 Call swank-clojure-slime-mo... 664 (add-hook 'clojure-mode-hook 'swank-clojure-slime-mode-hook)
bbc939d8 » technomancy 2009-02-18 Enable SLIME for all clojur... 665 (dolist (buffer (buffer-list))
e1664572 » technomancy 2009-02-27 Message test/failure/error ... 666 (with-current-buffer buffer
667 (if (equal major-mode 'clojure-mode)
3bb58f31 » technomancy 2009-02-26 Call swank-clojure-slime-mo... 668 (swank-clojure-slime-mode-hook)))))
bbc939d8 » technomancy 2009-02-18 Enable SLIME for all clojur... 669
670 (add-hook 'slime-connected-hook 'clojure-enable-slime-on-existing-buffers)
671
93ad64c0 » technomancy 2008-12-27 Put appropriate autoloads i... 672 ;;;###autoload
673 (add-to-list 'auto-mode-alist '("\\.clj$" . clojure-mode))
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 674
93ad64c0 » technomancy 2008-12-27 Put appropriate autoloads i... 675 (provide 'clojure-mode)
3038db01 » jochu 2008-02-12 initial checkin of emacs cl... 676 ;;; clojure-mode.el ends here