1099 lines
39 KiB
Org Mode
1099 lines
39 KiB
Org Mode
#+TITLE: Emacs init
|
|
#+PROPERTY: tangle init2.el
|
|
#+STARTUP: showall
|
|
#+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">
|
|
|
|
* About this file
|
|
|
|
Inspired by such other projects as the literal Emacs init from [[http://sachac.github.io/.emacs.d/Sacha.html][Sacha
|
|
Chua]] and also from [[http://www.wisdomandwonder.com/wordpress/wp-content/uploads/2014/03/C3F.html][Grant Rettke]], here is my Emacs initialization
|
|
file.
|
|
|
|
*Note:* This is not my entire Emacs initialization file. It's a
|
|
work-in-progress. To keep on top of any changes to this file, or any
|
|
other part of my Emacs init, I recommend you follow [[http://code.ryuslash.org/dot/tom/emacs/][This project]]
|
|
([[http://code.ryuslash.org/dot/tom/emacs/atom/?h=master][Atom feed]]), which is where I keep my configuration.
|
|
|
|
** Preparation
|
|
|
|
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 it's 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've 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.
|
|
|
|
* Use lexical binding
|
|
|
|
For some of these functions, and general coolness, lexical binding
|
|
is a must. Without it, closures cannot be made.
|
|
|
|
#+BEGIN_SRC emacs-lisp :padline no
|
|
;; -*- lexical-binding: t -*-
|
|
#+END_SRC
|
|
|
|
* 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
|
|
|
|
* Clean up some UI elements
|
|
|
|
Some elements are only really useful if you use the mouse. Which I
|
|
don't, not if I can help it. Only when browsing the web or using the
|
|
odd graphical application do I touch the mouse, and even then as
|
|
little as I can.
|
|
|
|
** 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
|
|
|
|
** 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
|
|
|
|
** 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
|
|
|
|
** 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
|
|
|
|
** 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
|
|
|
|
** 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
|
|
|
|
** Cursors in inactive windows
|
|
|
|
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
|
|
|
|
** 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
|
|
|
|
** The default frame
|
|
|
|
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.
|
|
|
|
*** 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
|
|
|
|
*** 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:pixelsize=17")
|
|
#+END_SRC
|
|
|
|
*** 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
|
|
|
|
*** Setting the option
|
|
|
|
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
|
|
|
|
** 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
|
|
|
|
* 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
|
|
|
|
* 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
|
|
|
|
* 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
|
|
|
|
* 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
|
|
|
|
* 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"))))
|
|
|
|
(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
|
|
|
|
* 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
|
|
|
|
* 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
|
|
|
|
* 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
|
|
|
|
* 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
|
|
|
|
* 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
|
|
|
|
* 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
|
|
|
|
** 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
|
|
|
|
** 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 (in-string-p)
|
|
(error "You must be in a string for this command to work"))
|
|
|
|
(save-excursion
|
|
(while (in-string-p) (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
|
|
|
|
* Return to {{{key(C-j)}}} in electric indent mode
|
|
|
|
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 when =electric-indent-mode=
|
|
is enabled, switch the two.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'electric-indent-local-mode-hook
|
|
(lambda ()
|
|
(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
|
|
|
|
* Local minor mode for =electric-pair-mode=
|
|
|
|
Almost all modes benefit from automatic delimiter pairing, but not
|
|
all modes are equal. =paredit= works awesomely for anything lisp-like,
|
|
but not so much for other modes, that's where =electric-pair-mode=
|
|
comes in. Unfortunately it has no local version, so I copied the
|
|
code from =electric-indent-local-mode= and changed it work with
|
|
=electric-pair-mode=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
;; Copied from electric.el, modified from `electric-indent-local-mode'.
|
|
(define-minor-mode oni:electric-pair-local-mode
|
|
"Toggle `electric-pair-mode' only in this buffer."
|
|
:variable (buffer-local-value 'electric-pair-mode (current-buffer))
|
|
(cond
|
|
((eq electric-pair-mode (default-value 'electric-pair-mode))
|
|
(kill-local-variable 'electric-pair-mode))
|
|
((not (default-value 'electric-pair-mode))
|
|
;; Locally enabled, but globally disabled.
|
|
(electric-pair-mode 1) ; Setup the hooks.
|
|
(setq-default electric-pair-mode nil) ; But keep it globally disabled.
|
|
)))
|
|
#+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
|
|
|
|
- Automatically match parentheses and other delimiters.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'scss-mode-hook #'oni:electric-pair-local-mode)
|
|
#+END_SRC
|
|
|
|
- Automatically indent code.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'scss-mode-hook #'electric-indent-local-mode)
|
|
#+END_SRC
|
|
|
|
* Haml
|
|
|
|
- Automatically match parentheses and other delimiters.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'haml-mode-hook #'oni:electric-pair-local-mode)
|
|
#+END_SRC
|
|
|
|
* Ruby
|
|
|
|
- Automatically match parentheses and other delimiters.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'enh-ruby-mode-hook #'oni:electric-pair-local-mode)
|
|
#+END_SRC
|
|
|
|
* 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/
|