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