PageRenderTime 37ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/.emacs.d/lib/clojure-mode/clojure-mode.el

https://github.com/technomancy/dotfiles
Emacs Lisp | 2357 lines | 1892 code | 231 blank | 234 comment | 47 complexity | 0337fbff3e1039ed402e7c604228c70d MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0
  1. ;;; clojure-mode.el --- Major mode for Clojure code -*- lexical-binding: t; -*-
  2. ;; Copyright © 2007-2016 Jeffrey Chu, Lennart Staflin, Phil Hagelberg
  3. ;; Copyright © 2013-2016 Bozhidar Batsov, Artur Malabarba
  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. ;; Artur Malabarba <bruce.connor.am@gmail.com>
  10. ;; URL: http://github.com/clojure-emacs/clojure-mode
  11. ;; Keywords: languages clojure clojurescript lisp
  12. ;; Version: 5.6.0
  13. ;; Package-Requires: ((emacs "24.4"))
  14. ;; This file is not part of GNU Emacs.
  15. ;;; Commentary:
  16. ;; Provides font-lock, indentation, navigation and basic refactoring for the
  17. ;; Clojure programming language (http://clojure.org).
  18. ;; Using clojure-mode with paredit or smartparens is highly recommended.
  19. ;; Here are some example configurations:
  20. ;; ;; require or autoload paredit-mode
  21. ;; (add-hook 'clojure-mode-hook #'paredit-mode)
  22. ;; ;; require or autoload smartparens
  23. ;; (add-hook 'clojure-mode-hook #'smartparens-strict-mode)
  24. ;; See inf-clojure (http://github.com/clojure-emacs/inf-clojure) for
  25. ;; basic interaction with Clojure subprocesses.
  26. ;; See CIDER (http://github.com/clojure-emacs/cider) for
  27. ;; better interaction with subprocesses via nREPL.
  28. ;;; License:
  29. ;; This program is free software; you can redistribute it and/or
  30. ;; modify it under the terms of the GNU General Public License
  31. ;; as published by the Free Software Foundation; either version 3
  32. ;; of the License, or (at your option) any later version.
  33. ;;
  34. ;; This program is distributed in the hope that it will be useful,
  35. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  36. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  37. ;; GNU General Public License for more details.
  38. ;;
  39. ;; You should have received a copy of the GNU General Public License
  40. ;; along with GNU Emacs; see the file COPYING. If not, write to the
  41. ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  42. ;; Boston, MA 02110-1301, USA.
  43. ;;; Code:
  44. (eval-when-compile
  45. (defvar calculate-lisp-indent-last-sexp)
  46. (defvar font-lock-beg)
  47. (defvar font-lock-end)
  48. (defvar paredit-space-for-delimiter-predicates)
  49. (defvar paredit-version)
  50. (defvar paredit-mode))
  51. (require 'cl-lib)
  52. (require 'imenu)
  53. (require 'newcomment)
  54. (require 'align)
  55. (require 'subr-x)
  56. (declare-function lisp-fill-paragraph "lisp-mode" (&optional justify))
  57. (defgroup clojure nil
  58. "Major mode for editing Clojure code."
  59. :prefix "clojure-"
  60. :group 'languages
  61. :link '(url-link :tag "Github" "https://github.com/clojure-emacs/clojure-mode")
  62. :link '(emacs-commentary-link :tag "Commentary" "clojure-mode"))
  63. (defconst clojure-mode-version "5.5.2"
  64. "The current version of `clojure-mode'.")
  65. (defface clojure-keyword-face
  66. '((t (:inherit font-lock-constant-face)))
  67. "Face used to font-lock Clojure keywords (:something)."
  68. :package-version '(clojure-mode . "3.0.0"))
  69. (defface clojure-character-face
  70. '((t (:inherit font-lock-string-face)))
  71. "Face used to font-lock Clojure character literals."
  72. :package-version '(clojure-mode . "3.0.0"))
  73. (defface clojure-interop-method-face
  74. '((t (:inherit font-lock-preprocessor-face)))
  75. "Face used to font-lock interop method names (camelCase)."
  76. :package-version '(clojure-mode . "3.0.0"))
  77. (defcustom clojure-indent-style :always-align
  78. "Indentation style to use for function forms and macro forms.
  79. There are two cases of interest configured by this variable.
  80. - Case (A) is when at least one function argument is on the same
  81. line as the function name.
  82. - Case (B) is the opposite (no arguments are on the same line as
  83. the function name). Note that the body of macros is not
  84. affected by this variable, it is always indented by
  85. `lisp-body-indent' (default 2) spaces.
  86. Note that this variable configures the indentation of function
  87. forms (and function-like macros), it does not affect macros that
  88. already use special indentation rules.
  89. The possible values for this variable are keywords indicating how
  90. to indent function forms.
  91. `:always-align' - Follow the same rules as `lisp-mode'. All
  92. args are vertically aligned with the first arg in case (A),
  93. and vertically aligned with the function name in case (B).
  94. For instance:
  95. (reduce merge
  96. some-coll)
  97. (reduce
  98. merge
  99. some-coll)
  100. `:always-indent' - All args are indented like a macro body.
  101. (reduce merge
  102. some-coll)
  103. (reduce
  104. merge
  105. some-coll)
  106. `:align-arguments' - Case (A) is indented like `lisp', and
  107. case (B) is indented like a macro body.
  108. (reduce merge
  109. some-coll)
  110. (reduce
  111. merge
  112. some-coll)"
  113. :safe #'keywordp
  114. :type '(choice (const :tag "Same as `lisp-mode'" :always-align)
  115. (const :tag "Indent like a macro body" :always-indent)
  116. (const :tag "Indent like a macro body unless first arg is on the same line"
  117. :align-arguments))
  118. :package-version '(clojure-mode . "5.2.0"))
  119. (define-obsolete-variable-alias 'clojure-defun-style-default-indent
  120. 'clojure-indent-style "5.2.0")
  121. (defcustom clojure-use-backtracking-indent t
  122. "When non-nil, enable context sensitive indentation."
  123. :type 'boolean
  124. :safe 'booleanp)
  125. (defcustom clojure-max-backtracking 3
  126. "Maximum amount to backtrack up a list to check for context."
  127. :type 'integer
  128. :safe 'integerp)
  129. (defcustom clojure-docstring-fill-column fill-column
  130. "Value of `fill-column' to use when filling a docstring."
  131. :type 'integer
  132. :safe 'integerp)
  133. (defcustom clojure-docstring-fill-prefix-width 2
  134. "Width of `fill-prefix' when filling a docstring.
  135. The default value conforms with the de facto convention for
  136. Clojure docstrings, aligning the second line with the opening
  137. double quotes on the third column."
  138. :type 'integer
  139. :safe 'integerp)
  140. (defcustom clojure-omit-space-between-tag-and-delimiters '(?\[ ?\{)
  141. "Allowed opening delimiter characters after a reader literal tag.
  142. For example, \[ is allowed in :db/id[:db.part/user]."
  143. :type '(set (const :tag "[" ?\[)
  144. (const :tag "{" ?\{)
  145. (const :tag "(" ?\()
  146. (const :tag "\"" ?\"))
  147. :safe (lambda (value)
  148. (and (listp value)
  149. (cl-every 'characterp value))))
  150. (defcustom clojure-build-tool-files '("project.clj" "build.boot" "build.gradle")
  151. "A list of files, which identify a Clojure project's root.
  152. Out-of-the box clojure-mode understands lein, boot and gradle."
  153. :type '(repeat string)
  154. :package-version '(clojure-mode . "5.0.0")
  155. :safe (lambda (value)
  156. (and (listp value)
  157. (cl-every 'stringp value))))
  158. (defcustom clojure-refactor-map-prefix (kbd "C-c C-r")
  159. "Clojure refactor keymap prefix."
  160. :group 'clojure
  161. :type 'string
  162. :package-version '(clojure-mode . "5.6.0"))
  163. (defvar clojure-refactor-map
  164. (let ((map (make-sparse-keymap)))
  165. (define-key map (kbd "C-t") #'clojure-thread)
  166. (define-key map (kbd "t") #'clojure-thread)
  167. (define-key map (kbd "C-u") #'clojure-unwind)
  168. (define-key map (kbd "u") #'clojure-unwind)
  169. (define-key map (kbd "C-f") #'clojure-thread-first-all)
  170. (define-key map (kbd "f") #'clojure-thread-first-all)
  171. (define-key map (kbd "C-l") #'clojure-thread-last-all)
  172. (define-key map (kbd "l") #'clojure-thread-last-all)
  173. (define-key map (kbd "C-a") #'clojure-unwind-all)
  174. (define-key map (kbd "a") #'clojure-unwind-all)
  175. (define-key map (kbd "C-p") #'clojure-cycle-privacy)
  176. (define-key map (kbd "p") #'clojure-cycle-privacy)
  177. (define-key map (kbd "C-(") #'clojure-convert-collection-to-list)
  178. (define-key map (kbd "(") #'clojure-convert-collection-to-list)
  179. (define-key map (kbd "C-'") #'clojure-convert-collection-to-quoted-list)
  180. (define-key map (kbd "'") #'clojure-convert-collection-to-quoted-list)
  181. (define-key map (kbd "C-{") #'clojure-convert-collection-to-map)
  182. (define-key map (kbd "{") #'clojure-convert-collection-to-map)
  183. (define-key map (kbd "C-[") #'clojure-convert-collection-to-vector)
  184. (define-key map (kbd "[") #'clojure-convert-collection-to-vector)
  185. (define-key map (kbd "C-#") #'clojure-convert-collection-to-set)
  186. (define-key map (kbd "#") #'clojure-convert-collection-to-set)
  187. (define-key map (kbd "C-i") #'clojure-cycle-if)
  188. (define-key map (kbd "i") #'clojure-cycle-if)
  189. (define-key map (kbd "n i") #'clojure-insert-ns-form)
  190. (define-key map (kbd "n h") #'clojure-insert-ns-form-at-point)
  191. (define-key map (kbd "n u") #'clojure-update-ns)
  192. (define-key map (kbd "n s") #'clojure-sort-ns)
  193. (define-key map (kbd "s i") #'clojure-introduce-let)
  194. (define-key map (kbd "s m") #'clojure-move-to-let)
  195. (define-key map (kbd "s f") #'clojure-let-forward-slurp-sexp)
  196. (define-key map (kbd "s b") #'clojure-let-backward-slurp-sexp)
  197. map)
  198. "Keymap for Clojure refactoring commands.")
  199. (fset 'clojure-refactor-map clojure-refactor-map)
  200. (defvar clojure-mode-map
  201. (let ((map (make-sparse-keymap)))
  202. (define-key map (kbd "C-:") #'clojure-toggle-keyword-string)
  203. (define-key map (kbd "C-c SPC") #'clojure-align)
  204. (define-key map clojure-refactor-map-prefix 'clojure-refactor-map)
  205. (easy-menu-define clojure-mode-menu map "Clojure Mode Menu"
  206. '("Clojure"
  207. ["Toggle between string & keyword" clojure-toggle-keyword-string]
  208. ["Align expression" clojure-align]
  209. ["Cycle privacy" clojure-cycle-privacy]
  210. ["Cycle if, if-not" clojure-cycle-if]
  211. ("ns forms"
  212. ["Insert ns form at the top" clojure-insert-ns-form]
  213. ["Insert ns form here" clojure-insert-ns-form-at-point]
  214. ["Update ns form" clojure-update-ns]
  215. ["Sort ns form" clojure-sort-ns])
  216. ("Convert collection"
  217. ["Convert to list" clojure-convert-collection-to-list]
  218. ["Convert to quoted list" clojure-convert-collection-to-quoted-list]
  219. ["Convert to map" clojure-convert-collection-to-map]
  220. ["Convert to vector" clojure-convert-collection-to-vector]
  221. ["Convert to set" clojure-convert-collection-to-set])
  222. ("Refactor -> and ->>"
  223. ["Thread once more" clojure-thread]
  224. ["Fully thread a form with ->" clojure-thread-first-all]
  225. ["Fully thread a form with ->>" clojure-thread-last-all]
  226. "--"
  227. ["Unwind once" clojure-unwind]
  228. ["Fully unwind a threading macro" clojure-unwind-all])
  229. ("Let expression"
  230. ["Introduce let" clojure-introduce-let]
  231. ["Move to let" clojure-move-to-let]
  232. ["Forward slurp form into let" clojure-let-forward-slurp-sexp]
  233. ["Backward slurp form into let" clojure-let-backward-slurp-sexp])
  234. ("Documentation"
  235. ["View a Clojure guide" clojure-view-guide]
  236. ["View a Clojure reference section" clojure-view-reference-section]
  237. ["View the Clojure cheatsheet" clojure-view-cheatsheet]
  238. ["View the Clojure Grimoire" clojure-view-grimoire]
  239. ["View the Clojure style guide" clojure-view-style-guide])
  240. "--"
  241. ["Report a clojure-mode bug" clojure-mode-report-bug]
  242. ["Clojure-mode version" clojure-mode-display-version]))
  243. map)
  244. "Keymap for Clojure mode.")
  245. (defvar clojure-mode-syntax-table
  246. (let ((table (copy-syntax-table emacs-lisp-mode-syntax-table)))
  247. (modify-syntax-entry ?\{ "(}" table)
  248. (modify-syntax-entry ?\} "){" table)
  249. (modify-syntax-entry ?\[ "(]" table)
  250. (modify-syntax-entry ?\] ")[" table)
  251. (modify-syntax-entry ?? "_ p" table) ; ? is a prefix outside symbols
  252. (modify-syntax-entry ?# "_ p" table) ; # is allowed inside keywords (#399)
  253. (modify-syntax-entry ?~ "'" table)
  254. (modify-syntax-entry ?^ "'" table)
  255. (modify-syntax-entry ?@ "'" table)
  256. table)
  257. "Syntax table for Clojure mode.
  258. Inherits from `emacs-lisp-mode-syntax-table'.")
  259. (defconst clojure--prettify-symbols-alist
  260. '(("fn" . ?λ)))
  261. (defvar-local clojure-expected-ns-function nil
  262. "The function used to determine the expected namespace of a file.
  263. `clojure-mode' ships a basic function named `clojure-expected-ns'
  264. that does basic heuristics to figure this out.
  265. CIDER provides a more complex version which does classpath analysis.")
  266. (defun clojure-mode-display-version ()
  267. "Display the current `clojure-mode-version' in the minibuffer."
  268. (interactive)
  269. (message "clojure-mode (version %s)" clojure-mode-version))
  270. (defconst clojure-mode-report-bug-url "https://github.com/clojure-emacs/clojure-mode/issues/new"
  271. "The URL to report a clojure-mode issue.")
  272. (defun clojure-mode-report-bug ()
  273. "Report a bug in your default browser."
  274. (interactive)
  275. (browse-url clojure-mode-report-bug-url))
  276. (defconst clojure-guides-base-url "https://clojure.org/guides/"
  277. "The base URL for official Clojure guides.")
  278. (defconst clojure-guides '(("Getting Started" . "getting_started")
  279. ("FAQ" . "faq")
  280. ("spec" . "spec")
  281. ("Destructuring" . "destructuring")
  282. ("Threading Macros" . "threading_macros")
  283. ("Comparators" . "comparators")
  284. ("Reader Conditionals" . "reader_conditionals"))
  285. "A list of all official Clojure guides.")
  286. (defun clojure-view-guide ()
  287. "Open a Clojure guide in your default browser.
  288. The command will prompt you to select one of the available guides."
  289. (interactive)
  290. (let ((guide (completing-read "Select a guide: " (mapcar #'car clojure-guides))))
  291. (when guide
  292. (let ((guide-url (concat clojure-guides-base-url (cdr (assoc guide clojure-guides)))))
  293. (browse-url guide-url)))))
  294. (defconst clojure-reference-base-url "https://clojure.org/reference/"
  295. "The base URL for the official Clojure reference.")
  296. (defconst clojure-reference-sections '(("The Reader" . "reader")
  297. ("The REPL and main" . "repl_and_main")
  298. ("Evaluation" . "evaluation")
  299. ("Special Forms" . "special_forms")
  300. ("Macros" . "macros")
  301. ("Other Functions" . "other_functions")
  302. ("Data Structures" . "data_structures")
  303. ("Datatypes" . "datatypes")
  304. ("Sequences" . "sequences")
  305. ("Transients" . "transients")
  306. ("Transducers" . "transducers")
  307. ("Multimethods and Hierarchies" . "multimethods")
  308. ("Protocols" . "protocols")
  309. ("Metadata" . "metadata")
  310. ("Namespaces" . "namespaces")
  311. ("Libs" . "libs")
  312. ("Vars and Environments" . "vars")
  313. ("Refs and Transactions" . "refs")
  314. ("Agents" . "agents")
  315. ("Atoms" . "atoms")
  316. ("Reducers" . "reducers")
  317. ("Java Interop" . "java_interop")
  318. ("Compilation and Class Generation" . "compilation")
  319. ("Other Libraries" . "other_libraries")
  320. ("Differences with Lisps" . "lisps")))
  321. (defun clojure-view-reference-section ()
  322. "Open a Clojure reference section in your default browser.
  323. The command will prompt you to select one of the available sections."
  324. (interactive)
  325. (let ((section (completing-read "Select a reference section: " (mapcar #'car clojure-reference-sections))))
  326. (when section
  327. (let ((section-url (concat clojure-reference-base-url (cdr (assoc section clojure-reference-sections)))))
  328. (browse-url section-url)))))
  329. (defconst clojure-cheatsheet-url "http://clojure.org/api/cheatsheet"
  330. "The URL of the official Clojure cheatsheet.")
  331. (defun clojure-view-cheatsheet ()
  332. "Open the Clojure cheatsheet in your default browser."
  333. (interactive)
  334. (browse-url clojure-cheatsheet-url))
  335. (defconst clojure-grimoire-url "https://www.conj.io/"
  336. "The URL of the Grimoire community documentation site.")
  337. (defun clojure-view-grimoire ()
  338. "Open the Clojure Grimoire in your default browser."
  339. (interactive)
  340. (browse-url clojure-grimoire-url))
  341. (defconst clojure-style-guide-url "https://github.com/bbatsov/clojure-style-guide"
  342. "The URL of the Clojure style guide.")
  343. (defun clojure-view-style-guide ()
  344. "Open the Clojure style guide in your default browser."
  345. (interactive)
  346. (browse-url clojure-style-guide-url))
  347. (defun clojure-space-for-delimiter-p (endp delim)
  348. "Prevent paredit from inserting useless spaces.
  349. See `paredit-space-for-delimiter-predicates' for the meaning of
  350. ENDP and DELIM."
  351. (or endp
  352. (not (memq delim '(?\" ?{ ?\( )))
  353. (not (or (derived-mode-p 'clojure-mode)
  354. (derived-mode-p 'cider-repl-mode)))
  355. (save-excursion
  356. (backward-char)
  357. (cond ((eq (char-after) ?#)
  358. (and (not (bobp))
  359. (or (char-equal ?w (char-syntax (char-before)))
  360. (char-equal ?_ (char-syntax (char-before))))))
  361. ((and (eq delim ?\()
  362. (eq (char-after) ??)
  363. (eq (char-before) ?#))
  364. nil)
  365. (t)))))
  366. (defun clojure-no-space-after-tag (endp delimiter)
  367. "Prevent inserting a space after a reader-literal tag?
  368. When a reader-literal tag is followed be an opening delimiter
  369. listed in `clojure-omit-space-between-tag-and-delimiters', this
  370. function returns t.
  371. This allows you to write things like #db/id[:db.part/user]
  372. without inserting a space between the tag and the opening
  373. bracket.
  374. See `paredit-space-for-delimiter-predicates' for the meaning of
  375. ENDP and DELIMITER."
  376. (if endp
  377. t
  378. (or (not (member delimiter clojure-omit-space-between-tag-and-delimiters))
  379. (save-excursion
  380. (let ((orig-point (point)))
  381. (not (and (re-search-backward
  382. "#\\([a-zA-Z0-9._-]+/\\)?[a-zA-Z0-9._-]+"
  383. (line-beginning-position)
  384. t)
  385. (= orig-point (match-end 0)))))))))
  386. (declare-function paredit-open-curly "ext:paredit")
  387. (declare-function paredit-close-curly "ext:paredit")
  388. (declare-function paredit-convolute-sexp "ext:paredit")
  389. (defun clojure--replace-let-bindings-and-indent (orig-fun &rest args)
  390. "Advise `paredit-convolute-sexp' to replace s-expressions with their bound name if a let form was convoluted."
  391. (save-excursion
  392. (backward-sexp)
  393. (when (looking-back clojure--let-regexp)
  394. (clojure--replace-sexps-with-bindings-and-indent))))
  395. (defun clojure-paredit-setup (&optional keymap)
  396. "Make \"paredit-mode\" play nice with `clojure-mode'.
  397. If an optional KEYMAP is passed the changes are applied to it,
  398. instead of to `clojure-mode-map'.
  399. Also advice `paredit-convolute-sexp' when used on a let form as drop in
  400. replacement for `cljr-expand-let`."
  401. (when (>= paredit-version 21)
  402. (let ((keymap (or keymap clojure-mode-map)))
  403. (define-key keymap "{" #'paredit-open-curly)
  404. (define-key keymap "}" #'paredit-close-curly))
  405. (add-to-list 'paredit-space-for-delimiter-predicates
  406. #'clojure-space-for-delimiter-p)
  407. (add-to-list 'paredit-space-for-delimiter-predicates
  408. #'clojure-no-space-after-tag)
  409. (advice-add 'paredit-convolute-sexp :after #'clojure--replace-let-bindings-and-indent)))
  410. (defun clojure-mode-variables ()
  411. "Set up initial buffer-local variables for Clojure mode."
  412. (add-to-list 'imenu-generic-expression '(nil clojure-match-next-def 0))
  413. (setq-local indent-tabs-mode nil)
  414. (setq-local paragraph-ignore-fill-prefix t)
  415. (setq-local outline-regexp ";;;\\(;* [^ \t\n]\\)\\|(")
  416. (setq-local outline-level 'lisp-outline-level)
  417. (setq-local comment-start ";")
  418. (setq-local comment-start-skip ";+ *")
  419. (setq-local comment-add 1) ; default to `;;' in comment-region
  420. (setq-local comment-column 40)
  421. (setq-local comment-use-syntax t)
  422. (setq-local multibyte-syntax-as-symbol t)
  423. (setq-local electric-pair-skip-whitespace 'chomp)
  424. (setq-local electric-pair-open-newline-between-pairs nil)
  425. (setq-local fill-paragraph-function #'clojure-fill-paragraph)
  426. (setq-local adaptive-fill-function #'clojure-adaptive-fill-function)
  427. (setq-local normal-auto-fill-function #'clojure-auto-fill-function)
  428. (setq-local comment-start-skip
  429. "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\)\\(;+\\|#|\\) *")
  430. (setq-local indent-line-function #'clojure-indent-line)
  431. (setq-local indent-region-function #'clojure-indent-region)
  432. (setq-local lisp-indent-function #'clojure-indent-function)
  433. (setq-local lisp-doc-string-elt-property 'clojure-doc-string-elt)
  434. (setq-local clojure-expected-ns-function #'clojure-expected-ns)
  435. (setq-local parse-sexp-ignore-comments t)
  436. (setq-local prettify-symbols-alist clojure--prettify-symbols-alist)
  437. (setq-local open-paren-in-column-0-is-defun-start nil))
  438. ;;;###autoload
  439. (define-derived-mode clojure-mode prog-mode "Clojure"
  440. "Major mode for editing Clojure code.
  441. \\{clojure-mode-map}"
  442. (clojure-mode-variables)
  443. (clojure-font-lock-setup)
  444. (add-hook 'paredit-mode-hook #'clojure-paredit-setup))
  445. (defcustom clojure-verify-major-mode t
  446. "If non-nil, warn when activating the wrong major-mode."
  447. :type 'boolean
  448. :safe #'booleanp
  449. :package-version '(clojure-mode "5.3.0"))
  450. (defun clojure--check-wrong-major-mode ()
  451. "Check if the current major-mode matches the file extension.
  452. If it doesn't, issue a warning if `clojure-verify-major-mode' is
  453. non-nil."
  454. (when (and clojure-verify-major-mode
  455. (stringp (buffer-file-name)))
  456. (let* ((case-fold-search t)
  457. (problem (cond ((and (string-match "\\.clj\\'" (buffer-file-name))
  458. (not (eq major-mode 'clojure-mode)))
  459. 'clojure-mode)
  460. ((and (string-match "\\.cljs\\'" (buffer-file-name))
  461. (not (eq major-mode 'clojurescript-mode)))
  462. 'clojurescript-mode)
  463. ((and (string-match "\\.cljc\\'" (buffer-file-name))
  464. (not (eq major-mode 'clojurec-mode)))
  465. 'clojurec-mode)
  466. ((and (string-match "\\.cljx\\'" (buffer-file-name))
  467. (not (eq major-mode 'clojurex-mode)))
  468. 'clojurex-mode))))
  469. (when problem
  470. (message "[WARNING] %s activated `%s' instead of `%s' in this buffer.
  471. This could cause problems.
  472. \(See `clojure-verify-major-mode' to disable this message.)"
  473. (if (eq major-mode real-this-command)
  474. "You have"
  475. "Something in your configuration")
  476. major-mode
  477. problem)))))
  478. (add-hook 'clojure-mode-hook #'clojure--check-wrong-major-mode)
  479. (defsubst clojure-in-docstring-p ()
  480. "Check whether point is in a docstring."
  481. (eq (get-text-property (point) 'face) 'font-lock-doc-face))
  482. (defsubst clojure-docstring-fill-prefix ()
  483. "The prefix string used by `clojure-fill-paragraph'.
  484. It is simply `clojure-docstring-fill-prefix-width' number of spaces."
  485. (make-string clojure-docstring-fill-prefix-width ? ))
  486. (defun clojure-adaptive-fill-function ()
  487. "Clojure adaptive fill function.
  488. This only takes care of filling docstring correctly."
  489. (when (clojure-in-docstring-p)
  490. (clojure-docstring-fill-prefix)))
  491. (defun clojure-fill-paragraph (&optional justify)
  492. "Like `fill-paragraph', but can handle Clojure docstrings.
  493. If JUSTIFY is non-nil, justify as well as fill the paragraph."
  494. (if (clojure-in-docstring-p)
  495. (let ((paragraph-start
  496. (concat paragraph-start
  497. "\\|\\s-*\\([(;:\"[]\\|~@\\|`(\\|#'(\\)"))
  498. (paragraph-separate
  499. (concat paragraph-separate "\\|\\s-*\".*[,\\.]$"))
  500. (fill-column (or clojure-docstring-fill-column fill-column))
  501. (fill-prefix (clojure-docstring-fill-prefix)))
  502. (fill-paragraph justify))
  503. (let ((paragraph-start (concat paragraph-start
  504. "\\|\\s-*\\([(;:\"[]\\|`(\\|#'(\\)"))
  505. (paragraph-separate
  506. (concat paragraph-separate "\\|\\s-*\".*[,\\.[]$")))
  507. (or (fill-comment-paragraph justify)
  508. (fill-paragraph justify))
  509. ;; Always return `t'
  510. t)))
  511. (defun clojure-auto-fill-function ()
  512. "Clojure auto-fill function."
  513. ;; Check if auto-filling is meaningful.
  514. (let ((fc (current-fill-column)))
  515. (when (and fc (> (current-column) fc))
  516. (let ((fill-column (if (clojure-in-docstring-p)
  517. clojure-docstring-fill-column
  518. fill-column))
  519. (fill-prefix (clojure-adaptive-fill-function)))
  520. (do-auto-fill)))))
  521. ;;; #_ comments font-locking
  522. ;; Code heavily borrowed from Slime.
  523. ;; https://github.com/slime/slime/blob/master/contrib/slime-fontifying-fu.el#L186
  524. (defvar clojure--comment-macro-regexp
  525. (rx "#_" (* " ") (group-n 1 (not (any " "))))
  526. "Regexp matching the start of a comment sexp.
  527. The beginning of match-group 1 should be before the sexp to be
  528. marked as a comment. The end of sexp is found with
  529. `clojure-forward-logical-sexp'.
  530. By default, this only applies to code after the `#_' reader
  531. macro. In order to also font-lock the `(comment ...)' macro as a
  532. comment, you can set the value to:
  533. \"#_ *\\\\(?1:[^ ]\\\\)\\\\|\\\\(?1:(comment\\\\_>\\\\)\"")
  534. (defun clojure--search-comment-macro-internal (limit)
  535. (when (search-forward-regexp clojure--comment-macro-regexp limit t)
  536. (let* ((md (match-data))
  537. (start (match-beginning 1))
  538. (state (syntax-ppss start)))
  539. ;; inside string or comment?
  540. (if (or (nth 3 state)
  541. (nth 4 state))
  542. (clojure--search-comment-macro-internal limit)
  543. (goto-char start)
  544. (clojure-forward-logical-sexp 1)
  545. ;; Data for (match-end 1).
  546. (setf (elt md 3) (point))
  547. (set-match-data md)
  548. t))))
  549. (defun clojure--search-comment-macro (limit)
  550. "Find comment macros and set the match data.
  551. Search from point up to LIMIT. The region that should be
  552. considered a comment is between `(match-beginning 1)'
  553. and `(match-end 1)'."
  554. (let ((result 'retry))
  555. (while (and (eq result 'retry) (<= (point) limit))
  556. (condition-case nil
  557. (setq result (clojure--search-comment-macro-internal limit))
  558. (end-of-file (setq result nil))
  559. (scan-error (setq result 'retry))))
  560. result))
  561. ;;; General font-locking
  562. (defun clojure-match-next-def ()
  563. "Scans the buffer backwards for the next \"top-level\" definition.
  564. Called by `imenu--generic-function'."
  565. ;; we have to take into account namespace-definition forms
  566. ;; e.g. s/defn
  567. (when (re-search-backward "^(\\([a-z0-9.-]+/\\)?def\\sw*" nil t)
  568. (save-excursion
  569. (let (found?
  570. (start (point)))
  571. (down-list)
  572. (forward-sexp)
  573. (while (not found?)
  574. (forward-sexp)
  575. (or (if (char-equal ?[ (char-after (point)))
  576. (backward-sexp))
  577. (if (char-equal ?) (char-after (point)))
  578. (backward-sexp)))
  579. (cl-destructuring-bind (def-beg . def-end) (bounds-of-thing-at-point 'sexp)
  580. (if (char-equal ?^ (char-after def-beg))
  581. (progn (forward-sexp) (backward-sexp))
  582. (setq found? t)
  583. (set-match-data (list def-beg def-end)))))
  584. (goto-char start)))))
  585. (eval-and-compile
  586. (defconst clojure--sym-forbidden-rest-chars "][\";\'@\\^`~\(\)\{\}\\,\s\t\n\r"
  587. "A list of chars that a Clojure symbol cannot contain.
  588. See definition of 'macros': URL `http://git.io/vRGLD'.")
  589. (defconst clojure--sym-forbidden-1st-chars (concat clojure--sym-forbidden-rest-chars "0-9:")
  590. "A list of chars that a Clojure symbol cannot start with.
  591. See the for-loop: URL `http://git.io/vRGTj' lines: URL
  592. `http://git.io/vRGIh', URL `http://git.io/vRGLE' and value
  593. definition of 'macros': URL `http://git.io/vRGLD'.")
  594. (defconst clojure--sym-regexp
  595. (concat "[^" clojure--sym-forbidden-1st-chars "][^" clojure--sym-forbidden-rest-chars "]*")
  596. "A regexp matching a Clojure symbol or namespace alias.
  597. Matches the rule `clojure--sym-forbidden-1st-chars' followed by
  598. any number of matches of `clojure--sym-forbidden-rest-chars'."))
  599. (defconst clojure-font-lock-keywords
  600. (eval-when-compile
  601. `( ;; Top-level variable definition
  602. (,(concat "(\\(?:clojure.core/\\)?\\("
  603. (regexp-opt '("def" "defonce"))
  604. ;; variable declarations
  605. "\\)\\>"
  606. ;; Any whitespace
  607. "[ \r\n\t]*"
  608. ;; Possibly type or metadata
  609. "\\(?:#?^\\(?:{[^}]*}\\|\\sw+\\)[ \r\n\t]*\\)*"
  610. "\\(\\sw+\\)?")
  611. (1 font-lock-keyword-face)
  612. (2 font-lock-variable-name-face nil t))
  613. ;; Type definition
  614. (,(concat "(\\(?:clojure.core/\\)?\\("
  615. (regexp-opt '("defstruct" "deftype" "defprotocol"
  616. "defrecord"))
  617. ;; type declarations
  618. "\\)\\>"
  619. ;; Any whitespace
  620. "[ \r\n\t]*"
  621. ;; Possibly type or metadata
  622. "\\(?:#?^\\(?:{[^}]*}\\|\\sw+\\)[ \r\n\t]*\\)*"
  623. "\\(\\sw+\\)?")
  624. (1 font-lock-keyword-face)
  625. (2 font-lock-type-face nil t))
  626. ;; Function definition (anything that starts with def and is not
  627. ;; listed above)
  628. (,(concat "(\\(?:" clojure--sym-regexp "/\\)?"
  629. "\\(def[^ \r\n\t]*\\)"
  630. ;; Function declarations
  631. "\\>"
  632. ;; Any whitespace
  633. "[ \r\n\t]*"
  634. ;; Possibly type or metadata
  635. "\\(?:#?^\\(?:{[^}]*}\\|\\sw+\\)[ \r\n\t]*\\)*"
  636. "\\(\\sw+\\)?")
  637. (1 font-lock-keyword-face)
  638. (2 font-lock-function-name-face nil t))
  639. ;; (fn name? args ...)
  640. (,(concat "(\\(?:clojure.core/\\)?\\(fn\\)[ \t]+"
  641. ;; Possibly type
  642. "\\(?:#?^\\sw+[ \t]*\\)?"
  643. ;; Possibly name
  644. "\\(\\sw+\\)?" )
  645. (1 font-lock-keyword-face)
  646. (2 font-lock-function-name-face nil t))
  647. ;; lambda arguments - %, %&, %1, %2, etc
  648. ("\\<%[&1-9]?" (0 font-lock-variable-name-face))
  649. ;; Special forms
  650. (,(concat
  651. "("
  652. (regexp-opt
  653. '("def" "do" "if" "let" "let*" "var" "fn" "fn*" "loop" "loop*"
  654. "recur" "throw" "try" "catch" "finally"
  655. "set!" "new" "."
  656. "monitor-enter" "monitor-exit" "quote") t)
  657. "\\>")
  658. 1 font-lock-keyword-face)
  659. ;; Built-in binding and flow of control forms
  660. (,(concat
  661. "(\\(?:clojure.core/\\)?"
  662. (regexp-opt
  663. '("letfn" "case" "cond" "cond->" "cond->>" "condp"
  664. "for" "when" "when-not" "when-let" "when-first" "when-some"
  665. "if-let" "if-not" "if-some"
  666. ".." "->" "->>" "as->" "doto" "and" "or"
  667. "dosync" "doseq" "dotimes" "dorun" "doall"
  668. "ns" "in-ns"
  669. "with-open" "with-local-vars" "binding"
  670. "with-redefs" "with-redefs-fn"
  671. "declare") t)
  672. "\\>")
  673. 1 font-lock-keyword-face)
  674. ;; Macros similar to let, when, and while
  675. (,(rx symbol-start
  676. (or "let" "when" "while") "-"
  677. (1+ (or (syntax word) (syntax symbol)))
  678. symbol-end)
  679. 0 font-lock-keyword-face)
  680. (,(concat
  681. "\\<"
  682. (regexp-opt
  683. '("*1" "*2" "*3" "*agent*"
  684. "*allow-unresolved-vars*" "*assert*" "*clojure-version*"
  685. "*command-line-args*" "*compile-files*"
  686. "*compile-path*" "*data-readers*" "*default-data-reader-fn*"
  687. "*e" "*err*" "*file*" "*flush-on-newline*"
  688. "*in*" "*macro-meta*" "*math-context*" "*ns*" "*out*"
  689. "*print-dup*" "*print-length*" "*print-level*"
  690. "*print-meta*" "*print-readably*"
  691. "*read-eval*" "*source-path*"
  692. "*unchecked-math*"
  693. "*use-context-classloader*" "*warn-on-reflection*")
  694. t)
  695. "\\>")
  696. 0 font-lock-builtin-face)
  697. ;; Dynamic variables - *something* or @*something*
  698. ("\\(?:\\<\\|/\\)@?\\(\\*[a-z-]*\\*\\)\\>" 1 font-lock-variable-name-face)
  699. ;; Global constants - nil, true, false
  700. (,(concat
  701. "\\<"
  702. (regexp-opt
  703. '("true" "false" "nil") t)
  704. "\\>")
  705. 0 font-lock-constant-face)
  706. ;; Character literals - \1, \a, \newline, \u0000
  707. ("\\\\\\([[:punct:]]\\|[a-z0-9]+\\>\\)" 0 'clojure-character-face)
  708. ;; foo/ Foo/ @Foo/ /FooBar
  709. (,(concat "\\(?:\\<:?\\|\\.\\)@?\\(" clojure--sym-regexp "\\)\\(/\\)")
  710. (1 font-lock-type-face) (2 'default))
  711. ;; Constant values (keywords), including as metadata e.g. ^:static
  712. ("\\<^?\\(:\\(\\sw\\|\\s_\\)+\\(\\>\\|\\_>\\)\\)" 1 'clojure-keyword-face append)
  713. ;; Java interop highlighting
  714. ;; CONST SOME_CONST (optionally prefixed by /)
  715. ("\\(?:\\<\\|/\\)\\([A-Z]+\\|\\([A-Z]+_[A-Z1-9_]+\\)\\)\\>" 1 font-lock-constant-face)
  716. ;; .foo .barBaz .qux01 .-flibble .-flibbleWobble
  717. ("\\<\\.-?[a-z][a-zA-Z0-9]*\\>" 0 'clojure-interop-method-face)
  718. ;; Foo Bar$Baz Qux_ World_OpenUDP Foo. Babylon15.
  719. ("\\(?:\\<\\|\\.\\|/\\|#?^\\)\\([A-Z][a-zA-Z0-9_]*[a-zA-Z0-9$_]+\\.?\\>\\)" 1 font-lock-type-face)
  720. ;; foo.bar.baz
  721. ("\\<^?\\([a-z][a-z0-9_-]+\\.\\([a-z][a-z0-9_-]*\\.?\\)+\\)" 1 font-lock-type-face)
  722. ;; (ns namespace) - special handling for single segment namespaces
  723. (,(concat "(\\<ns\\>[ \r\n\t]*"
  724. ;; Possibly metadata
  725. "\\(?:\\^?{[^}]+}[ \r\n\t]*\\)*"
  726. ;; namespace
  727. "\\([a-z0-9-]+\\)")
  728. (1 font-lock-type-face nil t))
  729. ;; fooBar
  730. ("\\(?:\\<\\|/\\)\\([a-z]+[A-Z]+[a-zA-Z0-9$]*\\>\\)" 1 'clojure-interop-method-face)
  731. ;; #_ and (comment ...) macros.
  732. (clojure--search-comment-macro 1 font-lock-comment-face t)
  733. ;; Highlight `code` marks, just like `elisp'.
  734. (,(rx "`" (group-n 1 (optional "#'")
  735. (+ (or (syntax symbol) (syntax word)))) "`")
  736. (1 'font-lock-constant-face prepend))
  737. ;; Highlight escaped characters in strings.
  738. (clojure-font-lock-escaped-chars 0 'bold prepend)
  739. ;; Highlight grouping constructs in regular expressions
  740. (clojure-font-lock-regexp-groups
  741. (1 'font-lock-regexp-grouping-construct prepend))))
  742. "Default expressions to highlight in Clojure mode.")
  743. (defun clojure-font-lock-syntactic-face-function (state)
  744. "Find and highlight text with a Clojure-friendly syntax table.
  745. This function is passed to `font-lock-syntactic-face-function',
  746. which is called with a single parameter, STATE (which is, in
  747. turn, returned by `parse-partial-sexp' at the beginning of the
  748. highlighted region)."
  749. (if (nth 3 state)
  750. ;; This might be a (doc)string or a |...| symbol.
  751. (let ((startpos (nth 8 state)))
  752. (if (eq (char-after startpos) ?|)
  753. ;; This is not a string, but a |...| symbol.
  754. nil
  755. (let* ((listbeg (nth 1 state))
  756. (firstsym (and listbeg
  757. (save-excursion
  758. (goto-char listbeg)
  759. (and (looking-at "([ \t\n]*\\(\\(\\sw\\|\\s_\\)+\\)")
  760. (match-string 1)))))
  761. (docelt (and firstsym
  762. (function-get (intern-soft firstsym)
  763. lisp-doc-string-elt-property))))
  764. (if (and docelt
  765. ;; It's a string in a form that can have a docstring.
  766. ;; Check whether it's in docstring position.
  767. (save-excursion
  768. (when (functionp docelt)
  769. (goto-char (match-end 1))
  770. (setq docelt (funcall docelt)))
  771. (goto-char listbeg)
  772. (forward-char 1)
  773. (condition-case nil
  774. (while (and (> docelt 0) (< (point) startpos)
  775. (progn (forward-sexp 1) t))
  776. ;; ignore metadata and type hints
  777. (unless (looking-at "[ \n\t]*\\(\\^[A-Z:].+\\|\\^?{.+\\)")
  778. (setq docelt (1- docelt))))
  779. (error nil))
  780. (and (zerop docelt) (<= (point) startpos)
  781. (progn (forward-comment (point-max)) t)
  782. (= (point) (nth 8 state)))))
  783. font-lock-doc-face
  784. font-lock-string-face))))
  785. font-lock-comment-face))
  786. (defun clojure-font-lock-setup ()
  787. "Configures font-lock for editing Clojure code."
  788. (setq-local font-lock-multiline t)
  789. (add-to-list 'font-lock-extend-region-functions
  790. #'clojure-font-lock-extend-region-def t)
  791. (setq font-lock-defaults
  792. '(clojure-font-lock-keywords ; keywords
  793. nil nil
  794. (("+-*/.<>=!?$%_&:" . "w")) ; syntax alist
  795. nil
  796. (font-lock-mark-block-function . mark-defun)
  797. (font-lock-syntactic-face-function
  798. . clojure-font-lock-syntactic-face-function))))
  799. (defun clojure-font-lock-def-at-point (point)
  800. "Range between the top-most def* and the fourth element after POINT.
  801. Note that this means that there is no guarantee of proper font
  802. locking in def* forms that are not at top level."
  803. (goto-char point)
  804. (condition-case nil
  805. (beginning-of-defun)
  806. (error nil))
  807. (let ((beg-def (point)))
  808. (when (and (not (= point beg-def))
  809. (looking-at "(def"))
  810. (condition-case nil
  811. (progn
  812. ;; move forward as much as possible until failure (or success)
  813. (forward-char)
  814. (dotimes (_ 4)
  815. (forward-sexp)))
  816. (error nil))
  817. (cons beg-def (point)))))
  818. (defun clojure-font-lock-extend-region-def ()
  819. "Set region boundaries to include the first four elements of def* forms."
  820. (let ((changed nil))
  821. (let ((def (clojure-font-lock-def-at-point font-lock-beg)))
  822. (when def
  823. (cl-destructuring-bind (def-beg . def-end) def
  824. (when (and (< def-beg font-lock-beg)
  825. (< font-lock-beg def-end))
  826. (setq font-lock-beg def-beg
  827. changed t)))))
  828. (let ((def (clojure-font-lock-def-at-point font-lock-end)))
  829. (when def
  830. (cl-destructuring-bind (def-beg . def-end) def
  831. (when (and (< def-beg font-lock-end)
  832. (< font-lock-end def-end))
  833. (setq font-lock-end def-end
  834. changed t)))))
  835. changed))
  836. (defun clojure--font-locked-as-string-p (&optional regexp)
  837. "Non-nil if the char before point is font-locked as a string.
  838. If REGEXP is non-nil, also check whether current string is
  839. preceeded by a #."
  840. (let ((face (get-text-property (1- (point)) 'face)))
  841. (and (or (and (listp face)
  842. (memq 'font-lock-string-face face))
  843. (eq 'font-lock-string-face face))
  844. (or (clojure-string-start t)
  845. (unless regexp
  846. (clojure-string-start nil))))))
  847. (defun clojure-font-lock-escaped-chars (bound)
  848. "Highlight \escaped chars in strings.
  849. BOUND denotes a buffer position to limit the search."
  850. (let ((found nil))
  851. (while (and (not found)
  852. (re-search-forward "\\\\." bound t))
  853. (setq found (clojure--font-locked-as-string-p)))
  854. found))
  855. (defun clojure-font-lock-regexp-groups (bound)
  856. "Highlight grouping constructs in regular expression.
  857. BOUND denotes the maximum number of characters (relative to the
  858. point) to check."
  859. (let ((found nil))
  860. (while (and (not found)
  861. (re-search-forward (eval-when-compile
  862. (concat
  863. ;; A group may start using several alternatives:
  864. "\\(\\(?:"
  865. ;; 1. (? special groups
  866. "(\\?\\(?:"
  867. ;; a) non-capturing group (?:X)
  868. ;; b) independent non-capturing group (?>X)
  869. ;; c) zero-width positive lookahead (?=X)
  870. ;; d) zero-width negative lookahead (?!X)
  871. "[:=!>]\\|"
  872. ;; e) zero-width positive lookbehind (?<=X)
  873. ;; f) zero-width negative lookbehind (?<!X)
  874. "<[=!]\\|"
  875. ;; g) named capturing group (?<name>X)
  876. "<[[:alnum:]]+>"
  877. "\\)\\|" ;; end of special groups
  878. ;; 2. normal capturing groups (
  879. ;; 3. we also highlight alternative
  880. ;; separarators |, and closing parens )
  881. "[|()]"
  882. "\\)\\)"))
  883. bound t))
  884. (setq found (clojure--font-locked-as-string-p 'regexp)))
  885. found))
  886. ;; Docstring positions
  887. (put 'ns 'clojure-doc-string-elt 2)
  888. (put 'def 'clojure-doc-string-elt 2)
  889. (put 'defn 'clojure-doc-string-elt 2)
  890. (put 'defn- 'clojure-doc-string-elt 2)
  891. (put 'defmulti 'clojure-doc-string-elt 2)
  892. (put 'defmacro 'clojure-doc-string-elt 2)
  893. (put 'definline 'clojure-doc-string-elt 2)
  894. (put 'defprotocol 'clojure-doc-string-elt 2)
  895. ;;; Vertical alignment
  896. (defcustom clojure-align-forms-automatically nil
  897. "If non-nil, vertically align some forms automatically.
  898. Automatically means it is done as part of indenting code. This
  899. applies to binding forms (`clojure-align-binding-forms'), to cond
  900. forms (`clojure-align-cond-forms') and to map literals. For
  901. instance, selecting a map a hitting \\<clojure-mode-map>`\\[indent-for-tab-command]'
  902. will align the values like this:
  903. {:some-key 10
  904. :key2 20}"
  905. :package-version '(clojure-mode . "5.1")
  906. :safe #'booleanp
  907. :type 'boolean)
  908. (defcustom clojure-align-binding-forms
  909. '("let" "when-let" "when-some" "if-let" "if-some" "binding" "loop"
  910. "doseq" "for" "with-open" "with-local-vars" "with-redefs")
  911. "List of strings matching forms that have binding forms."
  912. :package-version '(clojure-mode . "5.1")
  913. :safe #'listp
  914. :type '(repeat string))
  915. (defcustom clojure-align-cond-forms '("condp" "cond" "cond->" "cond->>" "case" "are")
  916. "List of strings identifying cond-like forms."
  917. :package-version '(clojure-mode . "5.1")
  918. :safe #'listp
  919. :type '(repeat string))
  920. (defun clojure--position-for-alignment ()
  921. "Non-nil if the sexp around point should be automatically aligned.
  922. This function expects to be called immediately after an
  923. open-brace or after the function symbol in a function call.
  924. First check if the sexp around point is a map literal, or is a
  925. call to one of the vars listed in `clojure-align-cond-forms'. If
  926. it isn't, return nil. If it is, return non-nil and place point
  927. immediately before the forms that should be aligned.
  928. For instance, in a map literal point is left immediately before
  929. the first key; while, in a let-binding, point is left inside the
  930. binding vector and immediately before the first binding
  931. construct."
  932. ;; Are we in a map?
  933. (or (and (eq (char-before) ?{)
  934. (not (eq (char-before (1- (point))) ?\#)))
  935. ;; Are we in a cond form?
  936. (let* ((fun (car (member (thing-at-point 'symbol) clojure-align-cond-forms)))
  937. (method (and fun (clojure--get-indent-method fun)))
  938. ;; The number of special arguments in the cond form is
  939. ;; the number of sexps we skip before aligning.
  940. (skip (cond ((numberp method) method)
  941. ((null method) 0)
  942. ((sequencep method) (elt method 0)))))
  943. (when (and fun (numberp skip))
  944. (clojure-forward-logical-sexp skip)
  945. (comment-forward (point-max))
  946. fun)) ; Return non-nil (the var name).
  947. ;; Are we in a let-like form?
  948. (when (member (thing-at-point 'symbol)
  949. clojure-align-binding-forms)
  950. ;; Position inside the binding vector.
  951. (clojure-forward-logical-sexp)
  952. (backward-sexp)
  953. (when (eq (char-after) ?\[)
  954. (forward-char 1)
  955. (comment-forward (point-max))
  956. ;; Return non-nil.
  957. t))))
  958. (defun clojure--find-sexp-to-align (end)
  959. "Non-nil if there's a sexp ahead to be aligned before END.
  960. Place point as in `clojure--position-for-alignment'."
  961. ;; Look for a relevant sexp.
  962. (let ((found))
  963. (while (and (not found)
  964. (search-forward-regexp
  965. (concat "{\\|(" (regexp-opt
  966. (append clojure-align-binding-forms
  967. clojure-align-cond-forms)
  968. 'symbols))
  969. end 'noerror))
  970. (let ((ppss (syntax-ppss)))
  971. ;; If we're in a string or comment.
  972. (unless (or (elt ppss 3)
  973. (elt ppss 4))
  974. ;; Only stop looking if we successfully position
  975. ;; the point.
  976. (setq found (clojure--position-for-alignment)))))
  977. found))
  978. (defun clojure--search-whitespace-after-next-sexp (&optional bound _noerror)
  979. "Move point after all whitespace after the next sexp.
  980. Set the match data group 1 to be this region of whitespace and
  981. return point."
  982. (unwind-protect
  983. (ignore-errors
  984. (clojure-forward-logical-sexp 1)
  985. (search-forward-regexp "\\([,\s\t]*\\)" bound)
  986. (pcase (syntax-after (point))
  987. ;; End-of-line, try again on next line.
  988. (`(12) (clojure--search-whitespace-after-next-sexp bound))
  989. ;; Closing paren, stop here.
  990. (`(5 . ,_) nil)
  991. ;; Anything else is something to align.
  992. (_ (point))))
  993. (when (and bound (> (point) bound))
  994. (goto-char bound))))
  995. (defun clojure-align (beg end)
  996. "Vertically align the contents of the sexp around point.
  997. If region is active, align it. Otherwise, align everything in the
  998. current \"top-level\" sexp.
  999. When called from lisp code align everything between BEG and END."
  1000. (interactive (if (use-region-p)
  1001. (list (region-beginning) (region-end))
  1002. (save-excursion
  1003. (let ((end (progn (end-of-defun)
  1004. (point))))
  1005. (clojure-backward-logical-sexp)
  1006. (list (point) end)))))
  1007. (setq end (copy-marker end))
  1008. (save-excursion
  1009. (goto-char beg)
  1010. (while (clojure--find-sexp-to-align end)
  1011. (let ((sexp-end (save-excursion
  1012. (backward-up-list)
  1013. (forward-sexp 1)
  1014. (point-marker)))
  1015. (clojure-align-forms-automatically nil)
  1016. (count 1))
  1017. ;; For some bizarre reason, we need to `align-region' once for each
  1018. ;; group.
  1019. (save-excursion
  1020. (while (search-forward-regexp "^ *\n" sexp-end 'noerror)
  1021. (cl-incf count)))
  1022. (dotimes (_ count)
  1023. (align-region (point) sexp-end nil
  1024. '((clojure-align (regexp . clojure--search-whitespace-after-next-sexp)
  1025. (group . 1)
  1026. (separate . "^ *$")
  1027. (repeat . t)))
  1028. nil))
  1029. ;; Reindent after aligning because of #360.
  1030. (indent-region (point) sexp-end)))))
  1031. ;;; Indentation
  1032. (defun clojure-indent-region (beg end)
  1033. "Like `indent-region', but also maybe align forms.
  1034. Forms between BEG and END are aligned according to
  1035. `clojure-align-forms-automatically'."
  1036. (prog1 (let ((indent-region-function nil))
  1037. (indent-region beg end))
  1038. (when clojure-align-forms-automatically
  1039. (condition-case nil
  1040. (clojure-align beg end)
  1041. (scan-error nil)))))
  1042. (defun clojure-indent-line ()
  1043. "Indent current line as Clojure code."
  1044. (if (clojure-in-docstring-p)
  1045. (save-excursion
  1046. (beginning-of-line)
  1047. (when (and (looking-at "^\\s-*")
  1048. (<= (string-width (match-string-no-properties 0))
  1049. (string-width (clojure-docstring-fill-prefix))))
  1050. (replace-match (clojure-docstring-fill-prefix))))
  1051. (lisp-indent-line)))
  1052. (defvar clojure-get-indent-function nil
  1053. "Function to get the indent spec of a symbol.
  1054. This function should take one argument, the name of the symbol as
  1055. a string. This name will be exactly as it appears in the buffer,
  1056. so it might start with a namespace alias.
  1057. This function is analogous to the `clojure-indent-function'
  1058. symbol property, and its return value should match one of the
  1059. allowed values of this property. See `clojure-indent-function'
  1060. for more information.")
  1061. (defun clojure--get-indent-method (function-name)
  1062. "Return the indent spec for the symbol named FUNCTION-NAME.
  1063. FUNCTION-NAME is a string. If it contains a `/', also try only
  1064. the part after the `/'.
  1065. Look for a spec using `clojure-get-indent-function', then try the
  1066. `clojure-indent-function' and `clojure-backtracking-indent'
  1067. symbol properties."
  1068. (or (when (functionp clojure-get-indent-function)
  1069. (funcall clojure-get-indent-function function-name))
  1070. (get (intern-soft function-name) 'clojure-indent-function)
  1071. (get (intern-soft function-name) 'clojure-backtracking-indent)
  1072. (when (string-match "/\\([^/]+\\)\\'" function-name)
  1073. (or (get (intern-soft (match-string 1 function-name))
  1074. 'clojure-indent-function)
  1075. (get (intern-soft (match-string 1 function-name))
  1076. 'clojure-backtracking-indent)))
  1077. (when (string-match (rx (or "let" "when" "while") (syntax symbol))
  1078. function-name)
  1079. (clojure--get-indent-method (substring (match-string 0 function-name) 0 -1)))))
  1080. (defvar clojure--current-backtracking-depth 0)
  1081. (defun clojure--find-indent-spec-backtracking ()
  1082. "Return the indent sexp that applies to the sexp at point.
  1083. Implementation function for `clojure--find-indent-spec'."
  1084. (when (and (>= clojure-max-backtracking clojure--current-backtracking-depth)
  1085. (not (looking-at "^")))
  1086. (let ((clojure--current-backtracking-depth (1+ clojure--current-backtracking-depth))
  1087. (pos 0))
  1088. ;; Count how far we are from the start of the sexp.
  1089. (while (ignore-errors (clojure-backward-logical-sexp 1)
  1090. (not (or (bobp)
  1091. (eq (char-before) ?\n))))
  1092. (cl-incf pos))
  1093. (let* ((function (thing-at-point 'symbol))
  1094. (method (or (when function ;; Is there a spec here?
  1095. (clojure--get-indent-method function))
  1096. (ignore-errors
  1097. ;; Otherwise look higher up.
  1098. (pcase (syntax-ppss)
  1099. (`(,(pred (< 0)) ,start . ,_)
  1100. (goto-char start)
  1101. (clojure--find-indent-spec-backtracking)))))))
  1102. (when (numberp method)
  1103. (setq method (list method)))
  1104. (pcase method
  1105. ((pred functionp)
  1106. (when (= pos 0)
  1107. method))
  1108. ((pred sequencep)
  1109. (pcase (length method)
  1110. (`0 nil)
  1111. (`1 (let ((head (elt method 0)))
  1112. (when (or (= pos 0) (sequencep head))
  1113. head)))
  1114. (l (if (>= pos l)
  1115. (elt method (1- l))
  1116. (elt method pos)))))
  1117. ((or `defun `:defn)
  1118. (when (= pos 0)
  1119. :defn))
  1120. (_
  1121. (message "Invalid indent spec for `%s': %s" function method)
  1122. nil))))))
  1123. (defun clojure--find-indent-spec ()
  1124. "Return the indent spec that applies to current sexp.
  1125. If `clojure-use-backtracking-indent' is non-nil, also do
  1126. backtracking up to a higher-level sexp in order to find the
  1127. spec."
  1128. (if clojure-use-backtracking-indent
  1129. (save-excursion
  1130. (clojure--find-indent-spec-backtracking))
  1131. (let ((function (thing-at-point 'symbol)))
  1132. (clojure--get-indent-method function))))
  1133. (defun clojure--normal-indent (last-sexp indent-mode)
  1134. "Return the normal indentation column for a sexp.
  1135. Point should be after the open paren of the _enclosing_ sexp, and
  1136. LAST-SEXP is the start of the previous sexp (immediately before
  1137. the sexp being indented). INDENT-MODE is any of the values
  1138. accepted by `clojure-indent-style'."
  1139. (goto-char last-sexp)
  1140. (forward-sexp 1)
  1141. (clojure-backward-logical-sexp 1)
  1142. (let ((last-sexp-start nil))
  1143. (if (ignore-errors
  1144. ;; `backward-sexp' until we reach the start of a sexp that is the
  1145. ;; first of its line (the start of the enclosing sexp).
  1146. (while (string-match
  1147. "[^[:blank:]]"
  1148. (buffer-substring (line-beginning-position) (point)))
  1149. (setq last-sexp-start (prog1 (point)
  1150. (forward-sexp -1))))
  1151. t)
  1152. ;; Here we have found an arg before the arg we're indenting which is at
  1153. ;; the start of a line. Every mode simply aligns on this case.
  1154. (current-column)
  1155. ;; Here we have reached the start of the enclosing sexp (point is now at
  1156. ;; the function name), so the behaviour depends on INDENT-MODE and on
  1157. ;; whether there's also an argument on this line (case A or B).
  1158. (let ((case-a ; The meaning of case-a is explained in `clojure-indent-style'.
  1159. (and last-sexp-start
  1160. (< last-sexp-start (line-end-position)))))
  1161. (cond
  1162. ;; For compatibility with the old `clojure-defun-style-default-indent', any
  1163. ;; value other than these 3 is equivalent to `always-body'.
  1164. ((not (memq indent-mode '(:always-align :align-arguments nil)))
  1165. (+ (current-column) lisp-body-indent -1))
  1166. ;; There's an arg after the function name, so align with it.
  1167. (case-a (goto-char last-sexp-start)
  1168. (current-column))
  1169. ;; Not same line.
  1170. ((eq indent-mode :align-arguments)
  1171. (+ (current-column) lisp-body-indent -1))
  1172. ;; Finally, just align with the function name.
  1173. (t (current-column)))))))
  1174. (defun clojure--not-function-form-p ()
  1175. "Non-nil if form at point doesn't represent a function call."
  1176. (or (member (char-after) '(?\[ ?\{))
  1177. (save-excursion ;; Catch #?@ (:cljs ...)
  1178. (skip-chars-backward "\r\n[:blank:]")
  1179. (when (eq (char-before) ?@)
  1180. (forward-char -1))
  1181. (and (eq (char-before) ?\?)
  1182. (eq (char-before (1- (point))) ?\#)))
  1183. ;; Car of form is not a symbol.
  1184. (not (looking-at ".\\(?:\\sw\\|\\s_\\)"))))
  1185. ;; Check the general context, and provide indentation for data structures and
  1186. ;; special macros. If current form is a function (or non-special macro),
  1187. ;; delegate indentation to `clojure--normal-indent'.
  1188. (defun clojure-indent-function (indent-point state)
  1189. "When indenting a line within a function call, indent properly.
  1190. INDENT-POINT is the position where the user typed TAB, or equivalent.
  1191. Point is located at the point to indent under (for default indentation);
  1192. STATE is the `parse-partial-sexp' state for that position.
  1193. If the current line is in a call to a Clojure function with a
  1194. non-nil property `clojure-indent-function', that specifies how to do
  1195. the indentation.
  1196. The property value can be
  1197. - `defun', meaning indent `defun'-style;
  1198. - an integer N, meaning indent the first N arguments specially
  1199. like ordinary function arguments and then indent any further
  1200. arguments like a body;
  1201. - a function to call just as this function was called.
  1202. If that function returns nil, that means it doesn't specify
  1203. the indentation.
  1204. - a list, which is used by `clojure-backtracking-indent'.
  1205. This function also returns nil meaning don't specify the indentation."
  1206. ;; Goto to the open-paren.
  1207. (goto-char (elt state 1))
  1208. ;; Maps, sets, vectors and reader conditionals.
  1209. (if (clojure--not-function-form-p)
  1210. (1+ (current-column))
  1211. ;; Function or macro call.
  1212. (forward-char 1)
  1213. (let ((method (clojure--find-indent-spec))
  1214. (last-sexp calculate-lisp-indent-last-sexp)
  1215. (containing-form-column (1- (current-column))))
  1216. (pcase method
  1217. ((or (pred integerp) `(,method))
  1218. (let ((pos -1))
  1219. (condition-case nil
  1220. (while (and (<= (point) indent-point)
  1221. (not (eobp)))
  1222. (clojure-forward-logical-sexp 1)
  1223. (cl-incf pos))
  1224. ;; If indent-point is _after_ the last sexp in the
  1225. ;; current sexp, we detect that by catching the
  1226. ;; `scan-error'. In that case, we should return the
  1227. ;; indentation as if there were an extra sexp at point.
  1228. (scan-error (cl-incf pos)))
  1229. (cond
  1230. ;; The first non-special arg. Rigidly reduce indentation.
  1231. ((= pos (1+ method))
  1232. (+ lisp-body-indent containing-form-column))
  1233. ;; Further non-special args, align with the arg above.
  1234. ((> pos (1+ method))
  1235. (clojure--normal-indent last-sexp :always-align))
  1236. ;; Special arg. Rigidly indent with a large indentation.
  1237. (t
  1238. (+ (* 2 lisp-body-indent) containing-form-column)))))
  1239. (`:defn
  1240. (+ lisp-body-indent containing-form-column))
  1241. ((pred functionp)
  1242. (funcall method indent-point state))
  1243. ;; No indent spec, do the default.
  1244. (`nil
  1245. (let ((function (thing-at-point 'symbol)))
  1246. (cond
  1247. ;; Preserve useful alignment of :require (and friends) in `ns' forms.
  1248. ((and function (string-match "^:" function))
  1249. (clojure--normal-indent last-sexp :always-align))
  1250. ;; This is should be identical to the :defn above.
  1251. ((and function
  1252. (string-match "\\`\\(?:\\S +/\\)?\\(def[a-z]*\\|with-\\)"
  1253. function)
  1254. (not (string-match "\\`default" (match-string 1 function))))
  1255. (+ lisp-body-indent containing-form-column))
  1256. ;; Finally, nothing special here, just respect the user's
  1257. ;; preference.
  1258. (t (clojure--normal-indent last-sexp clojure-indent-style)))))))))
  1259. ;;; Setting indentation
  1260. (defun put-clojure-indent (sym indent)
  1261. "Instruct `clojure-indent-function' to indent the body of SYM by INDENT."
  1262. (put sym 'clojure-indent-function indent))
  1263. (defmacro define-clojure-indent (&rest kvs)
  1264. "Call `put-clojure-indent' on a series, KVS."
  1265. `(progn
  1266. ,@(mapcar (lambda (x) `(put-clojure-indent
  1267. (quote ,(car x)) ,(cadr x)))
  1268. kvs)))
  1269. (defun add-custom-clojure-indents (name value)
  1270. "Allow `clojure-defun-indents' to indent user-specified macros.
  1271. Requires the macro's NAME and a VALUE."
  1272. (custom-set-default name value)
  1273. (mapcar (lambda (x)
  1274. (put-clojure-indent x 'defun))
  1275. value))
  1276. (defcustom clojure-defun-indents nil
  1277. "List of additional symbols with defun-style indentation in Clojure.
  1278. You can use this to let Emacs indent your own macros the same way
  1279. that it indents built-in macros like with-open. This variable
  1280. only works when set via the customize interface (`setq' won't
  1281. work). To set it from Lisp code, use
  1282. (put-clojure-indent \\='some-symbol :defn)."
  1283. :type '(repeat symbol)
  1284. :set 'add-custom-clojure-indents)
  1285. (define-clojure-indent
  1286. ;; built-ins
  1287. (ns 1)
  1288. (fn :defn)
  1289. (def :defn)
  1290. (defn :defn)
  1291. (bound-fn :defn)
  1292. (if 1)
  1293. (if-not 1)
  1294. (case 1)
  1295. (cond 0)
  1296. (condp 2)
  1297. (cond-> 1)
  1298. (cond->> 1)
  1299. (when 1)
  1300. (while 1)
  1301. (when-not 1)
  1302. (when-first 1)
  1303. (do 0)
  1304. (future 0)
  1305. (comment 0)
  1306. (doto 1)
  1307. (locking 1)
  1308. (proxy '(2 nil nil (:defn)))
  1309. (as-> 2)
  1310. (reify '(:defn (1)))
  1311. (deftype '(2 nil nil (:defn)))
  1312. (defrecord '(2 nil nil (:defn)))
  1313. (defprotocol '(1 (:defn)))
  1314. (definterface '(1 (:defn)))
  1315. (extend 1)
  1316. (extend-protocol '(1 :defn))
  1317. (extend-type '(1 :defn))
  1318. ;; specify and specify! are from ClojureScript
  1319. (specify '(1 :defn))
  1320. (specify! '(1 :defn))
  1321. (try 0)
  1322. (catch 2)
  1323. (finally 0)
  1324. ;; binding forms
  1325. (let 1)
  1326. (letfn '(1 ((:defn)) nil))
  1327. (binding 1)
  1328. (loop 1)
  1329. (for 1)
  1330. (doseq 1)
  1331. (dotimes 1)
  1332. (when-let 1)
  1333. (if-let 1)
  1334. (when-some 1)
  1335. (if-some 1)
  1336. (this-as 1) ; ClojureScript
  1337. (defmethod :defn)
  1338. ;; clojure.test
  1339. (testing 1)
  1340. (deftest :defn)
  1341. (are 2)
  1342. (use-fixtures :defn)
  1343. ;; core.logic
  1344. (run :defn)
  1345. (run* :defn)
  1346. (fresh :defn)
  1347. ;; core.async
  1348. (alt! 0)
  1349. (alt!! 0)
  1350. (go 0)
  1351. (go-loop 1)
  1352. (thread 0))
  1353. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1354. ;;
  1355. ;; Better docstring filling for clojure-mode
  1356. ;;
  1357. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1358. (defun clojure-string-start (&optional regex)
  1359. "Return the position of the \" that begins the string at point.
  1360. If REGEX is non-nil, return the position of the # that begins the
  1361. regex at point. If point is not inside a string or regex, return
  1362. nil."
  1363. (when (nth 3 (syntax-ppss)) ;; Are we really in a string?
  1364. (save-excursion
  1365. (save-match-data
  1366. ;; Find a quote that appears immediately after whitespace,
  1367. ;; beginning of line, hash, or an open paren, brace, or bracket
  1368. (re-search-backward "\\(\\s-\\|^\\|#\\|(\\|\\[\\|{\\)\\(\"\\)")
  1369. (let ((beg (match-beginning 2)))
  1370. (when beg
  1371. (if regex
  1372. (and (char-before beg) (eq ?# (char-before beg)) (1- beg))
  1373. (when (not (eq ?# (char-before beg)))
  1374. beg))))))))
  1375. (defun clojure-char-at-point ()
  1376. "Return the char at point or nil if at buffer end."
  1377. (when (not (= (point) (point-max)))
  1378. (buffer-substring-no-properties (point) (1+ (point)))))
  1379. (defun clojure-char-before-point ()
  1380. "Return the char before point or nil if at buffer beginning."
  1381. (when (not (= (point) (point-min)))
  1382. (buffer-substring-no-properties (point) (1- (point)))))
  1383. (defun clojure-toggle-keyword-string ()
  1384. "Convert the string or keyword at point to keyword or string."
  1385. (interactive)
  1386. (let ((original-point (point)))
  1387. (while (and (> (point) 1)
  1388. (not (equal "\"" (buffer-substring-no-properties (point) (+ 1 (point)))))
  1389. (not (equal ":" (buffer-substring-no-properties (point) (+ 1 (point))))))
  1390. (backward-char))
  1391. (cond
  1392. ((equal 1 (point))
  1393. (error "Beginning of file reached, this was probably a mistake"))
  1394. ((equal "\"" (buffer-substring-no-properties (point) (+ 1 (point))))
  1395. (insert ":" (substring (clojure-delete-and-extract-sexp) 1 -1)))
  1396. ((equal ":" (buffer-substring-no-properties (point) (+ 1 (point))))
  1397. (insert "\"" (substring (clojure-delete-and-extract-sexp) 1) "\"")))
  1398. (goto-char original-point)))
  1399. (defun clojure-delete-and-extract-sexp ()
  1400. "Delete the surrounding sexp and return it."
  1401. (let ((begin (point)))
  1402. (forward-sexp)
  1403. (let ((result (buffer-substring begin (point))))
  1404. (delete-region begin (point))
  1405. result)))
  1406. (defun clojure-project-dir (&optional dir-name)
  1407. "Return the absolute path to the project's root directory.
  1408. Use `default-directory' if DIR-NAME is nil.
  1409. Return nil if not inside a project."
  1410. (let* ((dir-name (or dir-name default-directory))
  1411. (choices (delq nil
  1412. (mapcar (lambda (fname)
  1413. (locate-dominating-file dir-name fname))
  1414. clojure-build-tool-files))))
  1415. (when (> (length choices) 0)
  1416. (car (sort choices #'file-in-directory-p)))))
  1417. (defun clojure-project-relative-path (path)
  1418. "Denormalize PATH by making it relative to the project root."
  1419. (file-relative-name path (clojure-project-dir)))
  1420. ;;; ns manipulation
  1421. (defun clojure-expected-ns (&optional path)
  1422. "Return the namespace matching PATH.
  1423. PATH is expected to be an absolute file path.
  1424. If PATH is nil, use the path to the file backing the current buffer."
  1425. (let* ((path (or path (file-truename (buffer-file-name))))
  1426. (relative (clojure-project-relative-path path))
  1427. (sans-file-type (substring relative 0 (- (length (file-name-extension path t)))))
  1428. (sans-file-sep (mapconcat 'identity (cdr (split-string sans-file-type "/")) "."))
  1429. (sans-underscores (replace-regexp-in-string "_" "-" sans-file-sep)))
  1430. ;; Drop prefix from ns for projects with structure src/{clj,cljs,cljc}
  1431. (replace-regexp-in-string "\\`clj[scx]?\\." "" sans-underscores)))
  1432. (defun clojure-insert-ns-form-at-point ()
  1433. "Insert a namespace form at point."
  1434. (interactive)
  1435. (insert (format "(ns %s)" (funcall clojure-expected-ns-function))))
  1436. (defun clojure-insert-ns-form ()
  1437. "Insert a namespace form at the beginning of the buffer."
  1438. (interactive)
  1439. (widen)
  1440. (goto-char (point-min))
  1441. (clojure-insert-ns-form-at-point))
  1442. (defun clojure-update-ns ()
  1443. "Update the namespace of the current buffer.
  1444. Useful if a file has been renamed."
  1445. (interactive)
  1446. (let ((nsname (funcall clojure-expected-ns-function)))
  1447. (when nsname
  1448. (save-excursion
  1449. (save-match-data
  1450. (if (clojure-find-ns)
  1451. (progn (replace-match nsname nil nil nil 4)
  1452. (message "ns form updated"))
  1453. (error "Namespace not found")))))))
  1454. (defun clojure--sort-following-sexps ()
  1455. "Sort sexps between point and end of current sexp.
  1456. Comments at the start of a line are considered part of the
  1457. following sexp. Comments at the end of a line (after some other
  1458. content) are considered part of the preceding sexp."
  1459. ;; Here we're after the :require/:import symbol.
  1460. (save-restriction
  1461. (narrow-to-region (point) (save-excursion
  1462. (up-list)
  1463. (1- (point))))
  1464. (skip-chars-forward "\r\n[:blank:]")
  1465. (sort-subr nil
  1466. (lambda () (skip-chars-forward "\r\n[:blank:]"))
  1467. ;; Move to end of current top-level thing.
  1468. (lambda ()
  1469. (condition-case nil
  1470. (while t (up-list))
  1471. (scan-error nil))
  1472. ;; We could be inside a symbol instead of a sexp.
  1473. (unless (looking-at "\\s-\\|$")
  1474. (clojure-forward-logical-sexp))
  1475. ;; move past comments at the end of the line.
  1476. (search-forward-regexp "$"))
  1477. ;; Move to start of ns name.
  1478. (lambda ()
  1479. (comment-forward)
  1480. (skip-chars-forward "[:blank:]\n\r[(")
  1481. (clojure-forward-logical-sexp)
  1482. (forward-sexp -1)
  1483. nil)
  1484. ;; Move to end of ns name.
  1485. (lambda ()
  1486. (clojure-forward-logical-sexp)))
  1487. (goto-char (point-max))
  1488. ;; Does the last line now end in a comment?
  1489. (when (nth 4 (parse-partial-sexp (point-min) (point)))
  1490. (insert "\n"))))
  1491. (defun clojure-sort-ns ()
  1492. "Internally sort each sexp inside the ns form."
  1493. (interactive)
  1494. (comment-normalize-vars)
  1495. (if (clojure-find-ns)
  1496. (save-excursion
  1497. (goto-char (match-beginning 0))
  1498. (redisplay)
  1499. (let ((beg (point))
  1500. (ns))
  1501. (forward-sexp 1)
  1502. (setq ns (buffer-substring beg (point)))
  1503. (forward-char -1)
  1504. (while (progn (forward-sexp -1)
  1505. (looking-at "(:[a-z]"))
  1506. (save-excursion
  1507. (forward-char 1)
  1508. (forward-sexp 1)
  1509. (clojure--sort-following-sexps)))
  1510. (goto-char beg)
  1511. (if (looking-at (regexp-quote ns))
  1512. (message "ns form is already sorted")
  1513. (sleep-for 0.1)
  1514. (redisplay)
  1515. (message "ns form has been sorted")
  1516. (sleep-for 0.1))))
  1517. (user-error "Namespace not found")))
  1518. (defconst clojure-namespace-name-regex
  1519. (rx line-start
  1520. "("
  1521. (zero-or-one (group (regexp "clojure.core/")))
  1522. (zero-or-one (submatch "in-"))
  1523. "ns"
  1524. (zero-or-one "+")
  1525. (one-or-more (any whitespace "\n"))
  1526. (zero-or-more (or (submatch (zero-or-one "#")
  1527. "^{"
  1528. (zero-or-more (not (any "}")))
  1529. "}")
  1530. (zero-or-more "^:"
  1531. (one-or-more (not (any whitespace)))))
  1532. (one-or-more (any whitespace "\n")))
  1533. (zero-or-one (any ":'")) ;; (in-ns 'foo) or (ns+ :user)
  1534. (group (one-or-more (not (any "()\"" whitespace))) symbol-end)))
  1535. (defun clojure-find-ns ()
  1536. "Return the namespace of the current Clojure buffer.
  1537. Return the namespace closest to point and above it. If there are
  1538. no namespaces above point, return the first one in the buffer."
  1539. (save-excursion
  1540. (save-restriction
  1541. (widen)
  1542. ;; The closest ns form above point.
  1543. (when (or (re-search-backward clojure-namespace-name-regex nil t)
  1544. ;; Or any form at all.
  1545. (and (goto-char (point-min))
  1546. (re-search-forward clojure-namespace-name-regex nil t)))
  1547. (match-string-no-properties 4)))))
  1548. (defconst clojure-def-type-and-name-regex
  1549. (concat "(\\(?:\\(?:\\sw\\|\\s_\\)+/\\)?"
  1550. ;; Declaration
  1551. "\\(def\\(?:\\sw\\|\\s_\\)*\\)\\>"
  1552. ;; Any whitespace
  1553. "[ \r\n\t]*"
  1554. ;; Possibly type or metadata
  1555. "\\(?:#?^\\(?:{[^}]*}\\|\\(?:\\sw\\|\\s_\\)+\\)[ \r\n\t]*\\)*"
  1556. ;; Symbol name
  1557. "\\(\\(?:\\sw\\|\\s_\\)+\\)"))
  1558. (defun clojure-find-def ()
  1559. "Find the var declaration macro and symbol name of the current form.
  1560. Returns a list pair, e.g. (\"defn\" \"abc\") or (\"deftest\" \"some-test\")."
  1561. (save-excursion
  1562. (unless (looking-at clojure-def-type-and-name-regex)
  1563. (beginning-of-defun))
  1564. (when (search-forward-regexp clojure-def-type-and-name-regex nil t)
  1565. (list (match-string-no-properties 1)
  1566. (match-string-no-properties 2)))))
  1567. ;;; Sexp navigation
  1568. (defun clojure--looking-at-non-logical-sexp ()
  1569. "Return non-nil if sexp after point represents code.
  1570. Sexps that don't represent code are ^metadata or #reader.macros."
  1571. (comment-normalize-vars)
  1572. (comment-forward (point-max))
  1573. (looking-at-p "\\^\\|#[?[:alpha:]]"))
  1574. (defun clojure-forward-logical-sexp (&optional n)
  1575. "Move forward N logical sexps.
  1576. This will skip over sexps that don't represent objects, so that ^hints and
  1577. #reader.macros are considered part of the following sexp."
  1578. (interactive "p")
  1579. (unless n (setq n 1))
  1580. (if (< n 0)
  1581. (clojure-backward-logical-sexp (- n))
  1582. (let ((forward-sexp-function nil))
  1583. (while (> n 0)
  1584. (while (clojure--looking-at-non-logical-sexp)
  1585. (forward-sexp 1))
  1586. ;; The actual sexp
  1587. (forward-sexp 1)
  1588. (skip-chars-forward ",")
  1589. (setq n (1- n))))))
  1590. (defun clojure-backward-logical-sexp (&optional n)
  1591. "Move backward N logical sexps.
  1592. This will skip over sexps that don't represent objects, so that ^hints and
  1593. #reader.macros are considered part of the following sexp."
  1594. (interactive "p")
  1595. (unless n (setq n 1))
  1596. (if (< n 0)
  1597. (clojure-forward-logical-sexp (- n))
  1598. (let ((forward-sexp-function nil))
  1599. (while (> n 0)
  1600. ;; The actual sexp
  1601. (backward-sexp 1)
  1602. ;; Non-logical sexps.
  1603. (while (and (not (bobp))
  1604. (ignore-errors
  1605. (save-excursion
  1606. (backward-sexp 1)
  1607. (clojure--looking-at-non-logical-sexp))))
  1608. (backward-sexp 1))
  1609. (setq n (1- n))))))
  1610. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1611. ;;
  1612. ;; Refactoring support
  1613. ;;
  1614. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1615. ;;; Threading macros related
  1616. (defcustom clojure-thread-all-but-last nil
  1617. "Non-nil means do not thread the last expression.
  1618. This means that `clojure-thread-first-all' and
  1619. `clojure-thread-last-all' not thread the deepest sexp inside the
  1620. current sexp."
  1621. :package-version '(clojure-mode . "5.4.0")
  1622. :safe #'booleanp
  1623. :type 'boolean)
  1624. (defun clojure--point-after (&rest actions)
  1625. "Return POINT after performing ACTIONS.
  1626. An action is either the symbol of a function or a two element
  1627. list of (fn args) to pass to `apply''"
  1628. (save-excursion
  1629. (dolist (fn-and-args actions)
  1630. (let ((f (if (listp fn-and-args) (car fn-and-args) fn-and-args))
  1631. (args (if (listp fn-and-args) (cdr fn-and-args) nil)))
  1632. (apply f args)))
  1633. (point)))
  1634. (defun clojure--maybe-unjoin-line ()
  1635. "Undo a `join-line' done by a threading command."
  1636. (when (get-text-property (point) 'clojure-thread-line-joined)
  1637. (remove-text-properties (point) (1+ (point)) '(clojure-thread-line-joined t))
  1638. (insert "\n")))
  1639. (defun clojure--unwind-last ()
  1640. (forward-sexp)
  1641. (save-excursion
  1642. (let ((beg (point))
  1643. (contents (clojure-delete-and-extract-sexp)))
  1644. (when (looking-at " *\n")
  1645. (join-line 'following))
  1646. (clojure--ensure-parens-around-function-names)
  1647. (let* ((sexp-beg-line (line-number-at-pos))
  1648. (sexp-end-line (progn (forward-sexp)
  1649. (line-number-at-pos)))
  1650. (multiline-sexp-p (not (= sexp-beg-line sexp-end-line))))
  1651. (down-list -1)
  1652. (if multiline-sexp-p
  1653. (insert "\n")
  1654. ;; `clojure--maybe-unjoin-line' only works when unwinding sexps that were
  1655. ;; threaded in the same Emacs session, but it also catches cases that
  1656. ;; `multiline-sexp-p' doesn't.
  1657. (clojure--maybe-unjoin-line))
  1658. (insert contents))))
  1659. (forward-char))
  1660. (defun clojure--ensure-parens-around-function-names ()
  1661. (clojure--looking-at-non-logical-sexp)
  1662. (unless (looking-at "(")
  1663. (insert-parentheses 1)
  1664. (backward-up-list)))
  1665. (defun clojure--unwind-first ()
  1666. "Unwind a thread first macro once.
  1667. Point must be between the opening paren and the -> symbol."
  1668. (forward-sexp)
  1669. (save-excursion
  1670. (let ((contents (clojure-delete-and-extract-sexp)))
  1671. (when (looking-at " *\n")
  1672. (join-line 'following))
  1673. (clojure--ensure-parens-around-function-names)
  1674. (down-list)
  1675. (forward-sexp)
  1676. (insert contents)
  1677. (forward-sexp -1)
  1678. (clojure--maybe-unjoin-line)))
  1679. (forward-char))
  1680. (defun clojure--pop-out-of-threading ()
  1681. (save-excursion
  1682. (down-list 2)
  1683. (backward-up-list)
  1684. (raise-sexp)))
  1685. (defun clojure--nothing-more-to-unwind ()
  1686. (save-excursion
  1687. (let ((beg (point)))
  1688. (forward-sexp)
  1689. (down-list -1)
  1690. (backward-sexp 2) ;; the last sexp, the threading macro
  1691. (when (looking-back "(\\s-*" (line-beginning-position))
  1692. (backward-up-list)) ;; and the paren
  1693. (= beg (point)))))
  1694. (defun clojure--fix-sexp-whitespace (&optional move-out)
  1695. (save-excursion
  1696. (when move-out (backward-up-list))
  1697. (let ((sexp (bounds-of-thing-at-point 'sexp)))
  1698. (clojure-indent-region (car sexp) (cdr sexp))
  1699. (delete-trailing-whitespace (car sexp) (cdr sexp)))))
  1700. ;;;###autoload
  1701. (defun clojure-unwind ()
  1702. "Unwind thread at point or above point by one level.
  1703. Return nil if there are no more levels to unwind."
  1704. (interactive)
  1705. (save-excursion
  1706. (let ((limit (save-excursion
  1707. (beginning-of-defun)
  1708. (point))))
  1709. (ignore-errors
  1710. (when (looking-at "(")
  1711. (forward-char 1)
  1712. (forward-sexp 1)))
  1713. (search-backward-regexp "([^-]*->" limit)
  1714. (if (clojure--nothing-more-to-unwind)
  1715. (progn (clojure--pop-out-of-threading)
  1716. (clojure--fix-sexp-whitespace)
  1717. nil)
  1718. (down-list)
  1719. (prog1 (cond
  1720. ((looking-at "[^-]*->\\_>") (clojure--unwind-first))
  1721. ((looking-at "[^-]*->>\\_>") (clojure--unwind-last)))
  1722. (clojure--fix-sexp-whitespace 'move-out))
  1723. t))))
  1724. ;;;###autoload
  1725. (defun clojure-unwind-all ()
  1726. "Fully unwind thread at point or above point."
  1727. (interactive)
  1728. (while (clojure-unwind)))
  1729. (defun clojure--remove-superfluous-parens ()
  1730. (when (looking-at "([^ )]+)")
  1731. (delete-pair)))
  1732. (defun clojure--thread-first ()
  1733. (down-list)
  1734. (forward-symbol 1)
  1735. (unless (looking-at ")")
  1736. (let ((contents (clojure-delete-and-extract-sexp)))
  1737. (backward-up-list)
  1738. (just-one-space 0)
  1739. (save-excursion
  1740. (insert contents "\n")
  1741. (clojure--remove-superfluous-parens))
  1742. (when (looking-at "\\s-*\n")
  1743. (join-line 'following)
  1744. (forward-char 1)
  1745. (put-text-property (point) (1+ (point))
  1746. 'clojure-thread-line-joined t))
  1747. t)))
  1748. (defun clojure--thread-last ()
  1749. (forward-sexp 2)
  1750. (down-list -1)
  1751. (backward-sexp)
  1752. (unless (eq (char-before) ?\()
  1753. (let ((contents (clojure-delete-and-extract-sexp)))
  1754. (just-one-space 0)
  1755. (backward-up-list)
  1756. (insert contents "\n")
  1757. (clojure--remove-superfluous-parens)
  1758. ;; cljr #255 Fix dangling parens
  1759. (forward-sexp)
  1760. (when (looking-back "^\\s-*\\()+\\)\\s-*" (line-beginning-position))
  1761. (let ((pos (match-beginning 1)))
  1762. (put-text-property pos (1+ pos) 'clojure-thread-line-joined t))
  1763. (join-line))
  1764. t)))
  1765. (defun clojure--threadable-p ()
  1766. (save-excursion
  1767. (forward-symbol 1)
  1768. (looking-at "[\n\r\t ]*(")))
  1769. ;;;###autoload
  1770. (defun clojure-thread ()
  1771. "Thread by one more level an existing threading macro."
  1772. (interactive)
  1773. (ignore-errors
  1774. (when (looking-at "(")
  1775. (forward-char 1)
  1776. (forward-sexp 1)))
  1777. (search-backward-regexp "([^-]*->")
  1778. (down-list)
  1779. (when (clojure--threadable-p)
  1780. (prog1 (cond
  1781. ((looking-at "[^-]*->\\_>") (clojure--thread-first))
  1782. ((looking-at "[^-]*->>\\_>") (clojure--thread-last)))
  1783. (clojure--fix-sexp-whitespace 'move-out))))
  1784. (defun clojure--thread-all (first-or-last-thread but-last)
  1785. (save-excursion
  1786. (insert-parentheses 1)
  1787. (insert first-or-last-thread))
  1788. (while (save-excursion (clojure-thread)))
  1789. (when (or but-last clojure-thread-all-but-last)
  1790. (clojure-unwind)))
  1791. ;;;###autoload
  1792. (defun clojure-thread-first-all (but-last)
  1793. "Fully thread the form at point using ->.
  1794. When BUT-LAST is passed the last expression is not threaded."
  1795. (interactive "P")
  1796. (clojure--thread-all "-> " but-last))
  1797. ;;;###autoload
  1798. (defun clojure-thread-last-all (but-last)
  1799. "Fully thread the form at point using ->>.
  1800. When BUT-LAST is passed the last expression is not threaded."
  1801. (interactive "P")
  1802. (clojure--thread-all "->> " but-last))
  1803. ;;; Cycling stuff
  1804. (defcustom clojure-use-metadata-for-privacy nil
  1805. "If nil, `clojure-cycle-privacy' will use (defn- f []).
  1806. If t, it will use (defn ^:private f [])."
  1807. :package-version '(clojure-mode . "5.5.0")
  1808. :safe #'booleanp
  1809. :type 'boolean)
  1810. ;;;###autoload
  1811. (defun clojure-cycle-privacy ()
  1812. "Make public the current private def, or vice-versa.
  1813. See: https://github.com/clojure-emacs/clj-refactor.el/wiki/cljr-cycle-privacy"
  1814. (interactive)
  1815. (save-excursion
  1816. (ignore-errors (forward-char 7))
  1817. (search-backward-regexp "(defn?\\(-\\| ^:private\\)?\\_>")
  1818. (if (match-string 1)
  1819. (replace-match "" nil nil nil 1)
  1820. (goto-char (match-end 0))
  1821. (insert (if (or clojure-use-metadata-for-privacy
  1822. (equal (match-string 0) "(def"))
  1823. " ^:private"
  1824. "-")))))
  1825. (defun clojure--convert-collection (coll-open coll-close)
  1826. "Convert the collection at (point) by unwrapping it an wrapping it between COLL-OPEN and COLL-CLOSE."
  1827. (save-excursion
  1828. (while (and
  1829. (not (bobp))
  1830. (not (looking-at "(\\|{\\|\\[")))
  1831. (backward-char))
  1832. (when (or (eq ?\# (char-before))
  1833. (eq ?\' (char-before)))
  1834. (delete-char -1))
  1835. (when (and (bobp)
  1836. (not (memq (char-after) '(?\{ ?\( ?\[))))
  1837. (user-error "Beginning of file reached, collection is not found"))
  1838. (insert coll-open (substring (clojure-delete-and-extract-sexp) 1 -1) coll-close)))
  1839. ;;;###autoload
  1840. (defun clojure-convert-collection-to-list ()
  1841. "Convert collection at (point) to list."
  1842. (interactive)
  1843. (clojure--convert-collection "(" ")"))
  1844. ;;;###autoload
  1845. (defun clojure-convert-collection-to-quoted-list ()
  1846. "Convert collection at (point) to quoted list."
  1847. (interactive)
  1848. (clojure--convert-collection "'(" ")"))
  1849. ;;;###autoload
  1850. (defun clojure-convert-collection-to-map ()
  1851. "Convert collection at (point) to map."
  1852. (interactive)
  1853. (clojure--convert-collection "{" "}"))
  1854. ;;;###autoload
  1855. (defun clojure-convert-collection-to-vector ()
  1856. "Convert collection at (point) to vector."
  1857. (interactive)
  1858. (clojure--convert-collection "[" "]"))
  1859. ;;;###autoload
  1860. (defun clojure-convert-collection-to-set ()
  1861. "Convert collection at (point) to set."
  1862. (interactive)
  1863. (clojure--convert-collection "#{" "}"))
  1864. (defun clojure--goto-if ()
  1865. (when (in-string-p)
  1866. (while (or (not (looking-at "("))
  1867. (in-string-p))
  1868. (backward-char)))
  1869. (while (not (looking-at "\\((if \\)\\|\\((if-not \\)"))
  1870. (condition-case nil
  1871. (backward-up-list)
  1872. (scan-error (user-error "No if or if-not found")))))
  1873. ;;;###autoload
  1874. (defun clojure-cycle-if ()
  1875. "Change a surrounding if to if-not, or vice-versa.
  1876. See: https://github.com/clojure-emacs/clj-refactor.el/wiki/cljr-cycle-if"
  1877. (interactive)
  1878. (save-excursion
  1879. (clojure--goto-if)
  1880. (cond
  1881. ((looking-at "(if-not")
  1882. (forward-char 3)
  1883. (delete-char 4)
  1884. (forward-sexp 2)
  1885. (transpose-sexps 1))
  1886. ((looking-at "(if")
  1887. (forward-char 3)
  1888. (insert "-not")
  1889. (forward-sexp 2)
  1890. (transpose-sexps 1)))))
  1891. ;;; let related stuff
  1892. (defvar clojure--let-regexp
  1893. "\(\\(when-let\\|if-let\\|let\\)\\(\\s-*\\|\\[\\)"
  1894. "Regexp matching let like expressions, i.e. let, when-let, if-let.
  1895. The first match-group is the let expression, the second match-group is the whitespace or the opening square bracket if no whitespace between the let expression and the bracket.")
  1896. (defun clojure--goto-let ()
  1897. "Go to the beginning of the nearest let form."
  1898. (when (in-string-p)
  1899. (while (or (not (looking-at "("))
  1900. (in-string-p))
  1901. (backward-char)))
  1902. (ignore-errors
  1903. (while (not (looking-at clojure--let-regexp))
  1904. (backward-up-list)))
  1905. (looking-at clojure--let-regexp))
  1906. (defun clojure--inside-let-binding-p ()
  1907. (ignore-errors
  1908. (save-excursion
  1909. (let ((pos (point)))
  1910. (clojure--goto-let)
  1911. (re-search-forward "\\[")
  1912. (if (< pos (point))
  1913. nil
  1914. (forward-sexp)
  1915. (up-list)
  1916. (< pos (point)))))))
  1917. (defun clojure--beginning-of-current-let-binding ()
  1918. "Move before the bound name of the current binding.
  1919. Assume that point is in the binding form of a let."
  1920. (let ((current-point (point)))
  1921. (clojure--goto-let)
  1922. (search-forward "[")
  1923. (forward-char)
  1924. (while (> current-point (point))
  1925. (forward-sexp))
  1926. (backward-sexp 2)))
  1927. (defun clojure--previous-line ()
  1928. "Keep the column position while go the previous line."
  1929. (let ((col (current-column)))
  1930. (forward-line -1)
  1931. (move-to-column col)))
  1932. (defun clojure--prepare-to-insert-new-let-binding ()
  1933. "Move to right place in the let form to insert a new binding and indent."
  1934. (if (clojure--inside-let-binding-p)
  1935. (progn
  1936. (clojure--beginning-of-current-let-binding)
  1937. (newline-and-indent)
  1938. (clojure--previous-line)
  1939. (indent-for-tab-command))
  1940. (clojure--goto-let)
  1941. (search-forward "[")
  1942. (backward-up-list)
  1943. (forward-sexp)
  1944. (down-list -1)
  1945. (backward-char)
  1946. (if (looking-at "\\[\\s-*\\]")
  1947. (forward-char)
  1948. (forward-char)
  1949. (newline-and-indent))))
  1950. (defun clojure--sexp-regexp (sexp)
  1951. (concat "\\([^[:word:]^-]\\)"
  1952. (mapconcat #'identity (mapcar 'regexp-quote (split-string sexp))
  1953. "[[:space:]\n\r]+")
  1954. "\\([^[:word:]^-]\\)"))
  1955. (defun clojure--replace-sexp-with-binding (bound-name init-expr end)
  1956. (save-excursion
  1957. (while (re-search-forward (clojure--sexp-regexp init-expr) end t)
  1958. (replace-match (concat "\\1" bound-name "\\2")))))
  1959. (defun clojure--replace-sexps-with-bindings (bindings end)
  1960. "Replace bindings with their respective bound names in the let form.
  1961. BINDINGS is the list of bound names and init expressions, END denotes the end of the let expression."
  1962. (let ((bound-name (pop bindings))
  1963. (init-expr (pop bindings)))
  1964. (when bound-name
  1965. (clojure--replace-sexp-with-binding bound-name init-expr end)
  1966. (clojure--replace-sexps-with-bindings bindings end))))
  1967. (defun clojure--replace-sexps-with-bindings-and-indent ()
  1968. (clojure--replace-sexps-with-bindings
  1969. (clojure--read-let-bindings)
  1970. (clojure--point-after 'clojure--goto-let 'forward-sexp))
  1971. (clojure-indent-region
  1972. (clojure--point-after 'clojure--goto-let)
  1973. (clojure--point-after 'clojure--goto-let 'forward-sexp)))
  1974. (defun clojure--read-let-bindings ()
  1975. "Read the bound-name and init expression pairs in the binding form.
  1976. Return a list: odd elements are bound names, even elements init expressions."
  1977. (clojure--goto-let)
  1978. (down-list 2)
  1979. (backward-char)
  1980. (let* ((start (point))
  1981. (sexp-start start)
  1982. (end (save-excursion
  1983. (forward-sexp)
  1984. (down-list -1)
  1985. (point)))
  1986. bindings)
  1987. (forward-char)
  1988. (while (/= sexp-start end)
  1989. (forward-sexp)
  1990. (let ((sexp (buffer-substring-no-properties sexp-start (point))))
  1991. (push (string-trim
  1992. (if (= start sexp-start)
  1993. (substring sexp 1)
  1994. sexp))
  1995. bindings))
  1996. (setq sexp-start (point)))
  1997. (nreverse bindings)))
  1998. (defun clojure--introduce-let-internal (name &optional n)
  1999. (if (numberp n)
  2000. (let ((init-expr-sexp (clojure-delete-and-extract-sexp)))
  2001. (insert name)
  2002. (ignore-errors (backward-up-list n))
  2003. (insert "(let" (clojure-delete-and-extract-sexp) ")")
  2004. (backward-sexp)
  2005. (down-list)
  2006. (forward-sexp)
  2007. (insert " [" name " " init-expr-sexp "]\n")
  2008. (clojure--replace-sexps-with-bindings-and-indent))
  2009. (insert "[ " (clojure-delete-and-extract-sexp) "]")
  2010. (backward-sexp)
  2011. (insert "(let " (clojure-delete-and-extract-sexp) ")")
  2012. (backward-sexp)
  2013. (down-list 2)
  2014. (insert name)
  2015. (forward-sexp)
  2016. (up-list)
  2017. (newline-and-indent)
  2018. (insert name)))
  2019. (defun clojure--move-to-let-internal (name)
  2020. (if (not (save-excursion (clojure--goto-let)))
  2021. (clojure--introduce-let-internal name)
  2022. (let ((contents (clojure-delete-and-extract-sexp)))
  2023. (insert name)
  2024. (clojure--prepare-to-insert-new-let-binding)
  2025. (insert contents)
  2026. (backward-sexp)
  2027. (insert " ")
  2028. (backward-char)
  2029. (insert name)
  2030. (clojure--replace-sexps-with-bindings-and-indent))))
  2031. (defun clojure--let-backward-slurp-sexp-internal ()
  2032. "Slurp the s-expression before the let form into the let form."
  2033. (clojure--goto-let)
  2034. (backward-sexp)
  2035. (let ((sexp (string-trim (clojure-delete-and-extract-sexp))))
  2036. (delete-blank-lines)
  2037. (down-list)
  2038. (forward-sexp 2)
  2039. (newline-and-indent)
  2040. (insert sexp)
  2041. (clojure--replace-sexps-with-bindings-and-indent)))
  2042. ;;;###autoload
  2043. (defun clojure-let-backward-slurp-sexp (&optional n)
  2044. "Slurp the s-expression before the let form into the let form.
  2045. With a numberic prefix argument slurp the previous N s-expression into the let form."
  2046. (interactive "p")
  2047. (unless n (setq n 1))
  2048. (dotimes (k n)
  2049. (save-excursion (clojure--let-backward-slurp-sexp-internal))))
  2050. (defun clojure--let-forward-slurp-sexp-internal ()
  2051. "Slurp the next s-expression after the let form into the let form."
  2052. (clojure--goto-let)
  2053. (forward-sexp)
  2054. (let ((sexp (string-trim (clojure-delete-and-extract-sexp))))
  2055. (down-list -1)
  2056. (newline-and-indent)
  2057. (insert sexp)
  2058. (clojure--replace-sexps-with-bindings-and-indent)))
  2059. ;;;###autoload
  2060. (defun clojure-let-forward-slurp-sexp (&optional n)
  2061. "Slurp the next s-expression after the let form into the let form.
  2062. With a numeric prefix argument slurp the next N s-expressions into the let form."
  2063. (interactive "p")
  2064. (unless n (setq n 1))
  2065. (dotimes (k n)
  2066. (save-excursion (clojure--let-forward-slurp-sexp-internal))))
  2067. ;;;###autoload
  2068. (defun clojure-introduce-let (&optional n)
  2069. "Create a let form, binding the form at point.
  2070. With a numeric prefix argument the let is introduced N lists up."
  2071. (interactive "P")
  2072. (clojure--introduce-let-internal (read-from-minibuffer "Name of bound symbol: ") n))
  2073. ;;;###autoload
  2074. (defun clojure-move-to-let ()
  2075. "Move the form at point to a binding in the nearest let."
  2076. (interactive)
  2077. (clojure--move-to-let-internal (read-from-minibuffer "Name of bound symbol: ")))
  2078. ;;; ClojureScript
  2079. (defconst clojurescript-font-lock-keywords
  2080. (eval-when-compile
  2081. `(;; ClojureScript built-ins
  2082. (,(concat "(\\(?:\.*/\\)?"
  2083. (regexp-opt '("js-obj" "js-delete" "clj->js" "js->clj"))
  2084. "\\>")
  2085. 0 font-lock-builtin-face)))
  2086. "Additional font-locking for `clojurescrip-mode'.")
  2087. ;;;###autoload
  2088. (define-derived-mode clojurescript-mode clojure-mode "ClojureScript"
  2089. "Major mode for editing ClojureScript code.
  2090. \\{clojurescript-mode-map}"
  2091. (font-lock-add-keywords nil clojurescript-font-lock-keywords))
  2092. ;;;###autoload
  2093. (define-derived-mode clojurec-mode clojure-mode "ClojureC"
  2094. "Major mode for editing ClojureC code.
  2095. \\{clojurec-mode-map}")
  2096. (defconst clojurex-font-lock-keywords
  2097. ;; cljx annotations (#+clj and #+cljs)
  2098. '(("#\\+cljs?\\>" 0 font-lock-preprocessor-face))
  2099. "Additional font-locking for `clojurex-mode'.")
  2100. ;;;###autoload
  2101. (define-derived-mode clojurex-mode clojure-mode "ClojureX"
  2102. "Major mode for editing ClojureX code.
  2103. \\{clojurex-mode-map}"
  2104. (font-lock-add-keywords nil clojurex-font-lock-keywords))
  2105. ;;;###autoload
  2106. (progn
  2107. (add-to-list 'auto-mode-alist
  2108. '("\\.\\(clj\\|dtm\\|edn\\)\\'" . clojure-mode))
  2109. (add-to-list 'auto-mode-alist '("\\.cljc\\'" . clojurec-mode))
  2110. (add-to-list 'auto-mode-alist '("\\.cljx\\'" . clojurex-mode))
  2111. (add-to-list 'auto-mode-alist '("\\.cljs\\'" . clojurescript-mode))
  2112. ;; boot build scripts are Clojure source files
  2113. (add-to-list 'auto-mode-alist '("\\(?:build\\|profile\\)\\.boot\\'" . clojure-mode)))
  2114. (provide 'clojure-mode)
  2115. ;; Local Variables:
  2116. ;; coding: utf-8
  2117. ;; End:
  2118. ;;; clojure-mode.el ends here