diff --git a/emacs/.emacs.d/init.org b/emacs/.emacs.d/init.org index 4893871..ef23b87 100644 --- a/emacs/.emacs.d/init.org +++ b/emacs/.emacs.d/init.org @@ -5,125 +5,147 @@ This is my personal Emacs configuration. The name was inspired by "Ghost in the Shell 2: Man-Machine Interface and Ryan Rix's "Complete Computing Environment". -To start off, first I need to enable lexical binding. +* Preamble -#+BEGIN_SRC emacs-lisp :padline no - ;; -*- lexical-binding: t; -*- -#+END_SRC + These are some settings that need to be taken care of before the + rest. -* Package configuration +** Lexical binding - Require package.el since I immediately start using its variables and - functions anyway, no need to delay loading. + To start off, first I need to enable lexical binding. It offers + better performance in some circumstances and enables me to use cool + things such as closures. - #+BEGIN_SRC emacs-lisp - (require 'package) - #+END_SRC + #+BEGIN_SRC emacs-lisp :padline no + ;; -*- lexical-binding: t; -*- + #+END_SRC - Add the MELPA and org package archives because I like living on the - bleeding edge. This should be done both at run-time and compile-time - so I can install packages at compile time. +** Load path - #+BEGIN_SRC emacs-lisp - (eval-and-compile - (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")) - (add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/"))) - #+END_SRC + Emacs' load path is where it looks to find Emacs Lisp files when + confronted with a =load= or =require= form. Most of my packages + are managed through the package manager, but not all of them. - Add the directory with my mode-specific configuration files to the - load path. +*** Mode-specific configuration directory - #+BEGIN_SRC emacs-lisp - (add-to-list 'load-path (locate-user-emacs-file "init/")) - #+END_SRC + Add the directory with my mode-specific configuration files to the + load path. - Add all my vendored packages to the load path. + #+BEGIN_SRC emacs-lisp + (add-to-list 'load-path (locate-user-emacs-file "init/")) + #+END_SRC - #+BEGIN_SRC emacs-lisp - (eval-and-compile - (mapc (lambda (d) (add-to-list 'load-path d)) - (directory-files - (locate-user-emacs-file "vendor-lisp/") t "^[^.]"))) - #+END_SRC +*** Vendor directory - Initialize package.el so that packages can be loaded and used. This - also needs to be done at both run-time and compile-time so packages - can be installed at compile-time. + Add all my vendored packages to the load path. - #+BEGIN_SRC emacs-lisp - (eval-and-compile (package-initialize)) - #+END_SRC + #+BEGIN_SRC emacs-lisp + (eval-and-compile + (mapc (lambda (d) (add-to-list 'load-path d)) + (directory-files + (locate-user-emacs-file "vendor-lisp/") t "^[^.]"))) + #+END_SRC - Some actions produce a lot of output that is usually uninteresting - during compilation. However, this information may be crucial when an - error occurs. So for these actions I can use this macro, which - stores all sent messages in a temporary buffer and prints them when - an error occurs, and hides them when it doesn't. +*** Site lisp - #+BEGIN_SRC emacs-lisp - (defmacro silently (title &rest body) - "Only output something when an error occurs. - Prefix with TITLE any output that occurs while executing BODY, - but only when an error occurs, otherwise discard it." - (declare (indent 1)) - (let ((buffer-var (cl-gensym)) - (error-var (cl-gensym))) - `(with-temp-buffer - (let ((,buffer-var (current-buffer))) - (cl-letf (((symbol-function 'message) - (lambda (msg &rest args) - (with-current-buffer ,buffer-var - (insert " " (apply 'format msg args) "\n"))))) - (condition-case ,error-var - (progn ,@body) - (error - (princ ,(concat title " output:\n")) - (princ (with-current-buffer ,buffer-var (buffer-string))) - (princ "Error:\n") - (princ " ") - (princ (cadr ,error-var)) - (princ "\n")))))))) - #+END_SRC + Setup everything so that any autoloads in ~site-lisp/~ get loaded + and can be used. - Refresh the package contents so packages can be installed from all - configured archives. Don't do this at run-time because it slows down - the process too much. + #+BEGIN_SRC emacs-lisp + (eval-and-compile + (add-to-list 'load-path (locate-user-emacs-file "site-lisp/")) + (let ((loaddefs (locate-user-emacs-file "site-lisp/site-autoloads.el"))) + (when (file-exists-p loaddefs) + (load loaddefs)))) + #+END_SRC - #+BEGIN_SRC emacs-lisp - (eval-when-compile - (let* ((not-installed (seq-remove 'package-installed-p - package-selected-packages)) - (available (seq-filter (lambda (p) - (assq p package-archive-contents)) - not-installed)) - (difference (- (length not-installed) (length available)))) - (when (> difference 0) - (silently "Refresh packages" - (package-refresh-contents))) - (when available - (mapc (lambda (p) (package-install p t)) available)))) - #+END_SRC +** Helper functions -* Site lisp + Some things are best abstracted into special functions and/or + macros so as not to make the setting itself too verbose. - Setup everything so that any autoloads in ~site-lisp/~ get loaded - and can be used. + I have some helper functions stored away in a separate file. - #+BEGIN_SRC emacs-lisp - (eval-and-compile - (add-to-list 'load-path (locate-user-emacs-file "site-lisp/")) - (let ((loaddefs (locate-user-emacs-file "site-lisp/site-autoloads.el"))) - (when (file-exists-p loaddefs) - (load loaddefs)))) - #+END_SRC - -* Helper functions - - I have some helper functions stored away in a separate file. - - #+BEGIN_SRC emacs-lisp + #+BEGIN_SRC emacs-lisp (require 'oni-helpers) - #+END_SRC + #+END_SRC + +** Package configuration + + Since Emacs 24 there has been a package manager in Emacs. A lot of + packages have been added to a number of package repositories. + +*** Load the package manager + + Require package.el since I immediately start using its variables + and functions anyway, no need to delay loading. + + #+BEGIN_SRC emacs-lisp + (require 'package) + #+END_SRC + +*** Add package archives + + The default package archive has some pretty neat packages, but the + Melpa package archive is much more popular because it doesn't + require copyright assignment to upload packages to it and it is + well integrated with git. + + I add these archives both at compile-time and run-time because I + install missing packages at compile-time. If the archives aren't + added then, the packages can't be installed. + +**** Add Melpa + + Add the Melpa package archive because I like living on the + bleeding edge. + + #+BEGIN_SRC emacs-lisp + (eval-and-compile + (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))) + #+END_SRC + +**** Add org + + Add the org package archive because it hosts the latest org + development release, and as stated above, I like living on the + bleeding edge. + + #+BEGIN_SRC emacs-lisp + (eval-and-compile + (add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/"))) + #+END_SRC + +*** Initialize the package manager + + Initialize package.el so that packages can be loaded and used. This + also needs to be done at both run-time and compile-time so packages + can be installed at compile-time. + + #+BEGIN_SRC emacs-lisp + (eval-and-compile (package-initialize)) + #+END_SRC + +*** Install missing packages + + Refresh the package contents so packages can be installed from all + configured archives. Don't do this at run-time because it slows down + the process too much. Afterwards + + #+BEGIN_SRC emacs-lisp + (eval-when-compile + (let* ((not-installed (seq-remove 'package-installed-p + package-selected-packages)) + (available (seq-filter (lambda (p) + (assq p package-archive-contents)) + not-installed)) + (difference (- (length not-installed) (length available)))) + (when (> difference 0) + (silently "Refresh packages" + (package-refresh-contents))) + (when available + (mapc (lambda (p) (package-install p t)) available)))) + #+END_SRC * Backups