30 Apr 2015
As one thing leads to another, it occurred to me that I didn't know
what __GNUC__
macro does. Which brought me to the manual page on
Common Predefined Macros.
Using org-mode
Babel to check the macro values
I decided that just skimming through the page wasn't enough, and I
wanted to brush up on my org-mode
babel. So I created this
wiki page
to which you're welcome if you ever need to check __BYTE_ORDER_
or
__UINT_FAST16_TYPE__
on your system.
Here's a small excerpt of it:
#+begin_src C :results verbatim
#include <stdio.h>
int main() {
// version stuff
printf("__GNUC__ %d\n", __GNUC__);
printf("__GNUC_MINOR__ %d\n", __GNUC_MINOR__);
printf("__GNUC_PATCHLEVEL__ %d\n", __GNUC_PATCHLEVEL__);
printf("__VERSION__ %s\n", __VERSION__);
return 0;
}
#+end_src
When you navigate to any place in the code and press C-c C-c, which calls (sic) org-ctrl-c-ctrl-c
,
it will re-compile and re-run your program.
I list here some of the config to make it all work:
(org-babel-do-load-languages
'org-babel-load-languages
'((C . t)
;; ...
))
(setq org-babel-C-compiler "gcc -std=c99")
New auto-yasnippet
method
You can read up on what auto-yasnippet
is in this post.
For the wiki page, I had to insert the printf
statements a bunch of times, some of them with triply-repeated symbols.
Take, for instance, this statement:
printf("__INT32_TYPE__ %s (%d)\n", ESTR(__INT32_TYPE__), sizeof(__INT32_TYPE__));
With the old method, I would insert ~
before each INT32
and call aya-create
. But it would result in this snippet, which isn't optimal:
printf("__$1 %s (%d)\\n", ESTR(__$1), sizeof(__$1));
With the new method (the old one still works, it's just that the new one takes priority), I would only quote the first field like so:
printf("__`INT32'_TYPE__ %s (%d)\n", ESTR(__INT32_TYPE__), sizeof(__INT32_TYPE__));
Which results in this snippet:
printf("__$1_TYPE__ %s (%d)\n", ESTR(__$1_TYPE__), sizeof(__$1_TYPE__));
Much better.
oremacs
wiki workflow
If you're crazy enough (in a good way) to follow oremacs, you'll get the
new wiki page delivered right to your config with
which will also update to the latest org-mode
and CEDET.
And here's how to access it:
- run
xmodmap etc/.Xmodmap
to make ; into a modifier
- press ;-k to open a dispatch hydra
- press w to select the wiki
- select
C
(currently, the only other candidate is git
)
Outro
Check out the new auto-yasnippet
method, I think it's pretty
efficient. I hope that you'll find the wiki page useful in your C
pursuits. And a big thanks to Eric Schulte for org-babel
.
28 Apr 2015
Intro
This is a slightly obscure feature that I've added today to
ivy-mode. It's obscure, since
very few packages give their candidates a face with a custom
background. Still, when that happens, a conflict arises:
Which face to apply: ivy-current-match
or the existing one?
In the image below, I've blended them both in a 50-50 mixture:
By the way, if you're wondering where the backgrounds come from in the
first place, it's lispy-goto
function (if you know what imenu
is, it's an advanced version of
that). This function collects all the Elisp tags in the current
directory, and offers to jump to them. The functions that have
interactive
in them, are highlighted with lispy-command-name-face
.
In the above screenshot, the first 7 functions are interactive, and the other 2 are not.
If you're interested in how color blending is done, I'll describe it
shortly below.
Color-building internals
First, a smaller and more clear example (I've used rainbow-mode
and htmlize-buffer
):
(colir-blend
(color-values "red")
(color-values "blue"))
#800080
Here, colir-blend
is a very small function that I'll describe below,
and color-values
is a function from faces.el that forwards to a C
function xw-color-values
with this doc:
Return a list of three integers, (RED GREEN BLUE), each between 0
and either 65280 or 65535 (the maximum depends on the system).
Which is a bit weird, since the last time I checked, the standard for
colors was one-byte per channel, not two. Granted, it was about 10
years ago that I checked, and indeed, the
entry on Wikipedia
says:
High-end digital image equipment are often able to deal with larger
integer ranges for each primary color, such as 0..1023 (10 bits),
0..65535 (16 bits) or even larger, by extending the 24-bits (three
8-bit values) to 32-bit, 48-bit, or 64-bit units
Apparently, Emacs is outfitted to deal high-end digital image
equipment. But I'm still pretty sure that most graphics cards that you
can buy only give 8 bits per each channel. Anyway, here's the code for
the basic functions:
(defun colir-join (r g b)
"Build a color from R G B.
Inverse of `color-values'."
(format "#%02x%02x%02x"
(ash r -8)
(ash g -8)
(ash b -8)))
(defun colir-blend (c1 c2 &optional alpha)
"Blend the two colors C1 and C2 with ALPHA.
C1 and C2 are in the format of `color-values'.
ALPHA is a number between 0.0 and 1.0 which corresponds to the
influence of C1 on the result."
(setq alpha (or alpha 0.5))
(apply #'colir-join
(cl-mapcar
(lambda (x y)
(round (+ (* x alpha) (* y (- 1 alpha)))))
c1 c2)))
All pretty simple:
- Split each color into red, green, and blue integers with
color-values
.
- Compute a mean for each color channel.
- Build the new color by concatenating the hex components into a string.
In the example above:
- The result of
(color-values "red")
is (65535 0 0)
.
- The result of
(color-values "blue")
is (0 0 65535)
.
- Their arithmetic mean is
(32768 0 32768)
.
- Divided by
256
with ash
, we get (128 0 128)
.
- Converted to hex,
(128 0 128)
is (80 0 80)
.
- And the final color is
"#800080"
.
Outro
I hope that you've enjoyed this little venture into Elisp and colors.
People say rough things about Elisp sometimes, but hey: it offers
functions ranging from the assembly-level ash
, all the way up to
Photoshop-grade color channel handling.
If only it could get a good optimization bump, like JavaScript got at
one point, and a small threading library, we'd be all set.
24 Apr 2015
I noticed that the packages that I've published on
Github in the last year did get a nice
boost in quality just from being published, viewed, used and commented
on.
So it makes sense to do the same for my full Emacs config, which lives in the oremacs repository as of today.
The config is personal in the sense that I'm actually using it
verbatim, but it's been configured in a way that's it's easy to
replicate and modify it.
Who can benefit from this config
The audience is people like me, who like to tinker with Elisp just for
fun of it. If you want things to just work, or you find learning
Elisp a chore, it's not for you.
The config won't work initially, it won't work always, but when it
finally does work (hopefully), it will be glorious!
Installation and Running
Requirements
Emacs 24 is required. Obviously, newer versions are better, but the
default emacs24
that you get from the package manager should work.
I'm currently switching between Emacs 24.5.2 built from source and the
current master from git.
Install command
This config doesn't assume to become your main config when you install
it. It installs in-place in the git directory and will start from
there without touching your main config. But you still get access to
all your stuff, like bookmarks stored in your actual ~/.emacs.d/
etc.
cd ~/git
git clone https://github.com/abo-abo/oremacs
cd oremacs
make install
Run command
Run without updating:
Run with an upstream + ELPA update:
Run with an upstream + ELPA + org-mode + CEDET update:
Perks
Standalone
You can try it without messing up your current Emacs config. I actually have multiple versions of this on my system to work-around incompatibility between versions. This way, I can use my full setup even in case I get a bug report for an older Emacs version.
Fast start up
With a SSD, it starts in 1 second. Most features are autoloaded and it's easy to add new autoloaded features.
Tracks the most recent org-mode and CEDET
Since these packages take a long time to byte compile, they are updated not with make up
but with make install
. They are actually git submodules, which means that they won't update if I don't update them in the upstream.
Bankruptcy-proof
It's hard to become Emacs-bankrupt with this config, since the config is composed of many independent pieces that you can simply ignore if you don't need them.
Anti-RSI QWERTY mod
The config comes with its own .Xmodmap
that makes ; into an additional modifier. RSI savers:
- ;-v instead of Enter.
- ;-o instead of Backspace.
- ;-f instead of Shift-9 and Shift-0.
- ;-a instead of -.
- ;-s instead of Shift--.
- ;-q instead of Shift-'.
- ;-e instead of =.
- ;-u in addition / instead of C-u.
And obviously the replacements for the two keys that the mod takes away:
- ;-j instead of ;.
- ;-d instead of Shift-;.
One more Elisp-level RSI-saver is the swap between C-p and C-h. Moving up/down line is very important, and it's nice to have these keys close, which C-n and C-h are.
It also includes:
- a bunch of Hydras that save you key strokes.
lispy-mode
which quickens any LISP mode, especially Elisp.
worf-mode
which quickens org-mode
.
ivy-mode
which quickens all completion.
swiper
which quickens isearch
(by replacing it).
- C/C++ is customized with
function-args-mode
and a bunch of hacks.
Org mode starter
The config starts you off with a fully configured org-mode
setup that includes:
- gtd.org for getting things done.
- ent.org to track entertainment.
- wiki folder for quickly starting and selecting wikis.
Outro
I hope that you try and enjoy the new config. Perhaps not verbatim,
but if you find the tips on this blog helpful, this config is their
actual implementation that you can use for reference.
22 Apr 2015
This release packs more than 90 commits, which is quite a lot for me.
The most important part of this release is ivy-mode
, which is a nice alternative to ido-mode
or helm-mode
.
I've mentioned it already in an earlier post,
I'll just review all the little details, changes and customizations here.
Important: remove the old ivy
package
One important change related to MELPA is that the ivy
package was merged into swiper
package. So if you still have a stand-alone ivy
package, you should delete it, or you'll get incompatibility problems.
Video Demo of counsel-git-grep
If you like videos, you can watch the this quick demo
which mostly shows off the new counsel-git-grep
function.
Fixes
Add work-around for window-start
being not current
From now on, you won't encounter some un-highlighted matches when your window is scrolled.
Make thing-at-point
work
C-h v and C-h f should select thing-at-point properly.
Don't try to fontify huge buffers
It's a nice feature of swiper that everything in the minibuffer is fontified. However, this can cause a slowdown for buffers with x10000 lines. So this feature is automatically turned off for these large buffers.
Exclude a few modes from font locking
Some modes just misbehave when font-lock-ensure
is called. Excluded:
org-agenda-mode
dired-mode
New Features
ivy-mode
: complete everything with Ivy
ivy-mode
uses swiper's approach to completion for almost all completion in Emacs, like:
execute-extended-command
package-install
find-file
See the wiki page for the details on the key bindings related to ivy-mode
, which are especially important to know for find-file
. Also see the intro video.
New Counsel functions
counsel-describe-variable
- replacement for C-h v.
counsel-describe-function
- replacement for C-h f.
counsel-info-lookup-symbol
- just a wrapper around info-lookup-symbol
, you get the same behavior by just calling info-lookup-symbol
with ivy-mode
on.
counsel-unicode-char
- replacement for ucs-insert
.
counsel-git-grep
This is a really cool command for grepping at once all the files in your current git repository. For smaller repositories (<20000) lines, ivy handles the completion by itself. For larger repositories, it defers the work to git grep
. It works really well for the Emacs repo with its 3,000,000 lines, especially if you're using Emacs 25 (from emacs-snapshot
or self-built).
This function makes use of C-M-n and C-M-p bindings, which switch between candidates without exiting the minibuffer. Also, they highlight the current candidate with the swiper faces. You can think of this command as multi-swiper.
Even for very large repos, it will always display the amount of matches correctly. Also note that swiper-style regex is used here (spaces are wild), and the case is ignored.
The arrows can take numeric arguments
C-n / C-p, C-s / C-r, and C-M-n / C-M-p can all take numeric args, e.g. M-5 or C-u.
Add a recenter binding
C-l will recenter the window in which swiper was called.
Look up Ivy key bindings with C-h m
While in the minibuffer, press C-h m to see the active modes. Ivy also has a paragraph with its bindings.
You can use these bindings to speed up your minibuffer scrolling.
Allow C-. to jump-to-definition
For counsel-describe-variable
and counsel-describe-function
:
- pressing C-m will actually describe the current candidate.
- pressing C-. will instead jump to definition of the the current candidate.
This is very useful for me, I jump to definitions more often that describe.
Bind arrows
The actual arrow keys are also bound to the corresponding Emacs arrows.
Add a way to exit ignoring the candidates
If your current input matches a candidate, C-m and C-j will exit with that candidate. If you want to exit with your exact input instead, press C-u C-j. This is very useful for creating new files and directories.
Use M-q to toggle regexp-quote
This can be useful while completing file names (with a lot of dots). Pressing M-q toggles between regex and non-regex matching.
Customize ivy-re-builders-alist
This is pretty intricate, look up the variable to see the details. In short, you can use this to apply `regexp-quote' for some types of completion if you want.
Customize what to do on DEL error
The standard behavior on a DEL error (usually empty minibuffer) is to exit the minibuffer. I like this behavior, since it's similar to the behavior to fixing wrongly typed chars: only in this case DEL "fixes" a wrongly typed command.
But if you want to customize it, just set ivy-on-del-error-function
to something other than minibuffer-keyboard-quit
.
Customize this if you don't want to see ../
and ./
while completing file names.
Customize ivy-sort-functions-alist
Use this variable to customize sorting, depending on what you're completing. For example:
(setq ivy-sort-functions-alist
'((read-file-name-internal . ivy-sort-file-function-default)
(internal-complete-buffer . nil)
(counsel-git-grep-function . nil)
(t . string-lessp)))
Customize ivy-subdir-face
While completing file names, the directories will use ivy-subdir-face
.
Outro
Big thanks to all who contributed, especially @tsdh.
19 Apr 2015
Just got this request a few minutes ago, and now this feature is in
the swiper
repository (available as counsel
from MELPA).
The motivation was to write an ivy equivalent of helm-git-grep.
I didn't use this feature before, but the only thing that I needed to get me started was this shell command:
git --no-pager grep --full-name -n --no-color -i -e foobar
The rest of the code (just 20 lines) followed all by itself:
(defun counsel-git-grep-function (string &optional _pred &rest _u)
"Grep in the current git repository for STRING."
(split-string
(shell-command-to-string
(format
"git --no-pager grep --full-name -n --no-color -i -e \"%s\""
string))
"\n"
t))
(defun counsel-git-grep ()
"Grep for a string in the current git repository."
(interactive)
(let ((default-directory (locate-dominating-file
default-directory ".git"))
(val (ivy-read "pattern: " 'counsel-git-grep-function))
lst)
(when val
(setq lst (split-string val ":"))
(find-file (car lst))
(goto-char (point-min))
(forward-line (1- (string-to-number (cadr lst)))))))
Thanks to the push from Stefan Monnier, ivy-read
also supports a
function to be passed instead of a static collection of strings. In
this case, it's counsel-git-grep-function
that basically takes one
argument: the thing that we're looking for.
After this, shell-command-to-string
is my go-to function to quickly
bring some shell output into Elisp. As you can see, it's enough to
pass it a shell command in a string form to get a string response. I
transform the response into a list of line strings with
split-string
, making sure to pass the t
argument to avoid empty
strings.
One final trick that you can learn for your own Elisp programming is
the let
/ default-directory
/ (locate-dominating-file default-directory ".git")
combo.
It's quite useful for dealing with git shell commands.
And that's it, it only remains to open a file and jump to the selected line.
I think that counsel-git-grep
might complement and slightly displace rgrep
or ag
in my setup.
So I've given it a nice binding:
(global-set-key (kbd "C-c j") 'counsel-git-grep)
I hope that I've made a good case of how easy it is to quickly write
something in Elisp, especially if it's just a shell command
wrapper. So if you're on the fence of whether to learn Elisp or not,
do yourself a favor and learn it: it pays off quickly and is a lot of
fun.
Side note: I've mentioned \bfun\b
in this blog 182 times, mostly as a variable representing a function (courtesy of counsel-git-grep
).