# -*- ispell-local-dictionary: "en"; -*-
#+TITLE: Emacs init
#+HTML_HEAD:
#+OPTIONS: num:nil toc:nil
#+PROPERTY: tangle init2.el
#+STARTUP: showall
* First things first: Lexical binding
To make sure that the code in this file follows the correct rules,
make sure it uses lexical binding.
#+BEGIN_SRC emacs-lisp :padline no
;;; -*- lexical-binding: t -*-
#+END_SRC
* Improved eval-after-load
A lot of the options and functionality isn't necessary until a
certain package has been loaded. So in order to keep start-up as
fast as possible, while still taking advantage of byte-compiling
everything, I wrap most settings in the following macro, which is
explained [[http://lunaryorn.com/2013/05/31/byte-compiling-eval-after-load/][here]].
#+BEGIN_SRC emacs-lisp
(defmacro stante-after (feature &rest forms)
"After FEATURE is loaded, evaluate FORMS.
FEATURE may be an unquoted feature symbol or a file name, see
`eval-after-load'."
(declare (indent 1) (debug t))
;; Byte compile the body. If the feature is not available, ignore
;; warnings. Taken from
;; http://lists.gnu.org/archive/html/bug-gnu-emacs/2012-11/msg01262.html
(let ((loaded (if (symbolp feature)
(require feature nil :no-error)
(load feature :no-error :no-message))))
`(,(if loaded
'progn
(message "stante-after: cannot find %s" feature)
'with-no-warnings)
(eval-after-load ',feature
`(funcall (function ,(lambda () ,@forms)))))))
#+END_SRC
* Executing things after initialization has finished
Some functionality, for example everything loaded with ~package.el~,
is only available after the initialization process has finished. So
code that requires ~package.el~ packages to be available or other
things that the initialization process does to be done should only
be executed after initialization has finished. The
=emacs-startup-hook= is good for this. This also seems more efficient
than using =(package-initialize)=.
#+BEGIN_SRC emacs-lisp
(defmacro eval-after-init (&rest body)
"Defer execution of BODY until after Emacs init."
(declare (indent 0))
`(add-hook 'emacs-startup-hook #'(lambda () ,@body)))
#+END_SRC
* Preparing the load-path
For anything that isn't loaded with ~package.el~ (like a manually
installed ~org-mode~) its directory should be in =load-path=. If there
happens to be a ~loaddefs.el~ in that same directory, load it so that
it can add some autoloads. These directories contain manually
installed packages, my local ~site-lisp~ directory and any project
directories for projects which I (occasionally) work on.
All of it is put in an =eval-and-compile= block so it is run both at
compile-time and run-time, since it is necessary to properly compile
my init file as well.
#+BEGIN_SRC emacs-lisp
(eval-and-compile
(defun loadpath-add-and-autoload (path)
"Add PATH to `load-path' and load a `loaddefs.el' if it exists."
(add-to-list 'load-path path)
(let ((loaddefs (concat path "/loaddefs.el")))
(when (file-exists-p loaddefs)
(load loaddefs))))
(mapc #'loadpath-add-and-autoload
'("~/.emacs.d/site-lisp" "~/projects/emacs/pony-mode/src"
"~/.emacs.d/vendor-lisp/org/lisp"
"~/.emacs.d/vendor-lisp/org/contrib/lisp"
"~/.emacs.d/vendor-lisp/eap" "/usr/share/emacs/site-lisp")))
#+END_SRC
* Speeding up yes/no questions
Typing ~yes~ or ~no~ when just ~y~ or ~n~ would suffice seems unnecessary.
I've been using it almost as long as Emacs and I haven't had any
accidents yet.
#+BEGIN_SRC emacs-lisp
(defalias 'yes-or-no-p 'y-or-n-p)
#+END_SRC
* Getting a more feature-full buffer list
~ibuffer~ has a lot more features than regular =list-buffers=, plus does
everything =list-buffers= does.
#+BEGIN_SRC emacs-lisp
(defalias 'list-buffers 'ibuffer)
#+END_SRC
* Getting more feature-full text-completion
One of the completion mechanisms of =hippie-expand= is a ~dabbrev~ based
expansion, so it should do everything =dabbrev-expand= does, plus
more. It also doesn't use =dabbrev-expand= directly, so it shouldn't
be a problem to switch them.
#+BEGIN_SRC emacs-lisp
(defalias 'dabbrev-expand 'hippie-expand)
#+END_SRC
* Making buffer names unique and understandable
The problem with the default way of making buffer names unique is
that it doesn't tell me anything about what makes them unique. I
don't know what makes ~init.el<1>~ different from ~init.el<2>~. However,
seeing it as, for example, ~init.el|.emacs.d~ and ~init.el|dotemacs~
tells me a lot more.
#+BEGIN_SRC emacs-lisp
(require 'uniquify)
(stante-after uniquify
(setq uniquify-buffer-name-style 'post-forward))
#+END_SRC
* Telling gnus where to look for its initialization file
I prefer to keep everything in my =~/.emacs.d/= directory, so =~/.gnus=
wouldn't work with that. To silence a compiler warning I define a
"vacuous" variable first, so Emacs knows the name is defined. I
don't specify an ~init-value~ with the =defvar= so that if it happens to
already be defined, =setq= will still change it (=defvar= won't).
#+BEGIN_SRC emacs-lisp
(defvar gnus-init-file)
(setq gnus-init-file "~/.emacs.d/site-lisp/gnus-init")
#+END_SRC
* Clean up the UI
There are things, like a blinking cursor, a menu bar, etc. that I
just don't need, so I want to turn them off. Since they all have the
same API, just loop through the symbols and turn each off.
#+BEGIN_SRC emacs-lisp
(defmacro turn-off (&rest modes)
"Turn off each mode in MODES."
`(progn ,@(mapcar (lambda (m) `(,m -1)) modes)))
(turn-off menu-bar-mode scroll-bar-mode tool-bar-mode blink-cursor-mode
column-number-mode line-number-mode tooltip-mode)
#+END_SRC
* Loading a theme at the correct time
A problem with loading some themes immediately at start-up, while
using the ~--daemon~ switch is that there is no guarantee that it will
ever use a window system, so it's like starting from the terminal.
This may affect the colors of some themes.
To get around this I use =lexical-binding= (because I'm not sure
dynamic binding will work here) and create a closure that tracks if
I've set the theme, so it doesn't reset it every time a new frame is
created. Then I have this executed one tenth of a second after a
frame is created, at which point there should be a window system and
colors should be correct.
One more problem is that when starting Emacs without the ~--daemon~
switch the =after-make-frame-functions= aren't run, so if we're not
running a daemon, just set the theme.
#+BEGIN_SRC emacs-lisp
(let ((setp (not (daemonp))))
(defun init-set-theme (frame)
"Try to set the theme for the current (first) frame."
(ignore frame)
(unless setp
(run-at-time .1 nil (lambda () (setq setp (load-theme 'yoshi t)))))))
(if (daemonp)
(add-hook 'after-make-frame-functions #'init-set-theme)
(eval-after-init (load-theme 'yoshi t)))
#+END_SRC
* Browsing with eww
=eww= is a very cool project, but I don't like where it downloads things.
#+BEGIN_SRC emacs-lisp
(setq eww-download-path "~/downloads/")
#+END_SRC
* Double space to end a sentence in Emacs Lisp
The Emacs Lisp syntax checker is hell-bent on forcing me to use a
double space at the end of sentences in comments and docstrings.
Fine, then I will use double spaces in Emacs Lisp.
#+BEGIN_SRC emacs-lisp
(defun init-locally-enable-double-spaces ()
(setq-local sentence-end-double-space t))
(add-hook 'emacs-lisp-mode-hook #'init-locally-enable-double-spaces)
#+END_SRC
* Show pretty symbols
Emacs lisp has the default of showing ~lambda~ as ~λ~. I also want to
show ~<=~ as ~≤~, ~>=~ as ~≥~ and ~sqrt~ as ~√~.
#+BEGIN_SRC emacs-lisp
(defun init-set-emacs-lisp-symbols ()
(setq prettify-symbols-alist
(append prettify-symbols-alist
'(("<=" . ?≤)
(">=" . ?≥)
("sqrt" . ?√)))))
(add-hook 'emacs-lisp-mode-hook #'init-set-emacs-lisp-symbols)
#+END_SRC
Aside from Emacs lisp, I would also like to show most of these in
Python. Though the ~sqrt~ doesn't seem applicable, I do want to show
~!=~ as ~≠~ here.
#+BEGIN_SRC emacs-lisp
(defun init-set-python-symbols ()
(setq prettify-symbols-alist
'(("lambda" . ?λ)
("<=" . ?≤)
(">=" . ?≥)
("!=" . ?≠))))
(add-hook 'python-mode-hook #'init-set-python-symbols)
#+END_SRC
Now just turn it on for =prog-mode=.
#+BEGIN_SRC emacs-lisp
(add-hook 'prog-mode-hook 'prettify-symbols-mode)
#+END_SRC
* Slime implementations
I usually use [[http://sbcl.org][SBCL]], but sometimes also [[http://www.clisp.org/][GNU CLISP]].
#+BEGIN_SRC emacs-lisp
(stante-after slime
(setq slime-lisp-implementations
'((sbcl ("sbcl" "--noinform") :coding-system utf-8-unix)
(clisp ("clisp") :coding-system utf-8-unix))
slime-default-lisp 'sbcl))
#+END_SRC
* Use Liberation Mono font for unicode
[[http://paratype.com/public/][PT Mono]] is a very nice font, but is misses some unicode characters I
would like to use. [[https://www.redhat.com/promo/fonts/][Liberation Mono]] on the other hand does seem to
contain these characters, so I use that for any unicode fonts.
#+BEGIN_SRC emacs-lisp
(set-fontset-font "fontset-default" 'unicode
(font-spec :family "Liberation Mono"
:width 'normal
:size 12.4
:weight 'normal))
#+END_SRC
* A command to sort python includes
At work I use Python. Our project is getting bigger and bigger,
import statements are growing. We use the following style:
#+BEGIN_SRC python :tangle no
from somemodule import (
Class1,
Class2,
Class3,
)
#+END_SRC
Which we found to be one of the better-looking ways to handle
multi-line import statements. To sort these lines I wrote a very
simplistic (and error-prone, but I'll handle it when I get to it)
command.
All it does is save the current point, searches backwards for a ~(~,
then forwards for a ~)~ and sorts the region in between (not
including) the ~()~.
#+BEGIN_SRC emacs-lisp
(defun sort-imports ()
(interactive)
(save-excursion
(sort-lines nil (1+ (search-backward "("))
(1- (search-forward ")")))))
#+END_SRC
* Bring back the z!
One or two versions of Emacs ago it was decided that the ~z~ character
was too easy to press accidentally, killing the current buffer if it
was based on =special-mode=. I disagree. I don't like the fact that
using ~q~ leaves the buffers open, usually I want to kill the buffers
when I'm done with them, though not always. So I want back my ~z~!
I don't, however, want to overwrite the ~z~ key in, say, =magit=, so I
define it in the =special-mode-map= so it only gets redefined if modes
based on =special-mode= don't rebind it themselves.
#+BEGIN_SRC emacs-lisp
(stante-after simple
(define-key special-mode-map "z" #'kill-this-buffer))
#+END_SRC
* Falling back to WM to switch windows
Emacs and any window manager have a difference op opinion on what
windows are. It doesn't have to matter, Emacs can manage its windows
and stumpwm can do the rest. When moving around with ~windmove~ and it
finds that there's no way to move in that direction, let stumpwm do
it.
First we have to know where the stumpish program is. SLIME could
also be used, but calling stumpish might be easier for now.
#+BEGIN_SRC emacs-lisp
(defvar init-stumpish-program
(expand-file-name
"~/.local/share/quicklisp/local-projects/stumpwm/contrib/stumpish")
"The location of the stumpish executable.")
#+END_SRC
Now that we know that, we should have an easy way to send stuff to
it.
#+BEGIN_SRC emacs-lisp
(defun stumpwm-command (cmd)
"Execute CMD in stumpwm."
(call-process init-stumpish-program nil nil nil cmd))
#+END_SRC
And then we can advise =windmove-do-window-select=, so that when it
finds there are no more windows to move to, it asks stumpwm to move
in the same direction.
#+BEGIN_SRC emacs-lisp
(defadvice windmove-do-window-select
(around init-windmove-stumpwm activate)
"If no window can be moved to, move stumpwm."
(condition-case err
ad-do-it
(error (stumpwm-command (format "move-focus %s" (ad-get-arg 0))))))
#+END_SRC
Now, whenever I try to move out of my Emacs windows, it just moves
to the next X11 window, whatever it might be. My stumpwm config has
a matching command that checks to see if the current window is
Emacs, and if so sends the ~S-~ key to Emacs, which in turn
calls stumpwm when it can't (getting a little crazy here).
I also wrote a simplistic macro to execute some stumpwm lisp in
Emacs.
#+BEGIN_SRC emacs-lisp
(defmacro stumpwm (&rest body)
"Execute BODY in stumpwm."
(declare (indent 0))
`(call-process init-stumpish-program nil nil nil
,(format "eval '%S'" `(progn ,@body))))
#+END_SRC
Which is pretty much the same as my =elisp= macro in my stumpwm
config.