From 27bf3c85b5fe821f1ea8dde00cad9437aa733cc4 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 3 Jan 2020 02:39:47 -0500 Subject: [PATCH] Generalize thing-at-point & region functions --- core/autoload/help.el | 5 +- core/autoload/text.el | 54 ++++++++++++++++++++++ modules/completion/ivy/autoload/ivy.el | 26 +++++------ modules/config/default/autoload/default.el | 2 +- modules/config/default/autoload/search.el | 15 ++---- modules/emacs/vc/autoload/vc.el | 6 +-- modules/tools/lookup/autoload/lookup.el | 30 +++--------- 7 files changed, 80 insertions(+), 58 deletions(-) diff --git a/core/autoload/help.el b/core/autoload/help.el index 91832fa1d..ca8f1f18f 100644 --- a/core/autoload/help.el +++ b/core/autoload/help.el @@ -621,10 +621,7 @@ config blocks in your private config." (defun doom--help-search-prompt (prompt) - (let ((query - (if (use-region-p) - (buffer-substring-no-properties (region-beginning) (region-end)) - (or (thing-at-point 'symbol t) "")))) + (let ((query (doom-thing-at-point-or-region))) (if (featurep 'counsel) query (read-string prompt query 'git-grep query)))) diff --git a/core/autoload/text.el b/core/autoload/text.el index 88ecc3208..3bd0dfcc1 100644 --- a/core/autoload/text.el +++ b/core/autoload/text.el @@ -57,9 +57,63 @@ POS defaults to the current position." ;;;###autoload (defun doom-point-in-string-or-comment-p (&optional pos) "Return non-nil if POS is in a string or comment." + (declare (side-effect-free t)) (or (doom-point-in-string-p pos) (doom-point-in-comment-p pos))) +;;;###autoload +(defun doom-region-active-p () + "Return non-nil if selection is active. +Detects evil visual mode as well." + (declare (side-effect-free t)) + (or (use-region-p) + (and (bound-and-true-p evil-local-mode) + (evil-visual-state-p)))) + +;;;###autoload +(defun doom-region-beginning () + "Return beginning position of selection. +Uses `evil-visual-beginning' if available." + (declare (side-effect-free t)) + (if (bound-and-true-p evil-local-mode) + evil-visual-beginning + (region-beginning))) + +;;;###autoload +(defun doom-region-end () + "Return end position of selection. +Uses `evil-visual-end' if available." + (declare (side-effect-free t)) + (if (bound-and-true-p evil-local-mode) + evil-visual-end + (region-end))) + +;;;###autoload +(defun doom-thing-at-point-or-region (&optional thing prompt) + "Grab the current selection, THING at point, or xref identifier at point. + +Returns THING if it is a string. Otherwise, if nothing is found at point and +PROMPT is non-nil, prompt for a string (if PROMPT is a string it'll be used as +the prompting string). Returns nil if all else fails. + +NOTE: Don't use THING for grabbing symbol-at-point. The xref fallback is smarter +in some cases." + (declare (side-effect-free t)) + (cond ((stringp thing) + thing) + ((doom-region-active-p) + (buffer-substring-no-properties + (doom-region-beginning) + (doom-region-end))) + (thing + (thing-at-point thing t)) + ((require 'xref nil t) + ;; A little smarter than using `symbol-at-point', though in most cases, + ;; xref ends up using `symbol-at-point' anyway. + (xref-backend-identifier-at-point (xref-find-backend))) + (prompt + (read-string (if (stringp prompt) prompt ""))))) + ;; ;;; Commands diff --git a/modules/completion/ivy/autoload/ivy.el b/modules/completion/ivy/autoload/ivy.el index b453c405a..fdabf446c 100644 --- a/modules/completion/ivy/autoload/ivy.el +++ b/modules/completion/ivy/autoload/ivy.el @@ -264,21 +264,17 @@ The point of this is to avoid Emacs locking up indexing massive file trees." " " (mapconcat #'shell-quote-argument args " ")))) (counsel-rg - (or (if query query) - (when (use-region-p) - (let ((beg (or (bound-and-true-p evil-visual-beginning) (region-beginning))) - (end (or (bound-and-true-p evil-visual-end) (region-end)))) - (when (> (abs (- end beg)) 1) - (let ((query (buffer-substring-no-properties beg end))) - ;; Escape characters that are special to ivy searches - (replace-regexp-in-string "[! |]" (lambda (substr) - (cond ((and (string= substr " ") - (not (featurep! +fuzzy))) - " ") - ((string= substr "|") - "\\\\\\\\|") - ((concat "\\\\" substr)))) - (rxt-quote-pcre query))))))) + (or query + (when (doom-region-active-p) + (replace-regexp-in-string + "[! |]" (lambda (substr) + (cond ((and (string= substr " ") + (not (featurep! +fuzzy))) + " ") + ((string= substr "|") + "\\\\\\\\|") + ((concat "\\\\" substr)))) + (rxt-quote-pcre (doom-thing-at-point-or-region))))) directory args (or prompt (format "rg%s [%s]: " diff --git a/modules/config/default/autoload/default.el b/modules/config/default/autoload/default.el index 6022a11a3..fdd1cc096 100644 --- a/modules/config/default/autoload/default.el +++ b/modules/config/default/autoload/default.el @@ -43,7 +43,7 @@ If ARG (universal argument), runs `compile' from the current directory." (unless (bound-and-true-p lsp-mode) (user-error "Not in an LSP buffer")) (call-interactively - (if (use-region-p) + (if (doom-region-active-p) #'lsp-format-region #'lsp-format-buffer))) diff --git a/modules/config/default/autoload/search.el b/modules/config/default/autoload/search.el index 595ec4aa9..dcd704895 100644 --- a/modules/config/default/autoload/search.el +++ b/modules/config/default/autoload/search.el @@ -45,17 +45,12 @@ If prefix ARG is set, prompt for a known project to search from." (+default/search-project 'other)) ;;;###autoload -(defun +default/search-project-for-symbol-at-point (&optional arg symbol) +(defun +default/search-project-for-symbol-at-point (&optional symbol arg) "Search current project for symbol at point. If prefix ARG is set, prompt for a known project to search from." (interactive - (list current-prefix-arg - (or (and (use-region-p) - (rxt-quote-pcre - (buffer-substring-no-properties (region-beginning) - (region-end)))) - (rxt-quote-pcre (thing-at-point 'symbol t)) - ""))) + (list (rxt-quote-pcre (or (doom-thing-at-point-or-region) "")) + current-prefix-arg)) (let ((default-directory (if arg (if-let (projects (projectile-relevant-known-projects)) @@ -74,7 +69,7 @@ If prefix ARG is set, prompt for a known project to search from." "Conduct a text search in the current project for symbol at point. If prefix ARG is set, prompt for a known project to search from." (interactive - (list (rxt-quote-pcre (or (thing-at-point 'symbol t) "")))) + (list (rxt-quote-pcre (or (doom-thing-at-point-or-region) "")))) (require 'org) (let ((default-directory org-directory)) (+default/search-project-for-symbol-at-point @@ -86,7 +81,7 @@ ARG is set, prompt for a known project to search from." (interactive) (require 'org) (let ((default-directory org-directory)) - (+default/search-project-for-symbol-at-point nil ""))) + (+default/search-project-for-symbol-at-point ""))) ;;;###autoload (defun +default/org-notes-headlines () diff --git a/modules/emacs/vc/autoload/vc.el b/modules/emacs/vc/autoload/vc.el index 8f9ac8d07..ccc68c9dc 100644 --- a/modules/emacs/vc/autoload/vc.el +++ b/modules/emacs/vc/autoload/vc.el @@ -8,8 +8,7 @@ If a selection is active, highlight them. Otherwise omits the #L suffix in the URL." (interactive) - (if (or (use-region-p) - (ignore-errors (evil-visual-state-p))) + (if (doom-region-active-p) (browse-at-remote) (browse-url (browse-at-remote--file-url (buffer-file-name))))) @@ -20,8 +19,7 @@ If a selection is active, highlight them. Otherwise omits the #L suffix in the URL." (interactive) (let ((url - (if (or (use-region-p) - (evil-visual-state-p)) + (if (doom-region-active-p) (browse-at-remote-get-url) (browse-at-remote--file-url (buffer-file-name))))) (kill-new url) diff --git a/modules/tools/lookup/autoload/lookup.el b/modules/tools/lookup/autoload/lookup.el index 9b8e697b7..3ee8f0cf4 100644 --- a/modules/tools/lookup/autoload/lookup.el +++ b/modules/tools/lookup/autoload/lookup.el @@ -162,24 +162,6 @@ This can be passed nil as its second argument to unset handlers for MODES. e.g. (better-jumper-set-jump (marker-position origin))) result))) -;;;###autoload -(defun +lookup-thing-or-region (&optional initial thing) - "Return INITIAL, grab the THING at point, or contents of selection. - -If THING is nil, uses `xref-backend-identifier-at-point' (like symbol, but -smarter)." - (cond ((stringp initial) - initial) - ((use-region-p) - (buffer-substring-no-properties (region-beginning) - (region-end))) - (thing - (thing-at-point thing t)) - ((require 'xref nil t) - ;; A little smarter than using `symbol-at-point', though in most cases, - ;; xref ends up using `symbol-at-point' anyway. - (xref-backend-identifier-at-point (xref-find-backend))))) - ;; ;;; Lookup backends @@ -250,7 +232,7 @@ Each function in `+lookup-definition-functions' is tried until one changes the point or current buffer. Falls back to dumb-jump, naive ripgrep/the_silver_searcher text search, then `evil-goto-definition' if evil-mode is active." - (interactive (list (+lookup-thing-or-region) + (interactive (list (doom-thing-at-point-or-region) current-prefix-arg)) (cond ((null identifier) (user-error "Nothing under point")) ((+lookup--jump-to :definition identifier nil arg)) @@ -263,7 +245,7 @@ evil-mode is active." Tries each function in `+lookup-references-functions' until one changes the point and/or current buffer. Falls back to a naive ripgrep/the_silver_searcher search otherwise." - (interactive (list (+lookup-thing-or-region) + (interactive (list (doom-thing-at-point-or-region) current-prefix-arg)) (cond ((null identifier) (user-error "Nothing under point")) ((+lookup--jump-to :references identifier nil arg)) @@ -276,7 +258,7 @@ search otherwise." First attempts the :documentation handler specified with `set-lookup-handlers!' for the current mode/buffer (if any), then falls back to the backends in `+lookup-documentation-functions'." - (interactive (list (+lookup-thing-or-region) + (interactive (list (doom-thing-at-point-or-region) current-prefix-arg)) (cond ((+lookup--jump-to :documentation identifier #'pop-to-buffer arg)) ((user-error "Couldn't find documentation for %S" identifier)))) @@ -297,7 +279,7 @@ Otherwise, falls back on `find-file-at-point'." (or (ffap-guesser) (ffap-read-file-or-url (if ffap-url-regexp "Find file or URL: " "Find file: ") - (+lookup-thing-or-region)))))) + (doom-thing-at-point-or-region)))))) (require 'ffap) (cond ((not path) (call-interactively #'find-file-at-point)) @@ -336,7 +318,7 @@ Otherwise, falls back on `find-file-at-point'." (defun +lookup/dictionary-definition (identifier &optional arg) "Look up the definition of the word at point (or selection)." (interactive - (list (or (+lookup-thing-or-region nil 'word) + (list (or (doom-thing-at-point-or-region 'word) (read-string "Look up in dictionary: ")) current-prefix-arg)) (cond ((and IS-MAC (require 'osx-dictionary nil t)) @@ -351,7 +333,7 @@ Otherwise, falls back on `find-file-at-point'." (defun +lookup/synonyms (identifier &optional arg) "Look up and insert a synonym for the word at point (or selection)." (interactive - (list (+lookup-thing-or-region nil 'word) ; TODO actually use this + (list (doom-thing-at-point-or-region 'word) ; TODO actually use this current-prefix-arg)) (unless (require 'powerthesaurus nil t) (user-error "No dictionary backend is available"))