(or emacs irrelevant)

Search for things with apropos

Until recently, I didn't even know that apropos was an actual word. I thought that it was just some gibberish that Emacs hackers invented to name a command. Turns out, it actually has a very appropriate meaning:

apropos

preposition

with reference to; concerning.

An apropos Hydra

I've just added this one to hydra-examples.el.

(defhydra hydra-apropos (:color blue
                         :hint nil)
  "
_a_propos        _c_ommand
_d_ocumentation  _l_ibrary
_v_ariable       _u_ser-option
^ ^          valu_e_"
  ("a" apropos)
  ("d" apropos-documentation)
  ("v" apropos-variable)
  ("c" apropos-command)
  ("l" apropos-library)
  ("u" apropos-user-option)
  ("e" apropos-value))

I recommend to bind it like this:

(global-set-key (kbd "C-c h") 'hydra-apropos/body)

Customary screenshot:

hydra-apropos.png

As you can see, there are a total of 7 apropos functions available. The most useful ones are apropos, apropos-command and apropos-variable. But apropos-value is very interesting as well: it will not match an object name with the input, but instead search for all objects whose contents match input. So, for instance, if you see something like "error 42" come up, and you don't know where it's coming from, it's likely that some variable holds the value 42. And that's when you use apropos-variable.

Apropos is like old-school googling, and I find it highly useful in finding the Emacs information that I need. I hope that you will find it useful as well. Happy hacking!

More on swiper and ivy

I'll describe two new things in swiper and ivy that happened within the day. Although you can install them separately from MELPA, they still live in a single git repository.

swiper / ivy faces now inherit the standard ones

It's a good idea by @purcell, and I tend to agree. So now, there are six faces that inherit highlight, isearch-lazy-highlight-face, isearch and match faces between them. The advantage is that most themes re-define the above four faces as they see fit, so the swiper faces will fit in better without customization.

Still, I really enjoy the previous faces that were derived from the Swiper sprite. You can have them as part of eclipse-theme. The theme creators can just copy them verbatim to a light theme if they so choose.

By the way, it seems that not all Emacs users are aware that you can customize faces. You can do so interactively for most popular packages. For example, after M-x customize-group swiper, you get a GUI for selecting most configurable things for swiper, including the faces.

The GUI will generate the code that looks something like this:

(custom-set-faces
  '(ivy-current-match ((t (:background "#e5b7c0")))))

Elisp completion with ivy

The code to complete Elisp code at point is very simple:

(defun counsel ()
  "Elisp completion at point."
  (interactive)
  (let* ((bnd (bounds-of-thing-at-point 'symbol))
         (str (buffer-substring-no-properties (car bnd) (cdr bnd)))
         (candidates (all-completions str obarray))
         (ivy-height 7)
         (res (ivy-read (format "pattern (%s): " str)
                        candidates)))
    (when (stringp res)
      (delete-region (car bnd) (cdr bnd))
      (insert res))))

The only function above that isn't one of the familiar primitives is ivy-read. But even that one has a similar interface to that of completing-read or ido-completing-read. I was using helm-lisp-completion-at-point before, but counsel is much less obtrusive, while offering comparable speed and convenience:

counsel-1.png

The default minibuffer height for ivy is set to 10 via ivy-height. It's quite reasonable all-around, but for counsel I've set it to 7 via a let binding.

Swiper now has an ivy back end

Intro

Just three days ago, I wrote swiper and introduced it in a post. And while swiper solved the problem of helm-swoop being awkward for me to use, swiper's code itself is pretty awkward, since even after using helm a dozen times in my packages, I'm still not well-versed in its internals.

And, apparently, there are people who don't like helm because it updates a lot. I don't know if it counts as a viable complaint, but I do agree that the helm update time is quite long. So I wrote down an alternative completion back end for swiper. It looks quite similar to ido-vertical-mode, although it is completely unrelated to ido. In fact, the matching algorithm currently is similar to helm-match-plugin: "for example" is transformed into "\\(for\\).*\\(example\\)".

swiper-ivy.png

The Details

Currently, in the ivy version of swiper only the anchoring algorithm is missing. Anchoring is what I call the process of selecting a close candidate when the number of candidates changes. It seems that helm doesn't implement an anchoring algorithm, so both helm-swoop and swiper implement their own. I don't know how easy it would be to write down the proper generic thing, my current implementation for the helm version of swiper is quite hacky.

Just to explain to you what needs to be done. Suppose there's an input "ab" that matches 50 candidates, and the candidate number 42 is the current one. Now, if the user types one char to make the input into "abc", the number of candidates has changed to 10, and the candidate that was current previously doesn't match any more. It is up to the matcher code to decide which of the 10 candidates has to be current now. Usually it doesn't matter much, but in the case of swiper it matters since the point will be moved to the current candidate in the original window.

In any case, there's still a lot of things that have to be done for ivy, but I think that it's quite usable now. Actually, I've already added it to my bindings:

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

Here's how it looks like:

ivy-swiper-1.png

And here's an example of completion in dired:

ivy-swiper-2.png

You need to have Emacs 24.4 in order to get a nicer highlight in the minibuffer that uses add-face-text-property instead of the old propertize.

There's a custom variable that decides the height of the minibuffer window, you can set it as you like:

(defcustom ivy-height 10
  "Number of lines for the minibuffer window."
  :type 'integer)

Outro

Give the new back end a go, see if you like it. It looks quite pretty and minimalist to me, but I'm biased since I made it.

ace-window display mode

Intro

Today, I'll describe a quite recent addition to ace-window, which comes from the idea by @deftsp:

Why not show the ace-window dispatch keys in the mode line all the time?

Certainly, there's no reason not to have this option, and it actually makes the whole interface better, since it becomes less feedback-based:

  • You glance at a window that you want.
  • You know which key you have to press before you call ace-window
  • You make a single-step call instead of:
    • press ace-window shortcut,
    • read the dispatch char,
    • press the dispatch char.

The feature is implemented as ace-window-display-mode - a minor mode that you can toggle on or off whenever you feel like it.

Here's how it looks like:

ace-window-display-mode.png

As you can see, I've made aw-keys list short on purpose, just to show you that the full path will be displayed. See, for instance, the *scratch* window: its path is gf.

Implementation

Since the implementation is quite short, I'll post it here and go over a few things that might interest people who write Elisp (on some level, please don't mock me for being obvious).

As per request of a curious reader, I've updated the code with the comments from below. Don't try this at home, excessive commenting is bad style.

;; Something that modifies the Emacs behavior should
;; preferrably be implemented as a minor mode.
;;;###autoload
(define-minor-mode ace-window-display-mode
    "Minor mode for showing the ace window key in the mode line."
  ;; And since this minor mode isn't tied to a particular
  ;; buffer, I declare it as global.
  ;;
  ;; An interesting quirk is that I have to put *something*
  ;; between the docstring and the body, otherwise it won't
  ;; work.
  :global t
  ;; Dispatch on the variable symbol of the mode -
  ;; `ace-window-display-mode`.  `define-minor-mode' will
  ;; define both a variable and function symbol.
  (if ace-window-display-mode
      (progn
        ;; Update the window parameters
        (aw-update)
        ;; Since `mode-line-format' is a buffer-local
        ;; variable, I set it with `set-default', in order
        ;; for the change to not just happen in the current
        ;; buffer.
        (set-default
         'mode-line-format
         `((ace-window-display-mode
            (:eval (window-parameter (selected-window)
                                     'ace-window-path)))
           ,@(default-value 'mode-line-format)))
        (force-mode-line-update t)
        ;; Each time a window is created or deleted, Emacs
        ;; will run the `window-configuration-change-hook' -
        ;; exactly what I need to update `mode-line-format'.
        (add-hook 'window-configuration-change-hook 'aw-update))
    (set-default
     'mode-line-format
     (assq-delete-all
      'ace-window-display-mode
      (default-value 'mode-line-format)))
    (remove-hook 'window-configuration-change-hook 'aw-update)))

(defun aw-update ()
  "Update ace-window-path window parameter for all windows."
  (avy-traverse
   (avy-tree (aw-window-list) aw-keys)
   (lambda (path leaf)
     ;; Use `set-window-parameter' to store a variable for
     ;; each window.  Buffer local variables would not work
     ;; here, since one buffer can be displayed in multiple
     ;; windows, and those would need a different key each.
     (set-window-parameter
      leaf 'ace-window-path
      (propertize
       (apply #'string (reverse path))
       'face 'aw-mode-line-face)))))

Since I'm writing something that modifies Emacs behavior when it's enabled, I first try to implement it as a minor mode. And since this minor mode isn't tied to a particular buffer, I declare it as global.

An interesting quirk is that I have to put something between the docstring and the body, otherwise it won't work. In this case, I put :global t.

Next, follows that standard dispatch on the variable symbol of the mode - ace-window-display-mode. The define-minor-mode macro will make both variable and function definition for the symbol it's given:

  • the variable is used to check if the mode is on.
  • the function is used to turn the mode on / off.

Note the use of assq-delete-all: this is for when some other package modifies the mode-line-format after ace-window does. In that case, ace-window's entry wouldn't be the first one any more.

Since mode-line-format is a buffer-local variable, I set it with set-default, in order for the change to not just happen in the current buffer.

Each time a window is created or deleted, Emacs will run the window-configuration-change-hook - exactly what I need to update mode-line-format.

One final trick is to use set-window-parameter to store a variable for each window. Buffer local variables would not work here, since one buffer can be displayed in multiple windows, and those would need a different key each.

I really like how the avy-tree / avy-traverse interface ended up as: the same functions are used for selecting window and setting mode-line-format.

Outro

I hope that you enjoy the update, and keep those interesting ideas coming!

Some git / magit / github tricks

Of course, I mean illusions not tricks.

Illusion 1: jump to a magit repository

This is just a copy-paste of the code from this post by Iqbal Ansari.

(setq magit-repo-dirs
      (mapcar
       (lambda (dir)
         (substring dir 0 -1))
       (cl-remove-if-not
        (lambda (project)
          (unless (file-remote-p project)
            (file-directory-p (concat project "/.git/"))))
        (projectile-relevant-known-projects))))

Basically it's just taking projectile's record of known projects, and then filtering it by whether that project has .git in its root.

To get a selection of repositories, call with C-u M-x magit-status. And don't forget to choose ido completion:

(setq magit-completing-read-function 'magit-ido-completing-read)

And here's how I use this in a dispatch:

(defhydra hydra-helm (:color blue)
  "helm"
  ("f" projectile-find-file "file")
  ("w" helm-org-wiki "wiki")
  ("g" (let ((current-prefix-arg 4))
         (call-interactively #'magit-status))
       "git")
  ("l" helm-locate "locate")
  ("q" nil "quit"))
(global-set-key "κ" 'hydra-helm/body)

If you're wondering what the letter in global-set-key is, it's the Greek letter kappa (see the post on my Xmodmap setup).

Illusion 2: quickly get Github pull requests on your system

I learned this from some HN post that I can't find now. Basically, you have to open your .git/config file and find the following contents:

[remote "origin"]
    url = [email protected]:abo-abo/hydra.git
    fetch = +refs/heads/*:refs/remotes/origin/*

Then, modify it by adding one line (same for all repositories):

[remote "origin"]
    url = [email protected]:abo-abo/hydra.git
    fetch = +refs/heads/*:refs/remotes/origin/*
    fetch = +refs/pull/*/head:refs/pull/origin/*

Now, if you issue:

git fetch --all

You can operate on your pull requests like so:

git merge refs/pull/origin/20

Here, 20 is the issue number. And after merging I finally get access to magit and ediff and all that jazz to see what the change is actually about. Before I learned this, I had to manually add remotes with magit-add-remote. And even before that, I was just clicking the merge button after thoughtfully browsing the diff in Firefox. Trust me, ediff is orders of magnitude better.

Illusion 3: edit a Github wiki in Emacs

Of course, I was always editing it in Emacs with It's All Text Firefox plugin. But when I wanted to add an image, I actually read the manual and found out that you can simply clone the wiki:

git clone https://github.com/abo-abo/hydra.wiki.git

Or with the ssh style, in order to not type the user name and password on pushing:

git clone [email protected]:abo-abo/hydra.wiki.git

By the way, today I've made a very large overhaul of hydra's README.md. So if you wanted to start writing your own hydras, but were hesitant because of the lack of documentation, now is the time to start.

If you figure out something that you think is worth documenting, you can immediately leave it on the wiki. By the way, here's the syntax for including an image, if you were wondering:

![hydra-helm](images/hydra-helm-unite.png)

You upload a file simply by adding it to the repository. Look Ma, no Imgur!

This is actually an issue that I ran into, when I was less experienced. I included some one megabyte gifs in the lispy repository to refer to them in README.md. Just a few of them resulted in a very uncomfortable cloning time, which is an issue for Travis CI and, you know, humans. Finally, I had to resort to bfg-repo-cleaner to remove the gifs from the repo history. It could all be avoided if I just posted all images on the wiki and linked to them in README.md.

Outro

I hope that you find these illusions useful to make you a better Emacs magician. Happy hacking!