Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
351 lines (295 sloc) 12.2 KB

Emacs configuration file

Packages

Managing extensions for Emacs is simplified using package which is built in to Emacs 24 and newer. To load downloaded packages we need to initialize package. cl is a library that contains many functions from Common Lisp, and comes in handy quite often, so we want to make sure it’s loaded, along with package, which is obviously needed.

(require 'cl)
(require 'package)
(package-initialize)

Packages can be fetched from different mirrors, melpa is the largest archive and is well maintained.

(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
(add-to-list 'package-archives '("melpa-stable" . "https://stable.melpa.org/packages/"))
(add-to-list 'package-archives '("org" . "https://orgmode.org/elpa/") t)

The configuration assumes that the packages listed below are installed. To ensure we install missing packages if they are missing.

 (let* ((package--builtins nil)
	  (packages
	   '(auto-compile         ; automatically compile Emacs Lisp libraries
	     company              ; Modular text completion framework
	     editorconfig	  ; Provides editor standards (linespacing, etc)
	     erlang               ; Erlang major mode
	     evil                 ; evil vim mode!
	     git-gutter-fringe    ; Fringe version of git-gutter.el
	     gnuplot              ; GNU Charting program
	     helm                 ; Incremental and narrowing framework
	     helm-company         ; Helm interface for company-mode
	     helm-projectile      ; Helm integration for Projectile
	     helm-rg              ; helm integration for ripgrep
	     htmlize              ; Pretty html for org exports
	     jedi                 ; Python auto-completion for Emacs
	     magit                ; control Git from Emacs
	     markdown-mode        ; Emacs Major mode for Markdown-formatted files
	     org                  ; Outline-based notes management and organizer
	     org-bullets          ; Pretty org bullets
	     projectile           ; Manage and navigate projects in Emacs easily
	     idle-require         ; load elisp libraries while Emacs is idle
	     solarized-theme      ; Solarized theme
	     try)))        				; Display available keybindings in popup
   (ignore-errors ;; This package is only relevant for Mac OS X.
     (when (memq window-system '(mac ns))
	 (push 'exec-path-from-shell packages)
	 (push 'reveal-in-osx-finder packages))
     (let ((packages (remove-if 'package-installed-p packages)))
	 (when packages
	   ;; Install uninstalled packages
	   (package-refresh-contents)
	   (mapc 'package-install packages)))))

Mac OS X

I run this configuration mostly on Mac OS X, so we need a couple of settings to make things work smoothly. In the package section exec-path-from-shell is included (only if you’re running OS X), this is to include environment-variables from the shell. It makes using Emacs along with external processes a lot simpler. I also prefer using the Command-key as the Meta-key.

(when (memq window-system '(mac ns))
  (setq ns-pop-up-frames nil
        x-select-enable-clIpboard t)
  (exec-path-from-shell-initialize)
  (when (fboundp 'mac-auto-operator-composition-mode)
    (mac-auto-operator-composition-mode 1)))'

Require

Some features are not loaded by default to minimize initialization time, so they have to be required (or loaded, if you will). require-calls tends to lead to the largest bottleneck’s in a configuration. idle-require delays the require-calls to a time where Emacs is in idle. So this is great for stuff you eventually want to load, but is not a high priority.

(require 'idle-require)             ; Need in order to use idle-require

(dolist (feature
         '(auto-compile             ; auto-compile .el files
           recentf))                  ; recently opened files
  (idle-require feature))

(setq idle-require-idle-delay 5)
(idle-require-mode 1)

Backup and autosave

To avoid doing this each time a change is made we can add a function to the after-save-hook ensuring to always tangle and byte-compile the org-document after changes.

(defun tangle-init ()
  "If the current buffer is 'emacs-init.org' the code-blocks are
tangled, and the tangled file is compiled."
  (when (equal (buffer-file-name)
               (expand-file-name (concat user-emacs-directory "emacs-init.org")))
    ;; Avoid running hooks when tangling.
    (let ((prog-mode-hook nil))
      (org-babel-tangle)
      (byte-compile-file (concat user-emacs-directory "emacs-init.el")))))

(add-hook 'after-save-hook 'tangle-init)

By default, emacs writes a backup file next to the file being editing with a trailing ~ turd.

;; store all autosave files in the tmp dir
(setq auto-save-file-name-transforms
      `((".*" ,temporary-file-directory t)))

;; backups in backup dir
(setq backup-by-copying t
      backup-directory-alist '(("." . "~/.emacs.d/backup"))
      delete-old-versions t
      kept-new-versions 24
      kept-old-versions 12
      version-control t)

(setq create-lockfiles nil)

Defaults

Sets all the defaults we need

 (setq inhibit-startup-screen t           ; No startup message
	 custom-file (make-temp-file "")    ; Discard customization's
	 initial-scratch-message nil       ; Clean scratch buffer
	 recentf-max-saved-items 200       ; Show more recent files
	 ring-bell-function 'ignore        ; Quiet
 )

 (setq recentf-exclude
         '("^/tmp\\.*" "^/private\\.*" "^/var/folders\\.*" "/TAGS$"))

Private

I’d like to keep a few settings private, so we load a private.el if it exists after the init-file has loaded.

(add-hook
 'after-init-hook
 (lambda ()
   (let ((private-file (concat user-emacs-directory "private.el")))
     (when (file-exists-p private-file)
       (load-file private-file)))))

Modes

There are some modes that are enabled by default that I don’t find particularly useful. We create a list of these modes, and disable all of these.

(dolist (mode
         '(tool-bar-mode                ; No toolbars, more room for text
           scroll-bar-mode              ; No scroll bars either
           blink-cursor-mode))          ; The blinking cursor gets old
  (funcall mode 0))

Enable useful modes:

 (dolist (mode
       '(abbrev-mode                  ; E.g. sopl -> System.out.println
         column-number-mode           ; Show column number in mode line
         delete-selection-mode        ; Replace selected text
         dirtrack-mode                ; directory tracking in *shell*
         global-company-mode          ; Auto-completion everywhere
         global-git-gutter-mode       ; Show changes latest commit
         global-prettify-symbols-mode ; Greek letters should look greek
         projectile-global-mode       ; Manage and navigate projects
         recentf-mode                 ; Recently opened files
         show-paren-mode))             ; Available keybindings in popup
(funcall mode 1))

Visual

Change the color-theme to solarized.

(load-theme 'solarized-dark t)

Package Settings

Company Mode

Company mode provides auto completion for editing.

(setq company-idle-delay 0
   company-echo-delay 0
   company-dabbrev-downcase nil
   company-minimum-prefix-length 2
   company-selection-wrap-around t
   company-transformers '(company-sort-by-occurrence
                          company-sort-by-backend-importance))

; Define key bindings for company mode
(define-key company-active-map (kbd "C-d") 'company-show-doc-buffer)
(define-key company-active-map (kbd "C-n") 'company-select-next)
(define-key company-active-map (kbd "C-p") 'company-select-previous)
(define-key company-active-map (kbd "<tab>") 'company-complete)

EditorConfig

(require 'editorconfig)
(editorconfig-mode 1)

Evil

(require 'evil)
(evil-mode 1)

Git Gutter

(require 'git-gutter-fringe)

(dolist (p '((git-gutter:added    . "#0c0")
             (git-gutter:deleted  . "#c00")
             (git-gutter:modified . "#c0c")))
  (set-face-foreground (car p) (cdr p))
  (set-face-background (car p) (cdr p)))

Helm

(require 'helm)
(require 'helm-config)
(require 'helm-rg)

;; Set a path for projectile to search for projects
(setq projectile-project-search-path '("~/repos/" "~/.dotfiles/"))

(setq helm-split-window-in-side-p t
   helm-M-x-fuzzy-match t
   helm-buffers-fuzzy-matching t
   helm-recentf-fuzzy-match t
   helm-move-to-line-cycle-in-source t
   projectile-completion-system 'helm)

(set-face-attribute 'helm-selection nil :background "cyan")
;; get rid of `find-file-read-only' and replace it with something
;; more useful.
(global-set-key (kbd "C-x C-r") 'helm-recentf)
(global-set-key (kbd "M-x") 'helm-M-x)
(global-set-key (kbd "C-x C-f") 'helm-find-files)

(global-set-key (kbd "C-c h") 'helm-command-prefix)
(global-unset-key (kbd "C-x c"))

(define-key helm-map (kbd "<tab>") 'helm-execute-persistent-action) ; rebind tab to run persistent action
(define-key helm-map (kbd "C-i") 'helm-execute-persistent-action) ; make TAB work in terminal
(define-key helm-map (kbd "C-z")  'helm-select-action) ; list actions using C-z

(helm-mode 1)
(helm-projectile-on)
(helm-adaptive-mode 1)

Org Mode

Default settings for orgmode, such as where files are located:

(require 'org)
(require 'htmlize)

(setq org-completion-use-ido nil)
;; Set to the location of your Org files on your local system
(setq org-directory "~/Dropbox/org")
(setq org-agenda-files '("~/Dropbox/org/inbox.org"
                      "~/Dropbox/org/gtd.org"
                      "~/Dropbox/org/tickler.org"))

(setq org-capture-templates '(("t" "Todo [inbox]" entry
                            (file+headline "~/Dropbox/org/inbox.org" "Tasks")
                            "* TODO %i%?")
                           ("T" "Tickler" entry
                            (file+headline "~/Dropbox/org/tickler.org" "Tickler")
                            "* %i%? \n %U")))

(setq org-refile-targets '(("~/Dropbox/org/gtd.org" :maxlevel . 3)
                        ("~/Dropbox/org/someday.org" :level . 1)
                        ("~/Dropbox/org/tickler.org" :maxlevel . 2)))

(setq org-todo-keywords '((sequence "TODO(t)" "WAITING(w)" "|" "DONE(d)" "CANCELLED(c)")))

Key bindings for orgmode.

(global-set-key "\C-cl" 'org-store-link)
(global-set-key "\C-ca" 'org-agenda)
(global-set-key "\C-cc" 'org-capture)
(global-set-key "\C-cb" 'org-iswitchb)

Enable babel to use different languages in orgmode:

(setq org-confirm-babel-evaluate nil)
(org-babel-do-load-languages
 'org-babel-load-languages
 '((emacs-lisp . t)
  (ditaa . t)
  (gnuplot . t)
  (ledger . t)
  (java . t)
  (python . t)
  (ruby . t)
  (shell . t)))

When editing org-files with source-blocks, we want the source blocks to be themed as they would in their native mode.

(setq org-src-fontify-natively t
      org-src-tab-acts-natively t
      org-confirm-babel-evaluate nil
      org-edit-src-content-indentation 0)

Add org-bullets:

(require 'org-bullets)
(add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))