Arte EbrahimiBlogGitHub

Named Eshell Buffers Part 2: Decoupling from Ivy

17 August, 2019 - 2 min read

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

Now, regardless of which completion library we are using, our function will work properly. We are no longer directly dependent on the ivy completion library. Awesome!