PageRenderTime 59ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/elpa/clojure-mode-2.2.0/clojure-mode.el

https://github.com/DeltaAlphaRho/.emacs.d
Emacs Lisp | 1310 lines | 1020 code | 126 blank | 164 comment | 22 complexity | d232bdf07498ee6dd24d83df4f0a4e39 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. ;;; clojure-mode.el --- Major mode for Clojure code
  2. ;; Copyright © 2007-2014 Jeffrey Chu, Lennart Staflin, Phil Hagelberg
  3. ;; Copyright © 2013-2014 Bozhidar Batsov
  4. ;;
  5. ;; Authors: Jeffrey Chu <jochu0@gmail.com>
  6. ;; Lennart Staflin <lenst@lysator.liu.se>
  7. ;; Phil Hagelberg <technomancy@gmail.com>
  8. ;; Bozhidar Batsov <bozhidar@batsov.com>
  9. ;; URL: http://github.com/clojure-emacs/clojure-mode
  10. ;; Version: 2.2.0
  11. ;; X-Original-Version: 2.2.0
  12. ;; Keywords: languages, lisp
  13. ;; This file is not part of GNU Emacs.
  14. ;;; Commentary:
  15. ;; Provides font-lock, indentation, and navigation for the Clojure
  16. ;; programming language (http://clojure.org).
  17. ;; Users of older Emacs (pre-22) should get version 1.4:
  18. ;; http://github.com/clojure-emacs/clojure-mode/tree/1.4
  19. ;; Slime integration has been removed; see the 1.x releases if you need it.
  20. ;; Using clojure-mode with paredit is highly recommended. Use paredit
  21. ;; as you would with any other minor mode; for instance:
  22. ;;
  23. ;; ;; require or autoload paredit-mode
  24. ;; (add-hook 'clojure-mode-hook 'paredit-mode)
  25. ;; See CIDER (http://github.com/clojure-emacs/cider) for
  26. ;; better interaction with subprocesses via nREPL.
  27. ;;; License:
  28. ;; This program is free software; you can redistribute it and/or
  29. ;; modify it under the terms of the GNU General Public License
  30. ;; as published by the Free Software Foundation; either version 3
  31. ;; of the License, or (at your option) any later version.
  32. ;;
  33. ;; This program is distributed in the hope that it will be useful,
  34. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  35. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  36. ;; GNU General Public License for more details.
  37. ;;
  38. ;; You should have received a copy of the GNU General Public License
  39. ;; along with GNU Emacs; see the file COPYING. If not, write to the
  40. ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  41. ;; Boston, MA 02110-1301, USA.
  42. ;;; Code:
  43. ;;; Compatibility
  44. (eval-and-compile
  45. ;; `setq-local' for Emacs 24.2 and below
  46. (unless (fboundp 'setq-local)
  47. (defmacro setq-local (var val)
  48. "Set variable VAR to value VAL in current buffer."
  49. `(set (make-local-variable ',var) ,val))))
  50. (eval-when-compile
  51. (defvar calculate-lisp-indent-last-sexp)
  52. (defvar font-lock-beg)
  53. (defvar font-lock-end)
  54. (defvar paredit-space-for-delimiter-predicates)
  55. (defvar paredit-version)
  56. (defvar paredit-mode))
  57. (require 'cl)
  58. (require 'tramp)
  59. (require 'inf-lisp)
  60. (require 'imenu)
  61. (declare-function clojure-test-jump-to-implementation "clojure-test-mode")
  62. (declare-function lisp-fill-paragraph "lisp-mode" (&optional justify))
  63. (defconst clojure-font-lock-keywords
  64. (eval-when-compile
  65. `(;; Top-level variable definition
  66. (,(concat "(\\(?:clojure.core/\\)?\\("
  67. (regexp-opt '("def" "defonce"))
  68. ;; variable declarations
  69. "\\)\\>"
  70. ;; Any whitespace
  71. "[ \r\n\t]*"
  72. ;; Possibly type or metadata
  73. "\\(?:#?^\\(?:{[^}]*}\\|\\sw+\\)[ \r\n\t]*\\)*"
  74. "\\(\\sw+\\)?")
  75. (1 font-lock-keyword-face)
  76. (2 font-lock-variable-name-face nil t))
  77. ;; Type definition
  78. (,(concat "(\\(?:clojure.core/\\)?\\("
  79. (regexp-opt '("defstruct" "deftype" "defprotocol"
  80. "defrecord"))
  81. ;; type declarations
  82. "\\)\\>"
  83. ;; Any whitespace
  84. "[ \r\n\t]*"
  85. ;; Possibly type or metadata
  86. "\\(?:#?^\\(?:{[^}]*}\\|\\sw+\\)[ \r\n\t]*\\)*"
  87. "\\(\\sw+\\)?")
  88. (1 font-lock-keyword-face)
  89. (2 font-lock-type-face nil t))
  90. ;; Function definition (anything that starts with def and is not
  91. ;; listed above)
  92. (,(concat "(\\(?:[a-z\.-]+/\\)?\\(def\[a-z\-\]*-?\\)"
  93. ;; Function declarations
  94. "\\>"
  95. ;; Any whitespace
  96. "[ \r\n\t]*"
  97. ;; Possibly type or metadata
  98. "\\(?:#?^\\(?:{[^}]*}\\|\\sw+\\)[ \r\n\t]*\\)*"
  99. "\\(\\sw+\\)?")
  100. (1 font-lock-keyword-face)
  101. (2 font-lock-function-name-face nil t))
  102. ;; (fn name? args ...)
  103. (,(concat "(\\(?:clojure.core/\\)?\\(fn\\)[ \t]+"
  104. ;; Possibly type
  105. "\\(?:#?^\\sw+[ \t]*\\)?"
  106. ;; Possibly name
  107. "\\(t\\sw+\\)?" )
  108. (1 font-lock-keyword-face)
  109. (2 font-lock-function-name-face nil t))
  110. ;; lambda arguments - %, %1, %2, etc
  111. ("\\<%[1-9]?" (0 font-lock-variable-name-face))
  112. ;; (ns namespace)
  113. (,(concat "(\\(?:clojure.core/\\)?ns[ \t]+"
  114. ;; namespace
  115. "\\(\\sw+\\)" )
  116. (1 font-lock-type-face nil t))
  117. ;; Special forms & control structures
  118. (,(concat
  119. "(\\(?:clojure.core/\\)?"
  120. (regexp-opt
  121. '("let" "letfn" "do"
  122. "case" "cond" "condp"
  123. "for" "loop" "recur"
  124. "when" "when-not" "when-let" "when-first" "when-some"
  125. "if" "if-let" "if-not" "if-some"
  126. "." ".." "->" "->>" "doto"
  127. "and" "or"
  128. "dosync" "doseq" "dotimes" "dorun" "doall"
  129. "load" "import" "unimport" "ns" "in-ns" "refer"
  130. "try" "catch" "finally" "throw"
  131. "with-open" "with-local-vars" "binding"
  132. "gen-class" "gen-and-load-class" "gen-and-save-class"
  133. "handler-case" "handle" "var") t)
  134. "\\>")
  135. 1 font-lock-keyword-face)
  136. ;; Global constants - nil, true, false
  137. (,(concat
  138. (regexp-opt
  139. '("true" "false" "nil") t)
  140. "\\>")
  141. 0 font-lock-constant-face)
  142. ;; Built-ins
  143. (,(concat
  144. "(\\(?:clojure.core/\\)?"
  145. (regexp-opt
  146. '("*" "*1" "*2" "*3" "*agent*"
  147. "*allow-unresolved-vars*" "*assert*" "*clojure-version*" "*command-line-args*" "*compile-files*"
  148. "*compile-path*" "*e" "*err*" "*file*" "*flush-on-newline*"
  149. "*in*" "*macro-meta*" "*math-context*" "*ns*" "*out*"
  150. "*print-dup*" "*print-length*" "*print-level*" "*print-meta*" "*print-readably*"
  151. "*read-eval*" "*source-path*" "*use-context-classloader*" "*warn-on-reflection*" "+"
  152. "-" "/"
  153. "<" "<=" "=" "==" ">"
  154. ">=" "accessor" "aclone"
  155. "agent" "agent-errors" "aget" "alength" "alias"
  156. "all-ns" "alter" "alter-meta!" "alter-var-root" "amap"
  157. "ancestors" "apply" "areduce" "array-map" "as->"
  158. "aset" "aset-boolean" "aset-byte" "aset-char" "aset-double"
  159. "aset-float" "aset-int" "aset-long" "aset-short" "assert"
  160. "assoc" "assoc!" "assoc-in" "associative?" "atom"
  161. "await" "await-for" "await1" "bases" "bean"
  162. "bigdec" "bigint" "bit-and" "bit-and-not"
  163. "bit-clear" "bit-flip" "bit-not" "bit-or" "bit-set"
  164. "bit-shift-left" "bit-shift-right" "bit-test" "bit-xor" "boolean"
  165. "boolean-array" "booleans" "bound-fn" "bound-fn*" "bound?" "butlast"
  166. "byte" "byte-array" "bytes" "cast" "char"
  167. "char-array" "char-escape-string" "char-name-string" "char?" "chars"
  168. "chunk" "chunk-append" "chunk-buffer" "chunk-cons" "chunk-first"
  169. "chunk-next" "chunk-rest" "chunked-seq?" "class" "class?"
  170. "clear-agent-errors" "clojure-version" "coll?" "comment" "commute"
  171. "comp" "comparator" "compare" "compare-and-set!" "compile"
  172. "complement" "concat" "cond->" "cond->>" "conj"
  173. "conj!" "cons" "constantly" "construct-proxy" "contains?"
  174. "count" "counted?" "create-ns" "create-struct" "cycle"
  175. "dec" "decimal?" "declare" "definline" "defmacro"
  176. "defmethod" "defmulti" "defn" "defn-" "defonce"
  177. "defstruct" "delay" "delay?" "deliver" "deref"
  178. "derive" "descendants" "destructure" "disj" "disj!"
  179. "dissoc" "dissoc!" "distinct" "distinct?"
  180. "doc"
  181. "double" "double-array" "doubles" "drop"
  182. "drop-last" "drop-while" "empty" "empty?" "ensure"
  183. "enumeration-seq" "eval" "even?" "every?"
  184. "extend" "extend-protocol" "extend-type" "extends?" "extenders" "ex-info" "ex-data"
  185. "false?" "ffirst" "file-seq" "filter" "filterv" "find" "find-doc"
  186. "find-ns" "find-var" "first" "flatten" "float" "float-array"
  187. "float?" "floats" "flush" "fn" "fn?"
  188. "fnext" "force" "format" "frequencies" "future"
  189. "future-call" "future-cancel" "future-cancelled?" "future-done?" "future?"
  190. "gen-interface" "gensym" "get" "get-in"
  191. "get-method" "get-proxy-class" "get-thread-bindings" "get-validator" "group-by"
  192. "hash" "hash-map" "hash-set" "identical?" "identity"
  193. "ifn?" "inc"
  194. "init-proxy" "instance?" "int" "int-array" "integer?"
  195. "interleave" "intern" "interpose" "into" "into-array"
  196. "ints" "io!" "isa?" "iterate" "iterator-seq"
  197. "juxt" "keep" "keep-indexed" "key" "keys" "keyword" "keyword?"
  198. "last" "lazy-cat" "lazy-seq"
  199. "line-seq" "list" "list*" "list?"
  200. "load-file" "load-reader" "load-string" "loaded-libs" "locking"
  201. "long" "long-array" "longs" "macroexpand"
  202. "macroexpand-1" "make-array" "make-hierarchy" "map" "mapv" "map?"
  203. "map-indexed" "mapcat" "max" "max-key" "memfn" "memoize"
  204. "merge" "merge-with" "meta" "method-sig" "methods"
  205. "min" "min-key" "mix-collection-hash" "mod" "name" "namespace"
  206. "neg?" "newline" "next" "nfirst" "nil?"
  207. "nnext" "not" "not-any?" "not-empty" "not-every?"
  208. "not=" "ns-aliases" "ns-imports" "ns-interns"
  209. "ns-map" "ns-name" "ns-publics" "ns-refers" "ns-resolve"
  210. "ns-unalias" "ns-unmap" "nth" "nthnext" "num"
  211. "number?" "odd?" "parents" "partial"
  212. "partition" "partition-all" "partition-by" "pcalls" "peek" "persistent!" "pmap"
  213. "pop" "pop!" "pop-thread-bindings" "pos?" "pr"
  214. "pr-str" "prefer-method" "prefers" "primitives-classnames" "print"
  215. "print-ctor" "print-doc" "print-dup" "print-method" "print-namespace-doc"
  216. "print-simple" "print-special-doc" "print-str" "printf" "println"
  217. "println-str" "prn" "prn-str" "promise" "proxy"
  218. "proxy-call-with-super" "proxy-mappings" "proxy-name" "proxy-super" "push-thread-bindings"
  219. "pvalues" "quot" "rand" "rand-int" "range"
  220. "ratio?" "rational?" "rationalize" "re-find" "re-groups"
  221. "re-matcher" "re-matches" "re-pattern" "re-seq" "read"
  222. "read-line" "read-string" "reify" "reduce" "reduce-kv" "ref" "ref-history-count"
  223. "ref-max-history" "ref-min-history" "ref-set" "refer-clojure"
  224. "release-pending-sends" "rem" "remove" "remove-method" "remove-ns"
  225. "repeat" "repeatedly" "replace" "replicate"
  226. "require" "reset!" "reset-meta!" "resolve" "rest"
  227. "resultset-seq" "reverse" "reversible?" "rseq" "rsubseq"
  228. "satisfies?" "second" "select-keys" "send" "send-off" "send-via" "seq"
  229. "seq?" "seque" "sequence" "sequential?" "set"
  230. "set-agent-send-executor!" "set-agent-send-off-executor!"
  231. "set-validator!" "set?" "short" "short-array" "shorts"
  232. "shutdown-agents" "slurp" "some" "some->" "some->>" "some?" "sort" "sort-by"
  233. "sorted-map" "sorted-map-by" "sorted-set" "sorted-set-by" "sorted?"
  234. "special-form-anchor" "special-symbol?" "specify" "specify!" "spit" "split-at" "split-with" "str"
  235. "stream?" "string?" "struct" "struct-map" "subs"
  236. "subseq" "subvec" "supers" "swap!" "symbol"
  237. "symbol?" "sync" "syntax-symbol-anchor" "take" "take-last"
  238. "take-nth" "take-while" "test" "the-ns" "time"
  239. "to-array" "to-array-2d" "trampoline" "transient" "tree-seq"
  240. "true?" "type" "unchecked-add" "unchecked-dec" "unchecked-divide"
  241. "unchecked-inc" "unchecked-multiply" "unchecked-negate" "unchecked-remainder" "unchecked-subtract"
  242. "underive" "unsigned-bit-shift-right" "unquote" "unquote-splicing" "update-in" "update-proxy"
  243. "use" "val" "vals" "var-get" "var-set"
  244. "var?" "vary-meta" "vec" "vector" "vector?"
  245. "while"
  246. "with-bindings" "with-bindings*" "with-in-str" "with-loading-context"
  247. "with-meta" "with-out-str" "with-precision"
  248. "with-redefs" "with-redefs-fn" "xml-seq" "zero?" "zipmap"
  249. ) t)
  250. "\\>")
  251. 1 font-lock-builtin-face)
  252. ;; Other namespaces in clojure.jar
  253. (,(concat
  254. "(\\(?:\.*/\\)?"
  255. (regexp-opt
  256. '(;; clojure.inspector
  257. "atom?" "collection-tag" "get-child" "get-child-count" "inspect"
  258. "inspect-table" "inspect-tree" "is-leaf" "list-model" "list-provider"
  259. ;; clojure.main
  260. "load-script" "main" "repl" "repl-caught" "repl-exception"
  261. "repl-prompt" "repl-read" "skip-if-eol" "skip-whitespace" "with-bindings"
  262. ;; clojure.set
  263. "difference" "index" "intersection" "join" "map-invert"
  264. "project" "rename" "rename-keys" "select" "union"
  265. ;; clojure.stacktrace
  266. "e" "print-cause-trace" "print-stack-trace" "print-throwable" "print-trace-element"
  267. ;; clojure.template
  268. "do-template" "apply-template"
  269. ;; clojure.test
  270. "*initial-report-counters*" "*load-tests*" "*report-counters*" "*stack-trace-depth*" "*test-out*"
  271. "*testing-contexts*" "*testing-vars*" "are" "assert-any" "assert-expr"
  272. "assert-predicate" "compose-fixtures" "deftest" "deftest-" "file-position"
  273. "function?" "get-possibly-unbound-var" "inc-report-counter" "is" "join-fixtures"
  274. "report" "run-all-tests" "run-tests" "set-test" "successful?"
  275. "test-all-vars" "test-ns" "test-var" "test-vars" "testing" "testing-contexts-str"
  276. "testing-vars-str" "try-expr" "use-fixtures" "with-test" "with-test-out"
  277. ;; clojure.walk
  278. "keywordize-keys" "macroexpand-all" "postwalk" "postwalk-demo" "postwalk-replace"
  279. "prewalk" "prewalk-demo" "prewalk-replace" "stringify-keys" "walk"
  280. ;; clojure.xml
  281. "*current*" "*sb*" "*stack*" "*state*" "attrs"
  282. "content" "content-handler" "element" "emit" "emit-element"
  283. ;; clojure.zip
  284. "append-child" "branch?" "children" "down" "edit"
  285. "end?" "insert-child" "insert-left" "insert-right" "left"
  286. "leftmost" "lefts" "make-node" "next" "node"
  287. "path" "prev" "remove" "replace" "right"
  288. "rightmost" "rights" "root" "seq-zip" "up"
  289. ) t)
  290. "\\>")
  291. 1 font-lock-builtin-face)
  292. ;; core.async control structures
  293. (,(concat
  294. "(\\(?:\.*/\\)?"
  295. (regexp-opt '("alt!" "alt!!" "go" "go-loop") t) "\\>")
  296. 1 font-lock-keyword-face)
  297. ;; core.async
  298. (,(concat
  299. "(\\(?:clojure.core.async/\\)?"
  300. (regexp-opt
  301. '(
  302. "<!" "<!!" ">!" ">!!" "admix" "alts!" "alts!!"
  303. "buffer" "chan" "close!" "do-alts" "dropping-buffer" "filter<" "filter>"
  304. "into" "map" "map<" "map>" "mapcat<" "mapcat>" "merge"
  305. "mix" "mult" "onto-chan" "partition" "partition-by" "pipe" "pub" "put!"
  306. "reduce" "remove<" "remove>" "sliding-buffer" "solo-mode" "split" "sub"
  307. "take" "take!" "tap" "thread" "thread-call" "timeout" "to-chan" "toggle"
  308. "unblocking-buffer?" "unique" "unmix" "unmix-all" "unsub" "unsub-all"
  309. "untap" "untap-all"
  310. ) t)
  311. "\\>")
  312. 1 font-lock-builtin-face)
  313. ;; clojure.core.typed
  314. (,(concat
  315. "(\\(?:clojure.core.typed/\\)?"
  316. (regexp-opt
  317. '(
  318. "ann-form" "cf" "defprotocol>" "doseq>" "dotimes>" "fn>"
  319. "for>" "into-array>" "let-fn>" "loop>" "pfn>" "ref>"
  320. "tc-ignore" "var>"
  321. ) t)
  322. "\\>")
  323. 1 font-lock-builtin-face)
  324. ;; Constant values (keywords), including as metadata e.g. ^:static
  325. ("\\<^?:\\(\\sw\\|\\s_\\)+\\(\\>\\|\\_>\\)" 0 font-lock-constant-face)
  326. ;; Meta type hint #^Type or ^Type
  327. ("\\(#?^\\)\\(\\(\\sw\\|\\s_\\)+\\)"
  328. (1 font-lock-preprocessor-face)
  329. (2 font-lock-type-face))
  330. ;; Java interop highlighting
  331. ;; .foo .barBaz .qux01 .-flibble .-flibbleWobble
  332. ("\\<\\.-?[a-z][a-zA-Z0-9]*\\>" 0 font-lock-preprocessor-face)
  333. ;; Foo Bar$Baz Qux_ World_OpenUDP Foo. Babylon15.
  334. ("\\(?:\\<\\|\\.\\)\\([A-Z][a-zA-Z0-9_]*[a-zA-Z0-9$_]+\\.?\\>\\)" 1 font-lock-type-face)
  335. ;; foo.bar.baz
  336. ("\\<[a-z][a-z0-9_-]+\\.\\([a-z][a-z0-9_-]+\\.?\\)+" 0 font-lock-type-face)
  337. ;; foo/ Foo/
  338. ("\\<\\([a-zA-Z][a-z0-9_-]*\\)/" 1 font-lock-type-face)
  339. ;; fooBar
  340. ("\\<[a-z]+[A-Z]+[a-z][a-zA-Z0-9$]*\\>" 0 font-lock-preprocessor-face)
  341. ;; Highlight grouping constructs in regular expressions
  342. (clojure-mode-font-lock-regexp-groups
  343. (1 'font-lock-regexp-grouping-construct prepend))))
  344. "Default expressions to highlight in Clojure mode.")
  345. (defgroup clojure nil
  346. "A mode for Clojure"
  347. :prefix "clojure-"
  348. :group 'languages
  349. :link '(url-link :tag "Github" "https://github.com/clojure-emacs/clojure-mode")
  350. :link '(emacs-commentary-link :tag "Commentary" "clojure-mode"))
  351. (defcustom clojure-font-lock-comment-sexp nil
  352. "Set to non-nil to enable fontification of (comment...) forms.
  353. If you change this option, use M-x clojure-mode to restart clojure mode.
  354. This option is experimental."
  355. :type 'boolean
  356. :group 'clojure
  357. :safe 'booleanp)
  358. (make-obsolete-variable
  359. 'clojure-font-lock-comment-sexp
  360. "This option will be removed in the next major clojure-mode release."
  361. "2.2")
  362. (defcustom clojure-load-command "(clojure.core/load-file \"%s\")\n"
  363. "Format-string for building a Clojure expression to load a file.
  364. This format string should use `%s' to substitute a file name and
  365. should result in a Clojure expression that will command the
  366. inferior Clojure to load that file."
  367. :type 'string
  368. :group 'clojure
  369. :safe 'stringp)
  370. (defcustom clojure-inf-lisp-command "lein repl"
  371. "The command used by `inferior-lisp-program'."
  372. :type 'string
  373. :group 'clojure
  374. :safe 'stringp)
  375. (defcustom clojure-defun-style-default-indent nil
  376. "When non-nil, use default indenting for functions and macros.
  377. Otherwise check `define-clojure-indent' and `put-clojure-indent'."
  378. :type 'boolean
  379. :group 'clojure
  380. :safe 'booleanp)
  381. (defcustom clojure-use-backtracking-indent t
  382. "When non-nil, enable context sensitive indentation."
  383. :type 'boolean
  384. :group 'clojure
  385. :safe 'booleanp)
  386. (defcustom clojure-max-backtracking 3
  387. "Maximum amount to backtrack up a list to check for context."
  388. :type 'integer
  389. :group 'clojure
  390. :safe 'integerp)
  391. (defcustom clojure-docstring-fill-column fill-column
  392. "Value of `fill-column' to use when filling a docstring."
  393. :type 'integer
  394. :group 'clojure
  395. :safe 'integerp)
  396. (defcustom clojure-omit-space-between-tag-and-delimiters '(?\[ ?\{)
  397. "Allowed opening delimiter characters after a reader literal tag.
  398. For example, \[ is allowed in :db/id[:db.part/user]."
  399. :type '(set (const :tag "[" ?\[)
  400. (const :tag "{" ?\{)
  401. (const :tag "(" ?\()
  402. (const :tag "\"" ?\"))
  403. :group 'clojure
  404. :safe (lambda (value)
  405. (and (listp value)
  406. (every 'characterp value))))
  407. (defvar clojure-mode-map
  408. (let ((map (make-sparse-keymap)))
  409. (set-keymap-parent map lisp-mode-shared-map)
  410. (define-key map (kbd "C-M-x") 'lisp-eval-defun)
  411. (define-key map (kbd "C-x C-e") 'lisp-eval-last-sexp)
  412. (define-key map (kbd "C-c C-e") 'lisp-eval-last-sexp)
  413. (define-key map (kbd "C-c C-l") 'clojure-load-file)
  414. (define-key map (kbd "C-c C-r") 'lisp-eval-region)
  415. (define-key map (kbd "C-c C-t") 'clojure-jump-between-tests-and-code)
  416. (define-key map (kbd "C-c C-z") 'clojure-display-inferior-lisp-buffer)
  417. (define-key map (kbd "C-:") 'clojure-toggle-keyword-string)
  418. map)
  419. "Keymap for Clojure mode. Inherits from `lisp-mode-shared-map'.")
  420. (easy-menu-define clojure-mode-menu clojure-mode-map
  421. "Menu for Clojure mode."
  422. '("Clojure"
  423. ["Eval Function Definition" lisp-eval-defun]
  424. ["Eval Last Sexp" lisp-eval-last-sexp]
  425. ["Eval Region" lisp-eval-region]
  426. "--"
  427. ["Run Inferior Lisp" clojure-display-inferior-lisp-buffer]
  428. ["Display Inferior Lisp Buffer" clojure-display-inferior-lisp-buffer]
  429. ["Load File" clojure-load-file]
  430. "--"
  431. ["Toggle between string & keyword" clojure-toggle-keyword-string]
  432. ["Jump Between Test and Code" clojure-jump-between-tests-and-code]))
  433. (defvar clojure-mode-syntax-table
  434. (let ((table (copy-syntax-table emacs-lisp-mode-syntax-table)))
  435. (modify-syntax-entry ?~ "' " table)
  436. ;; can't safely make commas whitespace since it will apply even
  437. ;; inside string literals--ick!
  438. ;; (modify-syntax-entry ?, " " table)
  439. (modify-syntax-entry ?\{ "(}" table)
  440. (modify-syntax-entry ?\} "){" table)
  441. (modify-syntax-entry ?\[ "(]" table)
  442. (modify-syntax-entry ?\] ")[" table)
  443. (modify-syntax-entry ?^ "'" table)
  444. ;; Make hash a usual word character
  445. (modify-syntax-entry ?# "_ p" table)
  446. table))
  447. (defvar clojure-prev-l/c-dir/file nil
  448. "Record last directory and file used in loading or compiling.
  449. This holds a cons cell of the form `(DIRECTORY . FILE)'
  450. describing the last `clojure-load-file' or `clojure-compile-file' command.")
  451. (defvar clojure-test-ns-segment-position -1
  452. "Which segment of the ns is \"test\" inserted in your test name convention.
  453. Customize this depending on your project's conventions. Negative
  454. numbers count from the end:
  455. leiningen.compile -> leiningen.test.compile (uses 1)
  456. clojure.http.client -> clojure.http.test.client (uses -1)")
  457. (defconst clojure-mode-version "2.2.0"
  458. "The current version of `clojure-mode'.")
  459. (defun clojure-mode-display-version ()
  460. "Display the current `clojure-mode-version' in the minibuffer."
  461. (interactive)
  462. (message "clojure-mode (version %s)" clojure-mode-version))
  463. ;; For compatibility with Emacs < 24, derive conditionally
  464. (defalias 'clojure-parent-mode
  465. (if (fboundp 'prog-mode) 'prog-mode 'fundamental-mode))
  466. (defun clojure-space-for-delimiter-p (endp delim)
  467. "Prevent paredit from inserting useless spaces.
  468. See `paredit-space-for-delimiter-predicates' for the meaning of
  469. ENDP and DELIM."
  470. (if (derived-mode-p 'clojure-mode)
  471. (save-excursion
  472. (backward-char)
  473. (if (and (or (char-equal delim ?\()
  474. (char-equal delim ?\")
  475. (char-equal delim ?{))
  476. (not endp))
  477. (if (char-equal (char-after) ?#)
  478. (and (not (bobp))
  479. (or (char-equal ?w (char-syntax (char-before)))
  480. (char-equal ?_ (char-syntax (char-before)))))
  481. t)
  482. t))
  483. t))
  484. (defun clojure-no-space-after-tag (endp delimiter)
  485. "Prevent inserting a space after a reader-literal tag?
  486. When a reader-literal tag is followed be an opening delimiter
  487. listed in `clojure-omit-space-between-tag-and-delimiters', this
  488. function returns t.
  489. This allows you to write things like #db/id[:db.part/user]
  490. without inserting a space between the tag and the opening
  491. bracket.
  492. See `paredit-space-for-delimiter-predicates' for the meaning of
  493. ENDP and DELIMITER."
  494. (if endp
  495. t
  496. (or (not (member delimiter clojure-omit-space-between-tag-and-delimiters))
  497. (save-excursion
  498. (let ((orig-point (point)))
  499. (not (and (re-search-backward
  500. "#\\([a-zA-Z0-9._-]+/\\)?[a-zA-Z0-9._-]+"
  501. (line-beginning-position)
  502. t)
  503. (= orig-point (match-end 0)))))))))
  504. ;;;###autoload
  505. (define-derived-mode clojure-mode clojure-parent-mode "Clojure"
  506. "Major mode for editing Clojure code.
  507. \\{clojure-mode-map}"
  508. (setq-local imenu-create-index-function
  509. (lambda ()
  510. (imenu--generic-function '((nil clojure-match-next-def 0)))))
  511. (setq-local indent-tabs-mode nil)
  512. (lisp-mode-variables nil)
  513. (setq fill-paragraph-function 'clojure-fill-paragraph)
  514. (setq adaptive-fill-function 'clojure-adaptive-fill-function)
  515. (setq-local normal-auto-fill-function 'clojure-auto-fill-function)
  516. (setq-local comment-start-skip
  517. "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\)\\(;+\\|#|\\) *")
  518. (setq-local lisp-indent-function 'clojure-indent-function)
  519. (when (< emacs-major-version 24)
  520. (setq-local forward-sexp-function 'clojure-forward-sexp))
  521. (setq-local lisp-doc-string-elt-property 'clojure-doc-string-elt)
  522. (setq-local inferior-lisp-program clojure-inf-lisp-command)
  523. (setq-local parse-sexp-ignore-comments t)
  524. (clojure-mode-font-lock-setup)
  525. (setq-local open-paren-in-column-0-is-defun-start nil)
  526. (add-hook 'paredit-mode-hook
  527. (lambda ()
  528. (when (>= paredit-version 21)
  529. (define-key clojure-mode-map "{" 'paredit-open-curly)
  530. (define-key clojure-mode-map "}" 'paredit-close-curly)
  531. (add-to-list 'paredit-space-for-delimiter-predicates
  532. 'clojure-space-for-delimiter-p)
  533. (add-to-list 'paredit-space-for-delimiter-predicates
  534. 'clojure-no-space-after-tag)))))
  535. (defsubst clojure-in-docstring-p ()
  536. "Check whether point is in a docstring."
  537. (eq (get-text-property (1- (point-at-eol)) 'face)
  538. 'font-lock-doc-face))
  539. (defun clojure-adaptive-fill-function ()
  540. "Clojure adaptive fill function.
  541. This only takes care of filling docstring correctly."
  542. (if (clojure-in-docstring-p) " "))
  543. (defun clojure-fill-paragraph (&optional justify)
  544. (if (clojure-in-docstring-p)
  545. (let ((paragraph-start
  546. (concat paragraph-start
  547. "\\|\\s-*\\([(;:\"[]\\|~@\\|`(\\|#'(\\)"))
  548. (paragraph-separate
  549. (concat paragraph-separate "\\|\\s-*\".*[,\\.]$"))
  550. (fill-column (or clojure-docstring-fill-column fill-column))
  551. (fill-prefix " "))
  552. (fill-paragraph justify))
  553. (lisp-fill-paragraph justify)))
  554. (defun clojure-auto-fill-function ()
  555. "Clojure auto-fill function."
  556. ;; Check if auto-filling is meaningful.
  557. (let ((fc (current-fill-column)))
  558. (when (and fc (> (current-column) fc))
  559. (let ((fill-column (if (clojure-in-docstring-p)
  560. clojure-docstring-fill-column
  561. fill-column))
  562. (fill-prefix (clojure-adaptive-fill-function)))
  563. (when fill-prefix (do-auto-fill))))))
  564. (defun clojure-display-inferior-lisp-buffer ()
  565. "Display a buffer bound to `inferior-lisp-buffer'."
  566. (interactive)
  567. (if (and inferior-lisp-buffer (get-buffer inferior-lisp-buffer))
  568. (pop-to-buffer inferior-lisp-buffer t)
  569. (run-lisp inferior-lisp-program)))
  570. (defun clojure-load-file (file-name)
  571. "Load a Clojure file FILE-NAME into the inferior Clojure process."
  572. (interactive (comint-get-source "Load Clojure file: "
  573. clojure-prev-l/c-dir/file
  574. '(clojure-mode) t))
  575. (comint-check-source file-name) ; Check to see if buffer needs saved.
  576. (setq clojure-prev-l/c-dir/file (cons (file-name-directory file-name)
  577. (file-name-nondirectory file-name)))
  578. (comint-send-string (inferior-lisp-proc)
  579. (format clojure-load-command file-name))
  580. (switch-to-lisp t))
  581. (defun clojure-match-next-def ()
  582. "Scans the buffer backwards for the next top-level definition.
  583. Called by `imenu--generic-function'."
  584. (when (re-search-backward "^(def\\sw*" nil t)
  585. (save-excursion
  586. (let (found?
  587. (start (point)))
  588. (down-list)
  589. (forward-sexp)
  590. (while (not found?)
  591. (forward-sexp)
  592. (or (if (char-equal ?[ (char-after (point)))
  593. (backward-sexp))
  594. (if (char-equal ?) (char-after (point)))
  595. (backward-sexp)))
  596. (destructuring-bind (def-beg . def-end) (bounds-of-thing-at-point 'sexp)
  597. (if (char-equal ?^ (char-after def-beg))
  598. (progn (forward-sexp) (backward-sexp))
  599. (setq found? t)
  600. (set-match-data (list def-beg def-end)))))
  601. (goto-char start)))))
  602. (defun clojure-mode-font-lock-setup ()
  603. "Configures font-lock for editing Clojure code."
  604. (interactive)
  605. (setq-local font-lock-multiline t)
  606. (add-to-list 'font-lock-extend-region-functions
  607. 'clojure-font-lock-extend-region-def t)
  608. (when clojure-font-lock-comment-sexp
  609. (add-to-list 'font-lock-extend-region-functions
  610. 'clojure-font-lock-extend-region-comment t)
  611. (make-local-variable 'clojure-font-lock-keywords)
  612. (add-to-list 'clojure-font-lock-keywords
  613. 'clojure-font-lock-mark-comment t)
  614. (setq-local open-paren-in-column-0-is-defun-start nil))
  615. (setq font-lock-defaults
  616. '(clojure-font-lock-keywords ; keywords
  617. nil nil
  618. (("+-*/.<>=!?$%_&~^:@" . "w")) ; syntax alist
  619. nil
  620. (font-lock-mark-block-function . mark-defun)
  621. (font-lock-syntactic-face-function
  622. . lisp-font-lock-syntactic-face-function))))
  623. (defun clojure-font-lock-def-at-point (point)
  624. "Range between the top-most def* and the fourth element after POINT.
  625. Note that this means that there is no guarantee of proper font
  626. locking in def* forms that are not at top level."
  627. (goto-char point)
  628. (condition-case nil
  629. (beginning-of-defun)
  630. (error nil))
  631. (let ((beg-def (point)))
  632. (when (and (not (= point beg-def))
  633. (looking-at "(def"))
  634. (condition-case nil
  635. (progn
  636. ;; move forward as much as possible until failure (or success)
  637. (forward-char)
  638. (dotimes (i 4)
  639. (forward-sexp)))
  640. (error nil))
  641. (cons beg-def (point)))))
  642. (defun clojure-font-lock-extend-region-def ()
  643. "Set region boundaries to include the first four elements of def* forms."
  644. (let ((changed nil))
  645. (let ((def (clojure-font-lock-def-at-point font-lock-beg)))
  646. (when def
  647. (destructuring-bind (def-beg . def-end) def
  648. (when (and (< def-beg font-lock-beg)
  649. (< font-lock-beg def-end))
  650. (setq font-lock-beg def-beg
  651. changed t)))))
  652. (let ((def (clojure-font-lock-def-at-point font-lock-end)))
  653. (when def
  654. (destructuring-bind (def-beg . def-end) def
  655. (when (and (< def-beg font-lock-end)
  656. (< font-lock-end def-end))
  657. (setq font-lock-end def-end
  658. changed t)))))
  659. changed))
  660. (defun clojure-mode-font-lock-regexp-groups (bound)
  661. "Highlight grouping constructs in regular expression.
  662. BOUND denotes the maximum number of characters (relative to the
  663. point) to check."
  664. (catch 'found
  665. (while (re-search-forward (concat
  666. ;; A group may start using several alternatives:
  667. "\\(\\(?:"
  668. ;; 1. (? special groups
  669. "(\\?\\(?:"
  670. ;; a) non-capturing group (?:X)
  671. ;; b) independent non-capturing group (?>X)
  672. ;; c) zero-width positive lookahead (?=X)
  673. ;; d) zero-width negative lookahead (?!X)
  674. "[:=!>]\\|"
  675. ;; e) zero-width positive lookbehind (?<=X)
  676. ;; f) zero-width negative lookbehind (?<!X)
  677. "<[=!]\\|"
  678. ;; g) named capturing group (?<name>X)
  679. "<[[:alnum:]]+>"
  680. "\\)\\|" ;; end of special groups
  681. ;; 2. normal capturing groups (
  682. ;; 3. we also highlight alternative
  683. ;; separarators |, and closing parens )
  684. "[|()]"
  685. "\\)\\)") bound t)
  686. (let ((face (get-text-property (1- (point)) 'face)))
  687. (when (and (or (and (listp face)
  688. (memq 'font-lock-string-face face))
  689. (eq 'font-lock-string-face face))
  690. (clojure-string-start t))
  691. (throw 'found t))))))
  692. (defun clojure-find-block-comment-start (limit)
  693. "Search for (comment...) or #_ style block comments.
  694. Places point at the beginning of the expression.
  695. LIMIT denotes the maximum number of characters (relative to the
  696. point) to check."
  697. (let ((pos (re-search-forward "\\((comment\\>\\|#_\\)" limit t)))
  698. (when pos
  699. (forward-char (- (length (match-string 1))))
  700. pos)))
  701. (defun clojure-font-lock-extend-region-comment ()
  702. "Set region boundaries to contain (comment ..) and #_ sexp entirely.
  703. This does not work if there is a whitespace between an opening
  704. parenthesis and \"comment\", but this omission allows the
  705. function to run faster."
  706. (let ((changed nil))
  707. (goto-char font-lock-beg)
  708. (condition-case nil (beginning-of-defun) (error nil))
  709. (let ((pos (clojure-find-block-comment-start font-lock-end)))
  710. (when pos
  711. (when (< (point) font-lock-beg)
  712. (setq font-lock-beg (point)
  713. changed t))
  714. (condition-case nil (forward-sexp) (error nil))
  715. (when (> (point) font-lock-end)
  716. (setq font-lock-end (point)
  717. changed t))))
  718. changed))
  719. (defun clojure-font-lock-mark-comment (limit)
  720. "Mark all (comment ..) and #_ forms with `font-lock-comment-face'.
  721. LIMIT denotes the maximum number of characters (relative to the
  722. point) to check."
  723. (let (pos)
  724. (while (and (< (point) limit)
  725. (setq pos (clojure-find-block-comment-start limit)))
  726. (when pos
  727. (condition-case nil
  728. (add-text-properties (point)
  729. (progn
  730. (forward-sexp)
  731. (point))
  732. '(face font-lock-comment-face multiline t))
  733. (error (forward-char 8))))))
  734. nil)
  735. ;; Docstring positions
  736. (put 'ns 'clojure-doc-string-elt 2)
  737. (put 'def 'clojure-doc-string-elt 2)
  738. (put 'defn 'clojure-doc-string-elt 2)
  739. (put 'defn- 'clojure-doc-string-elt 2)
  740. (put 'defmulti 'clojure-doc-string-elt 2)
  741. (put 'defmacro 'clojure-doc-string-elt 2)
  742. (put 'definline 'clojure-doc-string-elt 2)
  743. (put 'defprotocol 'clojure-doc-string-elt 2)
  744. (defun clojure-forward-sexp (n)
  745. "Move forward across one balanced Clojure expression (sexp).
  746. It treats record literals like #user.Foo[1] and #user.Foo{:size 1}
  747. as a single sexp so that CIDER will send them properly.
  748. This behavior may not be intuitive when the user presses C-M-f, but
  749. since these are single objects this behavior is okay."
  750. (let ((dir (if (> n 0) 1 -1))
  751. (forward-sexp-function nil)) ; force the built-in version
  752. (while (not (zerop n))
  753. (forward-sexp dir)
  754. (when (save-excursion ; move back to see if we're in a record literal
  755. (and
  756. (condition-case nil
  757. (progn (backward-sexp) 't)
  758. ('scan-error nil))
  759. (looking-at "#\\w")))
  760. (forward-sexp dir)) ; if so, jump over it
  761. (setq n (- n dir)))))
  762. (defun clojure-indent-function (indent-point state)
  763. "This function is the normal value of the variable `lisp-indent-function'.
  764. It is used when indenting a line within a function call, to see if the
  765. called function says anything special about how to indent the line.
  766. INDENT-POINT is the position where the user typed TAB, or equivalent.
  767. Point is located at the point to indent under (for default indentation);
  768. STATE is the `parse-partial-sexp' state for that position.
  769. If the current line is in a call to a Lisp function
  770. which has a non-nil property `lisp-indent-function',
  771. that specifies how to do the indentation.
  772. The property value can be
  773. - `defun', meaning indent `defun'-style;
  774. - an integer N, meaning indent the first N arguments specially
  775. like ordinary function arguments and then indent any further
  776. arguments like a body;
  777. - a function to call just as this function was called.
  778. If that function returns nil, that means it doesn't specify
  779. the indentation.
  780. This function also returns nil meaning don't specify the indentation."
  781. (let ((normal-indent (current-column)))
  782. (goto-char (1+ (elt state 1)))
  783. (parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t)
  784. (if (and (elt state 2)
  785. (not (looking-at "\\sw\\|\\s_")))
  786. ;; car of form doesn't seem to be a symbol
  787. (progn
  788. (if (not (> (save-excursion (forward-line 1) (point))
  789. calculate-lisp-indent-last-sexp))
  790. (progn (goto-char calculate-lisp-indent-last-sexp)
  791. (beginning-of-line)
  792. (parse-partial-sexp (point)
  793. calculate-lisp-indent-last-sexp 0 t)))
  794. ;; Indent under the list or under the first sexp on the same
  795. ;; line as calculate-lisp-indent-last-sexp. Note that first
  796. ;; thing on that line has to be complete sexp since we are
  797. ;; inside the innermost containing sexp.
  798. (backward-prefix-chars)
  799. (if (and (eq (char-after (point)) ?\[)
  800. (eq (char-after (elt state 1)) ?\())
  801. (+ (current-column) 2) ;; this is probably inside a defn
  802. (current-column)))
  803. (let* ((function (buffer-substring (point)
  804. (progn (forward-sexp 1) (point))))
  805. (open-paren (elt state 1))
  806. (method nil)
  807. (function-tail (first
  808. (last
  809. (split-string (substring-no-properties function) "/")))))
  810. (setq method (get (intern-soft function-tail) 'clojure-indent-function))
  811. (cond ((member (char-after open-paren) '(?\[ ?\{))
  812. (goto-char open-paren)
  813. (1+ (current-column)))
  814. ((or (eq method 'defun)
  815. (and clojure-defun-style-default-indent
  816. ;; largely to preserve useful alignment of :require, etc in ns
  817. (not (string-match "^:" function))
  818. (not method))
  819. (and (null method)
  820. (> (length function) 3)
  821. (string-match "\\`\\(?:\\S +/\\)?\\(def\\|with-\\)"
  822. function)))
  823. (lisp-indent-defform state indent-point))
  824. ((integerp method)
  825. (lisp-indent-specform method state
  826. indent-point normal-indent))
  827. (method
  828. (funcall method indent-point state))
  829. (clojure-use-backtracking-indent
  830. (clojure-backtracking-indent
  831. indent-point state normal-indent)))))))
  832. (defun clojure-backtracking-indent (indent-point state normal-indent)
  833. "Experimental backtracking support.
  834. Will upwards in an sexp to check for contextual indenting."
  835. (let (indent (path) (depth 0))
  836. (goto-char (elt state 1))
  837. (while (and (not indent)
  838. (< depth clojure-max-backtracking))
  839. (let ((containing-sexp (point)))
  840. (parse-partial-sexp (1+ containing-sexp) indent-point 1 t)
  841. (when (looking-at "\\sw\\|\\s_")
  842. (let* ((start (point))
  843. (fn (buffer-substring start (progn (forward-sexp 1) (point))))
  844. (meth (get (intern-soft fn) 'clojure-backtracking-indent)))
  845. (let ((n 0))
  846. (when (< (point) indent-point)
  847. (condition-case ()
  848. (progn
  849. (forward-sexp 1)
  850. (while (< (point) indent-point)
  851. (parse-partial-sexp (point) indent-point 1 t)
  852. (incf n)
  853. (forward-sexp 1)))
  854. (error nil)))
  855. (push n path))
  856. (when meth
  857. (let ((def meth))
  858. (dolist (p path)
  859. (if (and (listp def)
  860. (< p (length def)))
  861. (setq def (nth p def))
  862. (if (listp def)
  863. (setq def (car (last def)))
  864. (setq def nil))))
  865. (goto-char (elt state 1))
  866. (when def
  867. (setq indent (+ (current-column) def)))))))
  868. (goto-char containing-sexp)
  869. (condition-case ()
  870. (progn
  871. (backward-up-list 1)
  872. (incf depth))
  873. (error (setq depth clojure-max-backtracking)))))
  874. indent))
  875. ;; clojure backtracking indent is experimental and the format for these
  876. ;; entries are subject to change
  877. (put 'implement 'clojure-backtracking-indent '(4 (2)))
  878. (put 'letfn 'clojure-backtracking-indent '((2) 2))
  879. (put 'proxy 'clojure-backtracking-indent '(4 4 (2)))
  880. (put 'reify 'clojure-backtracking-indent '((2)))
  881. (put 'deftype 'clojure-backtracking-indent '(4 4 (2)))
  882. (put 'defrecord 'clojure-backtracking-indent '(4 4 (2)))
  883. (put 'defprotocol 'clojure-backtracking-indent '(4 (2)))
  884. (put 'extend-type 'clojure-backtracking-indent '(4 (2)))
  885. (put 'extend-protocol 'clojure-backtracking-indent '(4 (2)))
  886. (put 'specify 'clojure-backtracking-indent '(4 (2)))
  887. (put 'specify! 'clojure-backtracking-indent '(4 (2)))
  888. (defun put-clojure-indent (sym indent)
  889. (put sym 'clojure-indent-function indent))
  890. (defmacro define-clojure-indent (&rest kvs)
  891. `(progn
  892. ,@(mapcar (lambda (x) `(put-clojure-indent
  893. (quote ,(first x)) ,(second x))) kvs)))
  894. (defun add-custom-clojure-indents (name value)
  895. (custom-set-default name value)
  896. (mapcar (lambda (x)
  897. (put-clojure-indent x 'defun))
  898. value))
  899. (defcustom clojure-defun-indents nil
  900. "List of additional symbols with defun-style indentation in Clojure.
  901. You can use this to let Emacs indent your own macros the same way
  902. that it indents built-in macros like with-open. To manually set
  903. it from Lisp code, use (put-clojure-indent 'some-symbol 'defun)."
  904. :type '(repeat symbol)
  905. :group 'clojure
  906. :set 'add-custom-clojure-indents)
  907. (define-clojure-indent
  908. ;; built-ins
  909. (ns 1)
  910. (fn 'defun)
  911. (def 'defun)
  912. (defn 'defun)
  913. (bound-fn 'defun)
  914. (if 1)
  915. (if-not 1)
  916. (case 1)
  917. (condp 2)
  918. (when 1)
  919. (while 1)
  920. (when-not 1)
  921. (when-first 1)
  922. (do 0)
  923. (future 0)
  924. (comment 0)
  925. (doto 1)
  926. (locking 1)
  927. (proxy 2)
  928. (with-open 1)
  929. (with-precision 1)
  930. (with-local-vars 1)
  931. (reify 'defun)
  932. (deftype 2)
  933. (defrecord 2)
  934. (defprotocol 1)
  935. (extend 1)
  936. (extend-protocol 1)
  937. (extend-type 1)
  938. (try 0)
  939. (catch 2)
  940. (finally 0)
  941. ;; binding forms
  942. (let 1)
  943. (letfn 1)
  944. (binding 1)
  945. (loop 1)
  946. (for 1)
  947. (doseq 1)
  948. (dotimes 1)
  949. (when-let 1)
  950. (if-let 1)
  951. (when-some 1)
  952. (if-some 1)
  953. ;; data structures
  954. (defstruct 1)
  955. (struct-map 1)
  956. (assoc 1)
  957. (defmethod 'defun)
  958. ;; clojure.test
  959. (testing 1)
  960. (deftest 'defun)
  961. (are 1)
  962. (use-fixtures 'defun)
  963. ;; core.logic
  964. (run 'defun)
  965. (run* 'defun)
  966. (fresh 'defun)
  967. ;; core.async
  968. (alt! 0)
  969. (alt!! 0)
  970. (go 0)
  971. (go-loop 1)
  972. (thread 0))
  973. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  974. ;;
  975. ;; Better docstring filling for clojure-mode
  976. ;;
  977. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  978. (defun clojure-string-start (&optional regex)
  979. "Return the position of the \" that begins the string at point.
  980. If REGEX is non-nil, return the position of the # that begins the
  981. regex at point. If point is not inside a string or regex, return
  982. nil."
  983. (when (nth 3 (syntax-ppss)) ;; Are we really in a string?
  984. (save-excursion
  985. (save-match-data
  986. ;; Find a quote that appears immediately after whitespace,
  987. ;; beginning of line, hash, or an open paren, brace, or bracket
  988. (re-search-backward "\\(\\s-\\|^\\|#\\|(\\|\\[\\|{\\)\\(\"\\)")
  989. (let ((beg (match-beginning 2)))
  990. (when beg
  991. (if regex
  992. (and (char-before beg) (char-equal ?# (char-before beg)) (1- beg))
  993. (when (not (char-equal ?# (char-before beg)))
  994. beg))))))))
  995. (defun clojure-char-at-point ()
  996. "Return the char at point or nil if at buffer end."
  997. (when (not (= (point) (point-max)))
  998. (buffer-substring-no-properties (point) (1+ (point)))))
  999. (defun clojure-char-before-point ()
  1000. "Return the char before point or nil if at buffer beginning."
  1001. (when (not (= (point) (point-min)))
  1002. (buffer-substring-no-properties (point) (1- (point)))))
  1003. ;; TODO: Deal with the fact that when point is exactly at the
  1004. ;; beginning of a string, it thinks that is the end.
  1005. (defun clojure-string-end ()
  1006. "Return the position of the \" that ends the string at point.
  1007. Note that point must be inside the string - if point is
  1008. positioned at the opening quote, incorrect results will be
  1009. returned."
  1010. (save-excursion
  1011. (save-match-data
  1012. ;; If we're at the end of the string, just return point.
  1013. (if (and (string= (clojure-char-at-point) "\"")
  1014. (not (string= (clojure-char-before-point) "\\")))
  1015. (point)
  1016. ;; We don't want to get screwed by starting out at the
  1017. ;; backslash in an escaped quote.
  1018. (when (string= (clojure-char-at-point) "\\")
  1019. (backward-char))
  1020. ;; Look for a quote not preceeded by a backslash
  1021. (re-search-forward "[^\\]\\\(\\\"\\)")
  1022. (match-beginning 1)))))
  1023. (defun clojure-mark-string ()
  1024. "Mark the string at point."
  1025. (interactive)
  1026. (goto-char (clojure-string-start))
  1027. (forward-char)
  1028. (set-mark (clojure-string-end)))
  1029. (defun clojure-toggle-keyword-string ()
  1030. "Convert the string or keyword at (point) from string->keyword or keyword->string."
  1031. (interactive)
  1032. (let ((original-point (point)))
  1033. (while (and (> (point) 1)
  1034. (not (equal "\"" (buffer-substring-no-properties (point) (+ 1 (point)))))
  1035. (not (equal ":" (buffer-substring-no-properties (point) (+ 1 (point))))))
  1036. (backward-char))
  1037. (cond
  1038. ((equal 1 (point))
  1039. (message "beginning of file reached, this was probably a mistake."))
  1040. ((equal "\"" (buffer-substring-no-properties (point) (+ 1 (point))))
  1041. (insert ":" (substring (clojure-delete-and-extract-sexp) 1 -1)))
  1042. ((equal ":" (buffer-substring-no-properties (point) (+ 1 (point))))
  1043. (insert "\"" (substring (clojure-delete-and-extract-sexp) 1) "\"")))
  1044. (goto-char original-point)))
  1045. (defun clojure-delete-and-extract-sexp ()
  1046. "Delete the sexp and return it."
  1047. (interactive)
  1048. (let ((begin (point)))
  1049. (forward-sexp)
  1050. (let ((result (buffer-substring-no-properties begin (point))))
  1051. (delete-region begin (point))
  1052. result)))
  1053. (defconst clojure-namespace-name-regex
  1054. (rx line-start
  1055. (zero-or-more whitespace)
  1056. "("
  1057. (zero-or-one (group (regexp "clojure.core/")))
  1058. (zero-or-one (submatch "in-"))
  1059. "ns"
  1060. (zero-or-one "+")
  1061. (one-or-more (any whitespace "\n"))
  1062. (zero-or-more (or (submatch (zero-or-one "#")
  1063. "^{"
  1064. (zero-or-more (not (any "}")))
  1065. "}")
  1066. (zero-or-more "^:"
  1067. (one-or-more (not (any whitespace)))))
  1068. (one-or-more (any whitespace "\n")))
  1069. ;; why is this here? oh (in-ns 'foo) or (ns+ :user)
  1070. (zero-or-one (any ":'"))
  1071. (group (one-or-more (not (any "()\"" whitespace))) word-end)))
  1072. ;; for testing clojure-namespace-name-regex, you can evaluate this code and make
  1073. ;; sure foo (or whatever the namespace name is) shows up in results. some of
  1074. ;; these currently fail.
  1075. ;; (mapcar (lambda (s) (let ((n (string-match clojure-namespace-name-regex s)))
  1076. ;; (if n (match-string 4 s))))
  1077. ;; '("(ns foo)"
  1078. ;; "(ns
  1079. ;; foo)"
  1080. ;; "(ns foo.baz)"
  1081. ;; "(ns ^:bar foo)"
  1082. ;; "(ns ^:bar ^:baz foo)"
  1083. ;; "(ns ^{:bar true} foo)"
  1084. ;; "(ns #^{:bar true} foo)"
  1085. ;; "(ns #^{:fail {}} foo)"
  1086. ;; "(ns ^{:fail2 {}} foo.baz)"
  1087. ;; "(ns ^{} foo)"
  1088. ;; "(ns ^{:skip-wiki true}
  1089. ;; aleph.netty
  1090. ;; "
  1091. ;; "(ns
  1092. ;; foo)"
  1093. ;; "foo"))
  1094. (defun clojure-expected-ns ()
  1095. "Return the namespace name that the file should have."
  1096. (let* ((project-dir (file-truename
  1097. (locate-dominating-file default-directory
  1098. "project.clj")))
  1099. (relative (substring (file-truename (buffer-file-name))
  1100. (length project-dir)
  1101. (- (length (file-name-extension (buffer-file-name) t))))))
  1102. (replace-regexp-in-string
  1103. "_" "-" (mapconcat 'identity (cdr (split-string relative "/")) "."))))
  1104. (defun clojure-insert-ns-form-at-point ()
  1105. "Insert a namespace form at point."
  1106. (interactive)
  1107. (insert (format "(ns %s)" (clojure-expected-ns))))
  1108. (defun clojure-insert-ns-form ()
  1109. "Insert a namespace form at the beginning of the buffer."
  1110. (interactive)
  1111. (goto-char (point-min))
  1112. (clojure-insert-ns-form-at-point))
  1113. (defun clojure-update-ns ()
  1114. "Update the namespace of the current buffer.
  1115. Useful if a file has been renamed."
  1116. (interactive)
  1117. (let ((nsname (clojure-expected-ns)))
  1118. (when nsname
  1119. (save-restriction
  1120. (save-excursion
  1121. (save-match-data
  1122. (if (clojure-find-ns)
  1123. (replace-match nsname nil nil nil 4)
  1124. (error "Namesp…

Large files files are truncated, but you can click here to view the full file