11 May 2019
This release consists of 109 commits done over the course of the last 3 years by me and many
contributors. Similarly to the
release, the release notes are in
Changelog.org. I recommend
reading them inside Emacs.
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.
New API functions
New functions have been added as drop-in replacements of double-dash (private) Avy functions that
were used in other packages and configs. Please replace the references to the obsolete functions.
avy-jump is a drop-in replacement of
avy-process is a drop-in replacement of
New dispatch actions
The concept of dispatch actions was introduced in 0.4.0.
Suppose you have bound:
(global-set-key (kbd "M-t") 'avy-goto-word-1)
and a word that starts with a "w" and is select-able with "a". Here's what you can do now:
- M-t w a to jump there
- M-t w x a -
avy-action-kill-move: kill the word and move there,
- M-t w X a -
avy-action-kill-stay: kill the word without moving the point,
- M-t w i a -
avy-action-ispell: use ispell/flyspell to correct the word,
- M-t w y a -
avy-action-yank: yank the word at point,
- M-t w t a -
avy-action-teleport: kill the word and yank it at point,
- M-t w z a -
avy-action-zap-to-char: kill from point up to selected point.
You can customize
avy-dispatch-alist to modify these actions, and also ensure that there's no
overlap with your
avy-keys, if you customized them.
avy-style setting: 'words
You can now customize:
And you'll see overlays like "by", "if", "is", "it", "my" for 2-letter sequences, and "can", "car",
"cog" for 3-letter sequences. You might find them easier to type than "hla", "lls" and "jhl". But
you will have to adjust your
avy-dispatch-alist, e.g. to use only upper case characters.
This is feature is a mix of
ace-window-display-mode. You'll see the overlays when
you enable this mode, so that there's less context switch when you call
Suppose you jumped to a word that starts with "a". Now you want to jump to a different word that
also starts with "a". You can use
avy-resume for this.
Additionally, you can use
avy-prev to cycle between the last
candidates. Here's an example hydra to facilitate it:
(defhydra hydra-avy-cycle ()
("j" avy-next "next")
("k" avy-prev "prev")
("q" nil "quit"))
(global-set-key (kbd "C-M-'") 'hydra-avy-cycle/body)
Big thanks to all contributors, and I hope you enjoy the new release. Happy hacking!
11 Apr 2019
I'm constantly amazed by other people's Org workflows. Now that the weekly tips are a
thing, I see more and more cool Org configs, and I'm inspired to get more organized myself.
My own Org usage is simplistic in some areas, and quite advanced in others. While I wrote a lot of
code to manipulate Org files ( worf,
org-fu, counsel), the
amount of Org files and TODO items that I have isn't huge:
(counsel-git "org$ !log")
;; 174 items
(counsel-rg "\\* DONE|CANCELLED|TODO")
;; 8103 items
Still, that's enough to get out-of-date files: just today I dug up a file with 20 outstanding TODO
items that should have been canceled last November!
How to close 20 TODOs using a timestamp in the past
When I cancel an item, pressing tc (mnemonic for TODO-Cancel), Org mode inserts a time
stamp with the current time. However, for this file, I wanted to use October 31st 2018 instead of
the current time. Org mode already has options like
org-extend-today-until that manipulate the current time for
timestamps, but they didn't fit my use case.
So I've advised
(defvar-local worf--current-effective-time nil)
(defun worf--current-effective-time (orig-fn)
(defun worf-change-time ()
"Set `current-time' in the current buffer for `org-todo'.
Use `keyboard-quit' to unset it."
(org-read-date t 'totime)
A few things of note here:
worf--current-effective-time is buffer-local, so that it modifies time only for the current
- I re-use the awesome
org-read-date for a nice visual feedback when inputting the new time
- Instead of having a separate function to undo the current-time override, I capture the
signal that C-g sends.
The above code is already part of worf and is bound to
cT. I even added it to the manual. I hope you find it useful. Happy organizing!
07 Apr 2019
Since its introduction in 2015, swiper, while nice most of the time, had two problems:
- Slow startup for large buffers.
- Candidates were lines, so if you had two or more matches on the same line, the first one was selected.
Over time, workarounds were added to address these problems.
Problem 1: slow startup
Almost right away, calling
font-lock-ensure was limited to only small enough buffers.
counsel-grep-or-swiper was introduced. It
uses an external process (
grep) to search through large files.
In 2017, I found ripgrep, which does a better
grep for searching one file:
"rg -i -M 120 --no-heading --line-number --color never %s %s")
The advantage here is that the search can be performed on very large files. The trade-off is that we
have to type in at least 3 characters before we send it to the external process. Otherwise, when the
process returns a lot of results, Emacs will lag while receiving all that output.
Problem 2: candidates are lines
swiper-avy was added, which could also be
used as a workaround for many candidates on a single line. Press C-' to visually select
any candidate on screen using avy.
Finally, less than a week ago, I wrote
swiper-isearch to fix #1931.
Differences from the previous commands:
Every candidate is a point position and not a line. The UX of going from one candidate to the next
isearch-like, I enjoy it a lot.
swiper, no line numbers are added to the candidates. This allows it to be as fast as
counsel-grep, no external process is used. So you get feedback even after inputting a
I like it a lot so far, enough to make it my default search:
(global-set-key (kbd "C-s") 'swiper-isearch)
swiper-isearch, see if it can replace
swiper for you;
counsel-grep-or-swiper still has
its place, I think. Happy hacking!
PS. Thanks to everyone who supports me on Liberapay and
PPS. Thanks to everyone who contributes issues and patches!
24 Mar 2019
For a couple years now, I use M-x
shell as my main shell. Recently, I have fixed one of
the minor annoyances that go along with using
shell in Emacs. At least since Ubuntu 18.04, the
terminal "progress bar" feature, displayed below is non-optional:
It uses terminal escape codes to display the progress bar, and
shell-mode can't handle them well,
so they clobber a lot of the output.
Initial work around
Previously, I was using this work around, since
apt-get doesn't display the progress bar:
# sudo apt upgrade
sudo apt-get upgrade
Progress bar in the mode line
But typing 4 extra chars is hard. And
apt-get will likely get these progress bars at some point as
well. So I spent around an hour of my weekend hacking an Elisp solution. Here is the code:
(defun ora-ansi-color-apply-on-region (begin end)
"Fix progress bars for e.g. apt(8).
Display progress in the mode line instead."
(let ((end-marker (copy-marker end))
(goto-char (copy-marker begin))
(while (re-search-forward "\0337" end-marker t)
(setq mb (match-beginning 0))
(when (re-search-forward "\0338" end-marker t)
(delete-and-extract-region mb (point))
(defun ora-apt-progress-message (progress)
"Progress: \\[ *\\([0-9]+\\)%\\]" progress)
(concat ":%s "
(match-string 1 progress)
The solution will detect e.g.
"\0337...Progress: [ 25%]...\0338", remove it from the shell buffer
"25%" in the mode line instead.
Use the Echo Area instead of the mode line
The above is a good enough solution specifically for
apt(8), but not for the generic case. Let's
try to emulate how e.g.
gnome-terminal handles these escape sequences. It takes sequences like
"\0337.*\0338" and displays them in the bottom of the window. Kind of like the Emacs Echo
Area. That's easy enough to do:
(defun ora-apt-progress-message (progress)
Above, we use
ansi-color-apply to get rid of any extra terminal escape codes. I decided to stay
with the Echo Area version instead of the mode line version. Here's how it looks like:
You can find all of the above code in my config.
05 Mar 2018
I like Git. A lot. After years of use it has
really grown on me. It's (mostly) fast, (often) reliable, and (always)
distributed. For me, all properties are important, but being able to
git init to start a new project in seconds is the best feature.
When it comes to working with Git day-to-day, a nice GUI can really
make a difference. In Emacs world, of course it's
Magit. Outside of Emacs (brr),
git-cola looks to be the most promising
one. If you're aware of something better, please share - I'm keeping a
list of suggestions for my non-Emacs using colleagues.
Ivy integration for Git
The main two commands in ivy
that I use for Git are:
counsel-git: select a file tracked by Git
counsel-rg: grep for a line in all files tracked by Git, using
ripgrep as the backend.
There are many alternatives to
counsel-rg that use a different
counsel-rg is the fastest, especially when I have
to deal with Git repositories that are 2Gb in size (short explanation:
it's a Perforce repo with a bunch of binaries, because why not; and
I'm using git-p4 to interact with
.ignore with ripgrep
.ignore file to the root of your project can really speed
up your searches. In my sample project, I went from 10k files to less
than 500 files.
As you can see, both file patterns and directories are supported. One
other nifty thing that I discovered only recently is that you can use
ripgrep as the backed for
counsel-git in addition to
counsel-rg. Which means the same
.ignore file is used for both
commands. Here's the setting:
(setq counsel-git-cmd "rg --files")
And here's my setting for
"rg -i -M 120 --no-heading --line-number --color never %s .")
The main difference in comparison to the default
-M 120 which means: truncate all lines
that are longer than 120 characters. This is really helpful when Emacs
is accepting input from
ripgrep: a megabyte long line of minified JS
is not only useless since you can't see it whole, but it will also
likely hang Emacs for a while.
I hope you found these bits of info useful. Happy hacking!