In the last post How to Find Just About Anything On Your Computer With Emacs Part 1 I introduced a search hydra with a variety of functions and a few additional windows focused programs.
In this post, I'll comment on some of those functions, and introduce the emacs set-up code for counsel and ivy-rich.
But first, here is emacs anzu code, which I use instead of query-replace-regexp.
After remapping, anzu-query-replace-regexp is one of the functions I use the most. It's great for replacing text and expressions.
Anzu Mode Find and Replace
;show number of matches
(use-package anzu
:diminish
:config
(global-anzu-mode +1)
(global-set-key [remap query-replace] 'anzu-query-replace)
(global-set-key [remap query-replace-regexp] 'anzu-query-replace-regexp)
:hook
(after-init . global-anzu-mode)
);end anzu
;find and replace expressions in an emacs buffer
(global-set-key (kbd "M-&") 'query-replace-regexp)
Swiper
I used to use the emacs default buffer search function, which searches through text directly in the active buffer, moving from position to position and recentering the buffer.
I switched to Swiper last year. Swiper operates in the minibuffer, and shows a condensed list of lines with matches. I like this, but I still haven't gotten entirely used to it, especially the part where ending your search and starting again moves you back to the start of the matches list.
I suspect there are some tricks to working with Swiper I've yet to explore, but anyway, here's the code.
(use-package swiper
:bind* (("C-s" . swiper)
;("C-r" . swiper)
("C-M-s" . swiper-all))
:bind
(:map read-expression-map
("C-r" . counsel-minibuffer-history))
);end swiper
Before I show my counsel and ivy-rich set-up, let's talk about the main functions I use from the search Hydra I presented in the last post.
Main Functions I Use From the Search Hydra in Last Post
80% of the time I navigate with bookmarks and swiper to frequently used dired locations, like desktop, downloads, dropbox, document directories, or key project or storage git repos.
I often use either counsel-ibuffer, ibuffer, or counsel-buffer-or-recentf to search through open buffers.
When I want to search for text or code in directory I jump to that directory with a bookmark and use 'ag' from the search hydra.
In the past for some reason I didn't use 'ag' to search files recursively. I seem to recall some problem with it I had to fix or searching for a recursive elisp function on the webs.
It seems to work recursively now, and probably has been working recursively for quite some time because I search directory files recursively a lot.
ag-files (not ag-file!), thanks for pointing that out, is even better than 'ag,' because it's also recursive and you can narrow down your selections with file endings.
I will either navigate to a bookmarked directory and use Swiper or Ag, or use helm-org-rifle-agenda-files, which searches through files you've marked in your org init code as agenda files.
The org package is probably one of my largest initialization sections, and I don't think I've posted it (good things to come).
But in it, I set some agenda directories (path locations to directories on my computer where I capture and store data using org-capture.)
I have many blocks of org related code outside the org use-package declaration wrapped in `(with-eval-after-load 'org ` code, which delays initialization until after org loads.
(with-eval-after-load 'org
(setq org-directory (list
org-journal
org-agenda
org-clients
));end org directory
(setq cur_dir "agenda")
(defun pos-set-agenda-files ()
(interactive)
(cond
; if cmd-shell set to bash
((equal cur_dir "agenda")
(progn
;equal
(setq org-agenda-files (list org-dir-science)); dropbox comp sci files
(setq cur_dir "science")
(message "Agenda files set to: c:/Users/Methuselah/Dropbox/shared/computer-science-notes/ , toggle again for orgfiles")
);end progn
;else
);end cond 1
;if agenda
((equal cur_dir "science")
(progn
(setq org-agenda-files (list org-dir-p )); dropbox comp sci files
(setq cur_dir "orgfiles")
(message "Agenda files set to: C:/Users/Methuselah/Dropbox/documents/orgfiles/ toggle again for agenda files")
));end cond 2
;if science
((equal cur_dir "orgfiles")
(progn
;equal
(setq org-agenda-files (list org-agenda org-clients org-journal)); dropbox agenda files
(setq cur_dir "agenda")
(message "Agenda files set to just: ..orgfiles/agenda/, ..orgfiles/journal/, orgfiles/clients/, toggle again for science files")
));end cond 3
;else set to agenda
(t (progn
(setq org-agenda-files (list org-agenda org-clients org-journal)); dropbox agenda files
;equal
(setq cur_dir "agenda")
(message "Agenda files set to just: ..orgfiles/agenda/, ..orgfiles/journal/, orgfiles/clients/, toggle again for science files")
))
);end conditional
);end pos set agenda files directory
(setq org-agenda-files (list
org-journal
org-agenda
org-clients
));endo org agenda
)
In above, org-agenda-files is set to `org-journal`, `org-agenda`, or `org-clients`, which are physical directories (and git repos) with files on my hard drives.
pos-set-agenda-files cycles and sets the active org-agenda directory `please don't judge my code, time is short, it works`
Then I use helm-org-rifle-agenda-files to query agenda files like a data base.
It also works with :tags:, which can be added to every header via a capture system.
And of course there are many other ways of querying files for tags. I typically just use bookmark and ag or swiper, along with helm-org-rifle-agena-files and pos-set-agenda-files.
What about GitHub ‘Copilot’, the AI-Powered Code Completion Tool
I'm just mentioning this because modern code editors are getting super slick.
Emacs is a pretty massive code base and I don't know a ton about it under the hood. Respectfully speaking, that level of elisp is outside my wheelhouse. However, I suspect emacs will require a pretty major overhaul to keep pace with Vs Code, or Github Codespaces.
I'm really grateful there are people that work on that because they can. And I wish the best in terms of funding and recognition for emacs developers the world over!
Having said that, to the extent AI completion will radically improve programming, one suspects the technology will go open source.
If that happens, a Holy Grail will appear and in the best case scenerio an Elisp hero will put together a package that utilises it, and earn global notoriety.
Personally, even though my emacs completion is satisfactory and I no longer really use Atom of Vs Code, I suspect the completion packages are one of the key emacs package categories that could use an overhaul.
Counsel
Note: Counsel serves up great info on faces, colors, libraries, and functions.
Here's my configuration:
(use-package counsel
;:ensure t
:after ivy
:config
; Don't start searches with ^
(setq ivy-initial-inputs-alist nil)
(counsel-mode)
;show org-tags in counsel searches
(setq counsel-org-headline-display-tags t)
;show org-todos in counsel searches
(setq counsel-org-headline-display-todo t)
(define-key ivy-switch-buffer-map (kbd "C-d") 'mu-ivy-kill-buffer)
;ivy-todo calls org-set-tags-command, remap to counsel-org-tag
(global-set-key [remap org-set-tags-command] #'counsel-org-tag)
:bind (
([remap describe-function] . counsel-describe-function)
([remap describe-command] . helpful-command)
([remap describe-variable] . counsel-describe-variable)
([remap describe-key] . helpful-key)
("M-x" . counsel-M-x)
("C-x b" . counsel-switch-buffer)
("C-x C-b" . counsel-ibuffer)
("C-x C-m" . counsel-imenu) ;headers level 1
("C-x C-d" . counsel-bookmarked-directory)
("C-x f" . helm-org-rifle-current-buffer)
("C-x r" . helm-org-rifle)
("C-x C-r" . counsel-recentf)
("C-x C-f" . counsel-find-file)
("C-h b" . counsel-descbinds)
("M-y" . counsel-yank-pop)
("M-SPC" . counsel-shell-history)
:map minibuffer-local-map
("C-r" . 'counsel-minibuffer-history)
("C-d" . ivy-switch-buffer-kill); d for delete
);end bind
);end counsel
Counsel Locate Everything
Counsel locate everything is actually just `counsel-locate` configured for use with everything.exe.
I set everything.exe path to a variable called `everything-p` and use a custom (very simple) function to launch everything.exe before called counsel-locate.
Actually, a lot of times I just use everything.exe from its GUI.
I really like everything.exe because I can't stand it when windows indexing gets into my memory usuage, so I turn that off.
Actually, that's the same reason I don't use projectile, even though you can configure the indexing and set dedicated directories, I find it requires either indexing of some sort or manual attention. So no projectile for me, bookmarks are good enough.
(setq everything-launched 0)
(defun launch-everything ()
(interactive)
(w32-shell-execute nil everything-p nil )
);end launch-excel
(defun pos-counsel-locate()
(interactive)
(if (= everything-launched 0)
(progn
(launch-everything)
(counsel-locate)
(setq everything-launched 1)
);end progn
);end if
(counsel-locate)
);end pos-helm-locate
Counsel Web
This can enable web search in buffers (using eww or the newer linux browser frameworks).
I actually only use eww when I want to rip text from the web, so I don't even use counsel-web.
(use-package counsel-web
;:ensure t
:commands (counsel-web-suggest counsel-web-search)
:config
:disabled
;as opposed to in emacs
(setq counsel-web-search-action #'browse-url)
;alternate browser
;(setq counsel-web-search-alternate-action #'w3m)
(setq counsel-web-engine 'google)
;(setq counsel-web-engine 'duckduckgo)
;counsel-web-engine-alist
;update search results with each key press: experimental
(setq counsel-web-search-dynamic-update t)
);
ivy-rich
Super cool. Check it out.
(use-package ivy-rich
:after (:and ivy counsel)
;:ensure t
;:commands (counsel-mode)
:init
(setcdr (assq t ivy-format-functions-alist) #'ivy-format-function-line)
(ivy-rich-mode)
:config
;these are david wilsons configurations
(setq ivy-format-function #'ivy-format-function-line)
(setq ivy-rich-display-transformers-list
(plist-put ivy-rich-display-transformers-list
'ivy-switch-buffer
'(:columns
((ivy-rich-candidate (:width 40))
(ivy-rich-switch-buffer-indicators (:width 4 :face error :align right)); return the buffer indicators
(ivy-rich-switch-buffer-major-mode (:width 12 :face warning)) ; return the major mode info
(ivy-rich-switch-buffer-project (:width 15 :face success)) ; return project name using `projectile'
(ivy-rich-switch-buffer-path (:width (lambda (x) (ivy-rich-switch-buffer-shorten-path x (ivy-rich-minibuffer-width 0.3)))))) ; return file path relative to project root or `default-directory' if project is nil
:predicate
(lambda (cand)
(if-let ((buffer (get-buffer cand)))
;; Don't mess with EXWM buffers
(with-current-buffer buffer
(not (derived-mode-p 'exwm-mode))))))))
;:hook
;(after-init . ivy-rich-mode)
);end ivy-rich
custom ivy-rich
If you you switch from Helm to Ivy, you may have difficulty getting icons in the minibuffer. You can use 'use-package emacs' to enter custom code that will up the aesthetics that keep you going.
(use-package emacs
:after (ivy-rich all-the-icons-ivy-rich)
:config
;; Toggle `ivy-rich-mode' after modifying `ivy-rich-display-transformers-list'.
(setq ivy-rich-display-transformers-list
`(ivy-switch-buffer
(:columns ((all-the-icons-ivy-rich-buffer-icon)
(ivy-switch-buffer-transformer
(:width 0.2))
(ivy-rich-switch-buffer-major-mode
(:width 18 :face warning))
(ivy-rich-switch-buffer-project
(:width 15 :face success))
(ivy-rich-switch-buffer-indicators
(:width 4 :face error :align right))
(ivy-rich-switch-buffer-size
(:width 7))
(ivy-rich-switch-buffer-path
(:width (lambda (x)
(ivy-rich-switch-buffer-shorten-path
x (ivy-rich-minibuffer-width 0.2))))))
:predicate (lambda
(cand)
(get-buffer cand))
:delimiter " ")
ivy-switch-buffer-other-window
(:columns ((all-the-icons-ivy-rich-buffer-icon)
(ivy-rich-candidate
(:width 30))
(ivy-rich-switch-buffer-size
(:width 7))
(ivy-rich-switch-buffer-indicators
(:width 4 :face error :align right))
(ivy-rich-switch-buffer-major-mode
(:width 18 :face warning))
(ivy-rich-switch-buffer-project
(:width 15 :face success))
(ivy-rich-switch-buffer-path
(:width (lambda
(x)
(ivy-rich-switch-buffer-shorten-path
x (ivy-rich-minibuffer-width 0.3))))))
:predicate (lambda
(cand)
(get-buffer cand))
:delimiter " ")
counsel-switch-buffer
(:columns ((all-the-icons-ivy-rich-buffer-icon)
(ivy-rich-candidate
(:width 30))
(ivy-rich-switch-buffer-size
(:width 7))
(ivy-rich-switch-buffer-indicators
(:width 4 :face error :align right))
(ivy-rich-switch-buffer-major-mode
(:width 18 :face warning))
(ivy-rich-switch-buffer-project
(:width 15 :face success))
(ivy-rich-switch-buffer-path
(:width (lambda
(x)
(ivy-rich-switch-buffer-shorten-path
x (ivy-rich-minibuffer-width 0.3))))))
:predicate (lambda
(cand)
(get-buffer cand))
:delimiter " ")
counsel-projectile-switch-to-buffer
(:columns ((all-the-icons-ivy-rich-buffer-icon)
(ivy-rich-candidate
(:width 30))
(ivy-rich-switch-buffer-size
(:width 7))
(ivy-rich-switch-buffer-indicators
(:width 4 :face error :align right))
(ivy-rich-switch-buffer-major-mode
(:width 18 :face warning))
(ivy-rich-switch-buffer-project
(:width 15 :face success))
(ivy-rich-switch-buffer-path
(:width (lambda
(x)
(ivy-rich-switch-buffer-shorten-path
x (ivy-rich-minibuffer-width 0.3))))))
:predicate (lambda
(cand)
(get-buffer cand))
:delimiter " ")
counsel-switch-buffer-other-window
(:columns ((all-the-icons-ivy-rich-buffer-icon)
(ivy-rich-candidate
(:width 30))
(ivy-rich-switch-buffer-size
(:width 7))
(ivy-rich-switch-buffer-indicators
(:width 4 :face error :align right))
(ivy-rich-switch-buffer-major-mode
(:width 18 :face warning))
(ivy-rich-switch-buffer-project
(:width 15 :face success))
(ivy-rich-switch-buffer-path
(:width (lambda
(x)
(ivy-rich-switch-buffer-shorten-path
x (ivy-rich-minibuffer-width 0.3))))))
:predicate (lambda
(cand)
(get-buffer cand))
:delimiter " ")
package-install
(:columns ((ivy-rich-candidate (:width 30))
(ivy-rich-package-version (:width 16 :face font-lock-comment-face)) ; package version
(ivy-rich-package-archive-summary (:width 7 :face font-lock-builtin-face)) ; archive summary
(ivy-rich-package-install-summary (:face font-lock-doc-face)))) ; package description
persp-switch-to-buffer
(:columns ((all-the-icons-ivy-rich-buffer-icon)
(ivy-rich-candidate
(:width 30))
(ivy-rich-switch-buffer-size
(:width 7))
(ivy-rich-switch-buffer-indicators
(:width 4 :face error :align right))
(ivy-rich-switch-buffer-major-mode
(:width 18 :face warning))
(ivy-rich-switch-buffer-project
(:width 15 :face success))
(ivy-rich-switch-buffer-path
(:width (lambda
(x)
(ivy-rich-switch-buffer-shorten-path
x (ivy-rich-minibuffer-width 0.3))))))
:predicate (lambda
(cand)
(get-buffer cand))
:delimiter " ")
counsel-M-x
(:columns ((all-the-icons-ivy-rich-function-icon)
(counsel-M-x-transformer
(:width 50))
(ivy-rich-counsel-function-docstring
(:face font-lock-doc-face))))
counsel-describe-function
(:columns ((all-the-icons-ivy-rich-function-icon)
(counsel-describe-function-transformer
(:width 50))
(ivy-rich-counsel-function-docstring
(:face font-lock-doc-face))))
counsel-describe-variable
(:columns ((all-the-icons-ivy-rich-variable-icon)
(counsel-describe-variable-transformer
(:width 50))
(ivy-rich-counsel-variable-docstring
(:face font-lock-doc-face))))
counsel-set-variable
(:columns ((all-the-icons-ivy-rich-variable-icon)
(counsel-describe-variable-transformer
(:width 50))
(ivy-rich-counsel-variable-docstring
(:face font-lock-doc-face))))
counsel-apropos
(:columns ((all-the-icons-ivy-rich-symbol-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-info-lookup-symbol
(:columns ((all-the-icons-ivy-rich-symbol-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-descbinds
(:columns ((all-the-icons-ivy-rich-keybinding-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-find-file
(:columns ((all-the-icons-ivy-rich-file-icon)
(ivy-read-file-transformer))
:delimiter " ")
counsel-file-jump
(:columns ((all-the-icons-ivy-rich-file-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-dired
(:columns ((all-the-icons-ivy-rich-file-icon)
(ivy-read-file-transformer))
:delimiter " ")
counsel-dired-jump
(:columns ((all-the-icons-ivy-rich-file-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-el
(:columns ((all-the-icons-ivy-rich-symbol-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-fzf
(:columns ((all-the-icons-ivy-rich-file-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-git
(:columns ((all-the-icons-ivy-rich-file-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-recentf
(:columns ((all-the-icons-ivy-rich-file-icon)
(ivy-rich-candidate
(:width 0.2))
(ivy-rich-file-last-modified-time
(:face font-lock-comment-face)))
:delimiter " ")
counsel-buffer-or-recentf
(:columns ((all-the-icons-ivy-rich-file-icon)
(counsel-buffer-or-recentf-transformer
(:width 0.2))
(ivy-rich-file-last-modified-time
(:face font-lock-comment-face)))
:delimiter " ")
counsel-bookmark
(:columns ((ivy-rich-bookmark-type)
(all-the-icons-ivy-rich-bookmark-name
(:width 40))
(ivy-rich-bookmark-info))
:delimiter " ")
counsel-bookmarked-directory
(:columns ((all-the-icons-ivy-rich-file-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-package
(:columns ((all-the-icons-ivy-rich-package-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-fonts
(:columns ((all-the-icons-ivy-rich-font-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-major
(:columns ((all-the-icons-ivy-rich-function-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-find-library
(:columns ((all-the-icons-ivy-rich-library-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-load-library
(:columns ((all-the-icons-ivy-rich-library-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-load-theme
(:columns ((all-the-icons-ivy-rich-theme-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-world-clock
(:columns ((all-the-icons-ivy-rich-world-clock-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-tramp
(:columns ((all-the-icons-ivy-rich-tramp-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-git-checkout
(:columns ((all-the-icons-ivy-rich-git-branch-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-list-processes
(:columns ((all-the-icons-ivy-rich-process-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-projectile-switch-project
(:columns ((all-the-icons-ivy-rich-file-icon)
(ivy-rich-candidate))
:delimiter " ")
projectile-persp-switch-project
(:columns ((all-the-icons-ivy-rich-file-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-projectile-find-file
(:columns ((all-the-icons-ivy-rich-file-icon)
(counsel-projectile-find-file-transformer))
:delimiter " ")
counsel-projectile-find-dir
(:columns ((all-the-icons-ivy-rich-project-icon)
(counsel-projectile-find-dir-transformer))
:delimiter " ")
counsel-minor
(:columns ((all-the-icons-ivy-rich-mode-icon)
(ivy-rich-candidate))
:delimiter " ")
counsel-imenu
(:columns ((all-the-icons-ivy-rich-imenu-icon)
(ivy-rich-candidate))
:delimiter " ")
treemacs-projectile
(:columns ((all-the-icons-ivy-rich-file-icon)
(ivy-rich-candidate))
:delimiter " ")))
);end ivy-custom-ivy-rich
That's all for the search hydra.
Keep in mind that's a windows configuration, on your linux box you will obviously use grep or some other linux search program.