jochu / clojure-mode
- Source
- Commits
- Network (13)
- Issues (1)
- Downloads (0)
- Wiki (2)
- Graphs
-
Tree:
8c33362
clojure-mode / clojure-mode.el
| aebf4dda » | technomancy | 2008-12-27 | 1 | ;;; clojure-mode.el --- Major mode for Clojure code | |
| 3038db01 » | jochu | 2008-02-12 | 2 | ||
| 627ae650 » | technomancy | 2009-02-01 | 3 | ;; Copyright (C) 2007, 2008, 2009 Jeffrey Chu and Lennart Staflin | |
| bcacc766 » | jochu | 2008-03-07 | 4 | ;; | |
| aebf4dda » | technomancy | 2008-12-27 | 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 | 8 | ;; Version: 1.1 | |
| aebf4dda » | technomancy | 2008-12-27 | 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 | 16 | ;; with subprocesses for the Clojure language. (http://clojure.org) | |
| aebf4dda » | technomancy | 2008-12-27 | 17 | ||
| 18 | ;;; Installation: | ||||
| 19 | |||||
| 299eb2db » | technomancy | 2009-03-12 | 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 | 26 | ;; (0) Add this file to your load-path, usually the ~/.emacs.d directory. | |
| aebf4dda » | technomancy | 2008-12-27 | 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 | 33 | ;; Paredit users: | |
| 34 | |||||
| 4ec68c21 » | jochu | 2009-01-23 | 35 | ;; Download paredit v21 or greater | |
| 36 | ;; http://mumble.net/~campbell/emacs/paredit.el | ||||
| e359e311 » | jochu | 2009-01-23 | 37 | ||
| 627ae650 » | technomancy | 2009-02-01 | 38 | ;; Use paredit as you normally would with any other mode; for instance: | |
| 39 | ;; | ||||
| 0a90e587 » | jochu | 2009-01-23 | 40 | ;; ;; require or autoload paredit-mode | |
| e359e311 » | jochu | 2009-01-23 | 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 | 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 | 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 | 48 | ||
| 60d975b2 » | technomancy | 2009-01-21 | 49 | ;;; Todo: | |
| 50 | |||||
| 3bb58f31 » | technomancy | 2009-02-26 | 51 | ;; * installer doesn't work when git port is blocked | |
| 52 | ;; * updater/installer should know "last known good" sha1s? | ||||
| 60d975b2 » | technomancy | 2009-01-21 | 53 | ;; * hashbang is also a valid comment character | |
| 627ae650 » | technomancy | 2009-02-01 | 54 | ;; * do the inferior-lisp functions work without SLIME? needs documentation | |
| 60d975b2 » | technomancy | 2009-01-21 | 55 | ||
| aebf4dda » | technomancy | 2008-12-27 | 56 | ;;; License: | |
| 57 | |||||
| 3038db01 » | jochu | 2008-02-12 | 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 | 73 | ;;; Code: | |
| 74 | |||||
| 6615bc96 » | jochu | 2008-03-06 | 75 | (require 'cl) | |
| 3038db01 » | jochu | 2008-02-12 | 76 | ||
| 989d7ed9 » | jochu | 2008-03-07 | 77 | (defgroup clojure-mode nil | |
| 78 | "A mode for Clojure" | ||||
| 79 | :prefix "clojure-mode-" | ||||
| 80 | :group 'applications) | ||||
| 81 | |||||
| c08f8024 » | jochu | 2008-03-09 | 82 | (defcustom clojure-mode-font-lock-multiline-def t | |
| 8d9d0e7a » | jochu | 2008-03-08 | 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 | 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 | 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 | 93 | :type 'boolean | |
| 94 | :group 'clojure-mode) | ||||
| 95 | |||||
| 3bb58f31 » | technomancy | 2009-02-26 | 96 | (defcustom clojure-mode-load-command "(clojure.core/load-file \"%s\")\n" | |
| 3038db01 » | jochu | 2008-02-12 | 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 | 101 | :type 'string | |
| 102 | :group 'clojure-mode) | ||||
| 3038db01 » | jochu | 2008-02-12 | 103 | ||
| 9859c93c » | jochu | 2008-03-08 | 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 | 115 | (defcustom clojure-src-root (expand-file-name "~/src") | |
| 1db8b4c3 » | technomancy | 2009-02-02 | 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 | 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 | 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 | 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 | 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 | 155 | (modify-syntax-entry ?^ "'" table) | |
| 3038db01 » | jochu | 2008-02-12 | 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 | 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 | 167 | ;;;###autoload | |
| 3038db01 » | jochu | 2008-02-12 | 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 | 184 | (lisp-mode-variables nil) | |
| 3038db01 » | jochu | 2008-02-12 | 185 | (set-syntax-table clojure-mode-syntax-table) | |
| 989d7ed9 » | jochu | 2008-03-07 | 186 | ||
| 187 | (set (make-local-variable 'comment-start-skip) | ||||
| 3038db01 » | jochu | 2008-02-12 | 188 | "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\)\\(;+\\|#|\\) *") | |
| 989d7ed9 » | jochu | 2008-03-07 | 189 | (set (make-local-variable 'lisp-indent-function) | |
| 190 | 'clojure-indent-function) | ||||
| dfb0cf89 » | jochu | 2008-02-17 | 191 | (set (make-local-variable 'font-lock-multiline) t) | |
| 989d7ed9 » | jochu | 2008-03-07 | 192 | ||
| 60d975b2 » | technomancy | 2009-01-21 | 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 | 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 | 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 | 212 | ||
| 3038db01 » | jochu | 2008-02-12 | 213 | (setq font-lock-defaults | |
| b2e2e3f1 » | jochu | 2009-02-06 | 214 | '(clojure-font-lock-keywords ; keywords | |
| 215 | nil nil | ||||
| dfb0cf89 » | jochu | 2008-02-17 | 216 | (("+-*/.<>=!?$%_&~^:@" . "w")) ; syntax alist | |
| 217 | nil | ||||
| b2e2e3f1 » | jochu | 2009-02-06 | 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 | 225 | ;; Enable curly braces when paredit is enabled in clojure-mode-hook | |
| 4ec68c21 » | jochu | 2009-01-23 | 226 | (when (and (featurep 'paredit) paredit-mode (>= paredit-version 21)) | |
| e359e311 » | jochu | 2009-01-23 | 227 | (define-key clojure-mode-map "{" 'paredit-open-curly) | |
| 228 | (define-key clojure-mode-map "}" 'paredit-close-curly))) | ||||
| 3038db01 » | jochu | 2008-02-12 | 229 | ||
| 3bb58f31 » | technomancy | 2009-02-26 | 230 | ;; (define-key clojure-mode-map "{" 'self-insert-command) | |
| 231 | ;; (define-key clojure-mode-map "}" 'self-insert-command) | ||||
| 232 | |||||
| dfb0cf89 » | jochu | 2008-02-17 | 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 | 245 | (looking-at "(def")) | |
| dfb0cf89 » | jochu | 2008-02-17 | 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 | 255 | (defun clojure-font-lock-extend-region-def () | |
| dfb0cf89 » | jochu | 2008-02-17 | 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 | 273 | changed t))))) | |
| 274 | changed)) | ||||
| 3038db01 » | jochu | 2008-02-12 | 275 | ||
| 989d7ed9 » | jochu | 2008-03-07 | 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 | 284 | (let ((pos (re-search-forward "(comment\\>" font-lock-end t))) | |
| 989d7ed9 » | jochu | 2008-03-07 | 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 | 301 | (setq pos (re-search-forward "(comment\\>" limit t))) | |
| 989d7ed9 » | jochu | 2008-03-07 | 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 | 310 | (defconst clojure-font-lock-keywords | |
| 311 | (eval-when-compile | ||||
| 312 | `( ;; Definitions. | ||||
| c6302e91 » | jochu | 2008-04-29 | 313 | (,(concat "(\\(?:clojure/\\)?\\(def" | |
| 3038db01 » | jochu | 2008-02-12 | 314 | ;; Function declarations. | |
| a2c942ab » | technomancy | 2009-02-17 | 315 | "\\(n-?\\|multi\\|macro\\|method\\|test\\|" | |
| 3038db01 » | jochu | 2008-02-12 | 316 | ;; Variable declarations. | |
| 876bac71 » | mattrepl | 2008-08-30 | 317 | "struct\\|once\\|" | |
| 3038db01 » | jochu | 2008-02-12 | 318 | "\\)\\)\\>" | |
| 319 | ;; Any whitespace | ||||
| dfb0cf89 » | jochu | 2008-02-17 | 320 | "[ \r\n\t]*" | |
| 321 | ;; Possibly type or metadata | ||||
| 322 | "\\(?:#^\\(?:{[^}]*}\\|\\sw+\\)[ \r\n\t]*\\)?" | ||||
| 323 | |||||
| 3038db01 » | jochu | 2008-02-12 | 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 | 331 | '("let" "letfn" "do" | |
| 142c8c3b » | jochu | 2009-01-06 | 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 | 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 | 358 | "map" "mapcat" "vector?" "list?" "hash-map" "reduce" "filter" | |
| 359 | "vals" "keys" "rseq" "subseq" "rsubseq" "count" | ||||
| 0e11dd06 » | Lau-of-DK | 2008-12-27 | 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 | 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 | 367 | "\\>") | |
| 142c8c3b » | jochu | 2009-01-06 | 368 | 1 font-lock-builtin-face) | |
| 3038db01 » | jochu | 2008-02-12 | 369 | ;; (fn name? args ...) | |
| c6302e91 » | jochu | 2008-04-29 | 370 | (,(concat "(\\(?:clojure/\\)?\\(fn\\)[ \t]+" | |
| 3038db01 » | jochu | 2008-02-12 | 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 | 381 | ("\\<io\\!\\>" 0 font-lock-warning-face))) | |
| 3038db01 » | jochu | 2008-02-12 | 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 | 393 | (format clojure-mode-load-command file-name)) | |
| 3038db01 » | jochu | 2008-02-12 | 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 | 437 | (if (and (eq (char-after (point)) ?\[) | |
| 438 | (eq (char-after (elt state 1)) ?\()) | ||||
| 7c3a604a » | jochu | 2008-03-28 | 439 | (+ (current-column) 2) ;; this is probably inside a defn | |
| 440 | (current-column))) | ||||
| 3038db01 » | jochu | 2008-02-12 | 441 | (let ((function (buffer-substring (point) | |
| 442 | (progn (forward-sexp 1) (point)))) | ||||
| 6162bd89 » | jochu | 2008-03-06 | 443 | (open-paren (elt state 1)) | |
| 3038db01 » | jochu | 2008-02-12 | 444 | method) | |
| 445 | (setq method (get (intern-soft function) 'clojure-indent-function)) | ||||
| c6302e91 » | jochu | 2008-04-29 | 446 | ||
| fb85ade6 » | jochu | 2008-02-12 | 447 | (cond ((member (char-after open-paren) '(?\[ ?\{)) | |
| 6162bd89 » | jochu | 2008-03-06 | 448 | (goto-char open-paren) | |
| 449 | (1+ (current-column))) | ||||
| fb85ade6 » | jochu | 2008-02-12 | 450 | ((or (eq method 'defun) | |
| 3038db01 » | jochu | 2008-02-12 | 451 | (and (null method) | |
| 452 | (> (length function) 3) | ||||
| c6302e91 » | jochu | 2008-04-29 | 453 | (string-match "\\`\\(?:clojure/\\)?def" function))) | |
| 3038db01 » | jochu | 2008-02-12 | 454 | (lisp-indent-defform state indent-point)) | |
| 7c3a604a » | jochu | 2008-03-28 | 455 | ||
| 3038db01 » | jochu | 2008-02-12 | 456 | ((integerp method) | |
| 457 | (lisp-indent-specform method state | ||||
| 458 | indent-point normal-indent)) | ||||
| 459 | (method | ||||
| 9859c93c » | jochu | 2008-03-08 | 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 | 491 | (if (and (listp def) | |
| 492 | (< p (length def))) | ||||
| 9859c93c » | jochu | 2008-03-08 | 493 | (setq def (nth p def)) | |
| ab5e0616 » | jochu | 2008-03-08 | 494 | (if (listp def) | |
| 495 | (setq def (car (last def))) | ||||
| 496 | (setq def nil)))) | ||||
| 9859c93c » | jochu | 2008-03-08 | 497 | (goto-char (elt state 1)) | |
| ab5e0616 » | jochu | 2008-03-08 | 498 | (when def | |
| 499 | (setq indent (+ (current-column) def))))))) | ||||
| 9859c93c » | jochu | 2008-03-08 | 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 | 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 | 523 | ;; clojure backtracking indent is experimental and the format for these | |
| c6302e91 » | jochu | 2008-04-29 | 524 | ||
| 9859c93c » | jochu | 2008-03-08 | 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 | 528 | ||
| c6302e91 » | jochu | 2008-04-29 | 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 | 542 | (for 1) | |
| c6302e91 » | jochu | 2008-04-29 | 543 | (if 1) | |
| d587ea15 » | jochu | 2009-02-23 | 544 | (if-not 1) | |
| c6302e91 » | jochu | 2008-04-29 | 545 | (let 1) | |
| 7f3de0bd » | jochu | 2009-03-05 | 546 | (letfn 1) | |
| c6302e91 » | jochu | 2008-04-29 | 547 | (loop 1) | |
| 548 | (struct-map 1) | ||||
| 549 | (assoc 1) | ||||
| dd656296 » | jochu | 2009-02-23 | 550 | (condp 2) | |
| c6302e91 » | jochu | 2008-04-29 | 551 | ||
| 552 | (fn 'defun)) | ||||
| 553 | |||||
| fea3cab0 » | jochu | 2008-03-04 | 554 | ;; built-ins | |
| c6302e91 » | jochu | 2008-04-29 | 555 | (define-clojure-indent | |
| 374fa61d » | jochu | 2008-09-03 | 556 | (ns 1) | |
| c6302e91 » | jochu | 2008-04-29 | 557 | (binding 1) | |
| 558 | (comment 0) | ||||
| 559 | (defstruct 1) | ||||
| 992724e8 » | jochu | 2008-11-13 | 560 | (doseq 1) | |
| 561 | (dotimes 1) | ||||
| c6302e91 » | jochu | 2008-04-29 | 562 | (doto 1) | |
| 563 | (implement 1) | ||||
| 564 | (let 1) | ||||
| 992724e8 » | jochu | 2008-11-13 | 565 | (when-let 1) | |
| 566 | (if-let 1) | ||||
| c6302e91 » | jochu | 2008-04-29 | 567 | (locking 1) | |
| 568 | (proxy 2) | ||||
| 569 | (sync 1) | ||||
| 570 | (when 1) | ||||
| 992724e8 » | jochu | 2008-11-13 | 571 | (when-first 1) | |
| 572 | (when-let 1) | ||||
| c6302e91 » | jochu | 2008-04-29 | 573 | (when-not 1) | |
| 574 | (with-local-vars 1) | ||||
| 992724e8 » | jochu | 2008-11-13 | 575 | (with-open 1) | |
| 374fa61d » | jochu | 2008-09-03 | 576 | (with-precision 1)) | |
| fea3cab0 » | jochu | 2008-03-04 | 577 | ||
| 733a4e49 » | technomancy | 2009-02-02 | 578 | ;;; SLIME integration | |
| 579 | |||||
| 9c36712c » | technomancy | 2009-02-03 | 580 | ;;;###autoload | |
| 0f28b61d » | technomancy | 2009-01-22 | 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 | 595 | (slime-setup '(slime-fancy)) | |
| 0f28b61d » | technomancy | 2009-01-22 | 596 | ||
| 293e3968 » | technomancy | 2009-04-27 | 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 | 600 | ||
| 9c36712c » | technomancy | 2009-02-03 | 601 | ;;;###autoload | |
| 0f28b61d » | technomancy | 2009-01-22 | 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 | 607 | (read-string (concat "Install Clojure in (default: " | |
| 608 | clojure-src-root "): ") | ||||
| 609 | nil nil clojure-src-root))) | ||||
| 733a4e49 » | technomancy | 2009-02-02 | 610 | ||
| 82357642 » | technomancy | 2009-02-02 | 611 | (make-directory src-root t) | |
| 0f28b61d » | technomancy | 2009-01-22 | 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 | 620 | "git clone --depth 2 git://github.com/nablaone/slime.git")) | |
| 9219f13d » | technomancy | 2009-02-02 | 621 | (unless (= 0 (shell-command (format "cd %s; %s" src-root cmd))) | |
| 0f28b61d » | technomancy | 2009-01-22 | 622 | (error "Clojure installation step failed: %s" cmd))) | |
| 623 | |||||
| 624 | (message "Compiling...") | ||||
| 9219f13d » | technomancy | 2009-02-02 | 625 | (unless (= 0 (shell-command (format "cd %s/clojure; ant" src-root))) | |
| 733a4e49 » | technomancy | 2009-02-02 | 626 | (error "Couldn't compile Clojure.")) | |
| 0f28b61d » | technomancy | 2009-01-22 | 627 | ||
| 9219f13d » | technomancy | 2009-02-02 | 628 | (with-output-to-temp-buffer "clojure-install-note" | |
| 629 | (princ | ||||
| 630 | (if (equal src-root clojure-src-root) | ||||
| 293e3968 » | technomancy | 2009-04-27 | 631 | "Add a call to \"\(clojure-slime-config\)\" | |
| 0cf5eeb2 » | technomancy | 2009-02-04 | 632 | to your .emacs so you can use SLIME in future sessions." | |
| 9219f13d » | technomancy | 2009-02-02 | 633 | (setq clojure-src-root src-root) | |
| 82357642 » | technomancy | 2009-02-02 | 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 | 637 | ||
| 627ae650 » | technomancy | 2009-02-01 | 638 | \(setq clojure-src-root \"%s\"\) | |
| 293e3968 » | technomancy | 2009-04-27 | 639 | \(clojure-slime-config\)" src-root))) | |
| 9219f13d » | technomancy | 2009-02-02 | 640 | (princ "\n\n Press M-x slime to launch Clojure.")) | |
| 0f28b61d » | technomancy | 2009-01-22 | 641 | ||
| 9219f13d » | technomancy | 2009-02-02 | 642 | (clojure-slime-config)) | |
| 0f28b61d » | technomancy | 2009-01-22 | 643 | ||
| 43dfe592 » | technomancy | 2009-02-02 | 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 | 653 | (unless (= 0 (shell-command (format "cd %s/%s; git pull origin master" clojure-src-root repo))) | |
| 43dfe592 » | technomancy | 2009-02-02 | 654 | (error "Clojure update failed: %s" repo))) | |
| 655 | |||||
| 656 | (message "Compiling...") | ||||
| 4506f07f » | technomancy | 2009-02-03 | 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 | 660 | (message "Finished updating Clojure.")) | |
| 661 | |||||
| bbc939d8 » | technomancy | 2009-02-18 | 662 | (defun clojure-enable-slime-on-existing-buffers () | |
| 663 | (interactive) | ||||
| 3bb58f31 » | technomancy | 2009-02-26 | 664 | (add-hook 'clojure-mode-hook 'swank-clojure-slime-mode-hook) | |
| bbc939d8 » | technomancy | 2009-02-18 | 665 | (dolist (buffer (buffer-list)) | |
| e1664572 » | technomancy | 2009-02-27 | 666 | (with-current-buffer buffer | |
| 667 | (if (equal major-mode 'clojure-mode) | ||||
| 3bb58f31 » | technomancy | 2009-02-26 | 668 | (swank-clojure-slime-mode-hook))))) | |
| bbc939d8 » | technomancy | 2009-02-18 | 669 | ||
| 670 | (add-hook 'slime-connected-hook 'clojure-enable-slime-on-existing-buffers) | ||||
| 671 | |||||
| 93ad64c0 » | technomancy | 2008-12-27 | 672 | ;;;###autoload | |
| 673 | (add-to-list 'auto-mode-alist '("\\.clj$" . clojure-mode)) | ||||
| 3038db01 » | jochu | 2008-02-12 | 674 | ||
| 93ad64c0 » | technomancy | 2008-12-27 | 675 | (provide 'clojure-mode) | |
| 3038db01 » | jochu | 2008-02-12 | 676 | ;;; clojure-mode.el ends here | |
