1217 lines
33 KiB
Org Mode
1217 lines
33 KiB
Org Mode
#+TITLE: Tom-Emacs Interface
|
|
#+STARTUP: showall
|
|
|
|
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.
|
|
|
|
#+BEGIN_SRC emacs-lisp :padline no
|
|
;; -*- lexical-binding: t; -*-
|
|
#+END_SRC
|
|
|
|
* Package configuration
|
|
|
|
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 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.
|
|
|
|
#+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
|
|
|
|
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
|
|
|
|
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.
|
|
|
|
#+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
|
|
|
|
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-when-compile
|
|
(silently "Refresh packages"
|
|
(package-refresh-contents)))
|
|
#+END_SRC
|
|
|
|
This macro is inspired by use-package, but I want to maintain some
|
|
control of the syntax I use to configure my settings.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defmacro ensure-library (library &rest args)
|
|
"Make sure LIBRARY is installed.
|
|
|
|
ARGS should be a plist which may contain one of the following options:
|
|
|
|
- :package
|
|
|
|
Specify which package should actually be installed to ensure
|
|
the library named in LIBRARY exists.
|
|
|
|
- :path
|
|
|
|
Specify a path to add to the load path to be able to load this
|
|
package."
|
|
(declare (indent 1))
|
|
(let ((library-symbol (cl-gensym))
|
|
(package-symbol (cl-gensym))
|
|
(path-symbol (cl-gensym))
|
|
(package (or (plist-get args :package) library))
|
|
(path (plist-get args :path)))
|
|
`(progn
|
|
(eval-and-compile
|
|
(let ((,path-symbol ,path))
|
|
(if ,path-symbol
|
|
(add-to-list 'load-path
|
|
(if (file-name-absolute-p ,path-symbol)
|
|
,path-symbol
|
|
(concat user-emacs-directory ,path-symbol))))))
|
|
(eval-when-compile
|
|
(let ((,library-symbol ',library)
|
|
(,package-symbol ',package))
|
|
(unless (require ,library-symbol nil :noerror)
|
|
(package-install ,package-symbol)
|
|
(require ,library-symbol)))))))
|
|
#+END_SRC
|
|
|
|
* Site lisp
|
|
|
|
Setup everything so that any autoloads in ~site-lisp/~ get loaded
|
|
and can be used.
|
|
|
|
#+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 noticed that I refer to the combination of
|
|
=user-emacs-directory= and "data/" a lot, so I wrote this function
|
|
to make referencing it cleaner. Also useful if I ever want to move
|
|
my data directory.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun oni:data-location (file-name)
|
|
"Return the location of FILE-NAME within my data directory.
|
|
This is currently the data directory under the
|
|
`user-emacs-directory'."
|
|
(concat user-emacs-directory "data/" file-name))
|
|
#+END_SRC
|
|
|
|
I also wrote a test for it.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'ert
|
|
(ert-deftest oni:data-location ()
|
|
"Test that `oni:data-location' returns the correct locations."
|
|
(should (string= "~/.emacs.d/data/backup-files/"
|
|
(oni:data-location "backup-files/")))
|
|
(should (string= "~/.emacs.d/data/auto-save-files/"
|
|
(oni:data-location "auto-save-files/")))
|
|
(should (string= "~/.emacs.d/data/auto-save-list/.saves-"
|
|
(oni:data-location "auto-save-list/.saves-")))))
|
|
#+END_SRC
|
|
|
|
* Backups
|
|
|
|
I don't like having every directory filled with "filename~"
|
|
files. So instead of saving backup files to the same directory, save
|
|
them to a special one instead.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq backup-directory-alist `((".*" . ,(oni:data-location "backup-files/"))))
|
|
#+END_SRC
|
|
|
|
* Auto saves
|
|
|
|
I prefer to keep all autosave files in a single directory so they
|
|
don't clog up my filesystem so much. Usually these files get
|
|
deleted, but sometimes they don't, and I don't think they look
|
|
pretty. Add it to the end of the list because the default value
|
|
stores auto-saves for remote files in /tmp, which is fine by me.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-to-list 'auto-save-file-name-transforms
|
|
`(".*" ,(oni:data-location "auto-save-files/") t) :append)
|
|
#+END_SRC
|
|
|
|
Place the files which contain the auto save files in a similar
|
|
directory.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq auto-save-list-file-prefix (oni:data-location "auto-save-list/.saves-"))
|
|
#+END_SRC
|
|
|
|
* Tabs
|
|
|
|
Generally I prefer using spaces over tabs. Especially for lisp-like
|
|
languages.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq-default indent-tabs-mode nil)
|
|
#+END_SRC
|
|
|
|
A tab-width of 8 is too wide for me, and 2 is too narrow. 4 is just
|
|
right.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq-default tab-width 4)
|
|
#+END_SRC
|
|
|
|
* Font
|
|
|
|
Set the default font to a more pleasing one, in my opinion, with a
|
|
better size as well.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-to-list 'default-frame-alist '(font . "Fantasque Sans Mono-15"))
|
|
#+END_SRC
|
|
|
|
* Internal border
|
|
|
|
For aesthetics I like to have a thick border on the inside of my
|
|
Emacs window. I have the same border in URxvt, but I haven't found
|
|
out how to add it to Conkeror yet.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-to-list 'default-frame-alist '(internal-border-width . 15))
|
|
#+END_SRC
|
|
|
|
* Menu bar
|
|
|
|
I don't use the menu bar, so it just takes up space.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(menu-bar-mode -1)
|
|
#+END_SRC
|
|
|
|
* Tool bar
|
|
|
|
I don't use the tool bar, so it just takes up space.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(tool-bar-mode -1)
|
|
#+END_SRC
|
|
|
|
* Scroll bar
|
|
|
|
I don't use the scroll bar to either navigate my buffers or see
|
|
whereabouts I am, so they just take up space.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(scroll-bar-mode -1)
|
|
#+END_SRC
|
|
|
|
* Whitespace
|
|
|
|
I hate it when trailing whitespace is left around a file. I've been
|
|
using this for years, and apart from having some trouble working
|
|
with people who don't pay attention to it, it has worked flawlessly.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library destroy-trailing-whitespace
|
|
:path "vendor-lisp/destroy-trailing-whitespace")
|
|
(require 'destroy-trailing-whitespace)
|
|
(global-destroy-trailing-whitespace-mode)
|
|
#+END_SRC
|
|
|
|
Having a final newline at the end of the file is always a good
|
|
idea. Some programs just don't work without it and others produce
|
|
some strange results. Github diffs are an example.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq require-final-newline t)
|
|
#+END_SRC
|
|
|
|
* Long lines
|
|
|
|
By default Emacs wraps long lines around to the next line when they
|
|
reach the far end of the window. However I prefer to have them
|
|
truncated instead.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq-default truncate-lines t)
|
|
#+END_SRC
|
|
|
|
* Theme
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library yoshi-theme
|
|
:path "vendor-lisp/yoshi-theme")
|
|
(add-to-list 'custom-theme-load-path
|
|
(concat user-emacs-directory "vendor-lisp/yoshi-theme"))
|
|
(load-theme 'yoshi :no-confirm)
|
|
#+END_SRC
|
|
|
|
* Diminish
|
|
|
|
I really don't need to see some of the minor modes.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library diminish)
|
|
(require 'diminish)
|
|
#+END_SRC
|
|
|
|
* Ivy
|
|
|
|
Ivy is a completing read implementation that offers choises
|
|
vertically. I'm surprised how much I like it. I've tried Swiper
|
|
before and I didn't like that so much.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library ivy)
|
|
#+END_SRC
|
|
|
|
Also install the =flx= package to allow ivy to use fuzzy matching.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library flx)
|
|
#+END_SRC
|
|
|
|
Since I immediately use and enable Ivy, there's no need to autoload
|
|
it, so require it to keep the byte-compiler quiet.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(require 'ivy)
|
|
#+END_SRC
|
|
|
|
Don't show that ivy is enabled in the mode-line. It's enabled
|
|
globally and I'll notice it from other things anyway (like it
|
|
showing up).
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(diminish 'ivy-mode)
|
|
#+END_SRC
|
|
|
|
Enable fuzzy matching in Ivy.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq ivy-re-builders-alist '((t . ivy--regex-fuzzy))
|
|
ivy-initial-inputs-alist nil)
|
|
#+END_SRC
|
|
|
|
Enable Ivy.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ivy-mode)
|
|
#+END_SRC
|
|
|
|
* Counsel
|
|
|
|
Counsel is a group of functions that use Ivy to specialize on
|
|
certain built-in commands, such as M-x.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library counsel)
|
|
#+END_SRC
|
|
|
|
Since I enable Counsel mode immediately, there's no point in leaving
|
|
it to be autoloaded. Requiring it keeps the byte-compiler happy.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(require 'counsel)
|
|
#+END_SRC
|
|
|
|
Hide dotfiles in =counsel-find-file=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq counsel-find-file-ignore-regexp "\\`\\.")
|
|
#+END_SRC
|
|
|
|
Enable Counsel.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(counsel-mode)
|
|
#+END_SRC
|
|
|
|
Don't show that counsel is enabled in the mode-line. It's enabled
|
|
globally and I'll notice whenever I press M-x for example.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(diminish 'counsel-mode)
|
|
#+END_SRC
|
|
|
|
* Bookmarks
|
|
|
|
Save bookmarks in my data directory so my =user-emacs-directory= is less cluttered.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-when-compile (require 'bookmark))
|
|
(setq bookmark-default-file (oni:data-location "bookmarks"))
|
|
#+END_SRC
|
|
|
|
* Personal info
|
|
|
|
Set some personal info for, for example, Gnus to use.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq user-full-name "Tom Willemse"
|
|
user-mail-address "tom@ryuslash.org")
|
|
#+END_SRC
|
|
|
|
* Url browsing
|
|
|
|
Use Conkeror to open URLs.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-when-compile (require 'browse-url))
|
|
|
|
(with-eval-after-load 'browse-url
|
|
(setq browse-url-browser-function 'browse-url-conkeror))
|
|
#+END_SRC
|
|
|
|
* Minor modes
|
|
|
|
** Paredit
|
|
|
|
Paredit is an awesome minor-mode to have when you write in any
|
|
lisp-like languages. It can feel rather strict and uncomfortable at
|
|
first, but once you get the hang of using it, you won't want to
|
|
live without it.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library paredit)
|
|
#+END_SRC
|
|
|
|
Don't show that paredit is enabled, it should be obvious from the
|
|
effects it has. This will save some precious real-estate on my mode
|
|
line.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'paredit
|
|
(diminish 'paredit-mode))
|
|
#+END_SRC
|
|
|
|
** Electric indent mode
|
|
|
|
By default `electric-indent-mode' is enabled globally, but I prefer
|
|
to enable it locally where I need it.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(electric-indent-mode -1)
|
|
#+END_SRC
|
|
|
|
Since Emacs 24 `electric-indent-mode' switches the behavior of the
|
|
C-j and RET keys. I prefer the original situation because my
|
|
muscle-memory still remembers to use C-j for newline-and-indent
|
|
behaviour.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun oni:switch-newline-keys ()
|
|
"Switch the C-j and RET keys in the local buffer."
|
|
(if electric-indent-mode
|
|
(progn
|
|
(local-set-key (kbd "C-j") 'newline)
|
|
(local-set-key (kbd "RET") 'electric-newline-and-maybe-indent))
|
|
(local-unset-key (kbd "C-j"))
|
|
(local-unset-key (kbd "RET"))))
|
|
|
|
(add-hook 'electric-indent-local-mode-hook #'oni:switch-newline-keys)
|
|
#+END_SRC
|
|
|
|
** Flycheck
|
|
|
|
Flycheck lets me see (compiler) errors, warnings and info messages
|
|
while writing code.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library flycheck)
|
|
#+END_SRC
|
|
|
|
When developing packages with Cask, some special care needs to be
|
|
taken to ensure the checkers work correctly.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library flycheck-cask)
|
|
(add-hook 'flycheck-mode-hook 'flycheck-cask-setup)
|
|
#+END_SRC
|
|
|
|
I disable the pylint and pyflakes checkers because they don't seem
|
|
to add much except noise when used together with flake8. Also
|
|
pylint seems hell-bent on making Python written like a
|
|
statically-typed langauge.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'flycheck
|
|
(mapc (lambda (c) (delq c flycheck-checkers))
|
|
'(python-pylint python-pyflakes)))
|
|
#+END_SRC
|
|
|
|
Also show which columns messages appear in.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'flycheck
|
|
(setq flycheck-highlighting-mode 'columns))
|
|
#+END_SRC
|
|
|
|
Show the error message at point in a tooltip.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library flycheck-pos-tip)
|
|
|
|
(with-eval-after-load 'flycheck
|
|
(require 'flycheck-pos-tip)
|
|
(flycheck-pos-tip-mode))
|
|
#+END_SRC
|
|
|
|
** Auto revert mode
|
|
|
|
ARev isn't very descriptive, and fairly wide. Use a font-awesome icon instead.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'autorevert
|
|
(diminish 'auto-revert-mode
|
|
(propertize (concat " " (char-to-string #xf021))
|
|
'face '(:family "Font Awesome" :height 0.75))))
|
|
#+END_SRC
|
|
|
|
** Auto fill mode
|
|
|
|
"Fill" is fine as a mode-line lighter, but I prefer something
|
|
shorter.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(diminish 'auto-fill-function
|
|
(propertize (concat " " (char-to-string #xf149))
|
|
'face '(:family "Font Awesome" :height 0.75)))
|
|
#+END_SRC
|
|
|
|
** Diff highlight mode
|
|
|
|
Show the state of lines added, changed and removed since the last
|
|
commit.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library diff-hl)
|
|
(require 'diff-hl)
|
|
(global-diff-hl-mode)
|
|
#+END_SRC
|
|
|
|
** Hydra
|
|
|
|
Hydra is an interesting way of managing keybindings, I want to
|
|
experiment.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library hydra)
|
|
#+END_SRC
|
|
|
|
Add a hydra for org.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(global-set-key (kbd "C-c o") 'oni-hydra-org/body)
|
|
#+END_SRC
|
|
|
|
Add a hydra for magit.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(global-set-key (kbd "C-c m") 'oni-hydra-magit/body)
|
|
#+END_SRC
|
|
|
|
** Isearch
|
|
|
|
Replace the Isearch mode line lighter with a magnifying glass icon.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(diminish 'isearch-mode
|
|
(propertize (concat " " (char-to-string #xf002))
|
|
'face '(:family "Font Awesome" :height 0.75)))
|
|
#+END_SRC
|
|
|
|
* Major modes
|
|
|
|
** Emacs lisp mode
|
|
|
|
Enable paredit mode.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'emacs-lisp-mode-hook 'paredit-mode)
|
|
#+END_SRC
|
|
|
|
** Scheme mode
|
|
|
|
Enable paredit mode.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'scheme-mode-hook 'paredit-mode)
|
|
#+END_SRC
|
|
|
|
Add scsh to the list of known interpreters for scheme mode. This
|
|
way shell-scripts that don't have a file extension but specify scsh
|
|
as the interpreter are opened in scheme mode.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-to-list 'interpreter-mode-alist '("scsh" . scheme-mode))
|
|
#+END_SRC
|
|
|
|
** Inferior Emacs lisp mode (ielm)
|
|
|
|
Enable paredit mode.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'ielm-mode-hook 'paredit-mode)
|
|
#+END_SRC
|
|
|
|
** Mbsync configuration mode
|
|
|
|
I wrote a simple major-mode for editing my =.mbsyncrc= file. I
|
|
might release it as a package, but for now I keep it with the rest
|
|
of my configuration.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library mbsync-conf-mode
|
|
:path "vendor-lisp/mbsync-conf-mode")
|
|
#+END_SRC
|
|
|
|
Since it isn't installed by package.el, I need to specify the
|
|
autoload myself.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(autoload 'mbsync-conf-mode "mbsync-conf-mode"
|
|
"Major mode for editing mbsync configuration files."
|
|
:interactive)
|
|
#+END_SRC
|
|
|
|
I also need to add it to the =auto-mode-alist= so ~.mbsyncrc~ is
|
|
opened with mbsync conf mode.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-to-list 'auto-mode-alist '("\\.mbsyncrc\\'" . mbsync-conf-mode))
|
|
#+END_SRC
|
|
|
|
** Msmtprc mode
|
|
|
|
I wrote a simple major-mode for editing my =.msmtprc= file. I might
|
|
release it as a package, but for now I keep it with the rest of my
|
|
configuration.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library msmtprc-mode
|
|
:path "vendor-lisp/msmtprc-mode")
|
|
#+END_SRC
|
|
|
|
Since it isn't installed by package.el, I need to specify the
|
|
autoload myself.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(autoload 'msmtprc-mode "msmtprc-mode"
|
|
"Major mode for editing msmtp configuration files."
|
|
:interactive)
|
|
#+END_SRC
|
|
|
|
I also need to add it to the =auto-mode-alist= so ~.msmtprc~ is
|
|
opened with msmtprc mode.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-to-list 'auto-mode-alist '("\\.msmtprc\\'" . msmtprc-mode))
|
|
#+END_SRC
|
|
|
|
** Git commit mode
|
|
|
|
Enable =electric-quote-local-mode= to easily type nice-looking
|
|
quotes while writing commits.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'git-commit-mode-hook 'electric-quote-local-mode)
|
|
#+END_SRC
|
|
|
|
** Python mode
|
|
|
|
Enable electric pair mode.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'python-mode-hook 'electric-pair-local-mode)
|
|
#+END_SRC
|
|
|
|
Enable syntax and style checking with flycheck.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'python-mode-hook 'flycheck-mode)
|
|
#+END_SRC
|
|
|
|
** Web mode
|
|
|
|
Web mode is a good general-purpose web template mode. It works well
|
|
with many template languages and PHP as well.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library web-mode)
|
|
#+END_SRC
|
|
|
|
Enable a specialized whitespace mode for web mode that shows tabs
|
|
at the beginning of a line.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'web-mode-hook 'oni-whitespace-only-tabs-mode)
|
|
#+END_SRC
|
|
|
|
** Makefile mode
|
|
|
|
Show tabs in Makefiles. Tabs are required at the beginning of any
|
|
non-continuation line in a recipe. I don't use it for indenting,
|
|
however.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'makefile-mode-hook 'oni-whitespace-only-tabs-mode)
|
|
#+END_SRC
|
|
|
|
** CSS mode
|
|
|
|
Enable electric indent mode.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'css-mode-hook 'electric-indent-local-mode)
|
|
#+END_SRC
|
|
|
|
** Clojure mode
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library clojure-mode)
|
|
#+END_SRC
|
|
|
|
Install extra font-locking for clojure.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library clojure-mode-extra-font-locking)
|
|
|
|
(with-eval-after-load 'clojure-mode
|
|
(require 'clojure-mode-extra-font-locking))
|
|
#+END_SRC
|
|
|
|
Enable paredit mode.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'clojure-mode-hook 'paredit-mode)
|
|
#+END_SRC
|
|
|
|
Use the clojure repl as the inferior lisp mode.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-when-compile (require 'inf-lisp))
|
|
|
|
(defun oni:clojure-set-inferior-lisp ()
|
|
(setq inferior-lisp-program "lein repl"))
|
|
#+END_SRC
|
|
|
|
Add a little more font locking still, and some indentation. This is
|
|
included in the Clojure for the Brave and True configuration.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'clojure-mode-hook 'oni-clojure-add-font-lock)
|
|
(add-hook 'clojure-mode-hook 'oni-clojure-add-indent)
|
|
#+END_SRC
|
|
|
|
** Cider mode
|
|
|
|
Cider is like Slime for Common Lisp. This configuration is copied
|
|
from the one provided by Clojure for the Brave and True.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library cider)
|
|
#+END_SRC
|
|
|
|
Provides minibuffer documentation for the code you're typing into
|
|
the repl.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'cider-mode-hook 'cider-turn-on-eldoc-mode)
|
|
#+END_SRC
|
|
|
|
Go right to the REPL buffer when it's finished connecting
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'cider
|
|
(setq cider-repl-pop-to-buffer-on-connect t))
|
|
#+END_SRC
|
|
|
|
When there's a cider error, show its buffer and switch to it.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq cider-show-error-buffer t
|
|
cider-auto-select-error-buffer t)
|
|
#+END_SRC
|
|
|
|
Where to store the cider history.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq cider-repl-history-file
|
|
(oni:data-location "cider-history"))
|
|
#+END_SRC
|
|
|
|
Wrap when navigating history.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq cider-repl-wrap-history t)
|
|
#+END_SRC
|
|
|
|
Enable paredit in your REPL.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'cider-repl-mode-hook 'paredit-mode)
|
|
#+END_SRC
|
|
|
|
* Applications
|
|
|
|
** Magit
|
|
|
|
Magit is a very nice interface to Git for Emacs. It allows you to
|
|
do just about anything with Git without leaving the comfort of your
|
|
Emacs session.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library magit)
|
|
#+END_SRC
|
|
|
|
Show refined diffs in magit. This makes it much easier to see
|
|
/what/ has changed on a line.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-when-compile (require 'magit))
|
|
|
|
(with-eval-after-load 'magit
|
|
(setq magit-diff-refine-hunk 'all))
|
|
#+END_SRC
|
|
|
|
** Gnus
|
|
|
|
Gnus is one of the most extensible Email programs on the
|
|
planet. And it's not even made for email but NNTP.
|
|
|
|
Store all Gnus-related data in my data directory.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-when-compile (require 'gnus))
|
|
|
|
(with-eval-after-load 'gnus
|
|
(setq gnus-directory (oni:data-location "News")
|
|
gnus-article-save-directory gnus-directory
|
|
gnus-cache-directory gnus-directory
|
|
gnus-kill-files-directory gnus-directory))
|
|
#+END_SRC
|
|
|
|
Store all Mail source-related data in my data directory.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-when-compile (require 'mail-source))
|
|
|
|
(with-eval-after-load 'mail-source
|
|
(setq mail-source-directory (oni:data-location "Mail")))
|
|
#+END_SRC
|
|
|
|
Store all message-related data in the same place as the Mail source
|
|
data.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-when-compile (require 'message))
|
|
|
|
(with-eval-after-load 'message
|
|
(setq message-directory (oni:data-location "Mail")))
|
|
#+END_SRC
|
|
|
|
Store all nnfolder-related data in the same place as the Mail
|
|
source data.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-when-compile (require 'nnfolder))
|
|
|
|
(with-eval-after-load 'nnfolder
|
|
(setq nnfolder-directory (oni:data-location "Mail")))
|
|
#+END_SRC
|
|
|
|
Use msmtp to send mail.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-when-compile (require 'sendmail))
|
|
|
|
(with-eval-after-load 'sendmail
|
|
(setq send-mail-function 'sendmail-send-it)
|
|
(setq sendmail-program "/usr/bin/msmtp"))
|
|
#+END_SRC
|
|
|
|
Tell Gnus I'm not a novice anymore. One of the features of Gnus I
|
|
use a lot is deleting messages and as long as Gnus thinks I'm a
|
|
novice it will ask me if I'm sure every single time.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq gnus-novice-user nil)
|
|
#+END_SRC
|
|
|
|
Add a keybinding to the Gnus summary mode to easily delete
|
|
messages.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'gnus
|
|
(define-key gnus-summary-mode-map (kbd "M-d") 'oni-gnus-delete-forward))
|
|
#+END_SRC
|
|
|
|
*** ryuslash.org
|
|
|
|
Set my main email address as the primary select method for Gnus.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'gnus
|
|
(setq gnus-select-method
|
|
'(nnmaildir "ryuslash" (directory "~/documents/mail/ryuslash/"))))
|
|
#+END_SRC
|
|
|
|
When sending mail from the ryuslash inbox, use the ryuslash msmtp
|
|
account.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-when-compile (require 'gnus-msg))
|
|
|
|
(with-eval-after-load 'gnus-msg
|
|
(add-to-list 'gnus-posting-styles
|
|
'(".*"
|
|
(address "tom@ryuslash.org")
|
|
(eval (setq message-sendmail-extra-arguments
|
|
'("-a" "ryuslash"))))))
|
|
#+END_SRC
|
|
|
|
*** picturefix
|
|
|
|
Add my work email account as a secondary select method.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'gnus
|
|
(add-to-list 'gnus-secondary-select-methods
|
|
'(nnmaildir "picturefix"
|
|
(directory "~/documents/mail/picturefix/"))))
|
|
#+END_SRC
|
|
|
|
When sending mail from the picturefix account, use the picturefix
|
|
msmtp account and set the proper name and email address.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'gnus-msg
|
|
(add-to-list 'gnus-posting-styles
|
|
'("picturefix:"
|
|
(name "Tom Willemsen")
|
|
(address "tom@picturefix.nl")
|
|
(eval (setq message-sendmail-extra-arguments
|
|
'("-a" "picturefix"))))))
|
|
#+END_SRC
|
|
|
|
*** gmail
|
|
|
|
Add my other personal email as a secondary select method.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'gnus
|
|
(add-to-list 'gnus-secondary-select-methods
|
|
'(nnmaildir "gmail"
|
|
(directory "~/documents/mail/gmail/"))))
|
|
#+END_SRC
|
|
|
|
When sending mail from the gmail account, use the gmail msmtp
|
|
accound and set the proper email address.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'gnus-msg
|
|
(add-to-list 'gnus-posting-styles
|
|
'("gmail:"
|
|
(name "Tom Willemse")
|
|
(address "ryuslash@gmail.com")
|
|
(eval (setq message-sendmail-extra-arguments
|
|
'("-a" "gmail"))))))
|
|
#+END_SRC
|
|
|
|
** Linewise user-interface
|
|
|
|
This is the library used by Circe and Slack to display messages.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-when-compile (require 'lui))
|
|
#+END_SRC
|
|
|
|
Put the time stamp in lui buffers in the right margin. This gives
|
|
the text some extra room.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'lui
|
|
(setq lui-time-stamp-position 'right-margin))
|
|
#+END_SRC
|
|
|
|
Remove the "[]" from the time stamp, it's not really necessary.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'lui
|
|
(setq lui-time-stamp-format "%H:%M"))
|
|
#+END_SRC
|
|
|
|
Give the right margin just enough room to show the time-stamps, no
|
|
more, no less.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun oni:set-circe-margin-width ()
|
|
(setq right-margin-width 5))
|
|
|
|
(add-hook 'lui-mode-hook #'oni:set-circe-margin-width)
|
|
#+END_SRC
|
|
|
|
Fix the wrap prefix so that text at the prompt is aligned properly.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun oni:set-lui-prompt-wrap-prefix ()
|
|
(setq wrap-prefix " "))
|
|
|
|
(add-hook 'lui-mode-hook #'oni:set-lui-prompt-wrap-prefix)
|
|
#+END_SRC
|
|
|
|
Enable visual line mode in lui buffers so my text doesn't go
|
|
off-screen.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'lui-mode-hook 'visual-line-mode)
|
|
#+END_SRC
|
|
|
|
Turn off filling in lui buffers. I use visual-line mode instead.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq lui-fill-type nil)
|
|
#+END_SRC
|
|
|
|
** Circe
|
|
|
|
I switched to Circe from ERC because I couldn't make the
|
|
customizations I wanted to, Circe seems much better at this.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library circe)
|
|
#+END_SRC
|
|
|
|
Make sure that Emacs knows these function exist when the file is
|
|
being compiled.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-when-compile (require 'oni-circe))
|
|
#+END_SRC
|
|
|
|
I spend most of my time on IRC on Freenode.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-when-compile (require 'circe))
|
|
|
|
(with-eval-after-load 'circe
|
|
(add-to-list 'circe-network-options
|
|
`("Freenode"
|
|
:nick "ryuslash"
|
|
:channels ("#emacs"
|
|
"#mowedline"
|
|
"#ninthfloor"
|
|
"#dispass"
|
|
"#linuxvoice"
|
|
"#conkeror")
|
|
:nickserv-password
|
|
,(oni-circe-get-password-for "irc.freenode.net"))))
|
|
#+END_SRC
|
|
|
|
Sometimes I watch some Twitch streams as well.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'circe
|
|
(add-to-list 'circe-network-options
|
|
`("Twitch"
|
|
:use-tls nil
|
|
:nick "ryuslash"
|
|
:host "irc.twitch.tv"
|
|
:pass ,(oni-circe-get-password-for "irc.twitch.tv")
|
|
:port 6667)))
|
|
#+END_SRC
|
|
|
|
Enable coloring of nicks.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'circe
|
|
(require 'circe-color-nicks)
|
|
(enable-circe-color-nicks))
|
|
#+END_SRC
|
|
|
|
Align all nicks.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library sermon
|
|
:path "vendor-lisp/sermon")
|
|
|
|
(with-eval-after-load 'circe
|
|
(require 'sermon)
|
|
(enable-sermon))
|
|
#+END_SRC
|
|
|
|
** Org
|
|
|
|
Tell org-mode to fontify code blocks in their specified languages.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-when-compile (require 'org))
|
|
|
|
(with-eval-after-load 'org
|
|
(setq org-src-fontify-natively t))
|
|
#+END_SRC
|
|
|
|
Enable automatic text filling for org-mode.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'org-mode-hook 'auto-fill-mode)
|
|
#+END_SRC
|
|
|
|
** Jabber
|
|
|
|
I like using XMPP to talk to people, jabber.el is very good at
|
|
this.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(ensure-library jabber)
|
|
(eval-when-compile (require 'jabber))
|
|
#+END_SRC
|
|
|
|
Add my account.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq jabber-account-list
|
|
`((,(concat "ryuslash@dukgo.com/" (system-name)))
|
|
(:connection-type . starttls)))
|
|
#+END_SRC
|
|
|
|
Store any persistent data in the data directory.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq jabber-avatar-cache-directory (oni:data-location "jabber/avatars/")
|
|
jabber-history-dir (oni:data-location "jabber/hist/"))
|
|
#+END_SRC
|
|
|
|
Change the default prompts.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq jabber-chat-buffer-format "+%n"
|
|
jabber-chat-foreign-prompt-format "%t %u"
|
|
jabber-chat-local-prompt-format "%t %u"
|
|
jabber-chat-delayed-time-format "%H:%M"
|
|
jabber-groupchat-buffer-format "++%n"
|
|
jabber-groupchat-prompt-format "%t %u")
|
|
#+END_SRC
|
|
|
|
Don't show avatars, publish or retrieve avatars.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq jabber-chat-buffer-show-avatar nil
|
|
jabber-vcard-avatars-publish nil
|
|
jabber-vcard-avatars-retrieve nil)
|
|
#+END_SRC
|
|
|
|
Don't fill long lines in jabber chat buffers, but use visual line
|
|
mode.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq jabber-chat-fill-long-lines nil)
|
|
|
|
(add-hook 'jabber-chat-mode-hook 'visual-line-mode)
|
|
#+END_SRC
|
|
|
|
Don't send notifications about chat states.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq jabber-chatstates-confirm nil)
|
|
#+END_SRC
|
|
|
|
Colorize text in multi-user chats.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq jabber-muc-colorize-local t
|
|
jabber-muc-colorize-foreign t)
|
|
#+END_SRC
|
|
|
|
Enable recording history.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq jabber-history-enabled t
|
|
jabber-use-global-history nil)
|
|
#+END_SRC
|
|
|
|
Clean up the default view of the roster buffer.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq jabber-roster-show-bindings nil
|
|
jabber-show-offline-contacts nil)
|
|
|
|
(add-hook 'jabber-roster-mode-hook 'oni-jabber-set-roster-mode-line)
|
|
#+END_SRC
|
|
|
|
Use libnotify to send jabber notifications.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'jabber-alert-message-hooks 'jabber-message-libnotify)
|
|
(add-hook 'jabber-alert-muc-hooks 'jabber-muc-libnotify)
|
|
#+END_SRC
|
|
|
|
Don't echo presence changes in the mode line, show them in the
|
|
relevant buffer instead.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'jabber-alert
|
|
(remove-hook 'jabber-alert-presence-hooks 'jabber-presence-echo))
|
|
|
|
(add-hook 'jabber-alert-presence-hooks 'oni-jabber-show-status-in-buffer)
|
|
#+END_SRC
|
|
|
|
* Custom
|
|
|
|
Put the customize settings in a different file so that Emacs doesn't
|
|
have to modify this file whenever something changes through
|
|
customize. I put this into my init file last so any settings made in
|
|
there *can* overwrite the ones in the rest of the file, not that I
|
|
usually like to do that.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq custom-file (concat user-emacs-directory "custom.el"))
|
|
(load custom-file)
|
|
#+END_SRC
|