In my previous blog post, Named Eshell Buffers, we discussed how we can create named eshell buffers by utilizing a completion library (ivy). In this post, we will improve upon our previous solution by decoupling our function from ivy by using the completing-read function.

Minibuffer Completion

The completing-read function in emacs is the basic interface which reads from the minibuffer to provide completion from a list of candidates. Some commonly used completion libraries include ivy, helm, and ido. These completion libraries replace the completing-read function with their own implementation, by setting the completing-read-function variable.

Improving Our Previous Solution

Now, since we know that completing-read is the general interface used by emacs for completion, we can take advantage of it and refactor our previous solution. This will allow our eshell-with-name function to be extended to the currently selected completion library in emacs, rather than being tied to ivy exclusively.

Here's the refactored code:

( defun eshell-with-name ( ) ( interactive ) ( let* ( ( eshell-buffer-names ( mapcar ( lambda ( buf ) ( buffer-name buf ) ) ( buffer-list ) ) ) ( match ( completing-read "eshell buffers: " eshell-buffer-names ( lambda ( buf ) ( string-match-p "*eshell*" buf ) ) ) ) ( eshell-buffer-exists ( member match eshell-buffer-names ) ) ) ( if eshell-buffer-exists ( switch-to-buffer match ) ( eshell 99 ) ( rename-buffer ( concat "*eshell*<" match ">" ) ) ) ) )

What Did We Change?

Here's the major change from our previous solution:

( completing-read "eshell buffers: " eshell-buffer-names ( lambda ( buf ) ( string-match-p "*eshell*" buf ) ) )

Here, we pass the list of buffer names into completing-read rather than to ivy-read to match a completion. Also, we now pass our filter function into completing-read 's optional predicate argument, rather than filtering the buffer list beforehand.

Final Thoughts