Here’s another tip for taming your Emacs config. In particular, how to search
the huge body of elisp that is present with most Emacs installs - the
load-path. While the
load-path is a very important collection of
directories, searching it isn’t as easy and accessible as it should be. As
usual, Emacs compensates with plugins:
- elisp-refs - this excellent package is useful for canned searches that are often present in most IDE’s. Quite useful whenever your search fits into one of the use case supported.
- el-search - this is quite an advanced package that allows you to write queries with a deep understanding of elisp itself. An extremely useful plugin, but overkill when your query is simple.
A problem that is shared by both of the options above is that they’re a bit sluggish. Something that is fast, allows us to use familiar PCRE’s, is a missing piece.
Luckily, such a missing piece is glued together with a bit of elisp and the silver searcher:
(defun region-or-symbol-at-point () (if mark-active (buffer-substring-no-properties (region-beginning) (region-end)) (or (symbol-name (symbol-at-point)) ""))) (defun rg/grep-load-path (query) (interactive (let ((query (read-string (format "Grep (default %s): " (region-or-symbol-at-point)) nil 'git-grep (region-or-symbol-at-point)))) (list query))) (grep-find (mapconcat #'shell-quote-argument `("ag" "--search-zip" "--no-heading" "--no-color" ,query ,@(-filter #'f-exists? load-path)) " ")))
This gives us an interactive command where we can either the query manually, or
automatically insert the active region. Note that We’d like to use ag
specifically because of its support for searching gzip files. This is common for
elisp code in your
Folding Ergonomic with Origami¶
Not bad, but since the
load-path can be quite huge, the command inserted in
the grep output is a bit of an eye-sore. My favorite folding mode is origami,
but surely this can be done with something like
hideshow as well. First,
let’s define the folding functions:
(defun rg/find-grep-command-bounds () (save-excursion (goto-char (point-min)) (let ((start (re-search-forward "^Grep started at"))) (progn (forward-line 3) (list start (- (point) 1)))))) ;; make sure you have lexical scoping enabled for this function (defun rg/origami-grep-command (create-fold) (lambda (content) (destructuring-bind (beg end) (rg/find-grep-command-bounds) (list (funcall create-fold beg end 20 nil))))) (with-eval-after-load 'origami (add-to-list 'origami-parser-alist '(rg/origami-grep-command-style . rg/origami-grep-command)))
The gist of it being that we have a single fold spanning from our
started at" marker to the next 3 lines.
The only thing that remains is turn on this folding more and close all folds after completing the fold:
(defun rg/grep-load-path (query) (interactive (let ((query (read-string (format "Grep (default %s): " (region-or-symbol-at-point)) nil 'git-grep (region-or-symbol-at-point)))) (list query))) (let ((myb (grep-find (mapconcat #'shell-quote-argument `("ag" "--search-zip" "--no-heading" "--no-color" ,query ,@(-filter #'f-exists? load-path)) " ")))) (with-current-buffer myb (setq-local origami-fold-style 'rg/origami-grep-command-style) (origami-close-all-nodes myb))))
One annoying limitation is that the our fold settings aren’t preserved through updating the search results with (recompile). I haven’t ran into this problem enough for this issue to matter yet.
load-path is nice for gauging all that code is available to
Emacs, but what about searching what Emacs has actually loaded? This is where
load-history comes in. It should be easy enough to only search these files
with a similar command (or a prefix argument).