diff --git a/README.md b/README.md index 3a57279..cd17cc6 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ Starting/stopping a search: | F | Cycle through file modes: all, type, glob | | I | Switch to incremental search, re-running on every keystroke | | D | Change the search directory | +| K | Cycle through scopes: directory, directory-and-open, open | | ^ | Re-run the search in the parent directory | | g | Re-run the search | | TAB | Expand/collapse results for a file | diff --git a/deadgrep.el b/deadgrep.el index 145f73d..16ebd51 100644 --- a/deadgrep.el +++ b/deadgrep.el @@ -148,6 +148,8 @@ display." (put 'deadgrep--search-case 'permanent-local t) (defvar-local deadgrep--file-type 'all) (put 'deadgrep--file-type 'permanent-local t) +(defvar-local deadgrep--search-scope 'project) +(put 'deadgrep--search-scope 'permanent-local t) (defvar-local deadgrep--skip-if-hidden nil "Whether deadgrep should ignore hidden files (e.g. files called .foo).") @@ -454,10 +456,19 @@ with a text face property `deadgrep-match-face'." 'case nil 'help-echo "Change case sensitivity") +(define-button-type 'deadgrep-search-scope + 'action #'deadgrep--search-scope + 'case nil + 'help-echo "Change search scope") + (defun deadgrep--case (button) (setq deadgrep--search-case (button-get button 'case)) (deadgrep-restart)) +(defun deadgrep--scope (button) + (setq deadgrep--search-scope (button-get button 'scope)) +(deadgrep-restart)) + (define-button-type 'deadgrep-context 'action #'deadgrep--context 'context nil @@ -774,10 +785,28 @@ to obtain ripgrep results." (push "--" args) (push search-term args) - (push "." args) + (setq args (append + (deadgrep--shell-quote-filenames (deadgrep--files-to-search)) + args)) + + (message (format "searching this: %s" (deadgrep--files-to-search))) + (nreverse args))) +(defun deadgrep--files-to-search () + (cond + ((eq deadgrep--search-scope 'project) '(".")) + ((eq deadgrep--search-scope 'project-open-buffers) + (deadgrep--filenames-of-open-files-in-project)) + ((eq deadgrep--search-scope 'open-buffers) + (deadgrep--filenames-of-open-files)) + (t + (error "search scope wasn't set correctly!" 'deadgrep--search-scope)))) + +(defun deadgrep--shell-quote-filenames (filenames) + (-map (lambda (filename) (shell-quote-argument filename)) filenames)) + (defun deadgrep--write-heading () "Write the deadgrep heading with buttons reflecting the current search settings." @@ -828,6 +857,25 @@ search settings." (deadgrep--button "ignore" 'deadgrep-case 'case 'ignore)) "\n" + + (propertize "Scope: " + 'face 'deadgrep-meta-face) + (if (eq deadgrep--search-scope 'project) + "project" + (deadgrep--button "project" 'deadgrep-search-scope + 'scope 'project)) + " " + (if (eq deadgrep--search-scope 'project-open-buffers) + "project open buffers" + (deadgrep--button "project open buffers" 'deadgrep-search-scope + 'scope 'project-open-buffers)) + " " + (if (eq deadgrep--search-scope 'open-buffers) + "open buffers" + (deadgrep--button "open buffers" 'deadgrep-search-scope + 'scope 'open-buffers)) + + "\n" (propertize "Context: " 'face 'deadgrep-meta-face) (if deadgrep--context @@ -1032,6 +1080,16 @@ Returns a list ordered by the most recently accessed." ((eq deadgrep--search-case 'ignore) (setq deadgrep--search-case 'smart))) (deadgrep-restart)) +(defun deadgrep-cycle-search-scope () + (interactive) + (message "cycling") + (cond + ((eq deadgrep--search-scope 'project) (setq deadgrep--search-scope 'project-open-buffers)) + ((eq deadgrep--search-scope 'project-open-buffers) (setq deadgrep--search-scope 'open-buffers)) + ((eq deadgrep--search-scope 'open-buffers) (setq deadgrep--search-scope 'project))) + (deadgrep-restart)) + + (defvar deadgrep-mode-map (let ((map (make-sparse-keymap))) (define-key map (kbd "RET") #'deadgrep-visit-result) @@ -1042,6 +1100,7 @@ Returns a list ordered by the most recently accessed." (define-key map (kbd "T") #'deadgrep-cycle-search-type) (define-key map (kbd "C") #'deadgrep-cycle-search-case) (define-key map (kbd "F") #'deadgrep-cycle-files) + (define-key map (kbd "K") #'deadgrep-cycle-search-scope) (define-key map (kbd "D") #'deadgrep-directory) (define-key map (kbd "^") #'deadgrep-parent-directory) (define-key map (kbd "g") #'deadgrep-restart) @@ -1806,6 +1865,23 @@ This is intended for use with `next-error-function', which see." (dolist (buffer (deadgrep--buffers)) (kill-buffer buffer))) +(defun deadgrep--filenames-of-open-files () + "Get all open buffers that have a backing file" + (-map (lambda (buf) + (buffer-file-name buf)) + (-filter (lambda (buffer) (buffer-file-name buffer)) + (buffer-list)))) + +(defun deadgrep--filenames-of-open-files-in-project () + "Get all buffers that have a backing file in the current project" + (let* ((candidates (deadgrep--filenames-of-open-files)) + (prefix (cdr (project-current)))) + (-filter (lambda (path) + (if (s-starts-with? prefix path) + path + nil)) + candidates))) + (provide 'deadgrep) ;;; deadgrep.el ends here