doomemacs/modules/feature/jump/autoload/jump.el

144 lines
5.6 KiB
EmacsLisp

;;; feature/jump/autoload.el -*- lexical-binding: t; -*-
(defvar +jump--rg-installed-p (executable-find "rg"))
(defvar +jump--ag-installed-p (executable-find "ag"))
(defun +jump-to (prop identifier &optional other-window)
(with-selected-window
(if other-window
(save-excursion (other-window 1) (selected-window))
(selected-window))
(let ((fn (plist-get +jump-current-functions prop)))
(if (commandp fn)
(call-interactively fn)
(funcall fn identifier)))))
;;;###autoload
(defun +jump/definition (identifier &optional other-window)
"Jump to the definition of the symbol at point.
Tries xref and falls back to `dumb-jump', then rg/ag, then
`evil-goto-definition' (if evil is active)."
(interactive
(list (thing-at-point 'symbol t)
current-prefix-arg))
(cond ((null identifier)
(user-error "Nothing under point"))
((plist-member +jump-current-functions :definition)
(+jump-to :definition identifier))
((ignore-errors (if other-window
(xref-find-definitions-other-window identifier)
(xref-find-definitions identifier))
t))
((and (require 'dumb-jump nil t)
;; dumb-jump doesn't tell us if it succeeded or not
(let ((old-fn (symbol-function 'dumb-jump-get-results))
successful)
(cl-letf (((symbol-function 'dumb-jump-get-results)
(lambda (&optional prompt)
(let* ((plist (funcall old-fn prompt))
(results (plist-get plist :results)))
(when (and results (> (length results) 0))
(setq successful t))
plist))))
(if other-window
(dumb-jump-go-other-window)
(dumb-jump-go))
successful))))
((and identifier
(featurep 'counsel)
(let ((regex (rxt-quote-pcre identifier)))
(or (and +jump--rg-installed-p
(counsel-rg regex (doom-project-root)))
(and +jump--ag-installed-p
(counsel-ag regex (doom-project-root)))))))
((and (featurep 'evil)
evil-mode
(cl-destructuring-bind (beg . end)
(bounds-of-thing-at-point 'symbol)
(evil-goto-definition)
(let ((pt (point)))
(not (and (>= pt beg)
(< pt end)))))))
(t (user-error "Couldn't find '%s'" identifier))))
;;;###autoload
(defun +jump/references (identifier)
"Show a list of references to the symbol at point.
Tries `xref-find-references' and falls back to rg/ag."
(interactive (list (thing-at-point 'symbol t)))
(cond ((plist-member +jump-current-functions :references)
(+jump-to :references identifier))
((ignore-errors (xref-find-references identifier)
t))
((and identifier
(featurep 'counsel)
(let ((regex (rxt-quote-pcre identifier)))
(or (and (executable-find "rg")
(counsel-rg regex (doom-project-root)))
(and (executable-find "ag")
(counsel-ag regex (doom-project-root)))))))
(t (error "Couldn't find '%s'" identifier))))
;;;###autoload
(defun +jump/documentation (identifier)
"Show documentation for the symbol at point, if available."
(interactive (list (thing-at-point 'symbol t)))
(cond ((plist-member +jump-current-functions :documentation)
(+jump-to :documentation identifier))
(t
(+jump/online (caar +jump-search-provider-alist) identifier))))
(defun +jump--online-get-provider (&optional force-p)
(or (and (not force-p)
+jump--online-last)
(completing-read "Search on: "
(mapcar #'car +jump-search-provider-alist)
nil t)))
(defvar +jump--online-last nil)
;;;###autoload
(defun +jump/online (search &optional provider)
"Looks up SEARCH (a string) in you browser using PROVIDER.
PROVIDER should be a key of `+jump-search-provider-alist'.
When used interactively, it will prompt for a query and, for the first time, the
provider from `+jump-search-provider-alist'. On consecutive uses, the last
provider will be reused. If the universal argument is supplied, always prompt
for the provider."
(interactive
(list (or (and (region-active-p)
(buffer-substring-no-properties (region-beginning)
(region-end)))
(read-string "Search for: " (thing-at-point 'symbol t)))
(+jump--online-get-provider current-prefix-arg)))
(condition-case _ex
(let ((url (cdr (assoc provider +jump-search-provider-alist))))
(unless url
(error "'%s' is an invalid search engine" provider))
(when (or (functionp url) (symbolp url))
(setq url (funcall url)))
(cl-assert (and (stringp url) (not (string-empty-p url))))
(when (string-empty-p search)
(user-error "The search query is empty"))
(setq +jump--online-last provider)
(funcall +jump-search-browser-fn (format url (url-encode-url search))))
('error (setq +jump--online-last nil))))
;;;###autoload
(defun +jump/online-select ()
"Runs `+jump/online', but always prompts for the provider to use."
(interactive)
(let ((current-prefix-arg t))
(call-interactively #'+jump/online)))