Using prefix args in ivy actions

| categories: ivy, emacs | tags:

Table of Contents

There is a brand new feature in ivy which allows you to pass prefix args to the action functions. This change has made it into MELPA by now, so you can try it out. Check out this 1 for an emacs -Q setup that I used for this post. This installs ivy and org-ref with some minimal setup.

The video for this post can be found here: https://www.youtube.com/watch?v=Y8HHLAE_-yA

In this post I will show how to use this new feature to create an ivy selection function that inserts a citation from a bibtex file, and with a prefix arg lets you choose the type of citation to insert.

org-ref provides a function that generates candidates for selection. Each candidate is a list where the car of the list is a display string, and the cdr is an a-list of properties. I have a lot of entries in here, so it is important to have a convenient selection tool.

(setq org-ref-bibtex-files '("references.bib"))
(length (orhc-bibtex-candidates))

Here is an example of the first entry in my bibliography. We will need to extract the key from that.

(elt (orhc-bibtex-candidates) 0)

Here is the key from that entry.

(cdr (assoc "=key=" (elt (orhc-bibtex-candidates) 0)))

By default we will insert that as kitchin-2015-examp but there are other types of citations we might use too like kitchin-2015-examp. org-ref provides a list of citation types we could insert. Here they are. This somewhat complicated code just wraps the string so it fits in the blog post nicely.

(with-temp-buffer 
  (insert (format "%s" org-ref-cite-types))
  (fill-region (point-min) (point-max))
  (buffer-string))

So, we are now prepared to make a simple ivy function to query our bibliography that has a default action to insert a standard citation, but we can use a prefix to change the citation type. The prefix arg is stored in the global variable ivy-current-prefix-arg which can be checked inside the action function. We can check for it in the action function and do something different if a prefix arg is used. Here is the function.

(defun cite ()
  (interactive)
  (ivy-read "select: " (orhc-bibtex-candidates)
            :action (lambda (entry) 
                      (let ((key (cdr (assoc "=key=" entry)))
                            (type (if ivy-current-prefix-arg
                                      (ivy-read "type: " org-ref-cite-types)
                                    "cite")))
                        (with-ivy-window
                          (insert (format "%s:%s" type key)))))))

To get the default action, we run M-x cite, enter our query, select an entry and press return. To get an alternate cite type, we run M-x cite, enter the query, select an entry, then type C-u return, which will prompt you for an alternate citation type, then insert your choice and the citation. Here are some examples. kitchin-2015-examp kitchin-2015-examp kitchin-2015-examp

In summary, these aren't functions you would want to use; they don't handle a lot of the nuances of multiple citations. They are just to illustrate in a pretty simple way how easy it is to use a prefix arg in an ivy action function now!

1 Bare bones setup

This will setup the bare bones emacs that I used for this post.

(setq package-user-dir (expand-file-name "sandbox"))

(setq package-archives
      '(("melpa" . "http://melpa.org/packages/")))

(require 'package)

;;; Code:

(package-initialize)

(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

(eval-when-compile
  (require 'use-package))

(setq use-package-always-ensure t)

(use-package ivy)

(use-package org-ref
 :init 
 (setq org-ref-default-bibliography '("~/Dropbox/bibliography/references.bib"))
 :config (require 'org-ref-helm-cite))

(global-visual-line-mode 1)
(setq org-confirm-babel-evaluate nil)
(load-theme 'leuven)

Copyright (C) 2016 by John Kitchin. See the License for information about copying.

org-mode source

Org-mode version = 8.3.4

Discuss on Twitter