Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
1244 lines (1109 sloc) 36.9 KB

Basic things

Tidier UI

(setq inhibit-splash-screen t)

(tool-bar-mode 0)
(scroll-bar-mode 0)
(display-battery-mode 0)

Shorter prompt

(defalias 'yes-or-no-p 'y-or-n-p)

Scrolling behaviour

Avoids jumping half-a-screen when cursor reaches buttom of screen

(setq scroll-conservatively 10000)

Default tab settings

Don’t indent with tabs, and make tab-width 4 just-in-case (mainly for untabify)

(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)
(setq tab-width 4)

C++ indentation

Example indentation:

(setq-default c-basic-offset 4)
(setq-default c-default-style "bsd") ; or k&r?

Quieter visual bell

Message in minibuf on bell, instead of system beep etc

(setq ring-bell-function (lambda ()
                           (if (not (active-minibuffer-window))
                               (message "*beep*"))))

Flash scroll-lock LED (disabled)

;(setq ring-bell-function (lambda ()
;  (call-process-shell-command "xset led 3; xset -led 3" nil 0 nil)))

Avoid FS mess

Move autosave/backup files to ~/.emacs.d/autosaves and ~/.emacs.d/backups

(setq backup-directory-alist
      `((".*" . , "~/.emacs.d/backups/")))
(setq auto-save-file-name-transforms
      `((".*" ,"~/.emacs.d/autosaves/" t)))

Ensure directory exists

(make-directory "~/.emacs.d/backups" t)
(make-directory "~/.emacs.d/autosaves" t)

Remove old backups

Remove backups older than one week

(message "Deleting old backup files...")
(let ((week (* 60 60 24 7))
      (current (float-time (current-time))))
  (dolist (file (directory-files temporary-file-directory t))
    (when (and (backup-file-name-p file)
               (> (- current (float-time (nth 5 (file-attributes file))))
      (message file)
      (delete-file file))))

Empty default scratch buffer

(setq initial-scratch-message "")

Recent files

Enable recentf mode

Also limit to 25 files

(require 'recentf)
(setq recentf-max-menu-items 25)

Don’t clean up recent files

It potentially access network drives, which could trigger tramp,

(setq recentf-auto-cleanup 'never)

Bind to C-x C-r

“C-x r” would be better, but it interfers with “C-x r k” for kill-rectangle

(global-set-key "\C-x\ \C-r" 'recentf-open-files)

Guess mode for new buffer

Guess default mode in new buffers from file extension

(setq default-major-mode
      (lambda ()
        (let ((buffer-file-name (or buffer-file-name (buffer-name))))

uniqify buffer names

Replace useless blah.txt<2> with blah.txt<thedirectory>

(require 'uniquify)
(setq uniquify-buffer-name-style 'post-forward-angle-brackets)

Access killring menu

(global-set-key "\C-cy" '(lambda ()
   (popup-menu 'yank-menu)))

Cycle buffers with F1/F2

(global-set-key [f1] 'previous-buffer)
(global-set-key [f2] 'next-buffer)


Only really works on Linux

(defun fullscreen (&optional f)
  (set-frame-parameter f 'fullscreen
                       (if (frame-parameter f 'fullscreen) nil 'fullboth)))

;(add-hook 'after-make-frame-functions 'fullscreen) ; on startup
(global-set-key [f11] 'fullscreen)


More sane scrolling with OS X mouse/trackpad

(global-set-key [wheel-down] (lambda () (interactive) (scroll-up-command 1)))
(global-set-key [wheel-up] (lambda () (interactive) (scroll-down-command 1)))
(global-set-key [double-wheel-down] (lambda () (interactive) (scroll-up-command 2)))
(global-set-key [double-wheel-up] (lambda () (interactive) (scroll-down-command 2)))
(global-set-key [triple-wheel-down] (lambda () (interactive) (scroll-up-command 4)))
(global-set-key [triple-wheel-up] (lambda () (interactive) (scroll-down-command 4)))


Make cursor a vertical bar

Bar makes C-x r t and other box-related behaviour easier to intuit

(setq-default cursor-type 'bar)

Disable cursor blinking

<blink>For no particular reason</blink>

(blink-cursor-mode 0)

Cursor in other buffers

Use hollow box in inactive windows, as the disabled bar cursor looks identical in disabled windows.

(setq-default cursor-in-non-selected-windows 'hollow)

Start server

(setq server-use-tcp nil)

FS navigation

Use ido for shinier minibuf (C-x b and C-x C-f)

(ido-mode 1)

Ignore files in ido

Ignore .DS_Store and .pyc when finding files

(add-to-list 'ido-ignore-files "\\.DS_Store")
(add-to-list 'ido-ignore-files "\\.pyc")

Also OS X “Icon” file:

(add-to-list 'ido-ignore-files "Icon\n")

Prevent ido searching for locations

Disable auto searching for files unless called explicitly, prevents finding files in random directories automatically

(setq ido-auto-merge-delay-time 99999)

(define-key ido-file-dir-completion-map (kbd "C-c C-s")
    (ido-initiate-auto-merge (current-buffer))))

org-mode config

Enable shift-selection in org

(setq org-support-shift-select t)


(add-to-list 'auto-mode-alist '("\\.org$" . org-mode))

babel inline edit

Configure org-mode so that when you edit source code in an indirect buffer (with C-c ‘), the buffer is opened in the current window. That way, your window organization isn’t broken when switching.


(setq org-src-window-setup 'current-window)

org-capture config


(global-set-key "\C-cr" 'org-capture)

Capture templates

(setq org-capture-templates
      '(("t" "Todo" entry (file+headline (concat org-directory "/") "Tasks")
         "* TODO %?\n %i\n")
        ("l" "Link" plain (file (concat org-directory "/"))
         "- %?\n %x\n")))

todo keywords

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

(setq org-todo-keyword-faces
        ("TODO" . (:weight bold :foreground "#ff2020" :background "grey10"))
        ("WAIT" . (:weight bold :foreground "grey70" :background "grey10"))
        ("DONE" . (:weight bold :foreground "grey50"))

Load path

Get base directory

(setq dotfiles-dir (file-name-directory (or load-file-name (buffer-file-name))))

Load base ext/ directory

Store singular .el files in root of ext/ directory

(add-to-list 'load-path (expand-file-name "ext" dotfiles-dir))

Subdirs of ext/

    (d '(
  (add-to-list 'load-path (expand-file-name d (expand-file-name "ext" dotfiles-dir))))

Theme load-path

For emacs 24 builtin theming thing

(if (boundp 'custom-theme-load-path)
    ;; Only run for emacs >24
    (add-to-list 'custom-theme-load-path (expand-file-name "ext" dotfiles-dir)))

Environment vars

Executes .bashrc and pulls $PATH, $MANPATH and $PYTHONPATH into emacs env.

Allows opening normally, while retaining $PATH. Other way is to open by running “open -a Emacs” in the shell, but this is tidier

(require 'exec-path-from-shell)
(setq exec-path-from-shell-variables '("PATH" "MANPATH" "PYTHONPATH"))
(when (memq window-system '(mac ns))

Misc modules


Naquadah (disabled)

;(require 'naquadah-theme)


(load-theme 'ample t t)
(enable-theme 'ample)

; Tweak background
  `(default ((t (:background "gray20")))))

Undo window changes

Undo changes to layout with C-left C-right

(winner-mode 1)


Require module and set nicer colours

(require 'highlight-parentheses)
(setq hl-paren-colors (quote ("firebrick" "lightgreen" "orange" "cyan")))


(require 'cmake-mode)
(setq auto-mode-alist
      (append '(("CMakeLists\\.txt\\'" . cmake-mode)
                ("\\.cmake\\'" . cmake-mode))


Require and auto load for .py files

(require 'textmate)
(add-hook 'python-mode-hook
'(lambda ()

Window resizing shortcuts


(global-set-key [(super control right)] 'shrink-window-horizontally)
(global-set-key [(super control left)] 'enlarge-window-horizontally)
(global-set-key [(super control up)] 'shrink-window)
(global-set-key [(super control down)] 'enlarge-window)

Window-jumping shortcuts


(require 'windmove)
(windmove-default-keybindings 'super)

Non-arrow shortcuts

(global-set-key [(super n)]  'windmove-down)
(global-set-key [(super p)]  'windmove-up)
(global-set-key [(super b)]  'windmove-left)
(global-set-key [(super f)]  'windmove-right)

Super+return makes new line after current

(defun make-newline-after-current()

(global-set-key [(super return)] 'make-newline-after-current)

M-j joins line

Joins next line onto current one, like vim’s ‘shift+j’

(global-set-key (kbd "M-j")
            (lambda ()
                  (join-line -1)))


(require 'undo-tree)

Google maps


;(autoload 'google-maps)
(autoload 'google-maps "google-maps")


Useful for editing themes and CSS

(require 'rainbow-mode)


Load code

(require 'yasnippet)
(yas/global-mode 1)

Custom snippet dir

(yas/load-directory (expand-file-name "snippets" dotfiles-dir))

Change completion UI

Use text-based yas-dropdown-prompt, as it shows all the snippets most clearly, and allows selecition via numbers.

The default dialog in Cocoa is similar, but selection only works with arrows/return. The yas-ido-prompt doesn’t work well because all the snippets are similarly named

(require 'dropdown-list)
(setq yas-prompt-functions '(yas-dropdown-prompt))

Make it work in org-mode

org-mode’s tab overriding prevents yasnippet from working

(defun yas/org-very-safe-expand ()
  (let ((yas/fallback-behavior 'return-nil)) (yas/expand)))

(add-hook 'org-mode-hook
          (lambda ()
            ;; yasnippet (using the new org-cycle hooks)
            (make-variable-buffer-local 'yas/trigger-key)
            (setq yas/trigger-key [tab])
            (add-to-list 'org-tab-first-hook 'yas/org-very-safe-expand)
            (define-key yas/keymap [tab] 'yas/next-field)))


Prevent popups on OS X

(setq flymake-gui-warnings-enabled nil)

For python

(defun flymake-create-temp-in-system-tempdir (filename prefix)
  (make-temp-file (or prefix "flymake")))

(when (load "flymake" t)
  (defun flymake-pyflakes-init ()
    (let* ((temp-file (flymake-init-create-temp-buffer-copy
	   (local-file (file-relative-name
			(file-name-directory buffer-file-name))))
      (list "pyflakes" (list local-file))))

  (add-to-list 'flymake-allowed-file-name-masks
	       '("\\.py\\'" flymake-pyflakes-init)))

(add-hook 'find-file-hook 'flymake-find-file-hook)

Show error under cursor

If the cursor is sitting on a flymake error, display the message in the minibuf. Also bind C-c v to jump to next error

Originally found on

(defun show-fly-err-at-point ()
  "If the cursor is sitting on a flymake error, display the
message in the minibuffer"
  (let ((line-no (line-number-at-pos)))
    (dolist (elem flymake-err-info)
      (if (eq (car elem) line-no)
      (let ((err (car (second elem))))
        (message "%s" (fly-pyflake-determine-message err)))))))

(defun fly-pyflake-determine-message (err)
  "pyflake is flakey if it has compile problems, this adjusts the
message to display, so there is one ;)"
  (cond ((not (or (eq major-mode 'Python) (eq major-mode 'python-mode) t)))
    ((null (flymake-ler-file err))
     ;; normal message do your thing
     (flymake-ler-text err))
    (t ;; could not compile err
     (format "compile error, problem on line %s" (flymake-ler-line err)))))

(defadvice flymake-goto-next-error (after display-message activate compile)
  "Display the error in the mini-buffer rather than having to mouse over it"

(defadvice flymake-goto-prev-error (after display-message activate compile)
  "Display the error in the mini-buffer rather than having to mouse over it"

(defadvice flymake-mode (before post-command-stuff activate compile)
  "Add functionality to the post command hook so that if the
cursor is sitting on a flymake error the error information is
displayed in the minibuffer (rather than having to mouse over
  (set (make-local-variable 'post-command-hook)
       (cons 'show-fly-err-at-point post-command-hook)))

(defun my-flymake-show-next-error()
;;  (flymake-display-err-menu-for-current-line))

(global-set-key (kbd "C-c v") 'my-flymake-show-next-error)

Flycheck (disabled)

Try again when no-longer based on flymake

Fancy modern replacement for flymake


Bind to C-x C-b

(global-set-key (kbd "C-x C-b") 'ibuffer)

Misc config

Avoid prompts when killing buffers

(setq ibuffer-expert t)

Hide empty groups

(setq ibuffer-show-empty-filter-groups nil)

Configure groups

(setq ibuffer-saved-filter-groups
      (quote (("default"
               ("org" (or
                       (mode . org-mode)
                       (name . "\\*Org ")
               ("magit" (or
                         (name . "\\*magit:")
                         (mode . magit-mode)
               ("jabber" (or (mode . jabber-roster-mode)
                             (mode . jabber-chat-mode)
               ("Help" (or (mode . help-mode)
                           (name . "\*Help\*")
                           (name . "\*Apropos\*")
                           (name . "\*info\*")
               ("emacs" (or
                         ;(mode . fundamental)
                         (name . "\\*scratch\\*$")
                         (name . "\\*Messages\\*$")
                         (name . "\\*magit-process\\*$")
                         (name . "\\*Compile-Log\\*$")
                         (name . "\\*Backtrace\\*$")

                         ;; Magit internal stuff
                         (name . "\\*magit-")

(add-hook 'ibuffer-mode-hook
          (lambda ()
            (ibuffer-switch-to-saved-filter-groups "default")))

Fix find-file key override

ido’ify the overridden find-file shortcut, which starts ifo-find-file in the same directory as the file under the cursor


(require 'ibuffer)
(defun ibuffer-ido-find-file ()
  "Like 'ido-find-file', but default to the directory of the buffer at point."
   (let ((default-directory (let ((buf (ibuffer-current-buffer)))
			      (if (buffer-live-p buf)
				  (with-current-buffer buf
     (ido-find-file-in-dir default-directory))))

(define-key ibuffer-mode-map "\C-x\C-f" 'ibuffer-ido-find-file)

Increase column width

(setq ibuffer-formats
      '((mark modified read-only " "
              (name 30 30 :left :elide) " "
              (size 9 -1 :right) " "
              (mode 16 16 :left :elide) " " filename-and-process)
        (mark " " (name 16 -1) " " filename)))

Group by vc-root



Weighted ido’ish M-x enhancement


(require 'smex)

Key bindings:

(global-set-key (kbd "M-x") 'smex)
(global-set-key (kbd "M-X") 'smex-major-mode-commands)

Original M-x bound to C-c C-c M-x:

(global-set-key (kbd "C-c M-x") 'execute-extended-command)


For editing renderman’ish RIB files

(require 'rib-mode)
(add-to-list 'auto-mode-alist '("\\.rib$" . rib-mode))



(load "escreen")

Bind prefix to C-z

(setq escreen-prefix-char "\C-z")
(global-set-key escreen-prefix-char 'escreen-prefix)

uniqify buffer names

(require 'uniquify)
(setq uniquify-buffer-name-style 'post-forward-angle-brackets)

Scroll view by lines

(global-set-key (kbd "<M-up>") (lambda () (interactive) (scroll-down 1)))
(global-set-key (kbd "<M-down>") (lambda () (interactive) (scroll-up 1)))


Automatic removal of unused buffers

Enable mode

(require 'tempbuf)

Enable for specific modes

(add-hook 'buffer-list 'turn-on-tempbuf-mode)
(add-hook 'dired-mode-hook 'turn-on-tempbuf-mode)
(add-hook 'help-mode-hook 'turn-on-tempbuf-mode)


Auto-mode for .yml and .yaml, also .ocio (OpenColorIO config files)

(autoload 'yaml-mode "yaml-mode" nil t)
(add-to-list 'auto-mode-alist '("\\.yaml$" . yaml-mode))
(add-to-list 'auto-mode-alist '("\\.yml$" . yaml-mode))
(add-to-list 'auto-mode-alist '("\\.ocio$" . yaml-mode))

clear shell

Clear inferior-python shell etc

(defun clear-shell ()
  (let ((comint-buffer-maximum-size 0))

Mark word under cursor

M-@ to highlight word under cusror

(defun mark-word-under-cursor ()

(global-set-key [(meta @)] 'mark-word-under-cursor)

Search word under cusror

M-# for vim-ish search word under cursor

(defvar isearch-initial-string nil)

(defun isearch-set-initial-string ()
  (remove-hook 'isearch-mode-hook 'isearch-set-initial-string)
  (setq isearch-string isearch-initial-string)

(defun isearch-forward-at-point (&optional regexp-p no-recursive-edit)
  "Interactive search forward for the symbol at point."
  (interactive "P\np")
  (if regexp-p (isearch-forward regexp-p no-recursive-edit)
    (let* ((end (progn (skip-syntax-forward "w_") (point)))
           (begin (progn (skip-syntax-backward "w_") (point))))
      (if (eq begin end)
          (isearch-forward regexp-p no-recursive-edit)
        (setq isearch-initial-string (buffer-substring begin end))
        (add-hook 'isearch-mode-hook 'isearch-set-initial-string)
        (isearch-forward regexp-p no-recursive-edit)))))

(global-set-key (kbd "M-#") 'isearch-forward-at-point)

Home between beginning of line or indentation

(defun beginning-of-line-or-indentation ()
  "move to beginning of line, or indentation"
  (if (bolp)

(global-set-key [home] 'beginning-of-line-or-indentation)

end key to end of line

(global-set-key [end] 'end-of-line)

Move lines (disabled)

(defun move-text-internal (arg)
   ((and mark-active transient-mark-mode)
    (if (> (point) (mark))
    (let ((column (current-column))
          (text (delete-and-extract-region (point) (mark))))
      (forward-line arg)
      (move-to-column column t)
      (set-mark (point))
      (insert text)
      (setq deactivate-mark nil)))
    (let ((column (current-column)))
      (when (or (> arg 0) (not (bobp)))
        (when (or (< arg 0) (not (eobp)))
          (transpose-lines arg))
        (forward-line -1))
      (move-to-column column t)))))

(defun move-text-down (arg)
  "Move region (transient-mark-mode active) or current line
  arg lines down."
  (interactive "*p")
  (move-text-internal arg))

(defun move-text-up (arg)
  "Move region (transient-mark-mode active) or current line
  arg lines up."
  (interactive "*p")
  (move-text-internal (- arg)))

; (global-set-key [M-up] 'move-text-up)
; (global-set-key [M-down] 'move-text-down)


(autoload 'multi-term "multi-term" nil t)
(autoload 'multi-term-next "multi-term" nil t)

(setq multi-term-program "/bin/bash")

(global-set-key (kbd "C-c t") 'multi-term-next)
(global-set-key (kbd "C-c T") 'multi-term) ;; create a new one


(require 'fastnav)

; Useful
(global-set-key "\M-s" 'jump-to-char-forward)
(global-set-key "\M-S" 'jump-to-char-backward)
(global-set-key "\M-k" 'delete-char-forward)
(global-set-key "\M-K" 'delete-char-backward)

; Questionable
(global-set-key "\M-z" 'zap-up-to-char-forward)
(global-set-key "\M-Z" 'zap-up-to-char-backward)
(global-set-key "\M-R" 'replace-char-backward)
(global-set-key "\M-i" 'insert-at-char-forward)
(global-set-key "\M-I" 'insert-at-char-backward)
(global-set-key "\M-m" 'mark-to-char-forward)
(global-set-key "\M-M" 'mark-to-char-backward)
(global-set-key "\M-p" 'sprint-forward)
(global-set-key "\M-P" 'sprint-backward)

; Conflicting
;(global-set-key "\M-r" 'replace-char-forward)

Show trailing whitespace

F5 toggles showing trailing whitespace

(global-set-key (kbd "<f5>")
                (lambda ()
                  (setq show-trailing-whitespace (not show-trailing-whitespace))


(require 'git-blame)

Show hash and start of commit message

(setq git-blame-prefix-format "%h %.10s:")


(require 'restclient)


(autoload 'markdown-mode "markdown-mode.el"
   "Major mode for editing Markdown files" t)
(add-to-list 'auto-mode-alist '("\\.md$" . markdown-mode))
(add-to-list 'auto-mode-alist '("\\.markdown$" . markdown-mode))


(require 'ace-jump-mode)
(define-key global-map (kbd "C-c SPC") 'ace-jump-mode)

coffee-script mode

Auto-mode for .coffee

(require 'coffee-mode)
(add-to-list 'auto-mode-alist '("\\.coffee$" . coffee-mode))
(add-to-list 'auto-mode-alist '("Cakefile" . coffee-mode))

Convention’y tab-width

(defun coffee-custom ()
 (set (make-local-variable 'tab-width) 2))

(add-hook 'coffee-mode-hook
  '(lambda() (coffee-custom)))


git interface

Load module

(autoload 'magit-status "magit" nil t)

Custom key-bindings

C-i i to load magit-status

(global-set-key "\C-ci" 'magit-status)

Fullscreen status

(add-hook 'magit-status-mode-hook 'delete-other-windows)

Autoload magit-svn

(eval-after-load 'magit
  '(require 'magit-svn))
(add-hook 'magit-mode-hook 'magit-svn-mode)

mu4e (disabled)

Email client


Alternating line-colours in dired

(autoload 'stripe-buffer-mode "stripe-buffer.el" nil t)
(add-hook 'dired-mode-hook 'stripe-buffer-mode)

rST mode tweaks

Tweaks for rST mode

Docs for the mode,

(setq rst-preferred-decorations
      '((?= simple 0)
        (?* simple 0)
        (?+ simple 0)
        (?- simple 0)))



(setq fsm-debug nil) ;; Disable fms-debug buffer
(require 'jabber-autoloads)

(setq jabber-chat-fill-long-line nil)

Status in title

Shows status in top bar if not “online” (away/XA etc)

;; Show status in message if not online
(setq jabber-chat-header-line-format
      '(" " (:eval (jabber-jid-displayname jabber-chatting-with))
	" " (:eval (jabber-jid-resource jabber-chatting-with)) "\t";
	(:eval (let ((buddy (jabber-jid-symbol jabber-chatting-with)))
		   (cdr (assoc (get buddy 'show) jabber-presence-strings))
		   (get buddy 'show))
		  (or (cdr (assoc (get buddy 'show) jabber-presence-faces))
	"\t" (:eval (get (jabber-jid-symbol jabber-chatting-with) 'status))
	(:eval (unless (equal "" *jabber-current-show*)
		 (concat "\t (You're " *jabber-current-show* ")")))))

Order ‘chatty’ not-first

(setq jabber-sort-order (quote ("" "chat" "away" "dnd" "xa")))
(setq jabber-roster-sort-functions '(

Logging settings

(setq jabber-history-enabled t)
(setq jabber-use-global-history nil)

Misc settings

;(setq jabber-alert-message-hooks (quote (jabber-message-echo jabber-message-scroll)) t)
;(setq jabber-connection-ssl-program nil)

(setq jabber-roster-show-title nil)
(setq jabber-alert-presence-hooks nil)
(setq jabber-backlog-number 30)
(setq jabber-roster-line-format " %c %-25n %u %-8s  %S")
(setq jabber-roster-show-bindings nil)
(setq jabber-show-offline-contacts nil)

ido jabber-chat-with

Quickly open buffer to talk to someone, selecting JID with ido completion thing. Shortcut is C-x C-j C-j

(require 'ido)

(defvar *my-jid-history* '())

(defun my-jabber-read-jid-completing (prompt)
  (let* ((hist-items (remove-duplicates *my-jid-history* :test #'equal))
          (mapcar #'symbol-name (jabber-concat-rosters))))
    (setf choices (append hist-items
                          (sort (set-difference choices hist-items :test #'equal)
    (ido-completing-read prompt choices
                         nil nil nil '*my-jid-history*)))

(defun my-jabber-jid-connection (jid)
  (or (find-if
       #'(lambda (jc)
           (find jid (plist-get (fsm-get-state-data jc) :roster)
                    :key #'symbol-name
                    :test #'equal))
      (error "cannot determine connection for %s" jid)))

(defun my-jabber-chat-with (jid &optional other-window)
  "ido-based jabber-chat-with variant"
  (interactive (list (my-jabber-read-jid-completing "Chat with: ")
  (let* ((jc (my-jabber-jid-connection jid))
         (buffer (jabber-chat-create-buffer jc jid)))
    (if other-window
        (switch-to-buffer-other-window buffer)
      (switch-to-buffer buffer))))

(global-set-key "\C-x\C-j\C-j" 'my-jabber-chat-with)

X window urgency on notification

Unread messages cause window to flash, making alerts visible say on other virtual-desktops


(if (string-equal (symbol-name system-type) "gnu/linux")

    (defun x-urgency-hint (frame arg &optional source)
      (let* ((wm-hints (append (x-window-property 
                    "WM_HINTS" frame "WM_HINTS" source nil t) nil))
         (flags (car wm-hints)))
        (setcar wm-hints
            (if arg
            (logior flags #x00000100)
              (logand flags #x1ffffeff)))
        (x-change-window-property "WM_HINTS" wm-hints frame "WM_HINTS" 32 t)))
    (defun x-urgency-hint-all (value)
      (dolist (frame  (frame-list))
          (x-urgency-hint frame value))))
    (defvar jabber-activity-jids-count 0)
    (defun jabber-urgency-hint ()
      (let ((count (length jabber-activity-jids)))
        (unless (= jabber-activity-jids-count count)
          (if (zerop count)
          (x-urgency-hint-all nil)
        (x-urgency-hint-all t))
          (setq jabber-activity-jids-count count))))
    (add-hook 'jabber-activity-update-hook 'jabber-urgency-hint)


(defun x-jabber-clear-urgency ()
  (x-urgency-hint-all nil)

Cursor indicates overwrite etc

Change cursor color according to mode; inspired by

;; valid values are t, nil, box, hollow, bar, (bar . WIDTH), hbar,
;; (hbar. HEIGHT); see the docs for set-cursor-type
(setq djcb-normal-cursor-type    'bar)
(setq djcb-read-only-cursor-type 'hbar)
(setq djcb-overwrite-cursor-type 'box)

(defun djcb-set-cursor-according-to-mode ()
  "change cursor color and type according to some minor modes."

      (setq cursor-type djcb-read-only-cursor-type))
      (setq cursor-type djcb-overwrite-cursor-type))
      (setq cursor-type djcb-normal-cursor-type))))

(add-hook 'post-command-hook 'djcb-set-cursor-according-to-mode)

recursive minibuffer

Ability to call other minibuf-using functions while the minibuf is active

(setq enable-recursive-minibuffers t)
(minibuffer-depth-indicate-mode 1)


“M-x ack” like “M-x grep”


(defvar ack-history nil
  "History for the `ack' command.")

(defun ack (command-args)
   (let ((ack-command "ack --nogroup --with-filename "))
     (list (read-shell-command "Run ack (like this): "
  (let ((compilation-disable-input t))
    (compilation-start (concat command-args " < " null-device)

Disable interlocking

Disable .#blah.txt lock files

They are symlinks to fictious files ( which cause problems with various things, and the locking is of very little benefit to me

(setq create-lockfiles nil)


(autoload 'lua-mode "lua-mode" "Lua editing mode." t)
(add-to-list 'auto-mode-alist '("\\.lua$" . lua-mode))
(add-to-list 'interpreter-mode-alist '("lua" . lua-mode))


(require 'god-mode)
(global-set-key (kbd "<escape>") 'god-mode-all)


(autoload 'rust-mode "rust-mode" nil t)
(add-to-list 'auto-mode-alist '("\\.rs\\'" . rust-mode))

Cargo mode

(require 'cargo)
(add-hook 'rust-mode-hook 'cargo-minor-mode)


(autoload 'swift-mode "swift-mode" nil t)
(add-to-list 'auto-mode-alist '("\\.swift\\'" . swift-mode))


(autoload 'esup "esup" "Emacs Start Up Profiler." nil)

Show trailing whitespace

F5 toggles showing trailing whitespace

(global-set-key (kbd "<f5>")
                (lambda ()
                  (setq show-trailing-whitespace (not show-trailing-whitespace))

Host specific changes

Relative to this file,

  • perhost/current-host.el - useful for customisations specific to machines on a network with a shared home-dir. Not commited.
  • perhost/${HOST}.el - hostname-specific customisations. Could be commited.
  • perhost/{linux,windows,darwin,etc}.el - OS specific config
(defun dotemacs-joindirs (root &rest dirs)
  "Joins a series of directories together, like Python's os.path.join,
  (dotemacs-joindirs \"/tmp\" \"a\" \"b\" \"c\") => /tmp/a/b/c"

  (if (not dirs)
      root ; No more dirs to join, no more recursing
    (apply 'dotemacs-joindirs
           (expand-file-name (car dirs) root)
           (cdr dirs))))

(defun dotemacs-current-platform ()
  (let ((cur-plat-name (symbol-name system-type)) ; Current platform
        (platform-remap '( ; A map from akward-filesystem-names to simpler ones
                          ("gnu/linux" . "linux")
                          ("windows-nt" . "windows")
                          ("darwin" . "darwin")
    (cdr (assoc cur-plat-name platform-remap))))

(let ((local-conf-name    (dotemacs-joindirs dotfiles-dir "perhost" "current-host.el"))
      (perhost-conf-name  (dotemacs-joindirs dotfiles-dir (format "%s.el" (first (split-string system-name "\\.")))))
      (platform-conf-name (dotemacs-joindirs dotfiles-dir (format "%s.el" (dotemacs-current-platform))))

  (cond ((file-exists-p local-conf-name)
         (load-file local-conf-name))
        ((message "Local %s doesn't exist" local-conf-name)))
  (cond ((file-exists-p perhost-conf-name)
         (load-file perhost-conf-name))
        ((message "Platform-specific config %s doesn't exist" platform-conf-name))))


rgb to hex function

Might be useful for modifying theme at some point

(defun rgb (r &optional g b)
  "Converts three RGB values to HTMLish hex string.

  If supplied a single value, it is treated as a greyscale value (e.g
  (rgb 255) is identical to (rgb 255 255 255)

  ELISP> (rgb 0 128 255)
  ELISP> (rgb 255)
  (if (and g b)
      (format "#%02X%02X%02X" r g b)
    (format "#%02X%02X%02X" r r r)))

Jump to directory bash alias

Jumps to directory of current file (for reference, not evaluated)

alias jm='cd $(emacsclient -e "(with-current-buffer (window-buffer (frame-selected-window)) default-directory)" | '"sed -E 's/(^\")|(\"$)//g')"