(or emacs irrelevant)

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)

avy 0.4.0 is out

This release consists of 77 commits done over the course of the last 7 months by me and many contributors. Similarly to the 0.3.0 release, the release notes are in Changelog.org. You can read them either at github or inside Emacs. Big thanks to all contributors.

avy.png

Highlights

A lot of new code is just straight upgrades, you don't need to do anything extra to use them. Below, I'll describe the other part of the new code, which is new commands and custom vars.

avy-goto-char-timer

This command now allows as many characters as you like, which makes it similar to a isearch + avy-isearch combination. As you type, you get an isearch-like highlight, then after a short delay you automatically get the avy selection.

Switch the action midway from goto to kill/mark/copy

This is similar to the cool feature of ace-window that allows you to switch the action after you get the avy prompt.

For example, suppose you have:

(global-set-key (kbd "M-t") 'avy-goto-word-1)

Here's what you can do now to a word that starts with a "w" and is select-able with "a":

  • To jump there: M-t w a.
  • To copy the word instead of jumping to it: M-t w na
  • To mark the word after jumping to it: M-t w ma.
  • To kill the word after jumping to it: M-t w xa.

You can customize avy-dispatch-alist to modify these actions, and also ensure that it plays nicely with your avy-keys, if you customized them. By default, it works fine, since avy-keys is '(?a ?s ?d ?f ?g ?h ?j ?k ?l) and the keys on avy-dispatch-alist are '(?x ?m ?n).

avy-pop-mark

This command reverses avy-push-mark which most of avy commands call. It has its own history and works across multiple windows and frames. I'm using it currently as an upgrade to my old (set-mark-command 4) lambda:

(global-set-key (kbd "M-p") 'avy-pop-mark)

Here's a line to make avy-pop-mark work also for swiper:

(advice-add 'swiper :before 'avy-push-mark)

Using Emacs as system-wide Rhythmbox interface

In an earlier post, I described how I've been managing Rhythmbox from Emacs. I've bound the entry point to C-S-o:

(global-set-key (kbd "C-S-o") 'counsel-rhythmbox)

Obviously, this entry point won't work while outside Emacs. Today, I'll describe how I've made it work everywhere. Everywhere on Ubuntu 14.04, that is, although a similar approach should work for other distributions.

Step 1: Make sure the Emacs server is running

Here's the relevant part of my init.el:

(require 'server)
(or (server-running-p) (server-start))

Using emacsclient is essential to avoiding the extra startup time: even a startup time of one second feels sluggish when all I need is to open a menu with a song playlist.

Step 2: Install the relevant X window tool

Initially, I only wrote a call to emacsclient, which resulted in the Emacs window gaining focus in the end. Then I thought it would be nice to give the focus back the original window after the end of selection, and raise it as well.

I wanted to do something with wmctrl, but I found that xdotool can do what I want in a simple way.

sudo apt-get install xdotool

Step 3: Write a shell script

#!/bin/bash
wnd_id="$(xdotool getwindowfocus)"
emacsclient --eval "(progn (x-focus-frame nil) (counsel-rhythmbox))"
xdotool windowfocus $wnd_id
xdotool windowraise $wnd_id

Here, (x-focus-frame nil) will raise the Emacs window and give the keyboard input focus. emacsclient will return as soon as I select something or press C-g. At that point the keyboard focus will be returned to whatever window had it when the script was invoked.

By the way, here's a cool configuration that automatically makes a file executable if it starts with #!.

(add-hook
 'after-save-hook
 'executable-make-buffer-file-executable-if-script-p)

Step 4: Bind the shell script to a key

Open this (possibly using gnome-control-center instead, if applicable):

unity-control-center keyboard

And add a new shortcut in Shortcuts/Custom Shortcuts. I've bound that one to C-S-o as well.

The final result

It's pretty convenient: as I'm scrolling something I'm reading in Firefox with j (via Firemacs), I can seamlessly press C-S-o moo RET to play "Sisters of the Moon", and continue scrolling the web page with j.

What's more, Emacs has very nice support for input methods with C-\ (toggle-input-method), so I can also quickly select Ukrainian-titled songs, while still keeping shortcuts like C-n and C-m (without having to switch the input method back).

The whole experience is similar to gnome-do/synapse, which I was using a few years back, except better because now it's in Emacs.