# -*- 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.