(or emacs irrelevant)

Customizing ace-window leading char

With a recent change, it's now possible to customize ace-window like this:

(custom-set-faces
 '(aw-leading-char-face
   ((t (:inherit ace-jump-face-foreground :height 3.0)))))

Here's how it will look like:

ace-window-lead.png

It's slightly annoying that the buffer contents have to shift to accommodate for a larger character, but there's no way around it. Besides, you can customize the face features other than height, like foreground and background colors etc.

Note that in the screenshot, I'm using my usual ace-window setup, i.e. home row keys and no background:

(use-package ace-window
    :init
    (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l))
    (setq aw-background nil))

Compilation-style check-declare-file

As a follow-up to my older post on Elisp linting options, I've made check-declare-file and check-declare-directory give out warnings similar to those that e.g. byte-compile-file gives:

  • each warning now has a location in a file-line-column format
  • you can click on the link to jump to the warning location
  • first-error / next-error / previous-error work as well
  • the warning line blinks momentarily with each jump

Here's how it looks like:

check-declare

You can already use this feature if you're on Emacs trunk, otherwise you'll have to wait for 25.1 to come out.

There's also a new custom variable that you can set to get a more strict check:

(setq check-declare-ext-errors t)

Unless you set it, the standard behavior is to issue a "skipping external file" message when checking a statement like the one above. The reason is that the external package might not be loaded or something. As long as I'm checking, I prefer to check everything, so there's no reason not to have check-declare-ext-errors always true.

A trick to actually load slime-repl

Here's the Makefile target for check-declare:

check-declare:
    $(CASKEMACS) -batch $(LOAD) -l check-declare.elt

And here are the contents of check-declare.elt:

(setq check-declare-ext-errors t)
(setq files '("lispy.el"
              "lispy-inline.el"
              "le-clojure.el"
              "le-scheme.el"
              "le-lisp.el"))
(add-to-list 'load-path
             (concat (file-name-directory
                      (locate-library "slime"))
                     "contrib/"))
(require 'slime-repl)
(apply #'check-declare-files files)

As you see, I first find where slime.el is located using locate-library, and then add the contrib sub-directory to the load-path. After this, it's finally possible to (require 'slime-repl).

Rectangle-mode Hydra

Today, I'll show a very useful hydra that I found yesterday on the hydra wiki. The idea is by @zhaojiangbin, I've made some minor changes to get the arrows to work the way that I like, and made all keys into plain letters.

The code

(defun ora-ex-point-mark ()
  (interactive)
  (if rectangle-mark-mode
      (exchange-point-and-mark)
    (let ((mk (mark)))
      (rectangle-mark-mode 1)
      (goto-char mk))))

(defhydra hydra-rectangle (:body-pre (rectangle-mark-mode 1)
                           :color pink
                           :post (deactivate-mark))
  "
  ^_k_^     _d_elete    _s_tring     |\\     ‗,,,--,,‗
_h_   _l_   _o_k        _y_ank       /,`.-'`'   .‗  \-;;,‗
  ^_j_^     _n_ew-copy  _r_eset     |,4-  ) )‗   .;.(  `'-'
^^^^        _e_xchange  _u_ndo     '---''(‗/.‗)-'(‗\‗)
^^^^        ^ ^         _p_aste
"
  ("h" backward-char nil)
  ("l" forward-char nil)
  ("k" previous-line nil)
  ("j" next-line nil)
  ("e" ora-ex-point-mark nil)
  ("n" copy-rectangle-as-kill nil)
  ("d" delete-rectangle nil)
  ("r" (if (region-active-p)
           (deactivate-mark)
         (rectangle-mark-mode 1)) nil)
  ("y" yank-rectangle nil)
  ("u" undo nil)
  ("s" string-rectangle nil)
  ("p" kill-rectangle nil)
  ("o" nil nil))

(global-set-key (kbd "C-x SPC") 'hydra-rectangle/body)

There was a lot of screen estate left over, so I added some ASCII-art. I wanted something related to syrup, or at least pancakes, but instead I found a cat. Apparently, it's very easy to find pictures of cats on the internet. Who knew.

Here's how it looks like in-action:

hydra-rectangle

The pink variation is pretty useful here, since it doesn't get in the way of e.g. DEL or C-n or C-e or inserting spaces.

I've been using it today for editing some table data in org-mode, and it feels pretty efficient.

Some explanations

What does what:

  • d deletes rectangle; it's similar to C-d.
  • n copies rectangle; it's similar to M-w.
  • o exits; it's very easy to press.
  • e exchanges the point and mark; it's also quite useful to re-activate the region if you disabled it with n or r.
  • s fills the selected rectangle with a string.
  • y yanks the rectangle that you saved before with n.
  • r deactivates or activates the rectangle at point.
  • u calls undo.
  • p kills the rectangle; it's similar to C-w.

Profile your Emacs start-up time

I bet I could compete for the shortest ~/.emacs ever:

(load "~/Dropbox/source/site-lisp/init")

However, it being one line doesn't make it start up any faster. Here's what I have in my Makefile beside init.el:

profile:
    emacs -Q -l git/profile-dotemacs/profile-dotemacs.el \
    --eval "(setq profile-dotemacs-file \
        (setq load-file-name \"$(abspath init.el)\"))" \
    -f profile-dotemacs

The package that I'm using, profile-dotemacs.el comes from David Engster, one of the major contributors to CEDET, so you know it's got to be good. Once you launch it as I showed above, it will give you the times that various sections took to load in an overlay.

On very sunny days I can almost get Emacs to start under one second, although when I checked just now, it turned out to be 1.20s. I value short start up time very highly, since due to my messing with Elisp, the Emacs global state can become so messed up that it's a lot faster to just restart it, rather than spend 10 minutes surgically restoring the state. And, of course, it's a bonus for using Emacs on a laptop, which I do at home.

I've used two methods to shorten the boot time, I'll describe them below.

use-package :idle option

This one is a big time saver, since org-mode just takes so long to load:

(use-package org
    :defer t
    :idle (require 'oleh/org))

I'm cautious not to abuse :idle, since if it happens that I start Emacs and start frantically typing all over the place, Emacs will never get to be idle and the :idle statements won't load. So I only use it for org and one or two other things.

autoloading stuff

Here's some helper code for this:

(defun update-all-autoloads ()
  (interactive)
  (cd emacs-d)
  (let ((generated-autoload-file
         (expand-file-name "loaddefs.el")))
    (when (not (file-exists-p generated-autoload-file))
      (with-current-buffer (find-file-noselect
                            generated-autoload-file)
        (insert ";;")
        (save-buffer)))
    (mapcar #'update-directory-autoloads
            '("" "oleh" "oleh/modes"))))

Here, emacs-d is the directory of my init.el. The directory modes contains 44 Elisp files for each major mode or package that I customize.

For instance, here are the contents of Info.el:

(define-key Info-mode-map "j" 'ora-para-down)
(define-key Info-mode-map "k" 'ora-para-up)
(define-key Info-mode-map "v" 'recenter-top-bottom)
(define-key Info-mode-map "h" 'backward-char)
(define-key Info-mode-map "l" 'forward-char)
(define-key Info-mode-map "w" 'forward-word)
(define-key Info-mode-map "b" 'backward-word)
(define-key Info-mode-map "a" 'beginning-of-line)
(define-key Info-mode-map "e" 'end-of-line)
(define-key Info-mode-map "A" 'beginning-of-buffer)
(define-key Info-mode-map "E" 'end-of-buffer)

;;;###autoload
(defun oleh-Info-hook ())

This is one of the simpler ones, I think it would take around a week of posts to cover what I have in magit.el. The file Info.el never gets loaded until I open a buffer in Info-mode. Here's what gets loaded every time:

(load (concat emacs-d "loaddefs.el") nil t)
;; ...
(add-hook 'Info-mode-hook 'oleh-Info-hook)

My loaddefs.el is just over 1000 lines and is automatically generated by update-all-autoloads. And here are the lines in loaddefs.el responsible for loading Info.el:

(autoload 'oleh-Info-hook "oleh/modes/Info" "\


\(fn)" nil nil)

So the statements above are cheap to load. Actually, the largest chunk of my start up time, 28 percent, is taken by:

(require 'eclipse-theme)

I don't know why it takes so long to call custom-theme-set-faces, it's a mystery.

Hydra 0.11.0 is out

As usual, I'll just re-state the release notes and add some more notes in the end.

Fixes

  • Emacs 24.3 (and maybe earlier versions) compatibility added
  • (hydra-cleanup): Should not delete buffer first when window is dedicated.
  • (lv-message): Should not deactivate mark.
  • quit signals are intercepted, so that proper clean-up is done.
  • no defuns with the same name will be generated in case some heads' cmd parts coincide

New Features

Pink body color

When body color is pink, and hydra intercepts a binding which isn't a head, instead of quitting the hydra and executing the binding (default red behavior), it will execute the binding and not quit the hydra. This type of hydra is very similar to define-minor-mode.

So now, pink and amaranth are body colors that are a flavor of the default red that, instead of quitting when a non-head binding is intercepted, respectively run the binding or issue a warning.

Teal body color

Teal color behaves similarly to amaranth (issues a warning when intercepting foreign bindings), but the default behavior for each head is to quit.

The following evaluates to true:

(equal
 (macroexpand
  '(defhydra hydra-test (:color amaranth)
    ("a" fun-a)
    ("b" fun-b :color blue)
    ("c" fun-c :color blue)
    ("d" fun-d :color blue)
    ("e" fun-e :color blue)
    ("f" fun-f :color blue)))
 (macroexpand
  '(defhydra hydra-test (:color teal)
    ("a" fun-a :color red)
    ("b" fun-b)
    ("c" fun-c)
    ("d" fun-d)
    ("e" fun-e)
    ("f" fun-f))))

So if you want to write less, use teal color in this case.

Alternative color-less syntax

The color syntax is working quite well, since I was able to keep an almost full backward-compatibility: once you pinpoint a color it will have that behavior, all the new behaviors will be released under a new color.

Some might prefer an alternative set of switches rather than colors. New compat switches are:

- ":exit nil" for ":color red"; You don't have to specify either
  option in the body, since they are the default behavior that was
  available on Hydra release
- ":exit t" for ":color blue"
- ":foreign-keys warn" for ":color amaranth"
- ":foreign-keys warn :exit t" for ":color teal"
- ":foreign-keys run" for ":color pink"

The property :exit can be inherited and overridden in the same way as :color red or blue.

The following evaluates to true:

(equal
 (macroexpand
  '(defhydra hydra-test ()
    ("a" fun-a)
    ("b" fun-b :color blue)
    ("c" fun-c :color blue)
    ("d" fun-d :color blue)
    ("e" fun-e :color blue)
    ("f" fun-f :color blue)))
 (macroexpand
  '(defhydra hydra-test (:color blue)
    ("a" fun-a :color red)
    ("b" fun-b)
    ("c" fun-c)
    ("d" fun-d)
    ("e" fun-e)
    ("f" fun-f))))

The following two are exactly the same as the two above:

(equal
 (macroexpand
  '(defhydra hydra-test ()
    ("a" fun-a)
    ("b" fun-b :exit t)
    ("c" fun-c :exit t)
    ("d" fun-d :exit t)
    ("e" fun-e :exit t)
    ("f" fun-f :exit t)))
 (macroexpand
  '(defhydra hydra-test (:exit t)
    ("a" fun-a :exit nil)
    ("b" fun-b)
    ("c" fun-c)
    ("d" fun-d)
    ("e" fun-e)
    ("f" fun-f))))

Ruby-style string interpolation in docstrings

Here's an example:

(defhydra hydra-marked-items (dired-mode-map "")
  "
Number of marked items: %(length (dired-get-marked-files))
Auto-revert mode is:    %`auto-revert-mode
"
      ("m" dired-mark "mark"))

To enable this behavior, the docstring has to start with a newline (which will be stripped). This makes sense, since you usually want to align extensive docstrings, like I did this one. The escape syntax for variables is such that you can auto-complete them with company-mode. Both variables and sexps can use format style width specifiers. See the documentation of format for more details.

Examples 7-9 added to hydra-examples.el

These examples explain Ruby-style interpolation.

Updated faces

I've updated each face to match their color by default. Remember, that you can customize each face interactively with M-x customize-group hydra.

Alternative grey-scale or custom faces

If you don't want colors for some reason, you can customize hydra-fontify-head-function to your taste.

As an example:

(setq hydra-fontify-head-function
      #'hydra-fontify-head-greyscale)

This function is already defined in hydra.el, but you could define a similar one on your own:

(defun hydra-fontify-head-greyscale (head body)
  "Produce a pretty string from HEAD and BODY.
HEAD's binding is returned as a string wrapped with [] or {}."
  (let ((color (hydra--head-color head body)))
    (format
     (if (eq color 'blue)
         "[%s]"
       "(%s)") (car head))))

New switch :body-pre

This sexp or function will be prepended to the prefix/body function. Here's an example of use:

(defvar hydra-vi/init-pos nil)
(defhydra hydra-vi (:body-pre (setq hydra-vi/init-pos (point))
                    :color pink)
  "vi"
  ;; arrows
  ("h" backward-char)
  ("j" next-line)
  ("k" previous-line)
  ("l" forward-char)
  ;; exit points
  ("q" (goto-char hydra-vi/init-pos) "ins" :exit t)
  ("C-n" (forward-line 1) nil :exit t)
  ("C-p" (forward-line -1) nil :exit t))

Here, upon entering the hydra, the point position will be saved. And upon quitting, it will be restored.

Outro

I hope that you're enjoying the new updates as much as I do. Since the last release, there are two new blog posts about using hydra that I'm aware of: by Howard Abrams and John Kitchin.

Additionally, @hura, @kaushalmodi, and @glucas have made some additions to the Hydra wiki. Anyone is welcome to share their useful hydras there. Thanks a lot and happy hacking!