28 Mar 2017
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
the line in
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
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:
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 ()
(ring-insert find-tag-marker-ring (point-marker))
(or (and (require 'rtags nil t)
(and (require 'semantic/ia)
(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:
Use Irony for completion
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 ()
[remap completion-at-point] 'counsel-irony)
[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
18 Mar 2017
ediff.el --- a comprehensive visual interface to diff & patch
I wrote about
ediff years ago.
Today, I'll just reference a useful ediff snippet
from my config that I've added
some time ago and refined only recently.
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 ()
(let ((files (dired-get-marked-files))
(if (<= (length files) 2)
(let ((file1 (car files))
(file2 (if (cdr files)
(if (file-newer-than-file-p file1 file2)
(ediff-files file2 file1)
(ediff-files file1 file2))
(setq ediff-after-quit-hook-internal nil)
(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.
25 Feb 2017
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
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.
Example 1: convert
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:
- Navigate to
dired and press , (bound to
- Select the recipe you want using completion:
to-txt is 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:
- f5 (
mis-save-and-compile) will run
test.txt in the current directory.
- C-, (
mis-finalize) will finalize the operation,
test.txt to the parent directory (where
test.pdf was before), and deleting the staging directory.
- C-M-, (
mis-abort) will move
test.pdf back to its
initial location and delete all generated files. This command is
It takes a large chunk of text to describe everything, but the key sequence for doing all this is quite short:
- , -
- RET - select
- f5 - create
- C-, - finalize.
Example 2: make a gif from a series of png images
I'll describe the process of creating a high quality gif like this
one, which describes the effect of the C key
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
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)
anime.gif: Makefile $(DIRGIF)
rm -f anime.gif
gifsicle --delay=$(delay) --colors=256 --loop $(DIRGIF) > [email protected]
echo [email protected] >> provide
rm -f anime.gif provide
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.
Example 3: add a new recipe
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)
echo "add command here"
echo [email protected] >> provide
rm -f *.png provide
# Insert the install command here.
# e.g. sudo apt-get install ffmpeg
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:
height will go to the top of the
Makefile, where they can be customized.
[email protected] 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
- Write the recipe one time, never have to look up how to do the
same thing a few months from now.
- A chance to write the recipe zero times, if someone in the
community has already done it and shared the recipe with you.
- The Elisp layer takes care of hairy file names.
- Parallel commands on multiple files, i.e.
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.
28 Aug 2016
Recently, I've been looking at
didn't manage to fully figure out their CMake build system for
tutorials: although each tutorial has a
CMakeLists.txt, it's only
possible to build them all at once.
So I decided to replace
CMakeLists.txt with a good-old
how hard can it be? Concerning includes, not at all hard: the missing
files are found with
counsel-locate and added to the include path.
But I had some trouble matching a missing
ld dependency to a library
file. Fixed it with a bunch of googling and guesswork; I still wonder
if there's a better way. But in the process, I've found this useful
which produces e.g.:
Symbol table '.dynsym' contains 2732 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 000000000004faf0 0 SECTION LOCAL DEFAULT 8
2: 00000000000e8f20 0 FUNC GLOBAL DEFAULT 11 glGetIntegerui64i_vNV
3: 00000000000e13e0 0 FUNC GLOBAL DEFAULT 11 glGetMultiTexEnvfvEXT
4: 00000000000d7440 0 FUNC GLOBAL DEFAULT 11 glProgramUniform2uiv
5: 00000000000cfdc0 0 FUNC GLOBAL DEFAULT 11 glMultiTexCoord3sv
This is a pretty good representation of a binary file: in this
example, instead of one megabyte of gibberish I see a bit more than
2732 lines describing the functions this file uses and provides.
Viewing the symbol list automatically
I liked the above representation so much that I want to see it by
default. In Emacs, it's pretty easy to do with
(add-to-list 'auto-mode-alist '("\\.\\(?:a\\|so\\)\\'" . elf-mode))
The above code instructs Emacs to call
elf-mode function whenever
the file name ends in
And here's the body of
(defvar-local elf-mode nil)
(defun elf-mode ()
(let ((inhibit-read-only t))
(delete-region (point-min) (point-max))
(setq elf-mode nil))
(setq elf-mode t)
(delete-region (point-min) (point-max))
(format "readelf --syms %s" (buffer-file-name)))))
The idea is very simple:
elf-mode is a toggle function that replaces
the buffer contents with the shell command output. It carefully uses
set-buffer-modified-p so that the file will not
be overwritten by accident with the symbol names.
Using autoload to avoid overhead
As you might imagine, looking at binaries isn't really a common
task. Is it worth to be dragging this code around from now on, loading
it on each start? The answer is yes, of course. Since the actual cost
is negligible until the feature is used.
If you look above,
elf-mode has an
;;;###autoload cookie before
it. The cookie results in this line in my
(autoload 'elf-mode "modes/ora-elf" "" t nil)
init.el always loads
loaddefs.el, but never loads
where the function is defined. That file is only loaded when the
elf-mode is called for the first time. The above
statement simply instructs Emacs to load a particular file when
elf-mode needs to be called.
When you use the package manager, the autoloads file is generated and
loaded for you automatically:
$ tree elpa/ace-link-20160811.112/
0 directories, 4 files
Here, the package manager will always load
which instructs Emacs to load
ace-link.el when one of the
;;;###autoload functions is called and
ace-link.el isn't yet
As an example of how useful delayed loading is: my 6000 line
config starts in 1.8 seconds.
About 40% of that time is spent on
(package-initialize), which I
assume is the package manager loading all those
that I have in my
Let me know if there's interest to have
elf-mode on MELPA. Also, if
anyone knows how to set mode automatically based on the first few
chars of the file (all binaries seem to start with
^?ELF), I'd like
to know that as well. Happy hacking!
29 Jul 2016
If you've ever tried the
swiper, forget everything about
it. The command was super-awkward, since it had to parse all your
open files before giving you a chance enter anything, resulting in
dozens of seconds before the prompt.
Recently, I've had some time to examine and improve it and the result
looks very promising. The new command is now async, which means
there's no delay before the prompt comes up. Here's a result I got
with no delay while having around 50 buffers open:
The shortcut I'm using:
(global-set-key (kbd "C-c u") 'swiper-all)
For efficiency's sake a small trade off had to be made: the line
numbers are no longer displayed. This actually results in an advantage
that you can select different candidates on the same line.
There are still a few things I plan to try for the new command, like
adding file-less buffers, caching for incremental regexes and maybe
even newlines in wild cards, but even now it seems very usable. So
give it a try, enjoy and happy hacking!