(or emacs irrelevant)

Ivy 0.8.0 is out

Intro

Ivy is a completion method that's similar to Ido, but with emphasis on simplicity and customizability.

New package names

Changes on MELPA

Due to multiple requests, in an attempt to simplify things a new package ivy has been released on MELPA. The old package swiper, which used to provide most of the ivy features, now only provides swiper.el and depends on ivy. The third package counsel, which provides most of the goodies using ivy hasn't been changed and is still on MELPA. All three packages have the version 0.8.0 currently.

To reiterate the dependencies:

  • ivy depends on Emacs version larger than 24.1, preferably at least 24.3 (the most common one bundled currently with Linux distributions).
  • swiper depends on ivy and provides basically 3 commands: swiper, swiper-multi and swiper-all.
  • counsel depends on swiper and provides around 50 commands for all kinds of stuff. My favorites are counsel-M-x, counsel-git-grep, counsel-rhythmbox and counsel-grep-or-swiper.

Changes on GNU ELPA

On GNU ELPA, a single package ivy-0.8.0 has replaced the previous stable version swiper-0.7.0. This package provides all the files combined of the three separate MELPA packages.

Release summary

The release consists of 282 commits over 5 months by 15 authors. The detailed Changelog is available here, thanks to the ever useful Org mode export. The raw Org file is in doc/Changelog.org in the main repository.

The detailed documentation is available as an (ivy) Info node and also in HTML form here. If anyone wants to document something that's missing there, I'd appreciate the help: simply edit doc/ivy.org and send me a PR.

Release highlights

Below, I'll highlight some of the new features.

Allow to compose collections

For example, to stack the top 10 elements of recentf on top of counsel-locate, use this code:

(defun small-test ()
  (cl-subseq recentf-list 0 10))

(ivy-set-sources
 'counsel-locate
 '((small-test)
   (original-source)))

Here, (original-source) represents the async candidates of counsel-locate. All extra sources are static - each function is called once to generate a list of strings, which will be filtered later.

See #373 for more info.

Improved documentation

If you're not yet familiar with Ivy, you can get a quick reference card by pressing C-h m during any completion session. It will pop up an Org-mode buffer that describes most of the minibuffer key bindings.

Additionally, C-o (hydra-ivy/body), which serves a quick reference as well, received a small restructuring and a new binding. Press D to go to the definition of this hydra. This is useful to see what each key does, you might even want to customize some of it.

Completion in region

From now on, ivy-mode will also set completion-in-region-function. This means that functions like:

  • C-M-i complete-symbol in many major modes,
  • TAB while in the M-: (eval-expression) minibuffer,
  • TAB in a shell buffer,

will use ivy for completion.

Many improvements to ivy-occur-mode

You can "permanently" save any completion session by pressing C-c C-o (ivy-occur). This will generate a new buffer in ivy-occur-mode with all your current candidates inserted there. Clicking or pressing f on any of the candidates in that buffer will result in the appropriate action being called with that candidate.

ivy-occur-mode.png

The *ivy-occur ...* buffers can actually be customized per collection type. Specifically for swiper, counsel-git-grep, counsel-grep and counsel-ag, the customizations are already in place that allow you to:

  • Edit the buffer with wgrep by pressing C-x C-q (ivy-wgrep-change-to-wgrep-mode).
  • Refresh the buffer due to the original files being changed by pressing g (ivy-occur-revert-buffer).

The second feature is often useful to me when I want to somehow change a symbol throughout the project. First I make a list of all occurrences via e.g. swiper and ivy-occur. After I went through some of the occurrences, I can press g to refresh the search for the same symbol and see how many I still have left.

Yet another cool feature is to press c (ivy-occur-toggle-calling) to toggle calling the action after each line movement and cycle through candidates by holding either j (ivy-occur-next-line) or k (ivy-occur-previous-line).

ivy-set-action can work on all commands

Here's the code I'm using currently in my config:

(defun ivy-insert-action (x)
  (with-ivy-window
    (insert x)))

(ivy-set-actions
 t
 '(("I" ivy-insert-action "insert")))

This allows me to press M-o I to insert the current candidate into the buffer. For instance, if I want to quote an Emacs command, I can M-x (counsel-M-x), select the command I want and press M-o I to insert it instead of calling it.

Virtual views in ivy-switch-buffer

Here, "virtual" buffer means something that's close to a buffer but not an actual buffer. If you were using the setting ivy-use-virtual-buffers, you'd have your bookmarks and recentf items available to you as virtual buffers.

The new feature allows to select a whole window configuration with many buffers inside nested horizontal and vertical splits from ivy-switch-buffer.

To use it, set ivy-views, since it's nil by default. For instance, here's what I have in my config:

(setq ivy-views
      '(("dutch + notes {}"
         (vert
          (file "dutch.org")
          (buffer "notes")))
        ("ivy {}"
         (horz
          (file "ivy.el")
          (buffer "*scratch*")))))

For a more elaborate and detailed use, see this post by Manuel Uberti.

Magic slash in file name completion

From now on, if you want to enter a directory, simply select a candidate which is a directory and press /. You can still use the old binding C-j (ivy-alt-done), but / is shorter and easier to get used to if you're switching from Ido.

Note that this does not prevent the use of old functionality like:

  • // to enter the root directory,
  • /ssh: RET to connect via TRAMP.

A better way to search with counsel-grep-or-swiper

If you've ever been annoyed with the long start-up time of swiper in huge buffers, switch to this setting:

(global-set-key "\C-s" 'counsel-grep-or-swiper)

This command will use swiper for small buffers, and counsel-grep for large buffers.

Something very similar to this command was highlighted in this post by Karl Voit.

Just to give you an idea of how fast counsel-grep is:

  • It has 0s start-up time, since it's async.
  • For a two million line file weighing 50MB produced by copying org.el a few times, it takes 0.2s to find the 17,664 occurrences of the word hook. It still takes 7.5s to search for org in that file, simply because there are 500,000 candidates and it takes time for Emacs to simply receive that input.

A list of all new commands

The new commands since 0.7.0 are: counsel-tmm, counsel-imenu, counsel-decbinds, counsel-list-processes, ivy-switch-buffer-other-window, counsel-git-stash, counsel-git-log, counsel-pt, counsel-linux-app, counsel-ace-link, counsel-esh-history, counsel-shell-history, counsel-grep-or-swiper.

If any of those sound interesting, go ahead and try them out.

Outro

Thanks to all the contributors. Happy hacking!

Extended syntax for hydra docstrings

I've been getting more and more organized in tracking my tasks and time with Org-mode. Still using the usual suspects, of course: GTD and Pomodoro, I'm just getting more diligent with them than in the previous years.

So today I wanted to prettify the good old org-agenda-view-mode-dispatch, which is bound to v in org-agenda-mode. Currently, it's just a boring static message and read-char combination. Why not do it with a hydra instead?

Here's the current full code, that uses the newly extended doc syntax:

(define-key org-agenda-mode-map
    "v" 'hydra-org-agenda-view/body)

(defun org-agenda-cts ()
  (let ((args (get-text-property
               (min (1- (point-max)) (point))
               'org-last-args)))
    (nth 2 args)))

(defhydra hydra-org-agenda-view (:hint nil)
  "
_d_: ?d? day        _g_: time grid=?g? _a_: arch-trees
_w_: ?w? week       _[_: inactive      _A_: arch-files
_t_: ?t? fortnight  _f_: follow=?f?    _r_: report=?r?
_m_: ?m? month      _e_: entry =?e?    _D_: diary=?D?
_y_: ?y? year       _q_: quit          _L__l__c_: ?l?"
  ("SPC" org-agenda-reset-view)
  ("d" org-agenda-day-view
       (if (eq 'day (org-agenda-cts))
           "[x]" "[ ]"))
  ("w" org-agenda-week-view
       (if (eq 'week (org-agenda-cts))
           "[x]" "[ ]"))
  ("t" org-agenda-fortnight-view
       (if (eq 'fortnight (org-agenda-cts))
           "[x]" "[ ]"))
  ("m" org-agenda-month-view
       (if (eq 'month (org-agenda-cts)) "[x]" "[ ]"))
  ("y" org-agenda-year-view
       (if (eq 'year (org-agenda-cts)) "[x]" "[ ]"))
  ("l" org-agenda-log-mode
       (format "% -3S" org-agenda-show-log))
  ("L" (org-agenda-log-mode '(4)))
  ("c" (org-agenda-log-mode 'clockcheck))
  ("f" org-agenda-follow-mode
       (format "% -3S" org-agenda-follow-mode))
  ("a" org-agenda-archives-mode)
  ("A" (org-agenda-archives-mode 'files))
  ("r" org-agenda-clockreport-mode
       (format "% -3S" org-agenda-clockreport-mode))
  ("e" org-agenda-entry-text-mode
       (format "% -3S" org-agenda-entry-text-mode))
  ("g" org-agenda-toggle-time-grid
       (format "% -3S" org-agenda-use-time-grid))
  ("D" org-agenda-toggle-diary
       (format "% -3S" org-agenda-include-diary))
  ("!" org-agenda-toggle-deadlines)
  ("["
   (let ((org-agenda-include-inactive-timestamps t))
     (org-agenda-check-type t 'timeline 'agenda)
     (org-agenda-redo)))
  ("q" (message "Abort") :exit t))

And here's how it looks like in action, I simply pressed v while in the agenda:

hydra-sexp-docstring.png

Since many functions that org-agenda-view-mode-dispatch calls are toggles, it makes sense for hydra-org-agenda-view to display the status of these toggles.

And it's actually convenient to toggle a whole lot of things at once, and the default red hydra keys really come in handy here.

Quick explanation of the syntax

Each head of a hydra looks like:

(key cmd &optional doc &rest plist)

The fairly new bit that I'm using here is the ability to use a sexp instead of a plain string in the doc part. This sexp will be evaluated each time the doc is re-displayed. This means that it can represent a changing variable, for instance the state of a minor mode or a variable.

And here's the best part: the doc of each head can be quoted in the hydra's docstring by using the corresponding key, e.g. ?g?. This allows to have very complex docstrings while keeping them easily aligned in a tabular format.

Here is only the hydra's docstring, copied from the above code:

_d_: ?d? day        _g_: time grid=?g? _a_: arch-trees
_w_: ?w? week       _[_: inactive      _A_: arch-files
_t_: ?t? fortnight  _f_: follow=?f?    _r_: report=?r?
_m_: ?m? month      _e_: entry =?e?    _D_: diary=?D?
_y_: ?y? year       _q_: quit          _L__l__c_: ?l?

Doesn't that look simple?

Emacs completion for launching Linux desktop apps.

I'd like to highlight the new command counsel-linux-app that I recently added to the counsel package:

counsel-linux-app-1.png

This command looks through your /usr/share/applications/*.desktop and offers to launch them, just like the launcher that you normally get when you press the super key. My current system is Ubuntu, and the launcher here is really horrible, so I'm glad to have a much faster and reliable replacement.

Here's another screenshot, I open the keyboard settings quite often:

counsel-linux-app-2.png

Using rsync in dired

Here's a code snippet I've found long ago on the internet (the source seems to be no longer accessible), that has proven valuable time and time again:

;;;###autoload
(defun ora-dired-rsync (dest)
  (interactive
   (list
    (expand-file-name
     (read-file-name
      "Rsync to:"
      (dired-dwim-target-directory)))))
  ;; store all selected files into "files" list
  (let ((files (dired-get-marked-files
                nil current-prefix-arg))
        ;; the rsync command
        (tmtxt/rsync-command
         "rsync -arvz --progress "))
    ;; add all selected file names as arguments
    ;; to the rsync command
    (dolist (file files)
      (setq tmtxt/rsync-command
            (concat tmtxt/rsync-command
                    (shell-quote-argument file)
                    " ")))
    ;; append the destination
    (setq tmtxt/rsync-command
          (concat tmtxt/rsync-command
                  (shell-quote-argument dest)))
    ;; run the async shell command
    (async-shell-command tmtxt/rsync-command "*rsync*")
    ;; finally, switch to that window
    (other-window 1)))

(define-key dired-mode-map "Y" 'ora-dired-rsync)

Lets you copy huge files and directories without Emacs freezing up and with convenient progress bar updates. That is all.

Thanks to tmtxt, the mysterious hacker-person from whom the snippet likely originated . Good luck with getting your blog back up.

Visiting URLs and issues with counsel-find-file

Many experienced Emacs users are aware of ffap command:

Find FILENAME, guessing a default from text around point. If ffap-url-regexp is not nil, the FILENAME may also be an URL.

It's a great way to open an link, if you plan things in advance. But for me it was usually C-x C-f (annoyed grunt) C-g M-x ffap RET.

Now, thanks to counsel-find-file, it's C-x C-f (anticipated annoyance, followed by a sigh of relief) M-n.

With Ivy completion, M-n calls ivy-next-history-element, which tries to

predict the history element in case you've reached history's edge. The prediction usually simply inserts thing-at-point into the minibuffer. My favorite applications of this are:

  • C-s M-n - swiper thing-at-point, to get the occurrences of the current symbol in the current file.
  • C-c j M-n - counsel-git-grep thing-at-point, to get the mentions within the current project.
  • C-c g M-n - counsel-git thing-at-point to open a file to which the current symbol links.

One thing I've recently added is the \_<...\_> wrapper for when major-mode derives from prog-mode. Since the \_< regex matches the symbol start, and \_> matches the symbol end, there's no chance of getting partial matches. You can call undo or press M-n again in case the symbol bounds aren't useful.

Finally, C-x C-f M-n can be used to open URLs. Recently, I've added functionality to counsel-find-file that allows me to also visit Github issues by simply pointing at the plain issue number, e.g. #123 in either a version-controlled file or in a Magit buffer. The command will query:

$ git remote get-url origin

and fill in all the details. So I no longer bother with bug-reference-url-format and bug-reference-mode - now it's all automatic.

It's also possible to make it work for places other than Github, for instance this code (already included in counsel) makes it work for the Emacs Git repository:

(defun counsel-emacs-url-p ()
  "Return a Debbugs issue URL at point."
  (when (and (looking-at "#[0-9]+")
             (or
              (eq (vc-backend (buffer-file-name)) 'Git)
              (memq major-mode '(magit-commit-mode))))
    (let ((url (match-string-no-properties 0))
          (origin (shell-command-to-string
                   "git remote get-url origin")))
      (when (string-match "git.sv.gnu.org:/srv/git/emacs.git"
                          origin)
        (format "http://debbugs.gnu.org/cgi/bugreport.cgi?bug=%s"
                (substring url 1))))))

(add-to-list 'ivy-ffap-url-functions 'counsel-emacs-url-p)