From e604e35ae28fd6496cae0d9768b821012bc1b293 Mon Sep 17 00:00:00 2001 From: Tom Willemse Date: Sun, 3 Nov 2013 17:05:27 +0100 Subject: The literate emacs init is back --- .emacs.d/init.org | 287 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 .emacs.d/init.org (limited to '.emacs.d/init.org') diff --git a/.emacs.d/init.org b/.emacs.d/init.org new file mode 100644 index 0000000..0fd1f11 --- /dev/null +++ b/.emacs.d/init.org @@ -0,0 +1,287 @@ +# -*- 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/blog/2013/05/31_byte-compiling-eval-after-load.html][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 + +* Writing Dockerfiles + + I've been playing around with docker a little bit and I wasn't able + to find any modes that provided syntax highlighting for them. So I + wrote a very simple one. + + #+BEGIN_SRC emacs-lisp + (define-generic-mode docker-mode + '(?#) + '("FROM" "MAINTAINER" "RUN" "CMD" "EXPOSE" "ENV" "ADD" "ENTRYPOINT" "VOLUME" + "USER" "WORKDIR") + nil '("Dockerfile") nil + "A simple Dockerfile mode.") + #+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 + +* 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 -- cgit v1.2.3-54-g00ecf