Emacs Starter Kit
Table of Contents
Emacs outshines all other editing software in approximately the same way that the noonday sun does the stars. It is not just bigger and brighter; it simply makes everything else vanish.
– Neal Stephenson, "In the Beginning was the Command Line"
Introduction
This should provide a saner set of defaults than you get normally with Emacs. It's intended for beginners, but provides a good elisp initialization structure for all levels of users.
The main advantage of this Emacs Starter Kit are
- better default settings
- inclusion of many useful libraries and configurations
- "literate" customization embedded in Org-mode files
- an organizational directory structure
- git provides for version control, backup, and sharing
The latest version is at http://github.com/eschulte/emacs24-starter-kit/
Learning
This won't teach you Emacs, but it'll make it easier to get comfortable. To access the tutorial, press control-h followed by t from within Emacs.
The Emacs Wiki is also very handy.
Installation
- Install Emacs version 24 or greater. Use your package manager if you have one and it has an install candidate for Emacs 24, otherwise install it directly from source, or Mac binaries may be downloaded from the nightlies section of http://emacsformacosx.com/builds
- Checkout a version of the starter kit using git – if you're new to
git checkout this git-tutorial, also we'd highly recommend that you
try out magit the Emacs mode for git interaction.
git clone http://github.com/eschulte/emacs24-starter-kit.git
- Move the resulting directory to
~/.emacs.d
1 - Launch Emacs!
After setup you may need to restart Emacs one or twice while it
downloads packages from ELPA – errors parsing html from
*tromey.com:80*
can generally be safely ignored.
If you are missing some autoloads after an update (should manifest
itself as void function: foobar
errors) try M-x regen-autoloads.
If you want to keep your regular ~/.emacs.d
in place and just launch
a single instance using the starter kit, try the following invocation:
emacs -q -l ~/path/to/emacs24-starter-kit/init.el \ --eval "(run-hooks 'after-init-hook)"
Note that having a ~/.emacs
file might override the starter kit
loading, so if you've having trouble loading it, make sure that file
is not present.
Structure
The init.el
file is where everything begins. It is loaded
automatically by Emacs on startup, its sole purpose is to load the
elisp code embedded in this file. This file then loads some minimal
configuration which should be generally useful, and goes on to load
user-specific configuration files from the following locations
mentioned in customizations immediately below.
Customization
The defaults built into the starter kit are only the beginning of most users customization of Emacs to suit their needs. The starter kit provides a number of places for additional user and system specific customization. These are designed in such a way that it will be easy for you to continue tracking your own personal customization inside the starter-kit while retaining your ability to pull down general starter-kit updates without conflict.
- git branch
- The first step to user-specific customization is (like
in any git project) to MAKE A BRANCH FOR YOUR LOCAL CHANGES.
Save the master branch for pulling down new versions of the
starter kit, and save all of your personal information in a
personal branch. That way you never have to worry about
accidentally
git push
'ing up a patch with all of your gnus email passwords. - User specific config
- Your personal configuration information can
be stored in a user-specific-config file. This is the file named
after your user with the extensions
.el
or.org
2. If you're unsure of your user name evaluate the following code block to find out.echo $USER # note: on windows this is the USERNAME variable
If your configuration starts to feel cramped in a single file (although with the nested headlines of an Org-mode file, that could take a while) and you want to stretch your config's legs, you can also create a directory named after your system user name. If a such a directory exists, it will be added to the load-path, and any elisp or org-mode w/embedded elisp files in it will be loaded.
- System specific config
- Finally, you may want to configure
different settings for different machines. The Starter Kit will
look for a file named after the current hostname ending in
.el
or.org
which will allow host-specific configuration. If you're unsure of your hostname the following can be executed to find out.hostname
- Activating more of the starter kit
- By default, the starter kit
only includes customizations which are likely to be useful across
nearly any Emacs install (the only automatically loaded external
files are those listed in Load the rest of the starter kit core).
You may have noticed that there are many other
starter-kit-*.org
files located in this directory. A good first step is to browse these files and begin optionally loading those that look relevant to your workflow. For example, if you often work with Python source code you will probably want to loadstarter-kit-python.org
either by directly copying the sections that look useful into your personal config, or simply by loading the entire file directly with the following.(starter-kit-load "python")
Alternately you can load only one particular subsection of an included file, for example to load just the "pretty-summary" section of
starter-kit-gnus.org
run the following.(starter-kit-load "gnus" "pretty-summary")
Finally you can load just those subsections of a file which have a specific tag, so to load just the two sections of
starter-kit-misc-recommended.org
which are taggedvisual
add the following to your personal initialization. Note: header id's take priority over tags.(starter-kit-load "gnus" "visual")
- Installing more elisp libraries
- The easiest way to install new
libraries is through the Emacs Lisp Package Archive (see Emacs
Lisp Package Archive below). When a library is not available
through ELPA you can grab it's source and place it directly in
the
src
directory. Any packages found there will automatically be added to your load-path when Emacs starts up, and are guaranteed not to conflict with future starter-kit updates. - Misc
- Some additional miscellaneous configuration and getting
started suggestions
- First see the Customization node in the Emacs manual. Available
online or through the
info
command (run withC-h i
). grep
'ing through thestarter-kit-*
files in this directory can provide useful examples for how to do things like install major modes, define keybindings, etc..- read the following Key-Binding-Conventions before defining too many personal key bindings
- First see the Customization node in the Emacs manual. Available
online or through the
Optional starter kit packages
Emacs Lisp Package Archive
Libraries from ELPA are preferred when available since dependencies
are handled automatically, and the burden to update them is removed
from the user. ELPA is now an official part of Emacs so no special
configuration is required to download and install packages. Packages
installed through ELPA will be stored in the elpa/
sub-directory of
this directory.
Contributing
If you know your way around Emacs, please try out the starter kit as a replacement for your regular dotfiles for a while. If there's anything you just can't live without, add it or let me know so I can add it. Take a look at what happens in init.el to get started.
Files are licensed under the same license as Emacs unless otherwise specified. See the file COPYING for details.
The latest version is at http://github.com/eschulte/emacs24-starter-kit/
Implementation
This section contains all code implementing the Emacs Starter Kit. It is probably safe to stop reading at this point unless you are interested in the actual code implementing the starter kit.
Starter kit basics
- Load path etc.
(let ((elisp-dir (expand-file-name "src" starter-kit-dir))) ;; add the src directory to the load path (add-to-list 'load-path elisp-dir) ;; load specific files (when (file-exists-p elisp-dir) (let ((default-directory elisp-dir)) (normal-top-level-add-subdirs-to-load-path)))) (setq autoload-file (concat starter-kit-dir "loaddefs.el")) (setq package-user-dir (concat starter-kit-dir "elpa")) (setq custom-file (concat starter-kit-dir "custom.el"))
- Ubiquitous Packages which should be loaded on startup rather than
autoloaded on demand since they are likely to be used in every
session.
(require 'cl) (require 'cl-lib) (require 'saveplace) (require 'ffap) (require 'uniquify) (require 'ansi-color) (require 'recentf)
- Function to check if a packages exist in the load path. This may be
used to preempt the installation of ELPA versions of packages whose
source may already be found in the load path.
(defun starter-kit-loadable-p (package) "Check if PACKAGE is loadable from a directory in `load-path'." (let ((load-file (concat (symbol-name package) ".el"))) (catch 'file-found (dolist (dir load-path) (let ((path (expand-file-name load-file dir))) (when (file-exists-p path) (throw 'file-found path)))))))
- ELPA archive repositories and two packages to install by default.
(setq package-archives '(("gnu" . "http://elpa.gnu.org/packages/") ("org" . "http://orgmode.org/elpa/") ("melpa" . "http://melpa.milkbox.net/packages/") ("marmalade" . "http://marmalade-repo.org/packages/"))) (package-initialize) (defvar starter-kit-packages nil "Libraries that should be installed by default (currently none).") (defun starter-kit-install-if-needed (&rest packages) "Install PACKAGES using ELPA if they are not loadable or installed locally." (when packages (unless package-archive-contents (package-refresh-contents)) (dolist (package packages) (unless (or (starter-kit-loadable-p package) (package-installed-p package)) (package-install package)))))
- Function for loading other parts of the starter kit
(defun starter-kit-load (file &optional header-or-tag) "Load configuration from other starter-kit-*.org files. If the optional argument is the id of a subtree then only configuration from within that subtree will be loaded. If it is not an id then it will be interpreted as a tag, and only subtrees marked with the given tag will be loaded. For example, to load all of starter-kit-lisp.org simply add (starter-kit-load \"lisp\") to your configuration. To load only the 'window-system' config from starter-kit-misc-recommended.org add (starter-kit-load \"misc-recommended\" \"window-system\") to your configuration." (let ((file (expand-file-name (if (string-match "starter-kit-.+\.org" file) file (format "starter-kit-%s.org" file)) starter-kit-dir))) (org-babel-load-file (if header-or-tag (let* ((base (file-name-nondirectory file)) (dir (file-name-directory file)) (partial-file (expand-file-name (concat "." (file-name-sans-extension base) ".part." header-or-tag ".org") dir))) (unless (file-exists-p partial-file) (with-temp-file partial-file (insert (with-temp-buffer (insert-file-contents file) (save-excursion (condition-case nil ;; collect as a header (progn (org-link-search (concat"#"header-or-tag)) (org-narrow-to-subtree) (buffer-string)) (error ;; collect all entries with as tags (let (body) (org-map-entries (lambda () (save-restriction (org-narrow-to-subtree) (setq body (concat body "\n" (buffer-string))))) header-or-tag) body)))))))) partial-file) file))))
- Work around a bug on OS X where system-name is FQDN.
(if (or (eq system-type 'darwin) (eq system-type 'berkeley-unix)) (setq system-name (car (split-string system-name "\\."))))
Starter kit core
The following files contain the remainder of the core of the Emacs Starter Kit. All of the code in this section should be loaded by everyone using the starter kit.
- Starter kit function definitions in starter-kit-defuns
(starter-kit-load "starter-kit-defuns.org")
- Key Bindings in starter-kit-bindings
(starter-kit-load "starter-kit-bindings.org")
- Miscellaneous settings in starter-kit-misc
(starter-kit-load "starter-kit-misc.org")
- Registers for jumping to commonly used files in starter-kit-registers
(starter-kit-load "starter-kit-registers.org")
Load User/System Specific Files
System/User specific customizations
You can keep system- or user-specific customizations here in either raw emacs-lisp files or as embedded elisp in org-mode files (as done in this document).
You can keep elisp source in the src
directory. Packages loaded
from here will override those installed by ELPA. This is useful if
you want to track the development versions of a project, or if a
project is not in elpa.
After we've loaded all the Starter Kit defaults, lets load the User's stuff.
(cl-flet ((sk-load (base) (let* ((path (expand-file-name base starter-kit-dir)) (literate (concat path ".org")) (encrypted-org (concat path ".org.gpg")) (plain (concat path ".el")) (encrypted-el (concat path ".el.gpg"))) (cond ((file-exists-p encrypted-org) (org-babel-load-file encrypted-org)) ((file-exists-p encrypted-el) (load encrypted-el)) ((file-exists-p literate) (org-babel-load-file literate)) ((file-exists-p plain) (load plain))))) (remove-extension (name) (string-match "\\(.*?\\)\.\\(org\\(\\.el\\)?\\|el\\)\\(\\.gpg\\)?$" name) (match-string 1 name))) (let ((user-dir (expand-file-name user-login-name starter-kit-dir))) ;; load system-specific config (sk-load system-name) ;; load user-specific config (sk-load user-login-name) ;; load any files in the user's directory (when (file-exists-p user-dir) (add-to-list 'load-path user-dir) (mapc #'sk-load (remove-duplicates (mapcar #'remove-extension (directory-files user-dir t ".*\.\\(org\\|el\\)\\(\\.gpg\\)?$")) :test #'string=)))))
Settings from M-x customize
(load custom-file 'noerror)