Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/dp12/double-saber
Filter search output with extreme prejudice
https://github.com/dp12/double-saber
delete double emacs filter grep narrow plugin saber
Last synced: about 1 month ago
JSON representation
Filter search output with extreme prejudice
- Host: GitHub
- URL: https://github.com/dp12/double-saber
- Owner: dp12
- License: gpl-3.0
- Created: 2019-01-08T22:09:39.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2021-03-24T03:15:56.000Z (almost 4 years ago)
- Last Synced: 2024-08-05T06:04:00.740Z (5 months ago)
- Topics: delete, double, emacs, filter, grep, narrow, plugin, saber
- Language: Emacs Lisp
- Homepage:
- Size: 498 KB
- Stars: 26
- Watchers: 2
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README.org
- License: LICENSE
Awesome Lists containing this project
README
* [[file:https://i.imgur.com/7axtkyH.png]] double-saber
[[https://stable.melpa.org/#/double-saber][file:https://stable.melpa.org/packages/double-saber-badge.svg]]
[[https://melpa.org/#/double-saber][file:https://melpa.org/packages/double-saber-badge.svg]]
[[https://travis-ci.org/dp12/double-saber][file:https://api.travis-ci.org/dp12/double-saber.png?branch=master]]
[[http://www.gnu.org/licenses/gpl-3.0.html][file:http://img.shields.io/:license-gpl3-blue.svg]][[file:https://i.imgur.com/7YoialK.png]]
* Overview
Search buffer output from tools like [[https://github.com/nlamirault/ripgrep.el][ripgrep]], [[https://github.com/leoliu/ggtags][ggtags]], or [[https://oremacs.com/2015/11/04/ivy-occur/][ivy-occur]] often gets cluttered with results that are irrelevant. How can we remove the unwanted cruft?double-saber provides two methods of cutting away undesired output: narrow and delete.
=double-saber-narrow= (bound to =x=) deletes all lines of text that don't match a certain keyword.
=double-saber-delete= (bound to =d=) does the inverse and deletes all matching lines.
[[file:double-saber.gif]]
Smite undesired output by either providing a single regexp (with no spaces), or a series of space-delimited strings. For fans of narrowing (e.g. =narrow-to-defun= or =narrow-region=), it essentially acts like the mythical "=narrow-regexp=" tool.
Please note that double-saber, being a chopping weapon, is not meant to be very intelligent or precise. It won't play nicely with packages like [[https://github.com/Wilfred/deadgrep][deadgrep]] that interleave lines of search metadata between search results. But when grep is spitting out dark clouds of text and raw greptitude does not avail you, it might be exactly what you need.
* Installation
double-saber is available on MELPA. You can install it with:#+begin_src emacs-lisp
M-x package-install double-saber
#+end_srcdouble-saber can also be loaded with use-package:
#+begin_src emacs-lisp
(use-package double-saber
:load-path "~/double-saber"
:config
;; add double-saber hooks here
#+end_srcOr the traditional way with require:
#+begin_src emacs-lisp
(add-to-list 'load-path "/path/to/double-saber-dir/")
(require 'double-saber)
#+end_srcTo get double-saber working for a given mode, enable =double-saber-mode= in that function's mode hook. Additionally, you will likely want to set the following variables locally for that mode:
- =double-saber-start-line=: The start line where double-saber should start deleting/narrowing from. In most cases, it should be the line after the search command. Can be =nil=.
- =double-saber-end-text=: The end text, which denotes the line beyond which double-saber should not delete (inclusive). This prevents useful text like the number of search hits from getting deleted. Can be =nil=.The following are some examples for how to set up double-saber for different major modes:
#+begin_src emacs-lisp
(with-eval-after-load "ripgrep"
(add-hook 'ripgrep-search-mode-hook
(lambda ()
(double-saber-mode)
(setq-local double-saber-start-line 5)
(setq-local double-saber-end-text "Ripgrep finished"))))(with-eval-after-load "grep"
(add-hook 'grep-mode-hook
(lambda ()
(double-saber-mode)
(setq-local double-saber-start-line 5)
(setq-local double-saber-end-text "Grep finished"))))(with-eval-after-load "ggtags"
(add-hook 'ggtags-global-mode-hook
(lambda ()
(double-saber-mode)
(setq-local double-saber-start-line 5)
(setq-local double-saber-end-text "Global found"))))(with-eval-after-load "ivy"
(add-hook 'ivy-occur-grep-mode-hook
(lambda ()
(double-saber-mode)
(setq-local double-saber-start-line 5))))
#+end_src
* Keybindings
=double-saber-mode= provides the following keybindings when enabled:
| Key | Command |
|--------------+-------------------------|
| =d= | double-saber-delete |
| =x= | double-saber-narrow |
| =s= | double-saber-sort-lines |
| =u= | double-saber-undo |
| =C-r=, =C-_= | double-saber-redo |
* Hydras and Transient States
If you have abo-abo's excellent [[https://github.com/abo-abo/hydra][hydra]] package, you can define a keymap to narrow or delete specific strings without having to type them.
#+begin_src emacs-lisp
(defhydra hydra-foo-filter ()
"Foo filter"
("0" (double-saber-narrow "foo0") "foo0")
("1" (double-saber-narrow "foo1") "foo1")
("2" (double-saber-narrow "foo2") "foo2")
("b" (double-saber-narrow "bar") "bar")
("z" (double-saber-narrow "baz") "baz")
("h" (double-saber-narrow "\.h:") "*.h") ;; show only .h files
("d" (call-interactively 'double-saber-delete) "delete")
("x" (call-interactively 'double-saber-narrow) "narrow")
("q" nil "quit" :exit t ))
(with-eval-after-load "ripgrep"
(define-key ripgrep-search-mode-map (kbd "x") 'hydra-foo-filter/body))
#+end_srcOr, if you are a spacemacs user, you can use =spacemacs|define-transient-state=:
#+begin_src emacs-lisp
(spacemacs|define-transient-state foo-filter
:title "Foo Filter Transient State"
:doc
"\n[_0_] foo0 [_1_] foo1 [_2_] foo2 [_b_] bar [_z_] baz [_h_] *.h [_d_] delete [_x_] narrow [_q_] quit"
:bindings
("0" (double-saber-narrow "foo0"))
("1" (double-saber-narrow "foo1"))
("2" (double-saber-narrow "foo2"))
("b" (double-saber-narrow "bar"))
("z" (double-saber-narrow "baz"))
("h" (double-saber-narrow "\.h:")) ;; show only .h files
("d" (call-interactively 'double-saber-delete))
("x" (call-interactively 'double-saber-narrow))
("q" nil :exit t))
(with-eval-after-load "ripgrep"
(define-key ripgrep-search-mode-map (kbd "x") 'spacemacs/foo-filter-transient-state/body))
#+end_src
* FAQ
*Isn't this just the same as "flush-lines"?*One difference vs. =flush-lines= is if you enter multiple words for double-saber-delete, it will generate a matching regex that is handed to =delete-matching-lines=. So entering "emacs vim" will generate a regex that deletes lines containing emacs or vim. =flush-lines= will treat that as a single regex and delete neither. Another difference is that =flush-lines= deletes from the current line to the end of the buffer. double-saber will start deleting from the top of the buffer or whatever starting line is specified (usually after the search command).
double-saber also enables undo so that you can bring back what you deleted, something that is usually disabled in search buffers. On a similar note, most search buffers enable read-only mode, so double-saber temporarily disables that to modify the buffer.
Lastly, it keeps metadata like the search command and original number of search hits from being deleted.
*What's up with the name?*
The inspiration for this package came when I saw a reddit comment that jokingly
wished =M-x sword-mode= existed in emacs. After I created double-saber's core
filter functions to help me at my day job, I thought that two swords were better than one.*Your demo video of double-saber was a little lacking in excitement. Do you have a better one?*
While I would love to bring you amazing gifs of Michelle Yeoh using emacs and doing M-x butterfly-twists, I regret that I have but one YouTube link to give for my country. [[https://youtu.be/S9MafXsex2Y][Here you go]].
* Misc
double-saber is integration-tested with ecukes [[https://github.com/ecukes/ecukes][🥒]] and is licensed under the GPLv3.Saber icon by [[http://bogo-d.deviantart.com][Mihaiciuc Bogdan]], with slight modifications.
Feature requests and contributions welcome!