New feature in Ivy - ivy-occur
04 Nov 2015I've had an idea with this feature for quite some time, and only
recently got to finally implement it. So here it goes: with
ivy-occur, bound to C-c C-o while in the minibuffer, you
can store almost Ivy any
completion session in progress, and you can have as many of them as
you like.
Example 1
This is where the command name originates from: swiper + ivy-occur
= occur. You can store all of swiper's matching lines into a
separate buffer. This doesn't give too much advantage over the
good-old occur, the only thing is that you can use ivy-style regexps
with wild spaces, and have an interactive preview beforehand. Having
said that, it actually sounds pretty good!
Example 2
I press C-S-o, bound to counsel-rhythmbox, and enter
u2. After pressing C-c C-o, bound to ivy-occur, the
completion session is closed (effectively C-g), and a new
buffer *ivy-occur counsel-rhythmbox "u2"* is generated with all
songs that match u2.
As a reminder, counsel-rhythmbox has two actions: play (the
default) and enqueue. In this new buffer, pressing RET or
mouse-1 will call the play action (since it was active at the
moment ivy-occur was called) for the current candidate. So I've
effectively added a playlist functionality to counsel-rhythmbox
through a generic command.
Note that it's very easy to identify a completion session by the
command name and input. So I can distinguish e.g. *ivy-occur
counsel-rhythmbox "u2"* and *ivy-occur counsel-rhythmbox "ัะบัั"*,
and quickly select them with ivy-switch-buffer: just input rhy,
usually only these two and similar buffers will match.
Example 3
Suppose I want to go through the documentation of all variables that
end in -function. Easy:
- <f1> v (
counsel-describe-variable) with inputfunction$. - C-c C-o (
ivy-occur).
I get a new buffer named *ivy-occur cousnel-describe-variable
"function$*" with 346 candidates. I can go through them at my own
pace, possibly doing other completion stuff in between without
disturbing my process. It's also convenient to navigate these buffers
with swiper.
Example 4
Let's tweak the previous one. After inputting function$ I can press
C-M-a (ivy-read-action) followed by d to
select the definition action. Then again C-c C-o
(ivy-occur). Pressing RET in the resulting buffer will
take me to that variable's definition, instead of describing it as
before. A similar thing could be done for counsel-rhythmbox to get
the enqueue action in *ivy-occur* buffer, instead of play.
Example 5
This is an improvement to my workflow for quickly looking at a new
package's features. This can be done with oge
(lispy-goto-elisp-commands) from
lispy, which scans the source for
(interactive) tags and allows to jump to their definition.
It's a pretty cool optimization, compared to looking at all tags. For
example, projectile currently
has 375 top-level tags (functions and variables). But with
lispy-goto-elisp-commands I only get 48 tags. And now I can have
them in a convenient permanent list too.

Alternatively, if projectile is already loaded, I can use
counsel-M-x with input projectile-, followed by C-M-a d
to select the definition action, followed by C-c C-o.
As a reminder of how it works, counsel-M-x is defined with a single
action that calls the selected command. But then, I've also added this
statement at top-level of counsel.el:
(ivy-set-actions
'counsel-M-x
'(("d" counsel--find-symbol "definition")))
This means that you can add as many actions as you like to ivy-read
commands. And of course customize the binding and the hint, which are
in this case d and definition respectively.
Limitations
Unfortunately, since the *ivy-occur* buffer needs to know the action
to execute, it only works for commands that explicitly pass :action
to ivy-read. For instance, it won't work for package-install with
ivy-mode on: the buffer will be properly generated, but pressing
RET won't install a package.
Fortunately, it's not hard to write a version that works:
(defun counsel-package-install ()
(interactive)
(ivy-read "Install package: "
(delq nil
(mapcar (lambda (elt)
(unless (package-installed-p (car elt))
(symbol-name (car elt))))
package-archive-contents))
:action (lambda (x)
(package-install (intern x)))
:caller 'counsel-package-install))
Here's a buffer with a list of packages matching "ga"; pressing RET will install the selected package:

Small note on key bindings
In the initial post, I wanted to bind ivy-occur to C-c o
instead of C-c C-o. But I was reminded that C-c LETTER are
reserved.
I still think it's a better binding. If you agree, you can add it to your config:
(define-key ivy-minibuffer-map (kbd "C-c o") 'ivy-occur)
Additionally, ivy-occur is also available on C-o u,
through the C-o hydra.
Outro
I think ivy-occur is a very powerful command that shouldn't be
overlooked. Just as ivy-resume implements a sort of DEL
or C-u key for completion, ivy-occur implements a
convenient way to switch and store the completion context, a sort of
C-x o or C-x b for completion.