Git Product home page Git Product logo

deadgrep's Introduction

Deadgrep: use ripgrep from Emacs ☠️

Deadgrep is the fast, beautiful text search that your Emacs deserves.

Coverage Status MELPA

screenshot

Table of Contents

Usage

Installation

  1. Install ripgrep. You need version 0.8 or later.

  2. Install deadgrep from MELPA (do M-x package-install RET deadgrep within Emacs 25.1 or later), or copy it into your ~/.emacs.d.

  3. (Optional) add deadgrep to a convenient shortcut. I like F5.

(global-set-key (kbd "<f5>") #'deadgrep)

Keybindings

Navigating results:

Key Action
RET Visit the result, file or push button at point
o Visit the result in another window
n and p Move between search hits
M-n and M-p Move between file headers

The commands deadgrep-forward and deadgrep-backward are also available to move between buttons as well as search hits.

Starting/stopping a search:

Key Action
S Change the search term
T Cycle through available search types: string, words, regexp
C Cycle through case sensitivity types: smart, sensitive, ignore
F Cycle through file modes: all, type, glob
I Switch to incremental search, re-running on every keystroke
D Change the search directory
^ Re-run the search in the parent directory
g Re-run the search
TAB Expand/collapse results for a file
C-c C-k Stop a running search
C-u A prefix argument prevents search commands from starting automatically.

Additional interactive commands

Name Action
imenu Move between files in a results buffer.
deadgrep-kill-all-buffers Kill all open deadgrep buffers.
deadgrep-debug In a results buffer, view the rg command, output and environment used.

Minibuffer

You use the minibuffer to enter a new search term.

You can also reuse a previous search term with M-p in the minibuffer. To edit the default search term, use M-n.

Easy Debugging

The easiest way to debug search results is to review the actual rg command executed.

Fortunately, the deadgrep-debug function makes it easy:

  • Move to the deadgrep results buffer.
  • Type M-x deadgrep-debug.
  • Strike enter, and the debug buffer will appear.
  • Move to the deadgrep debug buffer.

Study the results to review the rg command string and other debugging information to assist you.

Features

Super Fast

Deadgrep uses ripgrep for extremely fast text searches.

If you change your search settings, deadgrep will immediately re-run your search.

Context Aware

Deadgrep works hard to minimise your keystrokes.

Search term: If the region is active, deadgrep uses that.

Search directory: If your current file is in a VCS repository, deadgrep uses that for your search directory.

Regexp and case sensitivity options: Deadgrep re-uses whatever settings you used in your last search.

Globbing and file types: Deadgrep suggests file types and globbing options that match the file you started the search from.

Host: If you're editing a remote file with Tramp, deadgrep will search the remote machine. This requires rg to be installed on that machine.

Easy Filtering

Didn't get the results you wanted? It's easy to change the search term, search type, or search directory, directly from the results buffer. Just push the relevant button.

screenshot

Polish

Deadgrep uses spinners to give you feedback on whether your search has finished.

screenshot

It highlights regexp syntax according to the syntax accepted by rg.

screenshot

When navigating to a line that matched, the relevant part of the line is temporarily highlighted.

screenshot

You can collapse and expand files with TAB.

screenshot

Deadgrep handles minified files robustly.

screenshot

You can always jump to exactly the position that point is on, even when searching files that contain tab characters. You can also navigate to the file itself from the file headings.

Beta Features

You can now edit files directly from results buffers with M-x deadgrep-edit-mode.

It is currently in beta. Alternatively, package wgrep added support for editing deadgrep buffers in April 2023 via wgrep-deadgrep. (One feature unlocked that way is, e.g., the ability to delete a line in edit mode via C-d)

Alternative Projects

I believe that deadgrep is the best tool for doing Emacs text searches, but there are some other great tools out there. See ALTERNATIVES for a discussion.

Why the name?

The name "deadgrep" is a pun on "R.I.P. grep", and ripgrep.el was already taken.

R.I.P wasn't actually the intention of the name "ripgrep" (see their FAQ), but deadgrep is easy to remember and type.

deadgrep's People

Contributors

antifuchs avatar divinedominion avatar fuco1 avatar gregsexton avatar grettke avatar iquiw avatar jdufresne avatar jokem59 avatar kidd avatar laurynas-biveinis avatar maw avatar mernst avatar pierre-rouleau avatar travisjeffery avatar wilfred avatar wyuenho avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

deadgrep's Issues

(optionally) prompt for root search directory

Thanks for deadgrep!

I often know I want to limit the search to a subtree of the (very large) auto-detected project root. Currently I can only do this by starting the search and then changing the directory, racing ripgrep who's currently busy reading lots of unneeded disk and loading it into the disk cache.

It would be nice if after invoking M-x deadgrep I got a second prompt for the search root directory, with the current auto-detected one pre-filled. I appreciate this is an extra keystroke for the current case, so it could also be a customize option to toggle this behaviour or not.

Do you think this is worth doing or is it too niche?

Wgrep-like functionality?

Hello,

I am trying deadgrep, I wanted to say thank-you for the very nice UI.

I was wondering if there is a wgrep-like functionality?

Gracefully handle ripgrep warnings on binary files

Debugger entered--Lisp error: (args-out-of-range "WARNING: stopped searching binary file \033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m after match (found \"\\u{0}\" byte around offset 56544)" 65 146)
  match-string(1 "WARNING: stopped searching binary file \033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m after match (found \"\\u{0}\" byte around offset 56544)")
  deadgrep--extract-regexp("\\`\033\\[0m\033\\[3[56]m\\(?:\\./\\)?\\(\\(?:.\\|\n\\)+?\\)\033\\[" "WARNING: stopped searching binary file \033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m after match (found \"\\u{0}\" byte around offset 56544)")
  (list (deadgrep--extract-regexp deadgrep--filename-regexp line) (string-to-number (deadgrep--extract-regexp deadgrep--line-num-regexp line)) (deadgrep--propertize-hits (deadgrep--extract-regexp deadgrep--line-contents-regexp line)))
  deadgrep--split-line("WARNING: stopped searching binary file \033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m after match (found \"\\u{0}\" byte around offset 56544)")
  (let* ((truncate-p (> (length line) deadgrep-max-line-length)) (line (if truncate-p (substring line 0 deadgrep-max-line-length) line)) (--dash-source-157-- (deadgrep--split-line line)) (filename (car-safe (prog1 --dash-source-157-- (setq --dash-source-157-- (cdr --dash-source-157--))))) (line-num (car-safe (prog1 --dash-source-157-- (setq --dash-source-157-- (cdr --dash-source-157--))))) (content (car --dash-source-157--)) (formatted-line-num (s-pad-right deadgrep--position-column-width " " (number-to-string line-num))) (pretty-line-num (propertize formatted-line-num (quote face) (quote deadgrep-meta-face) (quote deadgrep-filename) filename (quote deadgrep-line-number) line-num (quote read-only) t (quote front-sticky) t (quote rear-nonsticky) t)) (pretty-filename (propertize filename (quote face) (quote deadgrep-filename-face) (quote deadgrep-filename) filename (quote read-only) t (quote front-sticky) t))) (cond ((null deadgrep--current-file) (setq deadgrep--imenu-alist (cons (cons filename (point)) deadgrep--imenu-alist)) (insert pretty-filename "\n")) ((not (equal deadgrep--current-file filename)) (setq deadgrep--imenu-alist (cons (cons filename (1+ (point))) deadgrep--imenu-alist)) (insert "\n" pretty-filename "\n"))) (setq deadgrep--current-file filename) (insert pretty-line-num content) (if truncate-p (progn (insert (propertize " ... (truncated)" (quote face) (quote deadgrep-meta-face))))) (insert "\n") (setq prev-line-num line-num))
  (cond ((s-blank\? line)) ((string= line "--") (let ((separator "--")) (if prev-line-num (progn (setq separator (s-repeat (log prev-line-num 10) "-")))) (insert (propertize (concat separator "\n") (quote face) (quote deadgrep-meta-face))))) ((not (s-matches-p deadgrep--color-code line)) (if deadgrep--current-file (progn (setq deadgrep--current-file nil) (insert "\n"))) (insert line "\n\n")) (t (let* ((truncate-p (> (length line) deadgrep-max-line-length)) (line (if truncate-p (substring line 0 deadgrep-max-line-length) line)) (--dash-source-157-- (deadgrep--split-line line)) (filename (car-safe (prog1 --dash-source-157-- (setq --dash-source-157-- ...)))) (line-num (car-safe (prog1 --dash-source-157-- (setq --dash-source-157-- ...)))) (content (car --dash-source-157--)) (formatted-line-num (s-pad-right deadgrep--position-column-width " " (number-to-string line-num))) (pretty-line-num (propertize formatted-line-num (quote face) (quote deadgrep-meta-face) (quote deadgrep-filename) filename (quote deadgrep-line-number) line-num (quote read-only) t (quote front-sticky) t (quote rear-nonsticky) t)) (pretty-filename (propertize filename (quote face) (quote deadgrep-filename-face) (quote deadgrep-filename) filename (quote read-only) t (quote front-sticky) t))) (cond ((null deadgrep--current-file) (setq deadgrep--imenu-alist (cons (cons filename ...) deadgrep--imenu-alist)) (insert pretty-filename "\n")) ((not (equal deadgrep--current-file filename)) (setq deadgrep--imenu-alist (cons (cons filename ...) deadgrep--imenu-alist)) (insert "\n" pretty-filename "\n"))) (setq deadgrep--current-file filename) (insert pretty-line-num content) (if truncate-p (progn (insert (propertize " ... (truncated)" (quote face) (quote deadgrep-meta-face))))) (insert "\n") (setq prev-line-num line-num))))
  (let ((line (car --dolist-tail--))) (cond ((s-blank\? line)) ((string= line "--") (let ((separator "--")) (if prev-line-num (progn (setq separator (s-repeat ... "-")))) (insert (propertize (concat separator "\n") (quote face) (quote deadgrep-meta-face))))) ((not (s-matches-p deadgrep--color-code line)) (if deadgrep--current-file (progn (setq deadgrep--current-file nil) (insert "\n"))) (insert line "\n\n")) (t (let* ((truncate-p (> (length line) deadgrep-max-line-length)) (line (if truncate-p (substring line 0 deadgrep-max-line-length) line)) (--dash-source-157-- (deadgrep--split-line line)) (filename (car-safe (prog1 --dash-source-157-- ...))) (line-num (car-safe (prog1 --dash-source-157-- ...))) (content (car --dash-source-157--)) (formatted-line-num (s-pad-right deadgrep--position-column-width " " (number-to-string line-num))) (pretty-line-num (propertize formatted-line-num (quote face) (quote deadgrep-meta-face) (quote deadgrep-filename) filename (quote deadgrep-line-number) line-num (quote read-only) t (quote front-sticky) t (quote rear-nonsticky) t)) (pretty-filename (propertize filename (quote face) (quote deadgrep-filename-face) (quote deadgrep-filename) filename (quote read-only) t (quote front-sticky) t))) (cond ((null deadgrep--current-file) (setq deadgrep--imenu-alist (cons ... deadgrep--imenu-alist)) (insert pretty-filename "\n")) ((not (equal deadgrep--current-file filename)) (setq deadgrep--imenu-alist (cons ... deadgrep--imenu-alist)) (insert "\n" pretty-filename "\n"))) (setq deadgrep--current-file filename) (insert pretty-line-num content) (if truncate-p (progn (insert (propertize " ... (truncated)" ... ...)))) (insert "\n") (setq prev-line-num line-num)))) (setq --dolist-tail-- (cdr --dolist-tail--)))
  (while --dolist-tail-- (let ((line (car --dolist-tail--))) (cond ((s-blank\? line)) ((string= line "--") (let ((separator "--")) (if prev-line-num (progn (setq separator ...))) (insert (propertize (concat separator "\n") (quote face) (quote deadgrep-meta-face))))) ((not (s-matches-p deadgrep--color-code line)) (if deadgrep--current-file (progn (setq deadgrep--current-file nil) (insert "\n"))) (insert line "\n\n")) (t (let* ((truncate-p (> ... deadgrep-max-line-length)) (line (if truncate-p ... line)) (--dash-source-157-- (deadgrep--split-line line)) (filename (car-safe ...)) (line-num (car-safe ...)) (content (car --dash-source-157--)) (formatted-line-num (s-pad-right deadgrep--position-column-width " " ...)) (pretty-line-num (propertize formatted-line-num ... ... ... filename ... line-num ... t ... t ... t)) (pretty-filename (propertize filename ... ... ... filename ... t ... t))) (cond ((null deadgrep--current-file) (setq deadgrep--imenu-alist ...) (insert pretty-filename "\n")) ((not ...) (setq deadgrep--imenu-alist ...) (insert "\n" pretty-filename "\n"))) (setq deadgrep--current-file filename) (insert pretty-line-num content) (if truncate-p (progn (insert ...))) (insert "\n") (setq prev-line-num line-num)))) (setq --dolist-tail-- (cdr --dolist-tail--))))
  (let ((--dolist-tail-- lines)) (while --dolist-tail-- (let ((line (car --dolist-tail--))) (cond ((s-blank\? line)) ((string= line "--") (let ((separator "--")) (if prev-line-num (progn ...)) (insert (propertize ... ... ...)))) ((not (s-matches-p deadgrep--color-code line)) (if deadgrep--current-file (progn (setq deadgrep--current-file nil) (insert "\n"))) (insert line "\n\n")) (t (let* ((truncate-p ...) (line ...) (--dash-source-157-- ...) (filename ...) (line-num ...) (content ...) (formatted-line-num ...) (pretty-line-num ...) (pretty-filename ...)) (cond (... ... ...) (... ... ...)) (setq deadgrep--current-file filename) (insert pretty-line-num content) (if truncate-p (progn ...)) (insert "\n") (setq prev-line-num line-num)))) (setq --dolist-tail-- (cdr --dolist-tail--)))))
  (save-excursion (goto-char (point-max)) (let ((--dolist-tail-- lines)) (while --dolist-tail-- (let ((line (car --dolist-tail--))) (cond ((s-blank\? line)) ((string= line "--") (let (...) (if prev-line-num ...) (insert ...))) ((not (s-matches-p deadgrep--color-code line)) (if deadgrep--current-file (progn ... ...)) (insert line "\n\n")) (t (let* (... ... ... ... ... ... ... ... ...) (cond ... ...) (setq deadgrep--current-file filename) (insert pretty-line-num content) (if truncate-p ...) (insert "\n") (setq prev-line-num line-num)))) (setq --dolist-tail-- (cdr --dolist-tail--))))))
  (let ((inhibit-read-only t) (lines (s-lines output)) prev-line-num) (if finished nil (setq deadgrep--remaining-output (-last-item lines)) (setq lines (butlast lines))) (save-excursion (goto-char (point-max)) (let ((--dolist-tail-- lines)) (while --dolist-tail-- (let ((line (car --dolist-tail--))) (cond ((s-blank\? line)) ((string= line "--") (let ... ... ...)) ((not ...) (if deadgrep--current-file ...) (insert line "\n\n")) (t (let* ... ... ... ... ... ... ...))) (setq --dolist-tail-- (cdr --dolist-tail--)))))))
  deadgrep--insert-output("\033[0m\033[35m./user-lisp/isearch-customisations.el\033[0m:\033[0m\033[32m59\033[0m:(global-set-key (kbd \"<f12>\") #'\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./user-lisp/isearch-customisations.el\033[0m:\033[0m\033[32m60\033[0m:(global-set-key (kbd \"C-c <f12>\") #'\033[0m\033[1m\033[31mswiper\033[0m-all)\n\033[0m\033[35m./user-lisp/isearch-customisations.el\033[0m:\033[0m\033[32m64\033[0m:(global-set-key (kbd \"C-s\") #'\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./user-lisp/isearch-customisations.el\033[0m:\033[0m\033[32m67\033[0m:;; matches with ivy (used by \033[0m\033[1m\033[31mswiper\033[0m). Anzu style.\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy-pkg.el\033[0m:\033[0m\033[32m9\033[0m:  :url \"https://github.com/abo-abo/\033[0m\033[1m\033[31mswiper\033[0m\")\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m215\033[0m:split into three packages: ‘ivy’, ‘\033[0m\033[1m\033[31mswiper\033[0m’ and ‘counsel’; you can simply\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m244\033[0m:     First clone the \033[0m\033[1m\033[31mSwiper\033[0m repository with:\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m246\033[0m:          cd ~/git && git clone https://github.com/abo-abo/\033[0m\033[1m\033[31mswiper\033[0m\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m247\033[0m:          cd \033[0m\033[1m\033[31mswiper\033[0m && make compile\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m251\033[0m:          (add-to-list 'load-path \"~/git/\033[0m\033[1m\033[31mswiper\033[0m/\")\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m317\033[0m:          (global-set-key (kbd \"C-s\") '\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m353\033[0m:   ‘\033[0m\033[1m\033[31mswiper\033[0m’ or ‘counsel-M-x’ add more key bindings through the ‘keymap’\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m1100\033[0m:      '\033[0m\033[1m\033[31mswiper\033[0m\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m1460\033[0m:     ‘post-command-hook’.  See ‘\033[0m\033[1m\033[31mswiper\033[0m’ for an example usage.\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m1479\033[0m:     interrupted with ‘C-g’.  See ‘\033[0m\033[1m\033[31mswiper\033[0m’ for an example usage.\nWARNING: stopped searching binary file \033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m after match (found \"\\u{0}\" byte around offset 56544)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m6\033[0m:;; URL: https://github.com/abo-abo/\033[0m\033[1m\033[31mswiper\033[0m\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m202\033[0m:a behavior similar to `\033[0m\033[1m\033[31mswiper\033[0m'.\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m252\033[0m:`https://github.com/abo-abo/\033[0m\033[1m\033[31mswiper\033[0m/wiki/ivy-display-function'.\")\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1186\033[0m:                '(\033[0m\033[1m\033[31mswiper\033[0m \033[0m\033[1m\033[31mswiper\033[0m-isearch \033[0m\033[1m\033[31mswiper\033[0m-backward \033[0m\033[1m\033[31mswiper\033[0m-isearch-backward))\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1503\033[0m:                   (eq (ivy-state-caller ivy-last) '\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1821\033[0m:  '((\033[0m\033[1m\033[31mswiper\033[0m . ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1822\033[0m:    (\033[0m\033[1m\033[31mswiper\033[0m-multi . ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1823\033[0m:    (counsel-git-grep . ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1824\033[0m:    (counsel-grep . ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m-async)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3280\033[0m:                  '(ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3281\033[0m:                    ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m-async\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3282\033[0m:                    ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m-async-backward\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3283\033[0m:                    ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m-backward))\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3461\033[0m:               (not (eq caller '\033[0m\033[1m\033[31mswiper\033[0m")
  (save-current-buffer (set-buffer (process-buffer process)) (deadgrep--insert-output output))
  (progn (save-current-buffer (set-buffer (process-buffer process)) (deadgrep--insert-output output)))
  (if (buffer-live-p (process-buffer process)) (progn (save-current-buffer (set-buffer (process-buffer process)) (deadgrep--insert-output output))))
  deadgrep--process-filter(#<process rg swiper> "\033[0m\033[35m./user-lisp/isearch-customisations.el\033[0m:\033[0m\033[32m59\033[0m:(global-set-key (kbd \"<f12>\") #'\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./user-lisp/isearch-customisations.el\033[0m:\033[0m\033[32m60\033[0m:(global-set-key (kbd \"C-c <f12>\") #'\033[0m\033[1m\033[31mswiper\033[0m-all)\n\033[0m\033[35m./user-lisp/isearch-customisations.el\033[0m:\033[0m\033[32m64\033[0m:(global-set-key (kbd \"C-s\") #'\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./user-lisp/isearch-customisations.el\033[0m:\033[0m\033[32m67\033[0m:;; matches with ivy (used by \033[0m\033[1m\033[31mswiper\033[0m). Anzu style.\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy-pkg.el\033[0m:\033[0m\033[32m9\033[0m:  :url \"https://github.com/abo-abo/\033[0m\033[1m\033[31mswiper\033[0m\")\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m215\033[0m:split into three packages: ‘ivy’, ‘\033[0m\033[1m\033[31mswiper\033[0m’ and ‘counsel’; you can simply\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m244\033[0m:     First clone the \033[0m\033[1m\033[31mSwiper\033[0m repository with:\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m246\033[0m:          cd ~/git && git clone https://github.com/abo-abo/\033[0m\033[1m\033[31mswiper\033[0m\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m247\033[0m:          cd \033[0m\033[1m\033[31mswiper\033[0m && make compile\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m251\033[0m:          (add-to-list 'load-path \"~/git/\033[0m\033[1m\033[31mswiper\033[0m/\")\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m317\033[0m:          (global-set-key (kbd \"C-s\") '\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m353\033[0m:   ‘\033[0m\033[1m\033[31mswiper\033[0m’ or ‘counsel-M-x’ add more key bindings through the ‘keymap’\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m1100\033[0m:      '\033[0m\033[1m\033[31mswiper\033[0m\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m1460\033[0m:     ‘post-command-hook’.  See ‘\033[0m\033[1m\033[31mswiper\033[0m’ for an example usage.\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m:\033[0m\033[32m1479\033[0m:     interrupted with ‘C-g’.  See ‘\033[0m\033[1m\033[31mswiper\033[0m’ for an example usage.\nWARNING: stopped searching binary file \033[0m\033[35m./elpa/ivy-20190809.1551/ivy.info\033[0m after match (found \"\\u{0}\" byte around offset 56544)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m6\033[0m:;; URL: https://github.com/abo-abo/\033[0m\033[1m\033[31mswiper\033[0m\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m202\033[0m:a behavior similar to `\033[0m\033[1m\033[31mswiper\033[0m'.\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m252\033[0m:`https://github.com/abo-abo/\033[0m\033[1m\033[31mswiper\033[0m/wiki/ivy-display-function'.\")\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1186\033[0m:                '(\033[0m\033[1m\033[31mswiper\033[0m \033[0m\033[1m\033[31mswiper\033[0m-isearch \033[0m\033[1m\033[31mswiper\033[0m-backward \033[0m\033[1m\033[31mswiper\033[0m-isearch-backward))\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1503\033[0m:                   (eq (ivy-state-caller ivy-last) '\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1821\033[0m:  '((\033[0m\033[1m\033[31mswiper\033[0m . ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1822\033[0m:    (\033[0m\033[1m\033[31mswiper\033[0m-multi . ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1823\033[0m:    (counsel-git-grep . ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m1824\033[0m:    (counsel-grep . ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m-async)\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3280\033[0m:                  '(ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3281\033[0m:                    ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m-async\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3282\033[0m:                    ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m-async-backward\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3283\033[0m:                    ivy-recompute-index-\033[0m\033[1m\033[31mswiper\033[0m-backward))\n\033[0m\033[35m./elpa/ivy-20190809.1551/ivy.el\033[0m:\033[0m\033[32m3461\033[0m:               (not (eq caller '\033[0m\033[1m\033[31mswiper\033[0m")

why not rg.el?

Hi Wilfred,
Just wanted to note that rg.el has many hidden niceties like grouping (rg-group-result), search the current word in the current project for files like the curent one (rg-dwim) and is also compatible with wgrep.

Not to deter you from deadgrep (Wilfredware is proved to always have an edge), but maybe trying to add to rg instead of of creating your own wheel.....

I recently discovered that m-? is bound to xref-find-definitions in many modes, that is intended to cover yet the same use case. It doesn't use compile-mode but its own xref--xref-buffer-mode.

Just my 2c on that :)

[FR] possibility to change project-dir to super-project-dir

I use ripgrep on the command line to grep in a directory containing multiple git repos. Is it possible to change the directory used by deadgrep if deadgrep is started from a buffer, which is part of a git-repo? What I want is to search/grep in the super project instead of in the "current-project" returned by project-current.

Context awareness doesn't seem to work

Hi! In your readme, you write that if I'm in a git project, this will be used for the directory (instead of the current file's directory). This doesn't seem to work, however. What could be wrong?

Large single-line files hang Emacs

If there's a >1 MiB JSON file, all one line, which matches the search, then Emacs hangs whilst the regex is matched to the whole line. We should truncate before applying the regex.

Provide deadgrep on MELPA

I know that you already mentioned MELPA in the README, but I’m filing this issue to make sure I get notified when that’s done :)

Thanks!

Add separator when set before/after context

Hi Wilfred, thx for your work! Love the UI of *deadgrep* buffer.

I have a idea of enhancing and want to share it with you:

let's assume that we have a sample file "sample.js":

const A = () => {
  console.log("I'm function A");
};

const B = () => {
  console.log("I'm function B");
};

const C = () => {
  console.log("I'm function C");
};

I use deadgrep to search "console" and the result will be:

Search term: function change
Search type: string words regexp
Case: smart sensitive ignore
Context: none before after

Directory: ~/XXXX
Files: all type glob

sample.js
2    console.log("I'm function A");
6    console.log("I'm function B");
10   console.log("I'm function C");

Then I change both "before" and "after" context to 1, and I will get:

Search term: function change
Search type: string words regexp
Case: smart sensitive ignore
Context: none before:1 after:1

Directory: ~/XXXX
Files: all type glob

sample.js
1  const A = () => {
2    console.log("I'm function A");
3  };
5  const B = () => {
6    console.log("I'm function B");
7  };
9  const C = () => {
10   console.log("I'm function C");
11 };

It's hard to see the boundary of different result and I think a divider would help:

Search term: function change
Search type: string words regexp
Case: smart sensitive ignore
Context: none before:1 after:1

Directory: ~/XXXX
Files: all type glob

sample.js
1  const A = () => {
2    console.log("I'm function A");
3  };
...
5  const B = () => {
6    console.log("I'm function B");
7  };
...
9  const C = () => {
10   console.log("I'm function C");
11 };

To add a divider, I can see results with context in same file more clearly. What's your opinion?


M-x deadgrep-debug:

About your environment:
Platform: darwin
Emacs version: 26.1
Command: nil

Initial output from ripgrep:
nil

ripgrep version: 0.9.0.

Use project-root

Project doesn't have to be a cons.

(project-root project) is more idiomatic.

Support ripgrep 0.7

This is a pretty common release, and should just be a matter of supporting the correct colour codes.

Example output:

"�[m�[35mfoo/bar.txt�[m:�[m�[32m68�[m:    xxx�[m�[31m�[1msearch term�[mstuff

Doesn't work on Windows?

I have counsel-rg and rg.el working just fine on Windows (so rg can be found blah blah), but deadgrep is just sitting, spinning, never-ending, with no results. Anyone else test it on Windows?

Args out of range error

screenshot 2018-07-11 18 38 33

Debugger entered--Lisp error: (args-out-of-range "\33[m\33[35minit.el\33[m:\33[m\33[32m51\33[m:;; Bootstrap `\33[m\33[31m\33[1muse-package\33[m'." 2319 2320)
  (match-string 1 "\33[m\33[35minit.el\33[m:\33[m\33[32m51\33[m:;; Bootstrap `\33[m\33[31m\33[1muse-package\33[m'.")
  (deadgrep--extract-regexp "\\`\33\\[0m\33\\[3[56]m\\(\\(?:.\\|\n\\)+?\\)\33\\[" "\33[m\33[35minit.el\33[m:\33[m\33[32m51\33[m:;; Bootstrap `\33[m\33[31m\33[1muse-package\33[m'.")
  (deadgrep--split-line "\33[m\33[35minit.el\33[m:\33[m\33[32m51\33[m:;; Bootstrap `\33[m\33[31m\33[1muse-package\33[m'.")
  (deadgrep--insert-output "\33[m\33[35minit.el\33[m:\33[m\33[32m51\33[m:;; Bootstrap `\33[m\33[31m\33[1muse-package\33[m'.\n\33[m\33[35minit.el\33[m:\33[m\33[32m52\33[m:(unless (package-installed-p '\33[m\33[31m\33[1muse-package\33[m)\n\33[m\33[35minit.el\33[m:\33[m\33[32m54\33[m:  (package-install '\33[m\33[31m\33[1muse-package\33[m))\n\33[m\33[35minit.el\33[m:\33[m\33[32m57\33[m:  (require '\33[m\33[31m\33[1muse-package\33[m))\n\33[m\33[35minit.el\33[m:\33[m\33[32m62\33[m:(setq \33[m\33[31m\33[1muse-package\33[m-always-ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m64\33[m:;; Check loading times with `\33[m\33[31m\33[1muse-package\33[m'.\n\33[m\33[35minit.el\33[m:\33[m\33[32m65\33[m:(setq \33[m\33[31m\33[1muse-package\33[m-verbose t)\n\33[m\33[35minit.el\33[m:\33[m\33[32m67\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-functions :ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m68\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-dependencies :ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m69\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-theme :ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m70\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-defaults :ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m71\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-platform :ensure nil)\n\33[m\33[35minit.el\33")
  (deadgrep--process-filter #<process rg use-package> "\33[m\33[35minit.el\33[m:\33[m\33[32m51\33[m:;; Bootstrap `\33[m\33[31m\33[1muse-package\33[m'.\n\33[m\33[35minit.el\33[m:\33[m\33[32m52\33[m:(unless (package-installed-p '\33[m\33[31m\33[1muse-package\33[m)\n\33[m\33[35minit.el\33[m:\33[m\33[32m54\33[m:  (package-install '\33[m\33[31m\33[1muse-package\33[m))\n\33[m\33[35minit.el\33[m:\33[m\33[32m57\33[m:  (require '\33[m\33[31m\33[1muse-package\33[m))\n\33[m\33[35minit.el\33[m:\33[m\33[32m62\33[m:(setq \33[m\33[31m\33[1muse-package\33[m-always-ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m64\33[m:;; Check loading times with `\33[m\33[31m\33[1muse-package\33[m'.\n\33[m\33[35minit.el\33[m:\33[m\33[32m65\33[m:(setq \33[m\33[31m\33[1muse-package\33[m-verbose t)\n\33[m\33[35minit.el\33[m:\33[m\33[32m67\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-functions :ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m68\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-dependencies :ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m69\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-theme :ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m70\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-defaults :ensure nil)\n\33[m\33[35minit.el\33[m:\33[m\33[32m71\33[m:(\33[m\33[31m\33[1muse-package\33[m jn-platform :ensure nil)\n\33[m\33[35minit.el\33")

I do have these packages loading which seems to contribute to the error (maybe).

;; Let Emacs color Ansi symbols.
;; https://stackoverflow.com/questions/13397737/ansi-coloring-in-compilation-mode
(defun +theme-color-compilation-buffer ()
  (ignore-errors
    (require 'ansi-color)
    (when (eq major-mode 'compilation-mode)
      (ansi-color-apply-on-region compilation-filter-start (point-max)))))

(add-hook 'compilation-filter-hook #'+theme-color-compilation-buffer)

(use-package xterm-color
  :ensure t
  :commands (xterm-color-filter)
  :init
  (add-hook 'comint-preoutput-filter-functions 'xterm-color-filter)
  (setq comint-output-filter-functions
        (remove 'ansi-color-process-output comint-output-filter-functions)))

Compatibility with evil-mode?

Hi, there seem to be issues with evil-mode. Results are returned fine but jumping to results or collapsing results is not possible. Are there plans for support?

`query-replace` doesn't work with deadgrep-edit buffers

About your environment:
Platform: gnu/linux
Emacs version: 26.2
Command: nil
default-directory: "/home/brian/.emacs.d/"

Initial output from ripgrep:
nil


I'm on the latest master branch, commit 329119c.

If I run M-x query-replace from within a deadgrep-edit-mode buffer, it fails as I attempt to replace text.

Debugger entered--Lisp error: (error "Match data clobbered by buffer modification hooks")
  (replace-match "todo" t t)
  (replace-match-maybe-edit "todo" t t nil (179 183 #<buffer *deadgrep TODO ~/.emacs.d/*>) nil)
  (#f(compiled-function (from-string replacements query-flag regexp-flag delimited-flag &optional repeat-count map start end backward region-noncontiguous-p) "Subroutine of `query-replace'.  Its complexity handles interactive queries.\nDon't use this in your own program unless you want to query and set the mark\njust as `query-replace' does.  Instead, write a simple loop like this:\n\n  (while (re-search-forward \"foo[ \\t]+bar\" nil t)\n    (replace-match \"foobar\" nil nil))\n\nwhich will run faster and probably do exactly what you want.  Please\nsee the documentation of `replace-match' to find out how to simulate\n`case-replace'.\n\nThis function returns nil if and only if there were no matches to\nmake, or the user didn't cancel the call.\n\nREPLACEMENTS is either a string, a list of strings, or a cons cell\ncontaining a function and its first argument.  The function is\ncalled to generate each replacement like this:\n  (funcall (car replacements) (cdr replacements) replace-count)\nIt must return a string." #<bytecode 0x1f5c97>) "TODO" "todo" t nil nil nil nil nil nil nil nil)
  (ad-Advice-perform-replace #f(compiled-function (from-string replacements query-flag regexp-flag delimited-flag &optional repeat-count map start end backward region-noncontiguous-p) "Subroutine of `query-replace'.  Its complexity handles interactive queries.\nDon't use this in your own program unless you want to query and set the mark\njust as `query-replace' does.  Instead, write a simple loop like this:\n\n  (while (re-search-forward \"foo[ \\t]+bar\" nil t)\n    (replace-match \"foobar\" nil nil))\n\nwhich will run faster and probably do exactly what you want.  Please\nsee the documentation of `replace-match' to find out how to simulate\n`case-replace'.\n\nThis function returns nil if and only if there were no matches to\nmake, or the user didn't cancel the call.\n\nREPLACEMENTS is either a string, a list of strings, or a cons cell\ncontaining a function and its first argument.  The function is\ncalled to generate each replacement like this:\n  (funcall (car replacements) (cdr replacements) replace-count)\nIt must return a string." #<bytecode 0x1f5c97>) "TODO" "todo" t nil nil nil nil nil nil nil nil)
  (apply ad-Advice-perform-replace #f(compiled-function (from-string replacements query-flag regexp-flag delimited-flag &optional repeat-count map start end backward region-noncontiguous-p) "Subroutine of `query-replace'.  Its complexity handles interactive queries.\nDon't use this in your own program unless you want to query and set the mark\njust as `query-replace' does.  Instead, write a simple loop like this:\n\n  (while (re-search-forward \"foo[ \\t]+bar\" nil t)\n    (replace-match \"foobar\" nil nil))\n\nwhich will run faster and probably do exactly what you want.  Please\nsee the documentation of `replace-match' to find out how to simulate\n`case-replace'.\n\nThis function returns nil if and only if there were no matches to\nmake, or the user didn't cancel the call.\n\nREPLACEMENTS is either a string, a list of strings, or a cons cell\ncontaining a function and its first argument.  The function is\ncalled to generate each replacement like this:\n  (funcall (car replacements) (cdr replacements) replace-count)\nIt must return a string." #<bytecode 0x1f5c97>) ("TODO" "todo" t nil nil nil nil nil nil nil nil))
  (perform-replace "TODO" "todo" t nil nil nil nil nil nil nil nil)
  (query-replace "TODO" "todo" nil nil nil nil nil)
  (funcall-interactively query-replace "TODO" "todo" nil nil nil nil nil)
  (call-interactively query-replace nil nil)
  (command-execute query-replace)

open results buffer in other window

thanks for this package, it seems to have quite a few nice features (i was using ag.el) but one thing that bothers me a lot is that the results buffer is displayed in the current window. i often use search to find context for code that i'm working on, and that code now disappears from the screen as soon as i search. ag.el opens in another window (another ‘column’ on my screen typically) and i can keep looking at the code from which i started my search.

it seems changing this is not possible. or is it?

Activating swiper removes highlighting

Activating swiper in the deadgrep buffer removes all highlighting, never to come back (even after quitting swiper).

About your environment:
Platform: gnu/linux
Emacs version: 26.1
Command: /usr/bin/rg --color=ansi --line-number --no-heading --with-filename --fixed-strings --smart-case   -- use .
default-directory: "~/.emacs.d/"

Initial output from ripgrep:
"�[0m�[35m./README.md�[0m:�[0m�[32m9�[0m:means that �[0m�[1m�[31muse�[0mrs are not familiar with either the tool or the options the package configured for
�[0m�[35m./README.md�[0m:�[0m�[32m23�[0m:* By default `cmark` is �[0m�[1m�[31muse�[0md to markdown export/preview so it needs to be installed.
"

Please file bugs at https://github.com/Wilfred/deadgrep/issues/new
ripgrep 0.10.0
-SIMD -AVX (compiled)
+SIMD +AVX (runtime)

Maybe elgrep as an alternative.

Hi Wilfred,
since you are listing alternatives maybe you should include elgrep because it has some unique features.
See the Section on advanced search.
I think the most notable ones are:

  • Elgrep is pure Elisp if you do not grep pdf-files. (If you grep pdf-files pdftotext is used. But I actually want to switch to pdf-tools some time in the future.)
  • The advertized way to use Elgrep is via elgrep-menu. There you can make the specific settings for your usecase. At the end of the menu there is also a list of search queries. That is a kind of history. You can set all menu fields from a query already saved in the list. On demand you can even copy the shown code of a querry and paste it into your Elisp source code.
  • Elgrep can not only search for matches in files but also for matches in records. The record bounds determine what records are. They can be defined by regexp matches or function calls. If a record matches you can adjust the context such that the whole record is listed. By default only the matching lines are listed and the record boundaries match the beginning and the end of the file. So the whole file is one record.
  • Now that we know what a record is we can speak about matches. You can specify not only one regexp but a whole list of regexps. If all regexps match within the record all matches of the first regexp are listed (conjunction-operation). All regexps but the first one can also be negated. Negated ones may not match within the record to be listed.

The record thing, the multiple regexp thing, and negate thing make Elgrep even to a (admittingly simple) tool for queries in text based databases.

The many options have slowed it down a bit. Profiling and tuning is one of the next points in my development plan ;-) .

Best regards,
Tobias

Make projectile a soft dependency

It would be preferable to not require 'projectile in order to use this library. Indeed, the mechanism is already in place to allow for this via customizing deadgrep-project-root-function, however the (require 'projectile) statement prevents this by preventing 'deadgrep from loading if projectile is not loaded.

Changing this to (require 'projectile nil t) would permit me to use this library.

Many thanks!

always use deadgrep-executable

first of all, i really love this ui to ripgrep! thanks for that.

there is still a rg %s in the source, so it's not working for me. please always use deadgrep-executable.

Tramp support is broken on Windows

M-x deadgrep-debug

About your environment:
Platform: windows-nt
Emacs version: 26.1
Command: nil
default-directory: "c:/pscp:host:/directory"

Initial output from ripgrep:
nil

default-directory is c:/pscp:..., which should be /pscp:....

I did not track the cause yet, but git bisect points e961f42 is the first bad commit.

Deadgrep lacks multi-directory support available through rg

M-x deadgrep calls deadgrep-project-root-function to get a directory, and passes that directory down to deadgrep--buffer.

I have a situation where I want to search through my directory tree, plus various other directory trees in on-disk caches stored elsewhere. The underlying rg command supports that:

       rg [OPTIONS] PATTERN [PATH...]

Deadgrep doesn't: the user can only request one PATH. Can you extend the code to support a single directory or a list of directories? Once that's in place it should be simple to dynamically bind deadgrep-project-root-function in new commands to do what I need.

(Ag has the same problem, and ages ago I hand-copied the appropriate function to my .emacs and tweaked it. It's a brittle approach, though.)

Smarter detection of language extension

Currently we consider foo.ml to be ml rather than ocaml. This means we miss out on *.mli files.

A better heuristic would be to match the language with the most extensions.

Don't show result separators for the last result in a file

Search term: paragraph-separate change
Search type: string words regexp
Case: smart sensitive ignore
Context: none before:0 after:1

Directory: ~/src/emacs/
Files: all type glob

CONTRIBUTE
390  paragraph-separate: "[ 	]*$"
391  coding: utf-8
---

lisp/shell.el
553    (setq-local paragraph-separate "\\'")
554    (setq-local paragraph-start comint-prompt-regexp)
---

Messy search output

I ran deadgrep looking for use-package in my .emacs.d, but results are hard to read.

I think a picture describes it better.

shot

This is how I configured deadgrep:

(use-package deadgrep
  :load-path "~/githubs/deadgrep"
  :bind ("<f7>" . deadgrep))

And these are some details about my system:

GNU Emacs 27.0.50 (build 1, x86_64-debian-linux-gnu, GTK+ Version 3.22.30)
 of 2018-06-20

Repository revision: 3a47f3921bdaaf7b7d80dc3be05a5f1b1f2501eb
Configured using:
--host=x86_64-debian-linux-gnu

Emacs uptime: 3 minutes, 53 seconds
Colour theme: sanityinc-tomorrow-night
Operating system: Ubuntu 18.04 LTS
Window system: x11
Desktop environment: GNOME Shell 3.28.1

Python files suggest yacc rather than py as the type

I'm using the latest version of deadgrep available on MELPA, and ripgrep 11.0.1. Emacs 26.2, Arch Linux.

(deadgrep--relevant-file-type "foobar.py" (deadgrep--type-list)) ;; yacc: *.y
(deadgrep--relevant-file-type "foobar.pyi" (deadgrep--type-list)) ;; swig: *.i

Looks like the heuristic can be improved further: .py has one exact match so it should be preferred over .y...

In fact this looks like deadgrep--matches-globs-p doesn't work correctly and treats the . as in a regexp instead of a glob:

(-filter (-lambda ((_type globs))
	   (deadgrep--matches-globs-p "foobar.py" globs))
	 (deadgrep--type-list))
;; result: (("py" ("*.py")) ("yacc" ("*.y")))

Tramp support

Support running on a remote host if rg is installed there.

Please add some keyboard shortcuts to the search UI

In search results, it would be super useful (for me) to have several shortcuts to change search parameters. For instance:

  • t: change search term
  • y s, y w, y r: change search type to strings, words, regexp
  • C s, C e, C i: set case to smart, sensitive, ignore
  • c n, c b, c a: change context to none, before, after
  • d: change directory
  • f a, f t, f g: change files to all, type, glob

In other words, please let me change all search parameters without having to move the point to a button and then hitting RET! :)

Enable editable buffer and save changes to files

Feature request: Edit results in buffer and save all touched files.

Similar in spirit to wdired, make search results editable in buffer. C-c C-c would save any changes in all modified files.

Here's what that's like using helm-ag and pressing C-c C-e to open an editable buffer:

helm-ag-edit

[Feature Request] ability to loop through search hits

full-ack.el provides this functionality and it makes it really easy to do repo wide refactor

  1. make a search
  2. jump to first hit in the search result buffer
  3. start to record a macro C-x (
  4. Press enter (this will take you to the file and put the cursor at the start of the match)
  5. do the refactoring
  6. jump back to the search result buffer
  7. move to the nex hit
  8. finish the macro C-x (

The macro can now be applied for the rest of the hits using C-x e. The important functionality that makes this possible is the ability to move to the start of next search hit.

Visit in other window without changing focus

It would be useful to quickly preview search results without having to change focus back and forth between deadgrep buffer and the target buffer

Maybe O (to match o) or v (for "view").

"wrong-type-argument markerp nil" error when changing option.

I got the error when changing directory (other options seem same) after C-u M-x deadgrep.
Using ELPA version of spinner and latest Git version of dash, s, projectile and deadgrep.

This commit 39fa9be seems the first bad commit.

Debugger entered--Lisp error: (wrong-type-argument markerp nil)
  set-marker(nil nil)
  (let ((start-point (point)) (inhibit-read-only t)) (erase-buffer) (setq deadgrep--hidden-files nil) (set-marker overlay-arrow-position nil) (setq deadgrep--current-file nil) (setq deadgrep--spinner nil) (setq deadgrep--remaining-output nil) (setq deadgrep--current-file nil) (setq deadgrep--debug-first-output nil) (deadgrep--write-heading) (goto-char (min (point-max) start-point)) (if deadgrep--postpone-start (deadgrep--write-postponed) (deadgrep--start deadgrep--search-term deadgrep--search-type deadgrep--search-case)))
  deadgrep-restart()
  deadgrep--directory(#<marker (moves after insertion) at 1 in *deadgrep dead ~/.emacs.d/lisp*>)
  button-activate(#<marker (moves after insertion) at 1 in *deadgrep dead ~/.emacs.d/lisp*> nil)
  push-button(137)
  funcall-interactively(push-button 137)
  call-interactively(push-button nil nil)
  command-execute(push-button)

M-x deadgrep-debug (Command nil as using C-u M-x deadgrep)

About your environment:
Platform: windows-nt
Emacs version: 26.1
Command: nil

Initial output from ripgrep:
nil

Incremental search / search as you type

Updating the results as the user types would make the UI more responsive and would greatly improve usability.

Maybe even immediately show the results for the words under point, that would make deadgrep feel much snappier.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.