summaryrefslogtreecommitdiffstats
path: root/emacs/.emacs.d/init.org
diff options
context:
space:
mode:
authorGravatar Tom Willemse2014-08-21 00:23:56 +0200
committerGravatar Tom Willemse2014-08-21 00:23:56 +0200
commitc2778f0f713cc885087d6302196e421596ff248e (patch)
treef289c9e52bcaa6dd1ef7b64343df78492a36141d /emacs/.emacs.d/init.org
parent05415b9b2c455fb5e5f2521610b9d7dd33385d21 (diff)
downloaddotfiles-c2778f0f713cc885087d6302196e421596ff248e.tar.gz
dotfiles-c2778f0f713cc885087d6302196e421596ff248e.zip
Add Emacs config
Diffstat (limited to 'emacs/.emacs.d/init.org')
-rw-r--r--emacs/.emacs.d/init.org960
1 files changed, 960 insertions, 0 deletions
diff --git a/emacs/.emacs.d/init.org b/emacs/.emacs.d/init.org
new file mode 100644
index 0000000..1031ae2
--- /dev/null
+++ b/emacs/.emacs.d/init.org
@@ -0,0 +1,960 @@
+#+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)
+ (let ((from (message-fetch-field "From")))
+ (ispell-change-dictionary
+ (if (string-match (rx "@aethon.nl>" eol) from) "nl" "en")))))
+
+ (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
+
+* 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/