Thanks to @dotemacs for organizing the event and inviting me.
Thanks to @dotemacs for organizing the event and inviting me.
Ivy is a completion method that's
Ido, but with emphasis on simplicity and customizability.
The current release constitutes of
339 commits and almost a full
year of progress since
0.8.0. Many issues ranging
to #946 were fixed.
The number of people who contributed code as grown
Changelog.org has been a part of the repository since
can get the details of the current and past changes:
Many improvements are incremental and don't require any extra code to enable. I'll go over a few selected features that require a bit of information to make a good use of them.
ivy completions, pressing M-o allows to execute
one of the custom actions for the current command. Now you have an
option to use hydra for selecting
an action. Use this code to turn on the feature:
One big advantage of the new interface is that you can peak at the action list with M-o without dismissing the candidate list. Press M-o again to go back to candidate selection without selecting an action.
Here's some code from my config that ensures that I always have some extra actions to choose from:
(defun ora-insert (x) (insert (if (stringp x) x (car x)))) (defun ora-kill-new (x) (kill-new (if (stringp x) x (car x)))) (ivy-set-actions t '(("i" ora-insert "insert") ("w" ora-kill-new "copy")))
counsel-rg joins the group of grepping commands in
wraps around the newly popular and very
fast ripgrep shell tool.
A nice improvement to the grepping commands is the ability to specify
extra flags when you press C-u (
command. See this gif
for an example of excluding
*.el from the files searched by
Press M-o b to change the current directory to one of the virtual buffers' directories. You continue to select a file from that directory.
Press M-o r to find the current file as root.
You can now customize
#652 for using this to
counsel-git-log work on Windows.
counsel-info-lookup-symbolnow substitutes the built in
shell-commandnow gives you completion of your previous history.
Use the new
counsel-yank-pop-separator variable to make
There was breaking change for alist type collections some months
ago. Right now the action functions receive an
item from the
collection, instead of
(cdr item) like before. If anything breaks,
the easy fix is to add an extra
cdr to the action function.
Unique index for alist completion was added. The uniqueness assumption
is that the completion system is passed a list of unique strings, of
which one (or more) are selected. Unlike plain string completion,
alists may require violating the uniqueness assumption: there may be
two elements with the same
car but different
cdr. Example: C
function declaration and definition for tag completion. Until now,
whenever two equal strings were sent to
ivy-read, only the first one
could be selected. Now, each alist car gets an integer index assigned
to it as a text property
'idx. So it's possible to differentiate two
alist items with the same key.
Action functions don't require using
with-ivy-window anymore. This
allows for a lot of simplification, e.g. use
insert instead of
(lambda (x) (with-ivy-window (insert x))).
You can now customize faces in
ivy-switch-buffer by the mode of each buffer.
Here's a snippet from my config:
(setq ivy-switch-buffer-faces-alist '((emacs-lisp-mode . swiper-match-face-1) (dired-mode . ivy-subdir) (org-mode . org-level-4)))
Looks neat, I think:
swiper-include-line-number-in-search if you'd like to
match line numbers while using
Offers completion for
bookmark-jump. Press M-o d to
delete a bookmark and M-o e to edit it.
A custom option
counsel-bookmark-avoid-dired, which is off by
default, allows to continue completion for bookmarked
directories. Turn it on with:
(setq counsel-bookmark-avoid-dired t)
and when you choose a bookmarked directory, the choice will be
counsel-find-file instead of opening a
Completion for colors by name:
The colors are displayed in the minibuffer, it looks really cool:
You also get 108 shades of grey to choose from, for some reason.
Completion for faces by name:
Shows the history of the Emacs commands executed and lets you select and eval one again. See #826 for a nice screenshot.
company's candidates and inserts the result into the buffer.
Jump to a directory or a file in the current directory.
Wrap around the popular system package managers.
Install or uninstall Emacs packages with completion.
Navigate the current buffer's mark ring.
Navigate the current buffer's tags.
Navigate the current buffer's outlines.
Completion for the last hydra's heads.
Completion for headlines of files in your
Again, thanks to all the contributors. Happy hacking!
Recently, I've had to code some C++ at work. And I saw it as a good opportunity to step up my Emacs' IDE game. I've eschewed clang-based tools until now, but GCC isn't adding AST support any time soon, and CEDET is too slow and too clumsy with macros for the particular project that I had. Here's the line in Eigen that broke the camel's back. Basically it's 30 lines of macros that expand to 30 lines of typedefs. Maybe it's a valid implementation choice, I'd rather avoid the macros altogether, but in any case I couldn't get CEDET to parse that.
The first thing I tried
was rtags. My project was
CMake-based, so I just put this line in my subdirectory
cmake: cd ../build && cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 ..
-DCMAKE_EXPORT_COMPILE_COMMANDS=1 causes a
compile_commands.json file to be emitted during the actual
compilation. This file describes the compile flags for every source
file. These flags are essential in helping the parser understand
what's going on.
Then, in the
build directory I start:
rdm & jc -J .
rtags-find-symbol-at-point should work now. I still like to
use CEDET as backup, it's pretty good at tracking variables
defined in the current function:
(defun ciao-goto-symbol () (interactive) (deactivate-mark) (ring-insert find-tag-marker-ring (point-marker)) (or (and (require 'rtags nil t) (rtags-find-symbol-at-point)) (and (require 'semantic/ia) (condition-case nil (semantic-ia-fast-jump (point)) (error nil))))) (define-key c++-mode-map (kbd "M-.") 'ciao-goto-symbol) (define-key c++-mode-map (kbd "M-,") 'pop-tag-mark)
For my other C++ projects which aren't CMake-based, I use the
excellent bear tool to emit the
compile_commands.json file. It's as easy as:
make clean bear make
It didn't take long to figure out that
rtags isn't great at
completion. I almost accepted that's just the way it is. But this
morning I decided to make some changes and
try irony-mode. And it
worked beautifully for completion! What's ironic, is that
goto-symbol, so the time spent to figure out
was worth it.
Here's my Irony setup; I only changed the C-M-i binding to
the newly written
counsel-irony, now available in the
package on MELPA:
(add-hook 'c++-mode-hook 'irony-mode) (add-hook 'c-mode-hook 'irony-mode) (defun my-irony-mode-hook () (define-key irony-mode-map [remap completion-at-point] 'counsel-irony) (define-key irony-mode-map [remap complete-symbol] 'counsel-irony)) (add-hook 'irony-mode-hook 'my-irony-mode-hook) (add-hook 'irony-mode-hook 'irony-cdb-autosetup-compile-options)
And here are some screenshots of
First of all, the completion is displayed inline, similarly to modern IDEs. You can use all of Ivy's regex tricks to complete your candidate:
Note how the power of regex matching allows me to narrow the initial
1622 candidates to only 22 functions that have
arguments. One of the candidates is cut off for being longer than the
window width. You can still match against the invisible text, but you
won't see it. It's possible to use C-c C-o (
store the current candidates into a buffer:
Clicking the mouse on any of the lines in the new buffer will insert the appropriate symbol into the C++ buffer.
I'd like to thank the authors of
irony-mode for these
nice packages. Hopefully,
counsel-irony is a nice addition. Happy
ediff.el --- a comprehensive visual interface to diff & patch
The premise is quite simple: press e in
immediately ediff two marked files, no questions asked:
(define-key dired-mode-map "e" 'ora-ediff-files)
And here's the code, with a few bells and whistles:
;; -*- lexical-binding: t -*- (defun ora-ediff-files () (interactive) (let ((files (dired-get-marked-files)) (wnd (current-window-configuration))) (if (<= (length files) 2) (let ((file1 (car files)) (file2 (if (cdr files) (cadr files) (read-file-name "file: " (dired-dwim-target-directory))))) (if (file-newer-than-file-p file1 file2) (ediff-files file2 file1) (ediff-files file1 file2)) (add-hook 'ediff-after-quit-hook-internal (lambda () (setq ediff-after-quit-hook-internal nil) (set-window-configuration wnd)))) (error "no more than 2 files should be marked"))))
Some notes on how the extra code adds convenience:
In case no files are marked, the file at point is used as the first
read-file-name is used for the second file. Since I
have the magic
(setq dired-dwim-target t) in my config, in case a
dired buffer is open,
offer it as the starting directory during completion. Very useful
to compare two files in two different directories.
Depending on the order of the arguments to
changes will appear either as added or removed;
file-newer-than-file-p tries to put the arguments in a logical
order by looking at the files' last change times.
ediff-after-quit-hook-internal is used to restore the previous
window configuration after I quit
ediff with q.
That's about it. Hopefully, it's useful. Happy hacking.
make-it-so is an old package of mine that I haven't yet highlighted on the blog. This package helps you manage a collection of makefiles that are used to generate new files from existing files using shell commands.
You can think of these makefiles as a directory of shell functions, arranged by the extension of the files that they operate on:
$ cd make-it-so && find recipes -name Makefile recipes/ipynb/to-md/Makefile recipes/ogv/crop/Makefile recipes/ogv/trim/Makefile recipes/ogv/to-gif/Makefile recipes/pdf/to-txt/Makefile recipes/md/to-org/Makefile recipes/md/to-html/Makefile recipes/cue/split/Makefile recipes/dot/to-png/Makefile recipes/m4a/to-mp3/Makefile recipes/flac/to-mp3/Makefile recipes/gif/gifsicle/Makefile recipes/svg/to-png/Makefile recipes/chm/to-pdf/Makefile recipes/txt/encode-utf8/Makefile recipes/mp4/to-mp3/Makefile recipes/mp4/trim/Makefile recipes/mp4/replace-audio/Makefile recipes/png/to-gif/Makefile
When you call
make-it-so on a particular file, you get completion
for the recipes that are available for that file extension, along with
an option to create a new recipe.
Suppose you want to convert a PDF file
test.pdf to a text file
In case the recipe is in your collection, you don't have to remember the command or the command switches to do it anymore:
diredand press , (bound to
to-txtis already provided.
Your file and the makefile recipe are moved to the staging area:
The makefile is opened in a new buffer with the following bindings:
mis-save-and-compile) will run
test.txtin the current directory.
mis-finalize) will finalize the operation, moving
test.txtto the parent directory (where
test.pdfwas before), and deleting the staging directory.
mis-abort) will move
test.pdfback to its initial location and delete all generated files. This command is effectively an
It takes a large chunk of text to describe everything, but the key sequence for doing all this is quite short:
I'll describe the process of creating a high quality gif like this one, which describes the effect of the C key in lispy:
First, I use kazam to take two
screenshots of my Emacs screen:
$ ls -1 *.png Screenshot 2017-02-25 16:14:49.png Screenshot 2017-02-25 16:15:10.png
I plan to use gifsicle to sequence
the still images into a gif. But it only takes
gif as the input
format, so first I have to convert my
png files to non-animated
I open the
dired buffer where they are located and mark them with
dired-mark). Then call
make-it-so with ,
to-gif recipe. This recipe has no parameters, so there's
nothing else to do but f5 C-,. Two new files are created:
$ ls -1 *.png *.gif Screenshot_2017-02-25 16:14:49.gif Screenshot_2017-02-25 16:14:49.png Screenshot_2017-02-25 16:15:10.gif Screenshot_2017-02-25 16:15:10.png
Note that the file names (the defaults of
kazam) are problematic
when used with makefiles, since they contain spaces and colons. The
Elisp layer of
make-it-so takes care of that. It renames the files
back and forth so that the logic in the makefiles remains simple.
Next, I mark the two
gif files using *%
dired-mark-files-regexp), press , once more and select
gifsicle recipe. I'm presented a makefile with the following
# ——— parameters ————————————————————————————————— # delay between frames in hundredths of a second delay = 60 # ——— implementation ————————————————————————————— DIRGIF = $(shell ls *.gif | grep -v anime.gif) all: anime.gif anime.gif: Makefile $(DIRGIF) rm -f anime.gif gifsicle --delay=$(delay) --colors=256 --loop $(DIRGIF) > $@ echo $@ >> provide clean: rm -f anime.gif provide install-tools: sudo apt-get install gifsicle .PHONY: all install-tools clean
The most commonly useful parameter, the delay between frames, is
nicely documented at the top. I don't have to remember that the switch
--delay or that the switch style
--delay=60 is used. I
simply change the number above until I get the result that I want.
As a sample scenario, assume you want to convert *.svg to *.png.
An internet search leads to Stack Overflow and this command:
inkscape -z -e test.png -w 1024 -h 1024 test.svg
Navigate to the file(s) in
dired and call
,. No default actions are available, so just type "to-png"
and hit RET. The "to-" prefix signifies that this is a
conversion, adapting the Makefile to this form:
# This is a template for the Makefile. # Parameters should go in the upper half as: # width = 200 # and be referenced in the command as $(width) # ____________________________________________ DIRSVG = $(shell dir *.svg) DIRPNG = $(DIRSVG:.svg=.png) all: clean Makefile $(DIRPNG) %.png: %.svg echo "add command here" echo $@ >> provide clean: rm -f *.png provide # Insert the install command here. # e.g. sudo apt-get install ffmpeg install-tools: echo "No tools required" .PHONY: all install-tools clean
If the action name doesn't have a "to-" prefix, the transformation is assumed to be e.g. "svg" -> "out.svg". You can change this of course by editing the Makefile.
In case the command needs additional packages in order to work you
might want to change
echo "No tools required" to the appropriate
package install instruction, e.g.
sudo apt-get install inkscape.
When you're on a new system, this will serve as a reminder of what you should install in order for the Makefile to work. Simply call:
echo "add command here" with:
inkscape -z -e $@ -w $(width) -h $(height) $^
height will go to the top of the
Makefile, where they can be customized.
$@ refers to the output file,
test.png in this case.
$^ refers to the input file,
test.svg in this case.
That's it. You can see the final
Test if the command works with f5 from the Makefile. If
you're happy with it, call
mis-finalize with C-, from
dired. The Makefile will be saved for all future calls to
To summarize the advantages of
make -j8, are provided for free.
The most important usage tip: until you're sure that the command and the Makefile work properly make backups. In fact, make backups period. Happy hacking!