There are many ways to configure Emacs, but you always need an init file. Several 'ready-to-use' system have been proposed, including starter-kit, prelude, and various flavours based on those packaging systems (e.g., Eric Schulte's Starter Kit for Emacs 24, Kieran Healy's Starter Kit for the Social Sciences, or Xiao Hanyu's oh-my-emacs inspired by oh-my-zsh; see also Where I can find the most popular Emacs settings?). I don't really like the way they often are introduced--"to provide Emacs better defaults"--since Emacs is what it is and you are free to customize it the way you like. After all, Emacs default configuration is already a good one, compared to many other free Text editor (and yes, I know, Emacs is not just a Text editor).
I've tried two Starter Kits and prelude, but (1) nothing works right out of
the box, and (2) I dislike using pre-configured packages because I know I
will spend more time tweaking their many options than writing a set of
configuration files myself. This is not to say that these are bad
frameworks. They are just bad for me, because I know I will learn nothing
from copying them into my
.emacs directory, or I will spend too much time
parsing hundreds of Elisp files. Moreover, there are many Emacs modes that I
don't need (basically, I mainly work with R, Python, lisp, Markdown, and
shell), and other settings I am not used to when it comes to handle text
stream in Emacs. However, I very much appreciate the work made by
others--especially the litterate programming approach based on org-mode by
Eric Schulte, and I must acknowledge I shamelessly copy/paste many of Elisp
instructions in my own
.emacs for years. Now, I was just feeling it really
is time to build my own set of configuration files.
This is very much work in progress and things will probably change a little. I will eventually post this Emacs config files on GitHub.
A modular approach to package management
In a related post I
described how I configured my new MacBook Pro by using
Homebrew. This took me half a day before a trip to
Utrecht. It took me a couple of hours to build a whole directory of Elisp
files to manage my final Emacs configuration. Let's start by taking a look
at what is finally included in my
% tree -d -L 1 . ├── auto-save-list ├── cache ├── elpa ├── modules ├── snippets ├── var └── vendor 7 directories % ls README cache init.el snippets vendor auto-save-list elpa modules var
init.el file is quite simple: it consists in initializing Emacs
package manager, define a series of required packages(a) (if they
are not installed, they will be installed when Emacs starts) and some
specific directories, and finally launch Emacs daemon in order to ensure
that we can connect to the running instance of Emacs through
;; Init package manager and set up ELPA repository (require 'package) (setq package-archives '(("marmalade" . "http://marmalade-repo.org/packages/") ;; ("tromey" . "http://tromey.com/elpa/") ("melpa" . "http://melpa.milkbox.net/packages/"))) (package-initialize) (when (not package-archive-contents) (package-refresh-contents)) (defvar my-packages '(markdown-mode ido-ubiquitous ess mode-compile ac-python ac-math ac-nrepl git-gutter-fringe ibuffer-git elpy slime offlineimap geiser ac-geiser quack elisp-slime-nav scala-mode2 sbt-mode smex cider cider-tracing auctex clojure-mode coffee-mode pandoc-mode deft gist haskell-mode flx-ido magit smartparens projectile python auto-complete exec-path-from-shell) "A list of packages that will be installed if not present when firing Emacs") (dolist (p my-packages) (when (not (package-installed-p p)) (package-install p))) ;; Define top-level, vendor and custom files (defvar emacs-dir (file-name-directory load-file-name) "Top level Emacs dir.") (defvar vendor-dir (expand-file-name "vendor" emacs-dir) "Packages not yet available in ELPA.") (defvar module-dir (expand-file-name "modules" emacs-dir) "Personal stuff.") (defvar save-dir (expand-file-name "cache" emacs-dir) "Common place to save Emacs save/history-files.") ;; Add to load path (unless (file-exists-p save-dir) (make-directory save-dir)) (add-to-list 'load-path vendor-dir) (add-to-list 'load-path module-dir) ;; Require packages in modules/ (mapc 'load (directory-files module-dir nil "^[^#].*el$")) ;; Launch Emacs as daemon (require 'server) (unless (server-running-p) (server-start))
Here, I defined four custom directories:
emacs-dir is the root directory,
module-dir directories are where packages will be
save-dir will be the general place where cache and history
files will be stored.
Then, I wrote several Elisp files (list is growing) to customize different
modes (e.g., general lisp, Clojure, Python), but the most important ones are
text.el, where default options for Emacs look-and-feel
(including general theme options) and text handling are defined.
% ls modules my-ac.el my-email.el my-git.el my-octave.el my-project.el my-scheme.el my-tex.el my-ui.el my-cc.el my-ess.el my-lisp.el my-osx.el my-python.el my-shell.el my-text.el
Autocomplete is enabled for most programming languages, and I make heavy use
of Eldoc, Outline, and Ido/smex. All temporary or history files are saved in
cache/ directory, which avoids to clutter my user directory or the
.emacs.d/ folder itself. Although I do not use
better-defaults, I think I
setup almost everything as suggested by Phil Hagelberg. I do not make use of
Yas-snippet, but it is required by Python
elpy. At some point, I will
probably remove this dependance.
I'm quite happy with how things are working now. Regarding Lisp dialects
(Common Lisp, Clojure, and Scheme), I have the following settings:
my-scheme. Note that I configured
Slime in both cases (i.e., with SBCL and with Chicken Scheme).
Finally, as can be noted in one of the
first output above, I still have to manage how to put this
folder into the right place (
cache/), but that's a minor issue.
At some point, I should probably give Helm a try. However, I do not really like when there's too much fuzzy completion. As long as I can keep it simple and have access to my favorite commands within few keystrokes, I'm happy with my current configuration.
I was thinking I could organize R packages into two different folders:
core/ where most used and reliable packages would go and
I would copy packages that I barely use or that I just installed to check
some functions. This bears some idea from
that all packages will be listed under
.libPath(), and thus available at
any time. However, this would greatly simply their updating since I could
just list the 'core' packages in a separate text file that I could pass to
install.packages() when I need to update only those packages or for a
brand new installation of R.
(a) Actually, for testing purpose I also installed some packages by hand
M-x list-packages-install), and I added them back to my list of default
packages. This is why using a simple text file with the name of packages
would be a better alternative.