1653 lines
57 KiB
Org Mode
1653 lines
57 KiB
Org Mode
#+TITLE: Emacs init
|
|
#+PROPERTY: tangle init2.el
|
|
#+STARTUP: content
|
|
#+OPTIONS: author:nil num:nil toc:nil
|
|
#+MACRO: key @@html:<kbd>$1</kbd>@@@@ascii:`$1'@@
|
|
#+HTML_HEAD: <link href="https://ryuslash.org/org.css" rel="stylesheet" type="text/css">
|
|
|
|
* Introduction
|
|
|
|
Inspired by [[Other such projects][other such projects]], here is my Emacs initialization
|
|
file.
|
|
|
|
*Note:* This is not my entire Emacs initialization file. It's a
|
|
work-in-progress.
|
|
|
|
** Setup
|
|
|
|
I could use org-babel to load this file, but I don't like my
|
|
initialization file being dependent on too many things, especially
|
|
big things, and org is a big thing. It may be strange for you to
|
|
read this, as I have placed my entire Emacs configuration in an
|
|
org-mode file, but here are the make targets I use to tangle and
|
|
subsequently byte-compile my init file:
|
|
|
|
#+BEGIN_SRC makefile :tangle no
|
|
%.elc: %.el
|
|
emacs -Q -batch -eval "(byte-compile-file \"$<\")"
|
|
|
|
init.el: init.org
|
|
emacs -Q -batch -l "ob-tangle" -eval "(org-babel-tangle-file \"init.org\")
|
|
#+END_SRC
|
|
|
|
Executing the second target (either through make, or manually) will
|
|
get you my Emacs initialization file in plain Emacs Lisp.
|
|
|
|
*Note:* If you look at this file in its org-mode form you will notice
|
|
that I actually tangle ~init.org~ into ~init2.el~. This is a temporary
|
|
measure so that I can gradually move my configuration from my
|
|
existing ~init.el~ file into ~init.org~ without much trouble. Once I
|
|
have emptied out my ~init.el~ I will instruct babel to tangle into
|
|
~init.el~, this code already reflects that.
|
|
|
|
** The ~oni:~ prefix
|
|
|
|
To keep my functions and variables from ever accidentally
|
|
interfering with other packages or Emacs internal variables I
|
|
prefix all the functions I write and variables I declare with ~oni:~.
|
|
You don't have to copy it if you copy anything from this file, as
|
|
long as you do it consistently.
|
|
|
|
I sometimes forget to do this, though.
|
|
|
|
** The ~depends-on~ snippets
|
|
|
|
At certain points in this document you will find bits of code that
|
|
look like:
|
|
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(depends-on "somepackage")
|
|
#+END_SRC
|
|
|
|
These calls are from the Cask DSL. They specify that my
|
|
configuration depends on some package found in one of the ELPA
|
|
repositories I have setup.
|
|
|
|
These snippets don't belong in your =init.el=, but instead in a
|
|
separate =Cask= file, and only if you use Cask, not if you just use
|
|
the standard ~package.el~.
|
|
|
|
** Other such projects
|
|
|
|
As stated, this project is inspired and influenced by other
|
|
literate configurations. Here is a list of some of the ones I've
|
|
found:
|
|
|
|
- [[http://sachac.github.io/.emacs.d/Sacha.html][Sacha Chua]]
|
|
- [[http://www.wisdomandwonder.com/wordpress/wp-content/uploads/2014/03/C3F.html][Grant Rettke]]
|
|
- [[https://github.com/wasamasa/dotemacs][Vasilij Schneidermann]]
|
|
|
|
* Preparation
|
|
|
|
Some things have to be done to make sure that everything works as it
|
|
should. This includes enabling lexical binding, loading Cask and
|
|
keeping some comments.
|
|
|
|
** Use lexical binding
|
|
|
|
For some of my functions, and general coolness, lexical binding is
|
|
a must. Without it, closures cannot be made for example.
|
|
|
|
#+BEGIN_SRC emacs-lisp :padline no
|
|
;; -*- lexical-binding: t -*-
|
|
#+END_SRC
|
|
|
|
This line needs to appear at the beginning of the file to work.
|
|
Just to keep things looking nice I put it at the beginning of the
|
|
file.
|
|
|
|
** Keep package.el from changing my init
|
|
|
|
Some time ago my init file was changed by Emacs. It added a single
|
|
line of code and some explanatory comments. Apparently I need to
|
|
keep this comment in my initialization file so that Emacs doesn't
|
|
try to add the code again. I actually use [[http://cask.readthedocs.org/en/latest/][Cask]] to manage and load
|
|
my packages so I don't need this.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
;; (package-initialize)
|
|
#+END_SRC
|
|
|
|
** Load Cask
|
|
|
|
I use Cask to manage my installed packages and for that to work I
|
|
need to load Cask at the start of the initialization file. This
|
|
should be executed both when byte-compiling and loading at run-time
|
|
so that other bits and pieces can byte-compile without warnings or
|
|
errors.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-and-compile
|
|
(require 'cask "~/projects/ext/cask/cask.el")
|
|
(cask-initialize))
|
|
#+END_SRC
|
|
|
|
** Some helper functions
|
|
|
|
Certain functions make life a lot easier when configuring Emacs.
|
|
These don't generally belong to any one specific customization, but
|
|
make things look a lot prettier.
|
|
|
|
*** Optimized ~with-eval-after-load~
|
|
|
|
First offered [[http://www.lunaryorn.com/2013/05/01/byte-compiling-eval-after-load.html][here]] and then later updated [[http://www.lunaryorn.com/2013/06/25/introducing-with-eval-after-load.html][here]] (when
|
|
~with-eval-after-load~ was added). Makes for very nice on-demand
|
|
settings loading.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
;; http://www.lunaryorn.com/2013/06/25/introducing-with-eval-after-load/
|
|
(defmacro stante-after (feature &rest forms)
|
|
"After FEATURE is loaded, evaluate FORMS.
|
|
|
|
FEATURE may be an unquoted feature symbol or a file name, see
|
|
`eval-after-load'."
|
|
(declare (indent 1) (debug t))
|
|
`(,(if (or (not byte-compile-current-file)
|
|
(if (symbolp feature)
|
|
(require feature nil :noerror)
|
|
(load feature :no-message :no-error)))
|
|
`progn
|
|
(message "stante-after: cannot find %s" feature)
|
|
'with-no-warnings)
|
|
(with-eval-after-load ',feature ,@forms)))
|
|
#+END_SRC
|
|
|
|
* General customization
|
|
|
|
These customizations don't belong with any specific mode.
|
|
|
|
** Set some personal information
|
|
|
|
This information is used by some emacs commands and modules to make
|
|
your life easier.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq user-full-name "Tom Willemse"
|
|
user-mail-address "tom@ryuslash.org")
|
|
#+END_SRC
|
|
|
|
** Turn-off menu bar
|
|
|
|
The menu bar is one of the UI elements which work best with mouses.
|
|
Sure you can change your toolkit's key bindings to allow you to
|
|
more easily navigate, but {{{key(M-x)}}} or {{{key(M-`)}}}[fn:1]
|
|
are easier if you don't use the mouse. Long story short: It has got
|
|
to go.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(menu-bar-mode -1)
|
|
#+END_SRC
|
|
|
|
** Turn-off tool bar
|
|
|
|
The toolbar is another such thing, and it takes up quite a bit more
|
|
space too. Icons can look pretty cool, but in the end if you're not
|
|
going to click them they don't really server much of a purpose.
|
|
Again: It has got to go.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(tool-bar-mode -1)
|
|
#+END_SRC
|
|
|
|
** Turn-off blinking cursor
|
|
|
|
I suppose a blinking cursor doesn't get lost very easily. But on
|
|
the other hand, it can induce quite a few more headaches.
|
|
|
|
I've noticed that I don't really lose my cursor position all that
|
|
much, really, so there doesn't seem to be any point in making it
|
|
blink. Here we go again: It has got to go.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(blink-cursor-mode -1)
|
|
#+END_SRC
|
|
|
|
** Turn-off line numbers
|
|
|
|
As I'm currently using svg-mode-line-themes[fn:2] for my ~mode-line~
|
|
I don't need to show these. Also I didn't really use them much, I
|
|
don't often need to know what line I'm on.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(line-number-mode -1)
|
|
#+END_SRC
|
|
|
|
** Turn-off tooltips
|
|
|
|
Tooltips are another one of those UI elements that aren't quite
|
|
keyboard-friendly. As usually this information is shown just as well
|
|
in the echo area, this is not necessary.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(tooltip-mode -1)
|
|
#+END_SRC
|
|
|
|
** Change cursor type
|
|
|
|
I prefer using a bar as a cursor, as opposed to a box. Using a bar
|
|
is a better way of representing the location of the cursor, in my
|
|
opinion.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq-default cursor-type 'bar)
|
|
#+END_SRC
|
|
|
|
I use a bar cursor that's already pretty thin, so having an even
|
|
thinner one in inactive windows is not very clear. Even when I was
|
|
using a box cursor I didn't like seeing a hollow box everywhere my
|
|
focus /wasn't/.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq-default cursor-in-non-selected-windows nil)
|
|
#+END_SRC
|
|
|
|
** Truncate long lines
|
|
|
|
Sometimes, very long lines can't help but show up in code. The
|
|
default of wrapping lines around to the next line and showing an
|
|
image in the fringe is very visually disturbing to me when looking
|
|
at code[fn:3]. So I prefer to have it just run off the screen.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq-default truncate-lines t)
|
|
#+END_SRC
|
|
|
|
** Change default frame settings
|
|
|
|
Usually, most of these settings would be done with functions like
|
|
=set-frame-font= or =scroll-bar-mode=, but working with the Emacs
|
|
Daemon sometimes creates extra complications, because you might
|
|
start a graphical environment at some point (I usually do
|
|
immediately), but the startup process isn't.
|
|
|
|
*** Remove internal border
|
|
|
|
Set the internal border width to 0. This makes a small difference,
|
|
with my current setup it causes my window's width to increase from
|
|
120 to 121. Small, I know, but I'm very greedy when it comes to
|
|
screen space.
|
|
|
|
#+NAME: default-frame-internal-border
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(internal-border-width . 0)
|
|
#+END_SRC
|
|
|
|
*** Use a fantastic font
|
|
|
|
I've tried several fonts, and all of them were nice, but came up
|
|
short on some way. Some didn't have italic variants, some had
|
|
dotted zeroes instead of dashed zeroes, some even had entirely
|
|
clear zeroes which make them look like ~O~'s, others had
|
|
boring-looking parentheses[fn:4]. Not Fantasque Sans
|
|
Mono[fn:5][fn:6], it is awesome. If your web browser supports web
|
|
fonts you should also see it used in the code blocks here.
|
|
|
|
For normal Emacs setups you might use the =set-frame-font= function
|
|
like so:
|
|
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(set-frame-font "Fantasque Sans Mono-13" nil t)
|
|
#+END_SRC
|
|
|
|
However, this doesn't work when running Emacs as a Daemon. You
|
|
could (especially with lexical binding) add an
|
|
=after-make-frame-functions= hook or something similar, but I find
|
|
it easier to just specify the font in the =default-frame-alist=.
|
|
|
|
#+NAME: default-frame-font
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(font . "Fantasque Sans Mono-13")
|
|
#+END_SRC
|
|
|
|
*** Hide the scroll bar
|
|
|
|
The scroll-bar is almost just as informative as the current line
|
|
number and buffer position information shown in the (my) mode
|
|
line. As I don't usually need to know where I am, other than the
|
|
current line number occasionally, and I don't use the mouse, the
|
|
scroll bar doesn't add anything and only takes up space. Once
|
|
more: It has got to go.
|
|
|
|
Normally you would use something along the lines of:
|
|
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(scroll-bar-mode -1)
|
|
#+END_SRC
|
|
|
|
However, this doesn't work when running Emacs as a Daemon. So
|
|
instead I specify it in the =default-frame-alist=.
|
|
|
|
#+NAME: default-frame-scroll-bar
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(vertical-scroll-bars . nil)
|
|
#+END_SRC
|
|
|
|
*** Bringing it all together
|
|
|
|
So I've explained the reasons for each individual setting, but to
|
|
get them to work they have to be put in the =default-frame-alist=.
|
|
Here is the final setting:
|
|
|
|
#+BEGIN_SRC emacs-lisp :noweb yes
|
|
(setq default-frame-alist
|
|
`(<<default-frame-internal-border>>
|
|
<<default-frame-font>>
|
|
<<default-frame-scroll-bar>>))
|
|
#+END_SRC
|
|
|
|
** Set the frame title
|
|
|
|
Show the buffer name in the frame title to make multiple frames
|
|
identifiable by the buffer they're showing.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq frame-title-format '(:eval (concat "GNU Emacs: " (buffer-name))))
|
|
#+END_SRC
|
|
|
|
** Don't show dialog boxes
|
|
|
|
Unfortunately this doesn't remove /all/ dialog boxes, but at least it
|
|
keeps some of them from popping up. According to the docstring it
|
|
should only change anything for when the mouse is used, which I
|
|
don't ever do, but I still feel safer keeping this in my
|
|
configuration.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq use-dialog-box nil)
|
|
#+END_SRC
|
|
|
|
** Split windows equally
|
|
|
|
When splitting windows, give them all an equal amount of space. For
|
|
those very few time that I have more than two windows in my Emacs
|
|
frame it is much nicer to have each of them get ~33% space instead
|
|
of 50%, 25% and 25%. The way I have my desktop set-up I don't ever
|
|
split my windows horizontally.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq window-combination-resize t)
|
|
#+END_SRC
|
|
|
|
** Keep the cursor steady when scrolling
|
|
|
|
When scrolling through the buffer with, for example, {{{key(C-v)}}}
|
|
or {{{key(M-v)}}}, I find it much more intuitive to have the cursor
|
|
stay in the relative screen position from before. Otherwise I get
|
|
confused every time.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq scroll-preserve-screen-position t)
|
|
#+END_SRC
|
|
|
|
** Don't show a mode line for completions
|
|
|
|
One of the things I dislike about Emacs is its rigidity concerning
|
|
windows and other UI elements. One very simple way to make it
|
|
/feel/ less so is to show less of it where possible. A mode line for
|
|
completion buffers creates more separation than necessary, and I
|
|
can't recall a single time where I've used the completion's mode
|
|
line for anything.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'completion-list-mode-hook
|
|
(lambda () (setq mode-line-format nil)))
|
|
#+END_SRC
|
|
|
|
** Use pixels, not columns/rows to resize frames.
|
|
|
|
As of Emacs 24.4 frames can resize to pixel sizes instead of
|
|
columns and rows. This keeps annoying gaps from forming when using
|
|
a tiling window manager. The real difference is that when this is
|
|
done now, the actual text portions of the window get the extra
|
|
space, not some fringe or margin. This looks much nicer.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq frame-resize-pixelwise t)
|
|
#+END_SRC
|
|
|
|
** Don't just quit Emacs with {{{key(C-x C-c)}}} in the daemon
|
|
|
|
When working with Emacs as a daemon, which I do almost all of the
|
|
time, I prefer using {{{key(C-x C-c)}}} to close the current frame
|
|
instead of the entire session. Before this change I would
|
|
occasionally close my session by mistake.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun oni:close-client-window ()
|
|
"Close a client's frames."
|
|
(interactive)
|
|
(server-save-buffers-kill-terminal nil))
|
|
|
|
(when (daemonp)
|
|
(global-set-key (kbd "C-x C-c") 'oni:close-client-window))
|
|
#+END_SRC
|
|
|
|
** Don't minimize the frame with {{{key(C-z)}}}
|
|
|
|
One of the more annoying things that can happen is accidentally
|
|
minimizing the frame you're working with. This doesn't really matter
|
|
if you're working on a normal stacking window manager, but with a
|
|
tiling window manager and no task bar this just causes the Emacs
|
|
frame to hang until it is refocused or disappear with no way to get
|
|
it back.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(when (or window-system (daemonp))
|
|
(global-unset-key (kbd "C-z")))
|
|
#+END_SRC
|
|
|
|
** Lazily load some buffers
|
|
|
|
Don't load all buffers right away. Having a lot of buffers and
|
|
switching between projects a lot can take up quite a bit of time.
|
|
|
|
*Note:* See my [[Vacuous defvar][note]] on vacuous defvar for this use of =defvar=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defvar desktop-restore-eager)
|
|
(setq desktop-restore-eager 5)
|
|
#+END_SRC
|
|
|
|
** Ask for a ~y~ or ~n~, not ~yes~ or ~no~.
|
|
|
|
Emacs starts out asking for you to type ~yes~ or ~no~ with most
|
|
important questions. It is possible that this is used for such
|
|
important questions where accidentally saying ~yes~ when you meant ~no~
|
|
would be catastrophic (or at least could be). However, I've never
|
|
(so far) had this problem, and I find it quite tedious to have to
|
|
write out ~yes~ or ~no~ and then press {{{kbd(RET)}}}, give me a simple
|
|
~y~ or ~n~ with no {{{kdb(RET)}}} required and I'm quite happy.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defalias 'yes-or-no-p 'y-or-n-p)
|
|
#+END_SRC
|
|
|
|
** Use =hippie-expand=, not =dabbrev-expand=
|
|
|
|
I've never actually used =dabbrev-expand=, and only rarely use
|
|
=hippie-expand= really, but since =hippie-expand= also includes a
|
|
=dabbrev= expander and a lot more than just that, it seems alright to
|
|
do this.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defalias 'dabbrev-expand 'hippie-expand)
|
|
#+END_SRC
|
|
|
|
** Setting up =load-path=
|
|
|
|
First, to help, I create a function that takes a path, adds it to
|
|
=load-path= and then checks to see if there is a file named
|
|
~loaddefs.el~ in the given path. If there is, it loads it. This
|
|
~loaddefs.el~ file is something that is created from autoload cookies
|
|
in the files in some of these paths.
|
|
|
|
Since the =load-path= is also important during byte-compilation, this
|
|
function should be defined both at run-time and compile-time.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-and-compile
|
|
(defun oni:loadpath-add-and-autoload (path)
|
|
"Add PATH to `load-path' and load a `loaddefs.el' if it exists."
|
|
(add-to-list 'load-path path)
|
|
(let ((loaddefs (concat path "/loaddefs.el")))
|
|
(when (file-exists-p loaddefs)
|
|
(load loaddefs)))))
|
|
#+END_SRC
|
|
|
|
After that I add some directories to my =load-path= so I can use these
|
|
libraries when wanted. One of these is the ~site-lisp~ directory in my
|
|
~.emacs.d~ directory, which is where I keep most of my personal
|
|
non-ELPA modules (like module-specific initialization files). There
|
|
are also some directories I include in ~vendor-lisp~, which is where I
|
|
keep modules that I didn't write myself and, for some reason, can't
|
|
or don't want to use ELPA for. Again it is important to realize that
|
|
this information is relevant both at run-time and compile-time, so
|
|
we wrap it with an =eval-and-compile=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-and-compile
|
|
(mapc #'oni:loadpath-add-and-autoload
|
|
'("~/.emacs.d/site-lisp"
|
|
"~/.emacs.d/vendor-lisp/mozrepl"
|
|
"~/.emacs.d/vendor-lisp/eap" "/usr/share/emacs/site-lisp"
|
|
"/usr/lib/node_modules/tern/emacs/"
|
|
"~/.emacs.d/vendor-lisp/habitrpg.el")))
|
|
#+END_SRC
|
|
|
|
** Turn off bidirectional text
|
|
|
|
To speed things up a little, and because I have no contacts at all
|
|
(so far) who use right-to-left text, there is no reason for me to
|
|
use bidirectional text. For this reason I tell Emacs to always use
|
|
left-to-right by default, instead of checking each paragraph.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq-default bidi-paragraph-direction 'left-to-right)
|
|
#+END_SRC
|
|
|
|
** Don't use tabs
|
|
|
|
There is a war going on out there. Actually there are several, but
|
|
the one I'm talking about here is the one about tabs vs. spaces. I
|
|
have been deeply entrenched in the spaces camp for quite a while.
|
|
Indentation always gets screwy for me if I don't use the exact same
|
|
=tab-width= everyone else uses. I just like the consistency of using
|
|
spaces.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq-default indent-tabs-mode nil)
|
|
#+END_SRC
|
|
|
|
** Use four spaces for indentation
|
|
|
|
I once, long ago, started out with using eight spaces for each
|
|
level of indentation. Although I think, technically, I was using
|
|
tabs. This means that even just 3 levels of indentation take up a
|
|
/huge/ amount of space that can't be used for anything else. Since I
|
|
also try to limit the length of the lines in my code, this can make
|
|
for very little code per line.
|
|
|
|
I also tried (and enjoyed) two spaces, but after a while, looking
|
|
at bigger files, I noticed that it all becomes a blur. Two spaces
|
|
is not a big-enough visual difference to make code read nicely, in
|
|
my opinion.
|
|
|
|
So far, I have quite enjoyed four spaces for most code[fn:8].
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq-default tab-width 4)
|
|
#+END_SRC
|
|
|
|
** Keep the message buffer from growing too large
|
|
|
|
Keep at most one-thousand messages in the ~*Messages*~ buffer. I can
|
|
leave my Emacs session running for quite long times, sometimes
|
|
days, at a time. If there are a lot of messages it can get a little
|
|
tricky to manage/search.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq message-log-max 1000)
|
|
#+END_SRC
|
|
|
|
** Reject SSL/TLS certificates that don't check out
|
|
|
|
You just can't trust the internet. And I'd prefer to know if
|
|
something goes wrong.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defvar gnutls-verify-error)
|
|
|
|
(setq gnutls-verify-error t)
|
|
#+END_SRC
|
|
|
|
** Use Conkeror to browse URLs
|
|
|
|
Use the generic browse-url function to open URLs in Conkeror.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(stante-after browse-url
|
|
(setq browse-url-browser-function 'browse-url-generic)
|
|
(setq browse-url-generic-program "conkeror"))
|
|
#+END_SRC
|
|
|
|
* Major mode customization
|
|
|
|
Many major modes offer and require some customization.
|
|
|
|
** Org mode
|
|
|
|
Org mode offers /a lot/ of customization options. Most of mine are in
|
|
a separate file.
|
|
|
|
*** Add org-mode appointments to the diary
|
|
|
|
Diary offers reminders, which can be useful when scheduling
|
|
appointments.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defadvice org-agenda-redo (after ext:org-agenda-redo-add-appts)
|
|
"Pressing `r' on the agenda will also add appointments."
|
|
(setq appt-time-msg-list nil)
|
|
(org-agenda-to-appt))
|
|
#+END_SRC
|
|
|
|
** Ansi term
|
|
|
|
I don't use ansi term much. Though I probably should do it more.
|
|
Eshell is much nicer for many reasons but it can't handle
|
|
everything.
|
|
|
|
*** Close ansi-term buffer after exit
|
|
|
|
After the ansi-term process ends it leaves a buffer. I don't use
|
|
ansi term in such a way that this has ever been useful, so just kill
|
|
the ansi-term buffer after the process quits, no matter the exit
|
|
status. Usually this comes about when I press {{{kbd(C-d)}}} at the
|
|
command prompt.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defadvice term-handle-exit (after oni:kill-buffer-after-exit activate)
|
|
"Kill the term buffer if the process finished."
|
|
(kill-buffer (current-buffer)))
|
|
#+END_SRC
|
|
|
|
* Some general-purpose functions and macros
|
|
|
|
A configuration as big as mine is bound to have some functions and
|
|
macros that are used in many places.
|
|
|
|
** Turn off
|
|
|
|
This macro creates a function that will turn off a minor mode that
|
|
passed to it.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defmacro turn-off (func)
|
|
"Create a function that will turn off FUNC when called."
|
|
`(lambda () (eval (,func -1))))
|
|
#+END_SRC
|
|
|
|
** Change setting
|
|
|
|
Sometimes a mode just needs to change a certain setting to a
|
|
specific value.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defmacro change-settings (&rest settings)
|
|
"Create a function that changes the value of NAME to VALUE."
|
|
`(lambda () (setq ,@settings)))
|
|
#+END_SRC
|
|
|
|
** Whitespace only with tabs
|
|
|
|
In some modes I want to see the tabs in a buffer. Though I don't
|
|
want to be overwhelmed by seeing all spaces and line endings.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defvar whitespace-style)
|
|
|
|
(defun oni:whitespace-only-tabs ()
|
|
(setq-local whitespace-style '(face tabs))
|
|
(whitespace-mode))
|
|
#+END_SRC
|
|
|
|
** Eval after init
|
|
|
|
Some things can only really work after all other initialization
|
|
functions have completed. For example, any functions that require
|
|
any ELPA packages to be loaded, unless you want to load it in your
|
|
init manually (and have it loaded again later on after your config
|
|
has run).
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defmacro oni:eval-after-init (&rest body)
|
|
"Defer execution of BODY until after Emacs init."
|
|
(declare (indent 0))
|
|
`(add-hook 'emacs-startup-hook #'(lambda () ,@body)))
|
|
#+END_SRC
|
|
|
|
* Stumpwm integration
|
|
|
|
This variable, macro and function help with integrating Emacs and
|
|
Stumpwm. They are used by some other functions to make the two seem
|
|
extra connected.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defvar oni:stumpish-program
|
|
(expand-file-name
|
|
"~/.local/share/quicklisp/local-projects/stumpwm/contrib/util/stumpish/stumpish")
|
|
"The location of the stumpish executable.")
|
|
|
|
(defmacro oni:stumpwm (&rest body)
|
|
"Execute BODY in stumpwm."
|
|
(declare (indent 0))
|
|
`(call-process oni:stumpish-program nil nil nil
|
|
,(format "eval '%S'" `(progn ,@body))))
|
|
|
|
(defun oni:stumpwm-command (cmd)
|
|
"Execute CMD in stumpwm."
|
|
(call-process oni:stumpish-program nil nil nil cmd))
|
|
|
|
(defun oni:stumpwm-echo (message)
|
|
(call-process oni:stumpish-program nil nil nil (format "echo %s" message)))
|
|
#+END_SRC
|
|
|
|
** Fall back on stumpwm when moving around
|
|
|
|
Using the function specified in [[Stumpwm integration]] wrap the
|
|
=windmove-do-window-select= function and catch any error produced,
|
|
hoping it's the error that there's no more window to move to and
|
|
then request that stumpwm move the focus in the same direction as
|
|
windmove would have.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defadvice windmove-do-window-select
|
|
(around oni:windmove-stumpwm activate)
|
|
"If no window can be moved to, move stumpwm."
|
|
(condition-case err
|
|
ad-do-it
|
|
(error (oni:stumpwm-command
|
|
(format "move-focus %s" (ad-get-arg 0))))))
|
|
#+END_SRC
|
|
|
|
* Use the right dictionary
|
|
|
|
One of the caveats of using two (or more) languages in a single
|
|
installation of Gnus is that ispell sometimes gets confused. Having
|
|
come across a stackoverflow question[fn:7] about just this subject
|
|
it was easy to modify the source code posted there to come up with
|
|
this.
|
|
|
|
*Note:* See my [[Function declarations][note]] on function declarations about the use of
|
|
=declare-function=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(declare-function message-narrow-to-headers-or-head "message")
|
|
(declare-function message-fetch-field "message")
|
|
|
|
(defun oni:switch-ispell-dictionary ()
|
|
(save-excursion
|
|
(message-narrow-to-headers-or-head)
|
|
(when (string-match (rx (and "@" (or "aethon" "picturefix") ".nl>") eol)
|
|
(message-fetch-field "From"))
|
|
(ispell-change-dictionary "nl_NL"))))
|
|
|
|
(add-hook 'message-setup-hook 'oni:switch-ispell-dictionary)
|
|
#+END_SRC
|
|
|
|
* Don't let shr use background color
|
|
|
|
Reading mail in Gnus is very nice, but shr has become a little too
|
|
good at its job. Add to this the many occasions when a background is
|
|
specified without specifying a foreground, plus a color theme that
|
|
is the inverse of what is usually expected, and you can get
|
|
hard-to-read HTML messages, gray foreground and gray background.
|
|
|
|
I've looked at the other possible renderers, but they don't look
|
|
very nice compared to shr. So just remove its ability to add
|
|
background colors.
|
|
|
|
*Note:* See my [[Function declarations][note]] on function declarations about the use of
|
|
=declare-function=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(declare-function shr-colorize-region "shr")
|
|
|
|
(defun oni:shr-colorize-remove-last-arg (args)
|
|
"If ARGS has more than 3 items, remove the last one."
|
|
(if (> (length args) 3)
|
|
(butlast args)
|
|
args))
|
|
|
|
(with-eval-after-load 'shr
|
|
(advice-add #'shr-colorize-region :filter-args
|
|
#'oni:shr-colorize-remove-last-arg))
|
|
#+END_SRC
|
|
|
|
* Remember SQL input
|
|
|
|
Remembering input between sessions is a good thing.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(stante-after sql
|
|
(setf sql-input-ring-file-name
|
|
(expand-file-name "~/.emacs.d/sqliinput")))
|
|
#+END_SRC
|
|
|
|
* Fix some term keybindings
|
|
|
|
=ansi-term= passes along a lot of characters correctly, but things
|
|
like =forward-delete-word= are not, by default. This is confusing when
|
|
you see one thing and another is sent. Passing the correct keys
|
|
directly to the terminal fixes this problem.
|
|
|
|
*Note:* See my [[Vacuous defvar][note]] on vacuous defvar for this use of =defvar=.
|
|
|
|
*Note:* See my [[Function declarations][note]] on function declarations about the use of
|
|
=declare-function=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defvar term-raw-map)
|
|
(declare-function term-send-raw-string "term")
|
|
|
|
(defun oni:set-term-keys ()
|
|
(cl-flet ((zcommand (key)
|
|
(lambda ()
|
|
(interactive) (term-send-raw-string key))))
|
|
(define-key term-raw-map
|
|
(kbd "C-<backspace>") (zcommand "\C-H"))))
|
|
|
|
(add-hook 'term-mode-hook #'oni:set-term-keys)
|
|
#+END_SRC
|
|
|
|
* Some unconditional settings
|
|
|
|
Here are some settings that either need to be changed before certain
|
|
modules load, or that don't belong in any specific module.
|
|
|
|
** Gnus init file
|
|
|
|
I put my gnus initialization file right where I put all my
|
|
module-specific initialization files. Gnus is special, though: It
|
|
loads the file every time you start it. That keeps it from using a
|
|
simple =(eval-after-load 'gnus '(load "gnus-init"))=.
|
|
|
|
*Note:* See my [[Vacuous defvar][note]] on vacuous defvar for this use of =defvar=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defvar gnus-init-file)
|
|
(setq gnus-init-file "~/.emacs.d/site-lisp/gnus-init")
|
|
#+END_SRC
|
|
|
|
** Don't start =elnode= when Emacs starts
|
|
|
|
Elnode is an awesome project and I'm still looking for a moment
|
|
where I have the inspiration and time to actually do something with
|
|
it. I started at some point, but then I couldn't get the cookies to
|
|
work and I switched over to using Common Lisp, only to eventually
|
|
stop developing the project because there was not chance of it
|
|
seeing any use in the foreseeable future.
|
|
|
|
There is one little annoyance, though, and that is the fact that
|
|
elnode will start itself up when Emacs starts. I don't want that.
|
|
|
|
This bit of code can't be put in an =eval-after-load= or anything
|
|
like that because by the time it would be evaluated, elnode would
|
|
already have started.
|
|
|
|
*Note:* See my [[Vacuous defvar][note]] on vacuous defvar for this use of =defvar=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defvar elnode-do-init)
|
|
(setq elnode-do-init nil)
|
|
#+END_SRC
|
|
|
|
* Show python package name instead of file name
|
|
|
|
When working with python, knowing which package I'm in usually tells
|
|
me more about what I'm doing than the file name, especially when
|
|
working with django where almost every app will have a ~tests.py~ and
|
|
a ~models.py~. Of course =uniquify= fixes this pretty well too, though
|
|
in this case, it's less cool (imo).
|
|
|
|
First we define two functions that help us determine the package
|
|
name of the current file and the parent package name of the current
|
|
file. Finally we define a third function which determines the full
|
|
package name of the current buffer.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun oni:python--get-current-module-name ()
|
|
"Get the name of the current python module.
|
|
|
|
This is very simply just the filename of the current buffer with
|
|
the extension and pyath removed."
|
|
(file-name-sans-extension
|
|
(file-name-nondirectory (buffer-file-name))))
|
|
|
|
(defun oni:python--get-parent-module-name (&optional dir)
|
|
"This gets the currend file's parent module.
|
|
|
|
This function recursively gathers the parent package name of
|
|
either DIR or the current buffer's file name. Any directory where
|
|
an `__init__.py' file is found is considered to be a package.
|
|
|
|
This function returns either the parent package, with its
|
|
parents, or nil if the current directory isn't a python
|
|
package.."
|
|
(let* ((base (directory-file-name
|
|
(file-name-directory (or dir (buffer-file-name)))))
|
|
(package (file-name-nondirectory base)))
|
|
(if (file-exists-p (concat base "/__init__.py"))
|
|
(let ((parent (oni:python--get-parent-module-name base)))
|
|
(if parent
|
|
(concat parent "." package)
|
|
package))
|
|
nil)))
|
|
|
|
(defun oni:python-package-name ()
|
|
(let ((current-module (oni:python--get-current-module-name)))
|
|
(if (file-exists-p "__init__.py")
|
|
(concat (oni:python--get-parent-module-name)
|
|
"." current-module)
|
|
current-module)))
|
|
#+END_SRC
|
|
|
|
After all this we make Emacs show the package name rather than the
|
|
file name in the mode-line.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun oni:python-package-buffer-identification ()
|
|
"Have `mode-line-buffer-identification' show the python package name."
|
|
(setq mode-line-buffer-identification
|
|
'(:eval (oni:python-package-name))))
|
|
|
|
(add-hook 'python-mode-hook #'oni:python-package-buffer-identification)
|
|
#+END_SRC
|
|
|
|
* Add some known symbols for .conkerorrc/init.js to js2-mode
|
|
|
|
Conkeror has a lot of functions, and I don't like seeing them all as
|
|
unknowns. So add them to known symbols.
|
|
|
|
*Note:* See my [[Vacuous defvar][note]] on vacuous defvar for this use of =defvar=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defvar js2-additional-externs)
|
|
|
|
(defun oni:js2-add-conkeror-symbols ()
|
|
"Add known/used conkeror symbols to additional externs."
|
|
(when (string-suffix-p ".conkerorrc/init.js" (buffer-file-name))
|
|
(setq js2-additional-externs
|
|
'( ;; Functions
|
|
"add_hook" "check_buffer" "co_return" "content_buffer"
|
|
"define_browser_object_class" "define_key" "define_webjump"
|
|
"dumpln" "get_current_profile" "get_home_directory"
|
|
"get_recent_conkeror_window"
|
|
"hints_minibuffer_annotation_mode" "interactive" "load_spec"
|
|
"load_spec_uri_string" "load_url_in_new_buffer" "make_file"
|
|
"make_uri" "mode_line_adder"
|
|
"open_download_buffer_automatically" "prefix_completer"
|
|
"read_browser_object" "register_user_stylesheet"
|
|
"remove_hook" "require" "send_http_request" "session_pref"
|
|
"shell_command_blind" "theme_load"
|
|
;; Variables
|
|
"Cc" "Ci" "browser_object_history_url" "browser_object_links"
|
|
"buffer_count_widget" "buffer_icon_widget" "content_buffer"
|
|
"content_buffer_form_keymap" "content_buffer_normal_keymap"
|
|
"content_buffer_text_keymap" "content_policy_accept"
|
|
"content_policy_bytype" "content_policy_reject" "cwd"
|
|
"default_base_keymap" "default_global_keymap"
|
|
"downloads_status_widget" "external_content_handlers"
|
|
"hint_digits" "load_paths" "read_buffer_show_icons"
|
|
"read_url_handler_list" "session_auto_save_auto_load"
|
|
"theme_load_paths" "title_format_fn" "url_remoting_fn"
|
|
;; Keyword argument
|
|
"$alternative" "$browser_object" "$completer" "$completions"
|
|
"$initial_value" "$options" "$prompt" "$sort_order"
|
|
"$use_bookmarks" "$use_history" "$use_webjumps"))))
|
|
|
|
(add-hook 'js2-init-hook #'oni:js2-add-conkeror-symbols)
|
|
#+END_SRC
|
|
|
|
* Teach eww about <code> tags
|
|
|
|
Strangely enough, ~eww~ doesn't seem to be aware of =<code>= HTML tags.
|
|
Luckily it's trivial to teach it. It does know about =<pre>= HTML
|
|
tags, and basically I just want =<code>= tags to be treated almost as
|
|
=<pre>= tags, so to do that we just have to define a =shr-tag-code=
|
|
function. I've copied the =shr-tag-pre= function and removed the calls
|
|
to =ensure-newline=, because =<code>= tags are inline tags.
|
|
|
|
In order to remain a little future-proof, it should only be done if
|
|
it doesn't already exist.
|
|
|
|
*Note:* See my [[Vacuous defvar][note]] on vacuous defvar for this use of =defvar=.
|
|
|
|
*Note:* See my [[Function declarations][note]] on function declarations about the use of
|
|
=declare-function=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defvar shr-folding-mode)
|
|
(declare-function shr-indent "shr")
|
|
(declare-function shr-generic "shr")
|
|
|
|
(with-eval-after-load 'shr
|
|
(unless (fboundp 'shr-tag-code)
|
|
(defun shr-tag-code (cont)
|
|
(let ((shr-folding-mode 'none))
|
|
(shr-indent)
|
|
(shr-generic cont)))))
|
|
#+END_SRC
|
|
|
|
* Use scheme-mode for scsh interpreted files
|
|
|
|
Set the major mode for files interpreted by scsh (for example, by
|
|
having ~#!/usr/local/bin/scsh~ at the top) to use =scheme-mode=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-to-list 'interpreter-mode-alist '("scsh" . scheme-mode))
|
|
#+END_SRC
|
|
|
|
* Set default scheme implementation
|
|
|
|
Set the default implementation for geiser to guile so it doesn't ask
|
|
which implementation to use every time.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defvar geiser-default-implementation)
|
|
|
|
(with-eval-after-load 'geiser
|
|
(setq geiser-default-implementation 'guile))
|
|
#+END_SRC
|
|
|
|
* Setup eww-lnum
|
|
|
|
As recommended in the [[https://github.com/m00natic/eww-lnum][README]], set the keys in the =eww-mode-map=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defvar eww-mode-map)
|
|
|
|
(with-eval-after-load 'eww
|
|
(define-key eww-mode-map "f" 'eww-lnum-follow)
|
|
(define-key eww-mode-map "F" 'eww-lnum-universal))
|
|
#+END_SRC
|
|
|
|
* Don't compile scss files
|
|
|
|
By default =scss-mode= tries compiling a file each time it's saved. I
|
|
don't have SCSS properly installed globally so this always fails,
|
|
highly annoying.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defvar scss-compile-at-save)
|
|
|
|
(with-eval-after-load 'scss-mode
|
|
(setq scss-compile-at-save nil))
|
|
#+END_SRC
|
|
|
|
* Change listings in dired
|
|
|
|
The number of bytes a file is doesn't usually tell me much when it's
|
|
something like ~292837~. I prefer seeing just how many Kb or Mb a
|
|
certain file is. I also don't need to see the ~.~ and ~..~ directories
|
|
when I insert directories into the current dired buffer, as there is
|
|
a great chance that the current and parent directory are already
|
|
shown in the buffer.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defvar dired-subdir-switches)
|
|
|
|
(with-eval-after-load 'dired
|
|
(setq dired-listing-switches "-alh"
|
|
dired-subdir-switches "-Alh"))
|
|
#+END_SRC
|
|
|
|
* Useful functions
|
|
|
|
During your editing in Emacs you will undoubtedly find the need to
|
|
define your own editing functions or macros. Here are mine.
|
|
|
|
** Delete the contents of the string at point
|
|
|
|
First we define the function. It was inspired by [[http://www.masteringemacs.org/][Mickey's post on
|
|
swapping quote symbols]], mostly copied even. First we check if we
|
|
are even in a string, and if not we throw an error, after that we
|
|
move back to the beginning of the string, store that point, go to
|
|
the end of the string (using =forward-sexp=) and then delete the
|
|
region between the two points (non-inclusive).
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun oni:delete-string-contents ()
|
|
(interactive)
|
|
|
|
(unless (nth 3 (syntax-ppss))
|
|
(error "You must be in a string for this command to work"))
|
|
|
|
(save-excursion
|
|
(while (nth 3 (syntax-ppss)) (forward-char -1))
|
|
|
|
(let ((bos (point)))
|
|
(forward-sexp)
|
|
(delete-region (1+ bos) (1- (point))))))
|
|
#+END_SRC
|
|
|
|
Since for interactive functions it's kind of a pain to have to use
|
|
a personal "namespace" I prefer naming them regularly as if they're
|
|
just part of the environment. If ever Emacs comes up with a similar
|
|
function with the same name, I'd prefer using the built-in version.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(unless (fboundp 'delete-string-contents)
|
|
(defalias 'delete-string-contents 'oni:delete-string-contents))
|
|
#+END_SRC
|
|
|
|
Lastly, any function worth using often should probably be easily
|
|
accessible with a keybinding. In my case the {{{key(C-c i s)}}} is
|
|
inspired by the Vim keybindings like {{{key(ci")}}}.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(global-set-key (kbd "C-c i s") 'delete-string-contents)
|
|
#+END_SRC
|
|
|
|
* Show eldoc when evaluating expressions
|
|
|
|
Thanks to [[http://endlessparentheses.com/sweet-new-features-in-24-4.html][this post]] it was brought to my attention that eldoc mode
|
|
can be enabled when evaluating expressions using {{{key(M-:)}}}.
|
|
|
|
I vaguely remember having had this before, I just don't know how or
|
|
why it stopped working.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'eval-expression-minibuffer-setup-hook #'eldoc-mode)
|
|
#+END_SRC
|
|
|
|
* Remove whitespace when closing delimiters
|
|
|
|
In =electric-pair-mode=, skip over and delete white space if it stands
|
|
between the cursor and the closing delimiter.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq electric-pair-skip-whitespace 'chomp)
|
|
#+END_SRC
|
|
|
|
* Programming
|
|
|
|
Emacs is a real programmer's editor, especially so because it's so
|
|
programmable itself. It also offers modes for a lot of programming
|
|
languages and 3rd-party packages offer even more.
|
|
|
|
** SCSS
|
|
|
|
- Enable auto-completion
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(declare-function auto-complete-mode "auto-complete")
|
|
|
|
(add-hook 'scss-mode-hook #'auto-complete-mode)
|
|
#+END_SRC
|
|
|
|
- Enable imenu
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(declare-function scss-imenu-setup "scss-imenu")
|
|
|
|
(add-hook 'scss-mode-hook #'scss-imenu-setup)
|
|
#+END_SRC
|
|
|
|
** PHP
|
|
|
|
*** Show tabs and spaces in indent
|
|
|
|
I'm working with some WordPress plugins nowadays and their style
|
|
guide insists on using tabs, not spaces... I'd like to know that
|
|
I'm following this rule.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'php-mode-hook #'oni:whitespace-only-tabs)
|
|
#+END_SRC
|
|
|
|
*** Use web-mode for HTML-heavy files
|
|
|
|
I have to work with a lot of PHP and HTML interspersed. This makes
|
|
a difficult case since ~php-mode~ very deliberately doesn't support
|
|
that very well. On the other hand I really don't like ~web-mode~ for
|
|
PHP /without/ any HTML in it. So I decided to name the files that
|
|
contain mostly HTML with some PHP ~.html.php~ and have them load
|
|
~web-mode~ instead of ~php-mode~, whilst keeping the association for
|
|
plain ~.php~ files as it is.
|
|
|
|
Something tricky about doing this is that if this setting gets
|
|
evaluated /before/ ~php-mode~ is loaded it'll be further down the list
|
|
from ~php-mode~'s definition. This would cause the ~php-mode~ auto
|
|
mode definition from being accepted first (since ~.html.php~ also
|
|
matches ~.php~) and consequently render this definition useless.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(oni:eval-after-init
|
|
(add-to-list 'auto-mode-alist '("\\.html\\.php$" . web-mode)))
|
|
#+END_SRC
|
|
|
|
** Web
|
|
|
|
~web-mode~ has some quirks, such as not being able to handle the
|
|
fact that ~fci-mode~ puts a red line at the 80-column margin. This is
|
|
annoying to say the least.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(declare-function fci-mode "fci-mode")
|
|
(add-hook 'web-mode-hook (turn-off fci-mode))
|
|
#+END_SRC
|
|
|
|
Just like in ~php-mode~ I want to see the tabs.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'web-mode-hook #'oni:whitespace-only-tabs)
|
|
#+END_SRC
|
|
|
|
Set =indent-tabs-mode= for ~web-mode~ as well.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defvar web-mode-code-indent-offset)
|
|
(defvar web-mode-markup-indent-offset)
|
|
|
|
(add-hook 'web-mode-hook
|
|
(change-settings indent-tabs-mode t
|
|
web-mode-code-indent-offset 4
|
|
web-mode-markup-indent-offset 4))
|
|
#+END_SRC
|
|
|
|
Use it for ~.html.erb~ files.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(oni:eval-after-init
|
|
(add-to-list 'auto-mode-alist '("\\.html\\.erb$" . web-mode)))
|
|
#+END_SRC
|
|
|
|
** PO mode
|
|
|
|
Autoload =po-mode=, because it didn't come with an autloads file or
|
|
cookie.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(autoload 'po-mode "po-mode" nil t)
|
|
#+END_SRC
|
|
|
|
Automatically enable =po-mode= for files that end in =.po= or that have
|
|
a =.po= extension followed by others (such as =.po.erb=).
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-to-list 'auto-mode-alist '("\\.po\\'\\|\\.po\\." . po-mode))
|
|
#+END_SRC
|
|
|
|
* Minor modes
|
|
|
|
Emacs offers a lot of minor modes and even more can be found in the
|
|
ELPA, MELPA and Marmalade repositories. These offer a lot of
|
|
customization possibilities and added features.
|
|
|
|
** Electric indent
|
|
|
|
Automatically indenting code upon typing certain characters can be
|
|
very useful for certain modes where the indentation level can
|
|
easily be determined. One of the first things I liked about Emacs
|
|
was the way the {{{key(TAB)}}} key worked: It indents to the
|
|
"proper" level of indentation, instead of adding a tab character.
|
|
It quickly grew into a habit to press tab several times when
|
|
editing a line or a block of code. Electric indent is just an
|
|
extension of this that, for the most part, allows me to forget
|
|
about pressing tab.
|
|
|
|
It doesn't fit all modes though. When I worked in Python a lot I
|
|
was fighting the electric indent a lot more than it was helping me.
|
|
This is because instead of scope influencing indentation as in most
|
|
languages I've worked with, indentation determines scope in Python,
|
|
as anyone who's looked at it for more than a minute or two will
|
|
know. This means that any line can usually have several "proper"
|
|
indentation levels, depending on the meaning of meaning of that
|
|
line.
|
|
|
|
So, almost all modes use =electric-indent-local-mode=, but a few
|
|
don't. So I'm also very happy that recently this mode was added,
|
|
because =electric-indent-mode= is a global minor mode and I only want
|
|
to use it in some 99% of the available modes.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'css-mode-hook #'electric-indent-local-mode)
|
|
(add-hook 'js2-mode-hook #'electric-indent-local-mode)
|
|
(add-hook 'php-mode-hook #'electric-indent-local-mode)
|
|
(add-hook 'ruby-mode-hook #'electric-indent-local-mode)
|
|
(add-hook 'scss-mode-hook #'electric-indent-local-mode)
|
|
(add-hook 'sh-mode-hook #'electric-indent-local-mode)
|
|
#+END_SRC
|
|
|
|
*** Switch keys back
|
|
|
|
When =electric-indent-mode= is enabled the default function bound to
|
|
{{{key(C-j)}}} (=electric-newline-and-maybe-indent=) stops indenting
|
|
after adding a newline, whilst {{{key(RET)}}} starts doing it.
|
|
Since I use {{{key(C-j)}}} almost exclusively and don't use
|
|
{{{key(RET)}}} at all, it's really not useful to me. So I want to
|
|
switch the two when =electric-indent-mode= is enabled.
|
|
|
|
This is very simple. First I define a simple function that checks
|
|
if the =electric-indent-mode= variable is set (which it should be if
|
|
the mode is turned on) and if so I set the proper keys /locally/. If
|
|
=electric-indent-mode= is /not/ set, which happens when the mode is
|
|
turned off, I remove the local keybindings.
|
|
|
|
#+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"))))
|
|
#+END_SRC
|
|
|
|
And then I add it to the electric indent mode's hook.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'electric-indent-local-mode-hook #'oni:switch-newline-keys)
|
|
#+END_SRC
|
|
|
|
** Electric pairing
|
|
|
|
Electric pairing of delimiters is one of those features that is
|
|
just so essential to my feeling comfortable with an editor. Most of
|
|
the time I don't even use it, really. It's just that I'm so used to
|
|
having it and when I /do/ expect it to be there it is so frustrating
|
|
when it's not, or when it doesn't work properly.
|
|
|
|
This functionality, much like [[Electric indent]] isn't something I
|
|
want enabled in all modes, though for different reasons, and for a
|
|
time there was only the global =electric-pair-mode=. Again I'm very
|
|
happy that a local version was added.
|
|
|
|
The reason that I don't want it enabled for all modes is that some
|
|
modes (mostly Lisp-like language modes) have better alternatives.
|
|
But most non-Lisp-like language modes I really do need to have it.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'c-mode-hook #'electric-pair-local-mode)
|
|
(add-hook 'coffee-mode-hook #'electric-pair-local-mode)
|
|
(add-hook 'css-mode-hook #'electric-pair-local-mode)
|
|
(add-hook 'haml-mode-hook #'electric-pair-local-mode)
|
|
(add-hook 'java-mode-hook #'electric-pair-local-mode)
|
|
(add-hook 'js2-mode-hook #'electric-pair-local-mode)
|
|
(add-hook 'lua-mode-hook #'electric-pair-local-mode)
|
|
(add-hook 'python-mode-hook #'electric-pair-local-mode)
|
|
(add-hook 'ruby-mode-hook #'electric-pair-local-mode)
|
|
(add-hook 'scss-mode-hook #'electric-pair-local-mode)
|
|
(add-hook 'sh-mode-hook #'electric-pair-local-mode)
|
|
#+END_SRC
|
|
|
|
** Auto completion
|
|
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(depends-on "auto-complete")
|
|
#+END_SRC
|
|
|
|
I'm not a great fan of any type of auto completion functionality in
|
|
programming. I think it's basically only good for getting really
|
|
long names in your file faster. I started programming in C#, in
|
|
Visual Studio, and they have their very powerful Intellisense
|
|
mechanism, which I used a lot. What I noticed though was that it
|
|
was keeping me from learning the APIs. Whenever I wrote some code,
|
|
all but the most basic and most-used calls I wrote from memory.
|
|
Many others were done after a few seconds of browsing through the
|
|
Intellisense pop-up.
|
|
|
|
Because of this, I disable the normal auto-complete pop-up.
|
|
|
|
#+NAME: auto-complete-dont-show
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(setq ac-auto-show-menu nil)
|
|
#+END_SRC
|
|
|
|
On the rare occasion that I do call up the pop-up to see what the
|
|
completions I have available to me are, I don't want it to show the
|
|
quick help. The quick help usually shows up as a big extra pop-up
|
|
next to the completion list and it gets very messy when combined
|
|
with some other modes that add overlays to the buffer.
|
|
|
|
#+NAME: auto-complete-no-quickhelp
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(setq ac-use-quick-help nil)
|
|
#+END_SRC
|
|
|
|
To keep the byte-compiler from complaining about undefined
|
|
variables, I only want this to be done after =auto-complete= is
|
|
loaded, not sooner.
|
|
|
|
#+BEGIN_SRC emacs-lisp :noweb yes
|
|
(stante-after auto-complete
|
|
<<auto-complete-dont-show>>
|
|
<<auto-complete-no-quickhelp>>)
|
|
#+END_SRC
|
|
|
|
** Highlight indentation
|
|
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(depends-on "hl-indent")
|
|
#+END_SRC
|
|
|
|
Some languages base their ideas of scope on levels of indentation.
|
|
When these languages get long functions/branches it can get tricky
|
|
to see where these blocks end. Of course if you have such large
|
|
functions you might have other problems, but this is sometimes out
|
|
of your hands. To help, I use =hl-indent-mode=.
|
|
|
|
For other languages it might look fun for a little while as well,
|
|
but since they don't care about indentation as much it can
|
|
sometimes get messy.
|
|
|
|
First, =hl-indent-mode= doesn't have an =;;;###autoload= cookie for its
|
|
main entry-point, so I add it manually:
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(autoload 'hl-indent-mode "hl-indent" nil t)
|
|
#+END_SRC
|
|
|
|
Then I enable it for the languages I want.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'python-mode-hook #'hl-indent-mode)
|
|
(add-hook 'yaml-mode-hook #'hl-indent-mode)
|
|
(add-hook 'haml-mode-hook #'hl-indent-mode)
|
|
#+END_SRC
|
|
|
|
** Django helper
|
|
:PROPERTIES:
|
|
:ORDERED: t
|
|
:END:
|
|
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(depends-on "pony-mode")
|
|
#+END_SRC
|
|
|
|
Autoload =pony-mode= because it doesn't come with an autoload cookie.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(autoload 'pony-mode "pony-mode" nil t)
|
|
#+END_SRC
|
|
|
|
Turn on =compilation-shell-minor-mode= when =pony-mode= is enabled.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun oni:turn-on-compilation-shell-for-pony ()
|
|
"Turn on option `compilation-shell-minor-mode' for `pony-minor-mode'."
|
|
(add-hook 'pony-minor-mode-hook 'compilation-shell-minor-mode nil t))
|
|
|
|
(add-hook 'comint-mode-hook #'oni:turn-on-compilation-shell-for-pony)
|
|
#+END_SRC
|
|
|
|
** Automatic syntax checking on-the-fly
|
|
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(depends-on "flycheck")
|
|
(depends-on "flycheck-cask")
|
|
(depends-on "flycheck-commit-check" :git "git://github.com/ryuslash/flycheck-commit-check.git")
|
|
#+END_SRC
|
|
|
|
Flycheck provides awesome syntax checkers for many languages.
|
|
Enable it for the languages I use.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'haml-mode-hook 'flycheck-mode)
|
|
(add-hook 'emacs-lisp-mode-hook 'flycheck-mode)
|
|
(add-hook 'git-commit-mode-hook 'flycheck-mode)
|
|
(add-hook 'go-mode-hook 'flycheck-mode)
|
|
(add-hook 'html-mode-hook 'flycheck-mode)
|
|
(add-hook 'js2-mode-hook 'flycheck-mode)
|
|
(add-hook 'lua-mode-hook 'flycheck-mode)
|
|
(add-hook 'perl-mode-hook 'flycheck-mode)
|
|
(add-hook 'php-mode-hook 'flycheck-mode)
|
|
(add-hook 'python-mode-hook 'flycheck-mode)
|
|
(add-hook 'rst-mode-hook 'flycheck-mode)
|
|
(add-hook 'ruby-mode-hook 'flycheck-mode)
|
|
(add-hook 'rust-mode-hook 'flycheck-mode)
|
|
(add-hook 'sh-mode-hook 'flycheck-mode)
|
|
(add-hook 'texinfo-mode-hook 'flycheck-mode)
|
|
#+END_SRC
|
|
|
|
Whenever flycheck is started, try using it with Cask.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'flycheck-mode-hook 'flycheck-cask-setup)
|
|
#+END_SRC
|
|
|
|
Load my own git commit checker.
|
|
|
|
#+NAME: flycheck-commit-checker
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(require 'flycheck-commit-check)
|
|
#+END_SRC
|
|
|
|
Disable certain checkers.
|
|
|
|
#+NAME: flycheck-delete-checkers
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(mapc (lambda (c) (delq c flycheck-checkers))
|
|
'(python-pylint python-pyflakes))
|
|
#+END_SRC
|
|
|
|
Set the highlighting mode to columns so I can see (if possible)
|
|
where errors/warnings belong.
|
|
|
|
#+NAME: flycheck-columns
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(setq flycheck-highlighting-mode 'columns)
|
|
#+END_SRC
|
|
|
|
Try not to display the errors. A jumpy echo area makes me nervous
|
|
and {{{key(C-c ! l)}}} is a nicer way to look at it usually. It
|
|
still doesn't keep it from being displayed, only when nothing else
|
|
is displayed though.
|
|
|
|
#+NAME: flycheck-display
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(setq flycheck-display-errors-function (lambda (_) nil))
|
|
#+END_SRC
|
|
|
|
Do most of these things after flycheck is loaded.
|
|
|
|
#+BEGIN_SRC emacs-lisp :noweb yes
|
|
(stante-after flycheck
|
|
<<flycheck-commit-checker>>
|
|
<<flycheck-delete-checkers>>
|
|
<<flycheck-columns>>
|
|
<<flycheck-display>>)
|
|
#+END_SRC
|
|
|
|
* Magit
|
|
|
|
Recently Magit gained the annoying habit of producing a /huge/ warning
|
|
message whenever you don't tell it that you've already seen it. To
|
|
tell it you've already seen the message you need to specify the
|
|
following.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-and-compile
|
|
(defvar magit-last-seen-setup-instructions "1.4.0"))
|
|
#+END_SRC
|
|
|
|
I use a =defvar= here in order to keep the byte-compiler from
|
|
complaining about an undefined variable. It needs to be specified
|
|
before magit is loaded otherwise magit will keep complaining.
|
|
|
|
** Project directory
|
|
|
|
I keep all my projects in =~/projects/=, so Magit shouldn't have to
|
|
look anywhere else.
|
|
|
|
#+NAME: magit-repo-dirs
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(setq magit-repo-dirs '("~/projects/"))
|
|
#+END_SRC
|
|
|
|
** Show fine differences
|
|
|
|
I like to see all the little differences in diffs that I can. They
|
|
really help reading diffs. I also just want to see them on all
|
|
diffs and not the selected one, which would make an unnecessary
|
|
amount of navigation required to properly read the diffs.
|
|
|
|
#+NAME: magit-diff-refine-hunk
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(setq magit-diff-refine-hunk 'all)
|
|
#+END_SRC
|
|
|
|
** Don't revert all the buffers
|
|
|
|
I'd never noticed it much before, but lately magit's habit of
|
|
reverting all the buffers after almost every action I perform has
|
|
become disturbingly slow. I personally don't rely on that
|
|
functionality being either off or on, so turning it off shouldn't
|
|
bother me too much.
|
|
|
|
#+NAME: magit-auto-revert-mode
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(setq magit-auto-revert-mode nil)
|
|
#+END_SRC
|
|
|
|
** Delay setting
|
|
|
|
The settings in the previous sections should only be set after
|
|
Magit has loaded.
|
|
|
|
#+BEGIN_SRC emacs-lisp :noweb yes
|
|
(stante-after magit
|
|
<<magit-repo-dirs>>
|
|
<<magit-diff-refine-hunk>>
|
|
<<magit-auto-revert-mode>>)
|
|
#+END_SRC
|
|
|
|
* Final touches
|
|
|
|
These options and calls need to come last so they don't interfere
|
|
with the rest of the initialization process, or get interfered with.
|
|
|
|
** Load custom file
|
|
|
|
I don't really use the Emacs customization interface much, but I
|
|
have used it as a kind-of persistent datastore, specifically for
|
|
desktop-registry[fn:9]. I do very much like the idea of it, it's a
|
|
very cool thing to have. I also use ~custom.el~ for storing some
|
|
things that I really can't store in a public viewing location like
|
|
this file or the git repository it lives in.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq custom-file "~/.emacs.d/custom.el")
|
|
(load custom-file)
|
|
#+END_SRC
|
|
|
|
* Notes
|
|
|
|
Here are some random or somewhat general notes about things you may
|
|
run into when looking through my Emacs init.
|
|
|
|
** Vacuous defvar
|
|
|
|
A =defvar= without a value like =(defvar some-variable)= tells the
|
|
byte-compiler that the variable will appear, but doesn't give it a
|
|
value. It should only count for the file where it is used and once
|
|
the file with the /actual/ =defvar= is loaded it will be populated with
|
|
its value, contrary to what would happen if you'd given it a value
|
|
before loading its original file.
|
|
|
|
** Function declarations
|
|
|
|
The function =declare-function= tells the byte-compiler where to find
|
|
a certain function. This keeps the byte-compiler from complaining
|
|
about certain functions possibly not being defined at run-time.
|
|
|
|
* Footnotes
|
|
|
|
[fn:1] This runs =tmm-menubar=, which lets you navigate the menubar in a
|
|
text-driven way. I don't ever use it because I know what all my
|
|
favorite functions are called, but it seems a great deal more
|
|
efficient than having to click on everything.
|
|
|
|
[fn:2] https://github.com/sabof/svg-mode-line-themes
|
|
|
|
[fn:3] It works fine for me with something like jabber chats and the
|
|
like.
|
|
|
|
[fn:4] I like to program in Lisp, parentheses are important to me!
|
|
Parentheses should be nice and round, not almost like bars!
|
|
|
|
[fn:5] https://github.com/belluzj/fantasque-sans
|
|
|
|
[fn:6] Used to be Cosmic Sans Neue Mono, the name changed because
|
|
people misread it as "Comic" (me included, which was the original
|
|
reason I checked it out, for laughs) and hate Comic Sans, and also
|
|
because there was already a Cosmic Sans font as well, which could
|
|
cause confusion.
|
|
|
|
[fn:7] http://stackoverflow.com/questions/22175214/automatically-switch-language-in-gnus-depending-on-recipient
|
|
|
|
[fn:8] I still use 2 spaces for some languages, like HTML.
|
|
|
|
[fn:9] http://code.ryuslash.org/desktop-registry/about/
|