Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

229 line
9.4 KiB

4 年之前
  1. ;;; cider-find.el --- Functionality for finding things -*- lexical-binding: t -*-
  2. ;; Copyright © 2013-2019 Bozhidar Batsov, Artur Malabarba and CIDER contributors
  3. ;;
  4. ;; Author: Bozhidar Batsov <bozhidar@batsov.com>
  5. ;; Artur Malabarba <bruce.connor.am@gmail.com>
  6. ;; This program is free software: you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation, either version 3 of the License, or
  9. ;; (at your option) any later version.
  10. ;; This program is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;; GNU General Public License for more details.
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. ;; This file is not part of GNU Emacs.
  17. ;;; Commentary:
  18. ;; A bunch of commands for finding resources and definitions.
  19. ;;; Code:
  20. (require 'cider-client)
  21. (require 'cider-common)
  22. (require 'thingatpt)
  23. (defun cider--find-var-other-window (var &optional line)
  24. "Find the definition of VAR, optionally at a specific LINE.
  25. Display the results in a different window."
  26. (if-let* ((info (cider-var-info var)))
  27. (progn
  28. (if line (setq info (nrepl-dict-put info "line" line)))
  29. (cider--jump-to-loc-from-info info t))
  30. (user-error "Symbol `%s' not resolved" var)))
  31. (defun cider--find-var (var &optional line)
  32. "Find the definition of VAR, optionally at a specific LINE."
  33. (if-let* ((info (cider-var-info var)))
  34. (progn
  35. (if line (setq info (nrepl-dict-put info "line" line)))
  36. (cider--jump-to-loc-from-info info))
  37. (user-error "Symbol `%s' not resolved" var)))
  38. ;;;###autoload
  39. (defun cider-find-var (&optional arg var line)
  40. "Find definition for VAR at LINE.
  41. Prompt according to prefix ARG and `cider-prompt-for-symbol'.
  42. A single or double prefix argument inverts the meaning of
  43. `cider-prompt-for-symbol'. A prefix of `-` or a double prefix argument causes
  44. the results to be displayed in a different window. The default value is
  45. thing at point."
  46. (interactive "P")
  47. (if var
  48. (cider--find-var var line)
  49. (funcall (cider-prompt-for-symbol-function arg)
  50. "Symbol"
  51. (if (cider--open-other-window-p arg)
  52. #'cider--find-var-other-window
  53. #'cider--find-var))))
  54. ;;;###autoload
  55. (defun cider-find-dwim-at-mouse (event)
  56. "Find and display variable or resource at mouse EVENT."
  57. (interactive "e")
  58. (if-let* ((symbol-file (save-excursion
  59. (mouse-set-point event)
  60. (cider-symbol-at-point 'look-back))))
  61. (cider-find-dwim symbol-file)
  62. (user-error "No variable or resource here")))
  63. (defun cider--find-dwim (symbol-file callback &optional other-window)
  64. "Find the SYMBOL-FILE at point.
  65. CALLBACK upon failure to invoke prompt if not prompted previously.
  66. Show results in a different window if OTHER-WINDOW is true."
  67. (if-let* ((info (cider-var-info symbol-file)))
  68. (cider--jump-to-loc-from-info info other-window)
  69. (progn
  70. (cider-ensure-op-supported "resource")
  71. (if-let* ((resource (cider-sync-request:resource symbol-file))
  72. (buffer (cider-find-file resource)))
  73. (cider-jump-to buffer 0 other-window)
  74. (if (cider--prompt-for-symbol-p current-prefix-arg)
  75. (error "Resource or var %s not resolved" symbol-file)
  76. (let ((current-prefix-arg (if current-prefix-arg nil '(4))))
  77. (call-interactively callback)))))))
  78. (defun cider--find-dwim-interactive (prompt)
  79. "Get interactive arguments for jump-to functions using PROMPT as needed."
  80. (if (cider--prompt-for-symbol-p current-prefix-arg)
  81. (list
  82. (cider-read-from-minibuffer prompt (thing-at-point 'filename)))
  83. (list (or (thing-at-point 'filename) "")))) ; No prompt.
  84. (defun cider-find-dwim-other-window (symbol-file)
  85. "Jump to SYMBOL-FILE at point, place results in other window."
  86. (interactive (cider--find-dwim-interactive "Jump to: "))
  87. (cider--find-dwim symbol-file 'cider-find-dwim-other-window t))
  88. ;;;###autoload
  89. (defun cider-find-dwim (symbol-file)
  90. "Find and display the SYMBOL-FILE at point.
  91. SYMBOL-FILE could be a var or a resource. If thing at point is empty then
  92. show dired on project. If var is not found, try to jump to resource of the
  93. same name. When called interactively, a prompt is given according to the
  94. variable `cider-prompt-for-symbol'. A single or double prefix argument
  95. inverts the meaning. A prefix of `-' or a double prefix argument causes
  96. the results to be displayed in a different window. A default value of thing
  97. at point is given when prompted."
  98. (interactive (cider--find-dwim-interactive "Jump to: "))
  99. (cider--find-dwim symbol-file `cider-find-dwim
  100. (cider--open-other-window-p current-prefix-arg)))
  101. ;;;###autoload
  102. (defun cider-find-resource (path)
  103. "Find the resource at PATH.
  104. Prompt for input as indicated by the variable `cider-prompt-for-symbol'.
  105. A single or double prefix argument inverts the meaning of
  106. `cider-prompt-for-symbol'. A prefix argument of `-` or a double prefix
  107. argument causes the results to be displayed in other window. The default
  108. value is thing at point."
  109. (interactive
  110. (list
  111. (if (cider--prompt-for-symbol-p current-prefix-arg)
  112. (completing-read "Resource: "
  113. (cider-sync-request:resources-list)
  114. nil nil
  115. (thing-at-point 'filename))
  116. (or (thing-at-point 'filename) ""))))
  117. (cider-ensure-op-supported "resource")
  118. (when (= (length path) 0)
  119. (error "Cannot find resource for empty path"))
  120. (if-let* ((resource (cider-sync-request:resource path))
  121. (buffer (cider-find-file resource)))
  122. (cider-jump-to buffer nil (cider--open-other-window-p current-prefix-arg))
  123. (if (cider--prompt-for-symbol-p current-prefix-arg)
  124. (error "Cannot find resource %s" path)
  125. (let ((current-prefix-arg (cider--invert-prefix-arg current-prefix-arg)))
  126. (call-interactively 'cider-find-resource)))))
  127. (defun cider--invert-prefix-arg (arg)
  128. "Invert the effect of prefix value ARG on `cider-prompt-for-symbol'.
  129. This function preserves the `other-window' meaning of ARG."
  130. (let ((narg (prefix-numeric-value arg)))
  131. (pcase narg
  132. (16 -1) ; empty empty -> -
  133. (-1 16) ; - -> empty empty
  134. (4 nil) ; empty -> no-prefix
  135. (_ 4)))) ; no-prefix -> empty
  136. (defun cider--prefix-invert-prompt-p (arg)
  137. "Test prefix value ARG for its effect on `cider-prompt-for-symbol`."
  138. (let ((narg (prefix-numeric-value arg)))
  139. (pcase narg
  140. (16 t) ; empty empty
  141. (4 t) ; empty
  142. (_ nil))))
  143. (defun cider--prompt-for-symbol-p (&optional prefix)
  144. "Check if cider should prompt for symbol.
  145. Tests againsts PREFIX and the value of `cider-prompt-for-symbol'.
  146. Invert meaning of `cider-prompt-for-symbol' if PREFIX indicates it should be."
  147. (if (cider--prefix-invert-prompt-p prefix)
  148. (not cider-prompt-for-symbol) cider-prompt-for-symbol))
  149. (defun cider--find-ns (ns &optional other-window)
  150. "Find the file containing NS's definition.
  151. Optionally open it in a different window if OTHER-WINDOW is truthy."
  152. (if-let* ((path (cider-sync-request:ns-path ns)))
  153. (cider-jump-to (cider-find-file path) nil other-window)
  154. (user-error "Can't find namespace `%s'" ns)))
  155. ;;;###autoload
  156. (defun cider-find-ns (&optional arg ns)
  157. "Find the file containing NS.
  158. A prefix ARG of `-` or a double prefix argument causes
  159. the results to be displayed in a different window."
  160. (interactive "P")
  161. (cider-ensure-connected)
  162. (cider-ensure-op-supported "ns-path")
  163. (if ns
  164. (cider--find-ns ns)
  165. (let* ((namespaces (cider-sync-request:ns-list))
  166. (ns (completing-read "Find namespace: " namespaces)))
  167. (cider--find-ns ns (cider--open-other-window-p arg)))))
  168. ;;;###autoload
  169. (defun cider-find-keyword (&optional arg)
  170. "Find the namespace of the keyword at point and its first occurrence there.
  171. For instance - if the keyword at point is \":cider.demo/keyword\", this command
  172. would find the namespace \"cider.demo\" and afterwards find the first mention
  173. of \"::keyword\" there.
  174. Prompt according to prefix ARG and `cider-prompt-for-symbol'.
  175. A single or double prefix argument inverts the meaning of
  176. `cider-prompt-for-symbol'. A prefix of `-` or a double prefix argument causes
  177. the results to be displayed in a different window. The default value is
  178. thing at point."
  179. (interactive "P")
  180. (cider-ensure-connected)
  181. (let* ((kw (let ((kw-at-point (cider-symbol-at-point 'look-back)))
  182. (if (or cider-prompt-for-symbol arg)
  183. (read-string
  184. (format "Keyword (default %s): " kw-at-point)
  185. nil nil kw-at-point)
  186. kw-at-point)))
  187. (ns-qualifier (and
  188. (string-match "^:+\\(.+\\)/.+$" kw)
  189. (match-string 1 kw)))
  190. (kw-ns (if ns-qualifier
  191. (cider-resolve-alias (cider-current-ns) ns-qualifier)
  192. (cider-current-ns)))
  193. (kw-to-find (concat "::" (replace-regexp-in-string "^:+\\(.+/\\)?" "" kw))))
  194. (when (and ns-qualifier (string= kw-ns (cider-current-ns)))
  195. (error "Could not resolve alias `%s' in `%s'" ns-qualifier (cider-current-ns)))
  196. (cider--find-ns kw-ns arg)
  197. (search-forward-regexp kw-to-find nil 'noerror)))
  198. (provide 'cider-find)
  199. ;;; cider-find.el ends here