diff options
Diffstat (limited to 'init.org')
-rw-r--r-- | init.org | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/init.org b/init.org new file mode 100644 index 0000000..bf0d942 --- /dev/null +++ b/init.org @@ -0,0 +1,261 @@ +#+Title: Emacs Customizations +#+Author: Ricardo Wurmus + +#+PROPERTY: noweb tangle +#+PROPERTY: mkdirp t +#+OPTIONS: tasks:nil toc:1 + +* Introduction + +My Emacs configuration is a mess. As I’m writing this my Emacs +configuration stretches across multiple files, each containing various +snippets of code that seemed like a good idea to group. + +Unfortunately, there are a some things that don’t have a “natural” +home. Enabling the same minor mode in various major modes is one of +these cases—do I duplicate the hook and place it in a file for each +major mode? Or do I write a new file for the minor mode in which I +add it to the major modes at once? + +With multiple files I spend too much time trying to find the best +place for any bit of configuration I add. This slows me down and +sometimes I just append to the main =init.el=, so I often feel that my +configuration is in need of reorganisation. But configuring Emacs +should be fun! I don’t want it to create an uncomfortable clean-up +task as a side-effect. This is why I’m now trying to use a literate +approach with =org-mode=. My Emacs configuration should be prose +first and code second. In my experience, finding the right spot in +prose for a new paragraph requires a lot less effort as the text +itself acts as a connection between unrelated bits of code. + +* How to use this? + +The sole purpose of the =~/.emacs.d/init.el= file is now to load up +and interpret this =org-mode= file. (We don’t execute this code +here.) + +#+BEGIN_SRC elisp :tangle no +(require 'org) + +;; Load the actual configuration file +(org-babel-load-file + (expand-file-name (concat user-emacs-directory "init.org"))) +#+END_SRC + +Alternatively, we can take all code blocks in this file and assemble +an =init.el= from it. This is what the =org-babel-tangle= procedure +does for us. I actually prefer doing it this way, because startup +times are faster this way as org-mode doesn’t have to be loaded first. +We can even byte-compile the init file. + +* Initialise packages +:PROPERTIES: +:noweb-ref: packages +:END: + +Emacs is an operating system and I use it as such (see [[http://elephly.net/posts/2016-02-14-ilovefs-emacs.html][this blog +post]]). I rely on quite a few extensions that have been made available +on various ELPA repositories. Recently, I have moved to installing +and managing Emacs packages like any other software package on my +system with the functional package manager [[https://gnu.org/s/guix][GNU Guix]]. I find this more +reliable, although at first it is slightly less convenient as I can no +longer just use =package.el= but first need to package the Elisp code +for Guix. + +To install all packages via GNU Guix I can either use a manifest file +or use the following invocation: + +#+BEGIN_SRC bash :noweb-ref nil + guix package -i \ + emacs \ + emacs-auctex \ + emacs-better-defaults \ + emacs-clojure-mode \ + emacs-company \ + emacs-debbugs \ + emacs-emms \ + emacs-god-mode \ + emacs-haskell-mode \ + emacs-ido-ubiquitous \ + emacs-js2-mode \ + emacs-lispy \ + emacs-markdown-mode \ + emacs-mmm-mode \ + emacs-multiple-cursors \ + emacs-org-bullets \ + emacs-pdf-tools \ + emacs-projectile \ + emacs-smex \ + emacs-typo \ + emacs-undo-tree \ + emacs-web-mode \ + emacs-wget \ + emacs-zenburn-theme \ + paredit \ + geiser \ + magit \ + sicp \ +#+END_SRC + +There are some packages I use that are not yet packaged for Guix. +Here’s a list of them: + +#+BEGIN_SRC elisp +(defvar my/packages + '(centered-cursor-mode + org-beautify-theme + dired-details + dired+ + erc-hl-nicks + expand-region + fill-column-indicator + guide-key + hungry-delete + ido-vertical-mode + info+ + page-break-lines + paren-face + perspective + rich-minority + scss-mode + shell-switcher + skewer-mode + smart-mode-line + sublime-themes + tagedit + visual-regexp-steroids + znc)) +#+END_SRC + +I want these packages to be installed automatically. First I need to +define in what repositories Emacs should look for the packages. I’m +using packages from both the “melpa” and “marmalade” repositories. + +#+BEGIN_SRC elisp +(require 'package) +(add-to-list 'package-archives + '("melpa" . "http://melpa.milkbox.net/packages/")) +(add-to-list 'package-archives + '("marmalade" . "http://marmalade-repo.org/packages/")) +(package-initialize) +#+END_SRC + +If this is a fresh Emacs installation melpa needs to be initialised +first: + +#+BEGIN_SRC elisp +(unless (file-exists-p "~/.emacs.d/elpa/archives/melpa") + (package-refresh-contents)) +#+END_SRC + +Now we are ready to install packages if they aren’t yet installed. + +#+BEGIN_SRC elisp +(defun packages-install (packages) + (mapcar (lambda (package) + (when (not (package-installed-p package)) + (package-install package))) + packages) + (delete-other-windows)) + +(defun init--install-packages () + (packages-install my/packages)) +#+END_SRC + +Install packages as soon as this configuration is evaluated. If +there’s an error (e.g. because a package by this name cannot be found) +ask Emacs to refresh the list of packages and retry. If there’s an +error again we just ignore it. It could be that it’s because there’s +no Internet connection. + +#+BEGIN_SRC elisp +(condition-case e + (init--install-packages) + (error + (ignore-errors + (package-refresh-contents) + (init--install-packages)))) +#+END_SRC + +* TODO Initial stuff +:PROPERTIES: +:noweb-ref: initial +:END: + +This is supposed to happen at the very beginning, even before loading +packages. I still need to arrange these things nicely. + +#+BEGIN_SRC elisp +;; No splash screen please ... +(setq inhibit-startup-message t) + +;; FIXME: This is needed to be able to use IBus Pinyin with Emacs +(setenv "LC_CTYPE" "zh_CN.utf8") + +;; display tool tips in echo area only +(tooltip-mode -1) +(setq tooltip-use-echo-area t) +(setq frame-resize-pixelwise t) +(defalias 'yes-or-no-p 'y-or-n-p) + +;; disable mouse scrolling +(mouse-wheel-mode -1) + +(add-to-list 'load-path (concat user-emacs-directory "lisp")) +#+END_SRC + +* TODO More stuff +:PROPERTIES: +:noweb-ref: initial-after-packages +:END: + +This is even more stuff to be done after initialising packages. I +still need to process all of this and clean it up. + +#+BEGIN_SRC elisp +;; better defaults, includes hiding the GUI +(require 'better-defaults) +(require 'paren-face) +(global-paren-face-mode 1) +(require 'paren) +(setq show-paren-delay 0) +(show-paren-mode 1) + +(require 'projectile) +(projectile-global-mode) + +(require 'guide-key) +(setq guide-key/guide-key-sequence '("C-x r" "C-x 4" "C-c p")) +(guide-key-mode) + +;; Keep emacs Custom-settings in separate file +(setq custom-file (expand-file-name "custom.el" user-emacs-directory)) +(load custom-file) + +(setq frame-background-mode 'light) +(load-theme 'solarized t) +(set-default-font "DejaVu Sans Mono") + +(add-hook 'haskell-mode-hook + (lambda () + (turn-on-haskell-indentation) + (turn-on-haskell-doc))) +#+END_SRC + +* Putting it all together + +Having defined named code blocks in the sections above we can finally +put them all together to build the init file + +#+BEGIN_SRC elisp :noweb yes :tangle "~/.emacs.d/init.el" +<<initial>> +<<packages>> +<<initial-after-packages>> +(load "~/.emacs.d/old-init.el") +#+END_SRC + + +# Local Variables: +# org-edit-src-content-indentation: 0 +# eval: (add-hook 'org-babel-post-tangle-hook (lambda nil (byte-compile-file "~/.emacs.d/init.el") (load-file "~/.emacs.d/init.elc"))) +# End: |