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 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
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.
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!