branch: externals/urgrep commit d965e6b8487b327c32e875c64a4e73553f467d24 Author: Jim Porter <jporterb...@gmail.com> Commit: Jim Porter <jporterb...@gmail.com>
Add the ability to toggle regexp mode when entering a search --- urgrep-test.el | 8 ++--- urgrep.el | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 84 insertions(+), 17 deletions(-) diff --git a/urgrep-test.el b/urgrep-test.el index 9307f786bf..eaf721ed5f 100644 --- a/urgrep-test.el +++ b/urgrep-test.el @@ -30,19 +30,19 @@ (cl-letf (((symbol-function #'urgrep-get-tool) (lambda () (assoc "ag" urgrep-tools)))) (should (equal (urgrep-command "foo") - "ag --color-path 35 --color-match 1\\;31 --group foo")) + "ag --color-path 35 --color-match 1\\;31 -Q --group foo")) (let ((urgrep-group-matches nil)) (should (equal (urgrep-command "foo") - "ag --color-path 35 --color-match 1\\;31 --nogroup foo"))))) + "ag --color-path 35 --color-match 1\\;31 -Q --nogroup foo"))))) (ert-deftest urgrep-test-command-git-grep () (cl-letf (((symbol-function #'urgrep-get-tool) (lambda () (assoc "git-grep" urgrep-tools)))) (should (equal (urgrep-command "foo") - "git -c color.grep.filename\\=magenta grep -n --recurse-submodules --color --heading --break foo")) + "git -c color.grep.filename\\=magenta grep -n --recurse-submodules --color -F --heading --break foo")) (let ((urgrep-group-matches nil)) (should (equal (urgrep-command "foo") - "git -c color.grep.filename\\=magenta grep -n --recurse-submodules --color foo"))))) + "git -c color.grep.filename\\=magenta grep -n --recurse-submodules --color -F foo"))))) (ert-deftest urgrep-test-command-grep () (cl-letf (((symbol-function #'urgrep-get-tool) diff --git a/urgrep.el b/urgrep.el index 5e64bb138a..47a423391e 100644 --- a/urgrep.el +++ b/urgrep.el @@ -44,6 +44,11 @@ :type 'boolean :group 'urgrep) +(defcustom urgrep-search-regexp nil + "Default to searching via regexp." + :type 'boolean + :group 'urgrep) + (defface urgrep-hit '((t :inherit compilation-info)) "Face for matching files." :group 'urgrep) @@ -56,16 +61,11 @@ "Face for matching text." :group 'urgrep) -(defvar urgrep-search-history nil "History list for urgrep.") -(defvar urgrep-num-matches-found 0 - "Running total of matches found. This will be set buffer-locally.") - -;; Set the first column to 0 because that's how we currently count. -;; XXX: It might be worth changing this to 1 if we allow reading the column -;; number explicitly in the output. -(defvar urgrep-first-column 0) + +;; Urgrep tools (defun urgrep-rgrep--command (query) + ;; XXX: Support literal/regexp setting. (grep-compute-defaults) (rgrep-default-command query "*" nil)) @@ -74,13 +74,15 @@ (executable-name "ag") (always-arguments ("--color-path" "35" "--color-match" "1;31")) (group-arguments ((t ("--group")) - (nil ("--nogroup"))))) + (nil ("--nogroup")))) + (regexp-arguments ((nil ("-Q"))))) ("git-grep" (executable-name "git") (vc-backend "Git") (always-arguments ("-c" "color.grep.filename=magenta" "grep" "-n" "--recurse-submodules" "--color")) - (group-arguments ((t ("--heading" "--break"))))) + (group-arguments ((t ("--heading" "--break")))) + (regexp-arguments ((nil ("-F"))))) ("grep" (executable-name "grep") (command-function ,#'urgrep-rgrep--command))) @@ -112,6 +114,18 @@ (string= vc-backend-name tool-vc-backend))) (cl-return tool)))))) + +;; urgrep-mode + +(defvar urgrep-search-history nil "History list for urgrep.") +(defvar urgrep-num-matches-found 0 + "Running total of matches found. This will be set buffer-locally.") + +;; Set the first column to 0 because that's how we currently count. +;; XXX: It might be worth changing this to 1 if we allow reading the column +;; number explicitly in the output. +(defvar urgrep-first-column 0) + (defvar urgrep-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map compilation-minor-mode-map) @@ -212,6 +226,10 @@ See `compilation-error-regexp-alist' for format details.") (let ((group (urgrep-get-property-assoc tool 'group-arguments urgrep-group-matches))) (when group (setq arguments (append group arguments)))) + ;; Fill in regexp/literal arguments. + (let ((regexp (urgrep-get-property-assoc tool 'regexp-arguments + urgrep-search-regexp))) + (when regexp (setq arguments (append regexp arguments)))) ;; FIXME: Inside compile and dired buffers, `shell-quote-argument' ;; doesn't handle TRAMP right... (mapconcat #'shell-quote-argument @@ -284,6 +302,48 @@ This function is called from `compilation-filter-hook'." compilation-error-screen-columns nil) (add-hook 'compilation-filter-hook 'urgrep-filter nil t)) + +;; Minibuffer configuration + +(defun urgrep--search-prompt () + "Return the prompt to use when asking for the search query. +This depends on the current values of various urgrep options." + (concat "Search " + (if urgrep-search-regexp "regexp" "string") + ": ")) + +(defun urgrep--update-search-prompt () + "Update the search prompt in the minibuffer." + (interactive) + (save-excursion + (goto-char (point-min)) + (let* ((inhibit-read-only t) + (match (text-property-search-forward 'field t t)) + (begin (prop-match-beginning match)) + (end (prop-match-end match)) + (props (text-properties-at begin))) + (delete-region begin end) + (insert (apply #'propertize (urgrep--search-prompt) props)))) + ;; Fix up the point if it ends up in the prompt; this can happen if the point + ;; was at the beginning of the editable text. + (if (< (point) (minibuffer-prompt-end)) (goto-char (minibuffer-prompt-end)))) + +(defun urgrep-toggle-regexp () + "Toggle whether or not to use regexps for the current search." + ;; FIXME: Check that we're in the search minibuffer. + (interactive) + (setq urgrep-search-regexp (not urgrep-search-regexp)) + (urgrep--update-search-prompt)) + +(defvar urgrep-minibuffer-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map minibuffer-local-map) + (define-key map "\C-c\C-r" #'urgrep-toggle-regexp) + map)) + + +;; User-facing functions (and supporting helpers) + (defun urgrep--read-directory (arg) (cond ((not arg) (let ((proj (project-current))) @@ -292,10 +352,17 @@ This function is called from `compilation-filter-hook'." (t (read-directory-name "In directory: " nil nil t)))) ;;;###autoload -(defun urgrep (query &optional directory) - "Search in DIRECTORY for a given QUERY." +(cl-defun urgrep (query &optional directory &aux + (urgrep-search-regexp urgrep-search-regexp)) + "Search in DIRECTORY for a given QUERY. +\\<urgrep-minibuffer-map> +The following keys are bound in `urgrep-minibuffer-map', active when entering +the search query: + +Type \\[urgrep-toggle-regexp] to toggle regular-expression mode." (interactive - (list (read-from-minibuffer "Search for: " "" nil nil 'urgrep-search-history) + (list (read-from-minibuffer (urgrep--search-prompt) nil + urgrep-minibuffer-map nil 'urgrep-search-history) (urgrep--read-directory current-prefix-arg))) (let ((default-directory (or directory default-directory))) (compilation-start (urgrep-command query) 'urgrep-mode)))