A Semi-literate Emacs Configuration
Introductory comments
This document is my configuration for GNU Emacs, using Org Mode's Literate Programming facilities to automatically extract and evaluate all the relevant code snippets, ignoring the documenting comments.
To load this configuration, make sure you have the .org file locally
on your system, and call it using org-babel-load-file. Furthermore,
make sure that you've loaded the cl module with require. Eventually
you will have to load org too.
This document, it's code and comments, are in the public domain.
The following configuration hasn't been tested on multiple systems,
with different Emacs versions, etc. I only know that it works on my
deviceā¢, and sometimes I'm not even sure about that. No backwards
compatibility beyond Emacs 25.1 is intended.
This configuration is occasionally updated on my website, and the Git history (+source) is also public.
Personal Emacs History
My first encounters with Emacs must have been somewhere around late 2014, when I was looking around to find a proper text editor. Overwhelmed by the options, I tried a lot of things out, such as Sublime Text or Geany, but all of them felt missing, faulted incomplete or simply wrong. It didn't take long for me to understand that the two main players turned out to be some of the oldest ones: vi (ie. vim) and Emacs (ie. GNU Emacs).
Knowing nothing, I trusted common opinion and went with Vi(m). And it
was cool – a sin penance to say in an Emacs configuration. But while
the foundations were good, it had problems with being extended,
personalized, etc. Ultimately, I came to the conclusion that one
shouldn't customize Vi(m), or at the very least keep it as minimal as
possible (hence I use nvi and vis instead of Vim nowadays).
Yet this conclusion wasn't achieved by itself. It took Emacs to prove this, by demonstrating a properly extendable "environment" to teach me…
I remember that there was a bit of a gap between installing and using
Emacs. For a while I even had issues remembering and recognizing the
name! A particularly vivid memory is me looking through the Gnome (or
Unity?) configuration program, and encountering the "input method"
option, among which "Emacs" was an option – I assumed it was related
to Apple's computer brand… But when I opened Emacs for the first
few times it seemed a bit overwhelming, (unnecessarily) complex and
unhandy: everything was different. From names over the workflow
(which I didn't even understand) to the keybindings. All I used to
do, was open a file (C-x C-f), maybe move up and down (M-v and C-v)
change the theme (using the menu bar) and then close Emacs (C-x
C-x). That was pretty much all I knew.
But somewhere around early 2015 (if not earlier) for some reason I can't quite remember I was drawn towards Emacs. Possibilities could be
- Me having have met "real" Emacs users, and drawing my attention to the Editor, making me realize that it's not just a notepad with inconvenient keybindings.
- Me having have engaged with Lisp, while to be fair not knowing all it's potential understanding it's beauty.
So I slowly started trying to configure Emacs. Retroactively it seems to me that the resources were far harder to find. Having no idea what to do (and lacking the patience to sit through the Emacs Manual), I copied a few things from some blogs, a few things from some dotfile, some stuff from YouTube descriptions and others from Stackoverflow questions – to put it simply, it was a mess, and stuff broke quite freqently. I kept on reading that Org mode was great, but I didn't ever get why (I did eventually). But for some reason I didn't stop using Emacs, but neither did I go too deep.
After some 2 1/2 years of bare survival, ups and downs, I started to find out that people were writing literate configurations.
Then I read an article, that said the following:
They all used Emacs, of course. Hell, Eric Benson was one of the authors of XEmacs1. All of the greatest engineers in the world use Emacs. The world-changer types. Not the great gal in the cube next to you. Not Fred, the amazing guy down the hall. I'm talking about the greatest software developers of our profession, the ones who changed the face of the industry. The James Goslings, the Donald Knuths, the Paul Grahams2, the Jamie Zawinskis, the Eric Bensons. Real engineers use Emacs. […]
Emacs is the 100-year editor.
It didn't take long and I decided to rewrite my ~100-150 line configuration. My enthusiasm began to blossom somewhere around that time. And so, since February 2018 I have been maintaining this file.
Why use org/babel?
While it might appear to be a inconvenience at first, extracting ones configuration into a format like this one has multiple advantages, of which the main ones are:
- My actual
init.elis very short. All I do, disable filename handlers, increase the garbage collection threshold, and (if necessary) call Org/Babel. If the extracted file newer than the this org file, I just load that file. - Writing text with code (as opposed to code with comments) is much more informative, and makes me justify whatever I add. This, one the one hand contributes to simplicity, but also helps people who are configuring their config get a better feeling for what to do and why.
- After a while, every novice should entirely rewrite their configuration. In the beginning, one might just copy stuff from Manuals, Wikis and Blogs – and keep what sicks, but this results in code that's hard to maintain and keep an overview. I pushed myself to rewrite my configuration I started to write around 2014-15 and I enjoy a far better experience that had before. My potential had increased and I have used the opportunity to learn more about Emacs itself.
Inspirations for writing this configuration
Emacs is a tool you can use for years and always learn something new,
which make you feel stupid for not having known. The fun part when
writing a configuration like this one is that one actively learns
these things, instead of accidentally pressing the wrong keybinding,
and then going back to C-h l to find out what just happened.
So for my own assistance, and maybe also for other lost souls, reading this in the lookout for tricks and wizardry (note: you probably won't find any of this in my config), I list here other very interesting configurations:
- Org Mode – Organize Your Life in Plain Text!
- this is not
strictly a config, but it's an overall great
org-modeoverview - Using Emacs as a Development Environment
- this offered a few c-mode related tricks
- Sheruf Ghali's Emacs config
- recommendable due to being an expansive document with good (although not "literate") documentation and commentary.
- Caolan McMahon's Emacs Configuration
- A lot of packages with helpful commentary. Very well structured.
- John Wiegley's (
use-packagecreator) "dot-emacs" - Always up to date and permanently changing, this configuration shows a lot of maturity.
- Tu Do's "Emacs Mini Manual (PART 3)"
- Part of a series that
starts from nothing and gives a great introduction to Emacs. The
last part (linked here) introduces and explains a lot of useful
packages, as well as basic elisp concepts (
defun,add-to-list,mapc, …) - j3kyl's
init.el - Very extensive and occasionally obscure settings, structured and documented well enough to be understandable.
- Lard Tveito's "dot-emacs"
- Another literate configuration that demonstrates multiple packages with well written and helpful comments.
- Harry R. Schwarz' (hrs) "dotfiles"
- Part of his overall configuration, hrs (Organizer of the NYC Emacs meetup) provides an extensive list of packages, tricks and tips.
- Sacha Chua's Emacs configuration
- Very comprehensive but a bit disordered (IMO) literate configuration by the maintainer of the (very recommendable) Emacs News newsletter.
All of these configurations are worth reading and re-reading from time to time, since one can always find out something new to adopt into his/her own configuration.
A more comprehensive list can be found here.
Short note on my directory structure
While this configuration aims for a certain degree of portability, this isn't universally the case, since it's my personal setup, not a cool prelude. Portability is maintained between the devices I use Emacs on, by assuming a certain standardized directory structure, as follows:
~/ home
~/code/ programming and sysadmin related files
~/code/{c,haskell,go,...} directories devoted to specific programming languages
~/code/etc/... various other projects (including emacs source)
~/dl/ downloads gathering directory, preferably empty
~/doc/ texts, presentations and notes
~/doc/org/ most org-mode related files
~/media/ general directory for digial media
~/media/{img,vid,music,...} specific media directories
~/etc/ various other directories
~/etc/bin/ user binaries
~/etc/{mail,news,pub} gnus related directories
~/etc/sync syncthing directory
When porting or copying from this configuration, these notes might help.
General Setup
Lexical Scoping
;;; -*- lexical-binding: t -*-
All code written in this file, shall be "Lexically Scoped".
Package Management
(require 'package) (add-to-list 'package-archives '("melpa-stable" . "https://stable.melpa.org/packages/")) (setq package-enable-at-startup nil load-prefer-newer t) (package-initialize)
Only use melpa-stabe besides the standard gnu repository (which
should be in package-archives by default). This makes sure that all
the packages (see Packages).
Appearance
Initially deactivated Modes
(scroll-bar-mode -1) (menu-bar-mode -1) (tool-bar-mode -1) (blink-cursor-mode -1) (tooltip-mode -1)
Since I usually don't need my mouse to use Emacs, I turn off all GUI related tools, like scroll- toolbars, etc. This is done early on to avoid redrawing during startup.
Fonts
(set-face-attribute 'default nil
:font "Hack"
:height 140)
(set-face-attribute 'variable-pitch nil
:font "Lato"
:height 130)
My fonts are configured and changed frequently, making any more significant commentary on this code redundant.
Mode-bar customisations
(show-paren-mode t) (display-time-mode t) (display-battery-mode t)
To extend the default Emacs appearance, matching parentheses are highlighted, which is helpful when working with Lisp code. Furthermore the mode bar displays the current column of the active point and the current time, since I usually use Emacs in full screen mode withing a window manager without a built in clock facility.
Startup actions
(setq inhibit-startup-screen t
inhibit-startup-buffer-menu t
inhibit-startup-message t
inhibit-startup-hooks t)
In accordance to a minimalist and fast startup, I tell Emacs to not open the standard startup buffer (with a timestamp of when I opened Emacs), since I never use it anyways.
Whitespace and Formatting
(setq-default fill-column 72
tab-width 4)
These settings are purely personal preferences.
Exiting Emacs
(setq confirm-kill-emacs 'yes-or-no-p)
While it's not quite "appearance"-related, this will prevent Emacs
from being accidentally closed when I type C-x C-c instead of C-c
C-x.
Extra-Emacs Clipboard
(setq-default select-enable-clipboard t
x-select-enable-clipboard t)
Having the ability to interact with the system clipboard is very
welcome, especially when copying code from a (now eww) web browser.
Frame resizing
(setq frame-resize-pixelwise t)
When using graphical Emacs, this option enables more flexible resizing of the entire frame.
Cross-session Configuration
(setq history-delete-duplicates t
savehist-save-minibuffer-history t
savehist-additional-variables '(kill-ring
search-ring
eshell-history-ring
compile-command
recentf-list
calc-stack)
savehist-ignored-variables '(tmm--history
yes-or-no-p-history))
(savehist-mode t)
The preceding two function calls make sure that in-between opening
and closing Emacs (for example when I have to shut down my computer)
buffers and windows are saved, as well as minibuffer inputs plus the
contents of kill-ring, search-ring and compile-command. Other
variables, which are not needed are disregarded.
(setq desktop-restore-frames nil
desktop-restore-eager t)
(desktop-save-mode t)
To not loose all the buffers between sessions, desktop-save-mode
keeps track of buffers before Emacs exists, but doesn't keep track of
the frame layout. Furthermore, no buffers are "lazily" restored, but
instead all at once, since otherwise this leads to an annoying
behavior where buffers are being restored and Emacs, but because I
stopped typing for a second.
Backups
(setq-default backup-directory-alist `(("" . ,(expand-file-name "backup/" user-emacs-directory))) auto-save-default nil backup-by-copying t kept-old-versions 3 kept-new-versions 8 delete-old-versions t version-control t vc-make-backup-files t)
The default Emacs backup system is pretty annoying, so these are a some helpful tips I've gathered from around the internet, with a few modifications based on experience (eg. having have been saved by the backup system, more than just a few times).
Note: This is also probably one of the oldest parts on my configuration, staying mostly unchanged since mid-late 2014, when copied the code from this StackOverflow question.
Defaults
User information
(setq user-full-name "Philip K." user-mail-address "philip@warpmail.net")
Personal data?
Encoding
(prefer-coding-system 'utf-8)
Assume UTF8 by default.
"Large Files"
(setq large-file-warning-threshold 40000000)
Don't warn me about larger-but-not-actually-that-large files.
Uniquify
(setq uniquify-buffer-name-style 'forward uniquify-after-kill-buffer-p t uniquify-ignore-buffers-re "^\\*")
It happens far too often that I open two files with the same name,
eg. two Makefile or .gitignore files. To make this "mistake" more
pleasant, I customize the default behavior.
Aliases
(defalias 'yes-or-no-p 'y-or-n-p) (defalias 'perl-mode 'cperl-mode)
Don't use perl-mode, but cperl-mode! And instead of having to type
"yes" or "no" when emacs asks a question, respectively accept "y" or
"n" instead.
Emacs-generated files
(let ((custom-el (expand-file-name "custom.el" user-emacs-directory))) (setq-default custom-file custom-el) (when (file-exists-p custom-el) (load custom-file)))
I previously attempted to set custom-file to /dev/null/, but sadly I
kept getting the message that the find could not be
found. Therefore, to not clutter init.el, I dump all the
configurations in ~/.emacs.d/custom.el.
Sentences
(setq-default sentence-end "[.!?][\W_]*[[:space:]]+")
I dislike the standard sentence definition Emacs uses, since for me
a sentence is just a publication mark, followed by white space.
Optionally, non-word characters are acceptable between the
punctuation and the whitespace, like when writing _No!_ in Markdown.
Save Place
(save-place-mode t)
When re-entering a file, return to that place where I was when I left it the last time.
Recent files
(recentf-mode t)
For tools like Projectile, recentf is enabled, so to easily access recently opened files.
Setting the right mode
(setq-default major-mode (lambda () (if buffer-file-name (fundamental-mode) (let ((buffer-file-name (buffer-name))) (set-auto-mode)))))
When creating new buffers, use auto-mode-alist to automatically set
the major mode. Snippet from Stackoverflow.
Browser
(setq-default browse-url-browser-function 'browse-url-xdg-open eww-download-directory (expand-file-name "~/dl"))
Use whatever is set as the default browser on the current system,
when opening http:// links. (But still let eww be properly
configured.)
Time Locale
(setq system-time-locale "C")
Force Emacs (especially org-mode) to use English timestamps.
Abbrevations
(setq abbrev-file-name (expand-file-name "abbrev.defs" user-emacs-directory) save-abbrevs 'silent)
This setup will automatically initialize and save new abbreviations, which are used for writing.
Shell comands
(setq-default async-shell-command-display-buffer nil
async-shell-command-buffer 'new-buffer)
When asynchronously running commands, only create a new output buffer, if one is needed.
Week
(setq-default calendar-week-start-day 1
calendar-longitude 10.9887
calendar-latitude 49.4771
calendar-date-style 'iso
calendar-christian-all-holidays-flag t
calendar-mark-diary-entries-flag t)
The default Emacs calendar configuration is a bit simplistic and peculiar. I've always been used to weeks starting on Monday and prefer ISO over the American date format, so I set calendar to work accordingly. Furthermore, I request holidays and diary entries to be highlighted.
(add-hook 'calendar-move-hook
(lambda ()
(when (calendar-check-holidays (calendar-cursor-to-date t nil))
(calendar-cursor-holidays))))
This hook prints the holiday under the cursor to the minibuffer, in there there is any, since this seemingly cannot be enabled by default.
(setq holiday-general-holidays '((holiday-fixed 1 1 "New Year") (holiday-fixed 5 1 "1st Mai") (holiday-fixed 10 3 "Tag der Deutschen Einheit") (holiday-fixed 12 31 "Sylvester"))) (setq holiday-christian-holidays '((holiday-fixed 1 6 "Heilige Drei Könige") (holiday-easter-etc -48 "Rosenmontag") (holiday-easter-etc -2 "Karfreitag") (holiday-easter-etc 0 "Ostersonntag") (holiday-easter-etc +1 "Ostermontag") (holiday-easter-etc +39 "Christi Himmelfahrt") (holiday-easter-etc +49 "Pfingstsonntag") (holiday-easter-etc +50 "Pfingstmontag") (holiday-easter-etc +60 "Fronleichnam") (holiday-fixed 8 15 "Mariae Himmelfahrt") (holiday-fixed 11 1 "Allerheiligen") (holiday-float 11 0 1 "Totensonntag" 20) (holiday-float 12 0 -4 "1. Advent" 24) (holiday-float 12 0 -3 "2. Advent" 24) (holiday-float 12 0 -2 "3. Advent" 24) (holiday-float 12 0 -1 "4. Advent" 24) (holiday-fixed 12 25 "1. Weihnachtstag") (holiday-fixed 12 26 "2. Weihnachtstag")))
Based on the EmacsWiki Calendar Localization Article, I list inform Emacs German/Bavarian holidays, since these are relevant to me.
Spell Checking
(setq-default ispell-program-name (executable-find "aspell") ispell-extra-args '("--sug-mode=ultra"))
Just use Aspell.
Registers
(let ((files `((?c . ,(expand-file-name "conf.org" user-emacs-directory)) (?n . "~/doc/org/notes.org") (?h . "~") (?l . ,(format-time-string "~/doc/ledger/%Y/%m.lg")) (?u . "~/code/uni/") (?o . "~/doc/org/") (?w . "~/code/web/www/") (?r . "~/doc/read/")))) (mapc (lambda (c) (let ((file (expand-file-name (cdr c)))) (set-register (car c) (cons 'file file)))) files))
To quickly access certain files I tend to frequently use, I use Emacs's file registers.
Packages and Other Configurations
(unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package t)) (require 'bind-key) (setq-default use-package-always-defer t use-package-always-ensure t)
Generally, always defer packages and ensure their installation, unless
otherwise specified. It is assumed that use-package has already been
installed.
Utilities
Dired
(setq-default dired-dwim-target t dired-recursive-copies 'always dired-recursive-deletes 'top dired-ls-F-marks-symlinks t dired-ls-sorting-switches "v" dired-listing-switches "-ABhl --group-directories-first") (put 'dired-find-alternate-file 'disabled nil)
Not much to say: For the most part, a under-customized dired configuration.
(setq-default wdired-allow-to-change-permissions t
wdired-allow-to-redirect-links t)
Wdired by default only allows one to edit file names. Setting these variables, extends the abilities of this very interesting minor mode.
(use-package diredfl
:init
(diredfl-global-mode))
Enable extra coloring in dired buffers.
Hippie Expand
(setq hippie-expand-try-functions-list
'(try-expand-dabbrev
try-expand-dabbrev-all-buffers
try-complete-file-name-partially
try-expand-dabbrev-from-kill
try-complete-file-name
try-expand-list
try-expand-line
try-expand-all-abbrevs
try-complete-lisp-symbol-partially
try-complete-lisp-symbol))
For some reason hippie-expand (and it's little sister dabbrev) was
one of the tools I never noticed but couldn't forget about when I
did. Expanding dynamically and even quite intelligently, in all
buffers is something one might not quite understand at first, or
even find confusing, but especially in the context of Emacs is
really cool. To aid this experience, I've set and ordered a few
extra expand functions, I find helpful.
Helm
(use-package helm :disabled :init (setq helm-ff-guess-ffap-filenames t helm-M-x-fuzzy-match t helm-buffers-fuzzy-matching t helm-recentf-fuzzy-match t) :config (helm-autoresize-mode t) (helm-mode t) :bind (("M-x" . helm-M-x) ("C-h a" . helm-apropos) ("C-x b" . helm-mini) ("C-x C-b" . helm-buffers-list) ("C-x C-f" . helm-find-files) ("C-c h o" . helm-occur)))
This is my Helm setup, if I were to use it, which I currently don't.
Terminal
(setq explicit-shell-file-name (executable-find "sh"))
Use sh instead of bash as the term subshell.
(advice-add 'term-handle-exit :after (lambda (&rest args) (kill-buffer (current-buffer))))
Don't keep the buffer around as soon as the process ends.
which-key
(use-package which-key :config (which-key-mode t) :init (setq which-key-idle-delay 2.5 which-key-popup-type 'minibuffer))
Sometimes one forgets all the keybindings, and what commands are
hidden behind them. In fact this is one of the major criticisms
behind more "classical" editors like Emacs or vi. C-h b works, but
which-key helps, buy quickly and quietly popping up when I pause for
too long (> 2.5s) while in the middle of some keybinding.
Expand Region
(use-package expand-region :bind ("C-=" . er/expand-region))
The expand-region utility is a helpful function that let's the user
select increasingly larger semantically meaningful regions. I've
bound it to the recommended default
Eshell
(setq-default eshell-banner-message "")
I don't need to know I am using eshell, thanks.
Gnus
(use-package gnus :init (setq gnus-select-method '(nnnil "") gnus-secondary-select-methods '((nnimap "imap.fastmail.com" (nnimap-streaming t) (nnir-search-engine imap)) (nnimap "faumail.fau.de" (nnimap-streaming t) (nnir-search-engine imap))) mail-sources '((imap :server "faumail.fau.de") (imap :server "imap.fastmail.com")) gnus-group-sort-function 'gnus-group-sort-by-unread gnus-fetch-old-headers 'some gnus-thread-sort-functions '((not gnus-thread-sort-by-number)) message-directory "~/etc/mail/" gnus-directory "~/etc/news/" gnus-treat-from-gravatar 'head gnus-treat-mail-gravatar 'head gnus-posting-styles '(("faumail.fau.de" (signature "Hochachtungsvoll\nPhilip K.") (address "philip.kaludercic@fau.de")) ("imap.fastmail.com" (signature "Sincerely\nPhilip K.") (address "philip@warpmail.net"))) epa-pinentry-mode 'loopback gnus-agent t gnus-agent-go-online t gnus-agent-consider-all-articles t gnus-use-full-window nil gnus-novice-user nil gnus-expert-user t) (add-hook 'gnus-select-article-hook 'gnus-agent-fetch-selected-article) :config (gnus-demon-add-disconnection) (gnus-demon-add-scanmail) :bind ("C-c n" . gnus))
My current mail setup is still a bit unstable, since I wrote in it less than a day, yet it seems to be working. It is set up to work equally well with my university-, as well as my personal address.
Since my .authsource is encrypted, I have to enter my password from
time to time to access my mail. This also requires
~/.gnupg/.gpg-agent.conf to contain the following two lines,
allow-emacs-pinentry allow-loopback-pinentry
so that "pintetry" is used for query my paraphrase.
SMTP
(setq message-send-mail-function 'message-send-mail-with-sendmail message-sendmail-extra-arguments '("--read-envelope-from") message-sendmail-f-is-evil t message-sendmail-envelope-from 'header message-kill-buffer-on-exit t sendmail-program (executable-find "msmtp"))
Instead of using Emacs' internal SMTP service, I use msmtp, simply
for the sake of speed. Additionally, this setup automatically
chooses what server to contact, based on the From: field.
(add-hook 'message-mode-hook 'turn-on-orgstruct++) (add-hook 'message-mode-hook 'turn-on-orgtbl)
Furthermore, orgstruct is enabled to help writing and structuring
emails similarly to org-mode buffers.
BBDB
(use-package bbdb :init (setq bbdb-mua-auto-update-p 'update bbdb-complete-mail-allow-cycling t bbdb-mua-pop-up nil bbdb-completion-display-record nil bbdb-file (expand-file-name "bbdb" user-emacs-directory) compose-mail-user-agent-warnings nil) :config (bbdb-initialize 'gnus 'message 'pgp) (bbdb-mua-auto-update-init 'message) (bbdb-mua-auto-update-init 'gnus 'message) (define-key message-mode-map (kbd "M-<tab>") 'bbdb-complete-mail) (add-hook 'gnus-startup-hook 'bbdb-insinuate-gnus) :after gnus)
Install and setup BBDB (Insidious Big Brother Database) for contact management, and enable completion in message buffers.
Ido
Basic
(use-package ido :config (setq ido-enable-tramp-completion t ido-create-new-buffer 'always ido-ignore-extensions t ido-auto-merge-work-directories-length -1 ido-max-dir-file-cache 0 ido-max-work-file-list 0 ido-max-prospects 8) :init (ido-mode t) (ido-everywhere t))
In spite of many suggestions to the contrary (or rather in support
of Helm), I use Ido to extend the default find-file,
switch-to-buffer, … commands. I didn't derive any read advantages
from Helm, and Ido did everything I had to.
Vertical
(use-package ido-vertical-mode :init (ido-vertical-mode t) :after ido)
Vertically displaying ido queries doesn't really change anything substantially, but instead just offers a nice visual feeling, and maybe a slightly cleaner overview.
Flexible search
(use-package flx-ido :disabled :init (flx-ido-mode t) :after ido)
To enable better easier input, flexible searching (ie. arbitrary
sub-sequences are ignored) is enabled after ido loads.
Smex
(use-package smex :config (setq smex-save-file (expand-file-name "smex-items" user-emacs-directory)) :bind (("M-x" . smex) ("M-X" . smex-major-mode-commands)) :after ido)
Smex doesn't do much more than adding Ido-support to the default
execute-extended-command (M-x) keybinding.
flyspell-mode
(setq-default flyspell-issue-welcome-flag nil
flyspell-issue-message-flag nil)
When writing prose, or just comments, flyspell-mode (and
flyspell-prog-mode) prove themselves to be valuable utilities,
albeit a bit slow and cumbersome from time to time…
woman-mode
(setq-default woman-manpath "/usr/share/man/" woman-use-topic-at-point t woman-use-extended-font t woman-use-own-frame nil)
woman-mode (w/o man) is a pure elisp alternative to man-mode and in
general, seems to produce a few better results, due to seemingly
being more easily configurable, as shown above.
calc
(setq-default calc-angle-mode 'rad
calc-shift-prefix t
calc-symbolic-mode t
calc-infinite-mode t
calc-vector-brackets nil
calc-vector-commas nil
calc-matrix-just 'right
calc-matrix-brackets '(R O)
calc-complex-format 'i)
I have grown fond of Emacs Calc, even though it might is be big
complicated to go beyond the basics. Most of these options have been
taken from the auto generated calc.el file.
LaTeX/AUCTeX
(use-package auctex :config (progn (add-hook 'LaTeX-mode-hook (lambda () (setq-local company-backends '((company-latex-commands company-math))) (flycheck-mode) (turn-on-reftex) (TeX-fold-mode))) (add-hook 'LaTeX-language-de-hook (lambda () (ispell-change-dictionary "de_DE"))) (add-hook 'TeX-after-compilation-finished-functions 'TeX-revert-document-buffer)) :init (setq TeX-view-program-selection '((output-pdf "PDF Tools")) TeX-source-correlate-start-server t LaTeX-electric-left-right-brace t TeX-auto-save t TeX-parse-self t TeX-master nil TeX-PDF-mode t reftex-plug-into-AUCTeX t reftex-enable-partial-scans t) :mode ("\\.tex\\'" . LaTeX-mode))
Partially rewritten LaTeX configuration.
(use-package cdlatex :init (add-hook 'LaTeX-mode-hook 'cdlatex-mode) :after auctex)
Additionally, CDLaTeX provides a more comfortable input and intuitive automation, where possible.
Org
(use-package org :demand t :init
The following configuration is wrapped in a use-package macro…
(setq org-hide-emphasis-markers t org-yank-adjusted-subtrees t org-completion-use-ido t org-startup-folded t org-highlight-latex-and-related '(latex) org-alphabetical-lists t org-export-date-timestamp-format "%x" org-support-shift-select t)
Basic stylistic and movment options (especially enabling using the shift key to mark a region).
(setq org-src-fontify-natively t
org-src-tab-acts-natively t
org-src-window-setup 'current-window)
Especially this document uses a lot of source blocks, so highlighting and indenting them appropriately is very convenient.
(setq org-directory (expand-file-name "~/doc/org/") org-agenda-files (list org-directory) org-agenda-include-diary t org-agenda-window-setup 'current-window org-default-notes-file (expand-file-name "notes.org" org-directory))
Within my documents directory (~/doc/) I have an org directory just
for org files, which I notify org-mode of. Furthermore, I inform Org
about my notes and agenda file.
(setq org-capture-templates '(("a" "Appointment" entry (file "pers.org") "* %^t %?\n") ("t" "Todo" entry (file "todo.org") "* TODO %?\n %T\n\n%i") ("c" "Comments" entry (file org-default-notes-file) "* %?\n ") ("l" "Link" entry (file org-default-notes-file) "* %?\n %a")))
Having special capture templates will probably help in getting used to using org-mode for taking notes.
(setq org-todo-keywords '((sequence "TODO(t)" "NEXT(n)" "DONE(d)")))
Since I don't require a complex TODO setup, I have chosen to keep the default keywords, as one often finds them recommended.
(setq org-html-head "<style>body{max-width:50em;text-align:justify;margin:2% auto;}</style>" org-latex-listings 'minted org-latex-pdf-process '("pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f" "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f" "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f") org-latex-packages-alist '(("" "microtype") ("" "babel") ("" "minted") ("" "lmodern")))
By default, exporting to LaTeX would produce visually unpleasing code. But by enabling minted, this issue is mitigated quite easily.
Furthermore, a few extra default packages are added, which I always enable.
(add-hook 'org-mode-hook
(lambda ()
(turn-on-auto-fill)
(flyspell-mode-off)
(flyspell-prog-mode)))
Since most of the text I write in org-mode is prose, auto-fill-mode
seems to show itself to be convenient. I no longer require myself
to use M-q after each sentence or even work. Instead I can focus
(or at least try to) on the actual text I am writing.
(setq org-clock-into-drawer t)
Configure org-mode clocking.
:bind (("C-c c" . org-capture) ("C-c a" . org-agenda) ("C-c l" . org-store-link) :map org-mode-map ("M-<tab>" . pcomplete))
Here I set a few convenient keybindings for globally interacting with my org ecosystem.
Also: Flyspell sadly shadows org's auto-complete functionality,
with an alternative I never use. When instead re-binding pcomplete,
one get's a lot more out of Org, without having to look up
everyhing in the manual.
:config (add-to-list 'org-structure-template-alist '("el" "#+BEGIN_SRC emacs-lisp\n?\n#+END_SRC" "<src lang=\"emacs-lisp\">\n\n</src>"))
Adding this code to org-structure-template-alist, makes it easier
to maintain files like these, since expands <E to a source block
with emacs-lisp automatically chosen as the language. Due to a
org-mode bug, this has to be evaluated after the document has been
loaded.
(setq org-latex-preview-ltxpng-directory "/tmp/ltxpng/") (plist-put 'org-format-latex-options :scale 1.25)
LaTeX previews can be a bit small and clutter the working directory, so the following options should migrate these issues.
:mode ("\\.org\\'" . org-mode))
Finally, defer interpretation until a .org file is found, and
close the use-package block.
Ledger
(use-package ledger-mode :init (setq ledger-source-directory (expand-file-name "~/doc/ledger") ledger-master-file (expand-file-name "master.lg" ledger-source-directory) ledger-highlight-xact-under-point nil) (add-hook 'ledger-mode-hook (lambda () (company-mode) (flyspell-mode-off))) :mode ("\\.lg\\'" . ledger-mode))
In an effort to use ledger, I have set up ledger-mode with some
sane defaults.
ERC
(use-package erc :commands erc :init (setq erc-join-buffer 'bury erc-server-coding-system '(utf-8 . utf-8) erc-kill-buffer-on-part t erc-kill-queries-on-quit t erc-rename-buffers t erc-interpret-mirc-color t erc-prompt-for-password nil erc-hide-list '("JOIN" "PART" "QUIT") erc-prompt "> " erc-nick '("zge" "zge_" "zge__")))
For IRC, I use ERC and connect to my bouncer server.
Ibuffer
(setq ibuffer-expert t ibuffer-saved-filter-groups `(("default") ("personal" ("emacs" (or (name . "^\\*scratch\\*$") (name . "^\\*Messages\\*$") (name . "^\\*Help\\*$") (name . "^\\*Completions\\*$") (filename . ,user-emacs-directory))) ("org" (mode . org-mode)) ("go" (filename . "code/go")) ("web" (filename . "code/web")) ("lisp" (filename . "code/lisp")) ("c" (filename . "code/c")) ("media" (or (mode . pdf-view-mode) (mode . image-mode))) ("dired" (mode . dired-mode)))))
Ibuffer has turned out to be quite a nifty alternative to
list-buffers. Not only does it support filter-groups, as presented
here, but buffers can be filtered by modes, content or miscellaneous
attributes. This presents itself as very helpful, when managing a
large amount (more than 100) of buffer.
The above snippet is based on an EmacsWiki example.
Google Translate
(use-package google-translate :init (setq google-translate-show-phonetic t google-translate-enable-ido-completion t google-translate-default-source-language "en" google-translate-default-target-language "de") :bind (("C-c t" . google-translate-at-point) ("C-c r" . google-translate-at-point-reverse) ("C-c T" . google-translate-query-translate) ("C-c R" . google-translate-query-translate-reverse)))
When translating or writing texts, this package shows itself to be quite helpful, when I can't thing of a word.
Programming
gnuplot
(use-package gnuplot :interpreter ("gnuplot" . gnuplot-mode) :mode ("\\.gp\\'" . gnuplot-mode))
gnuplot [sic] has been my go-to plotter for a few years now. Most of
the time I use it in it's REPL, but especially when working with
scripts, gnuplot-mode proves itself to be helpful.
Due to the wierd package name, and the fact that I use .gp as the
file extention for gnuplot files, as few things have to be
re-aliased for the mode to work properly.
SLIME
(use-package slime :config (setq inferior-lisp-program (executable-find "sbcl") slime-contribs '(slime-company slime-fancy)) :interpreter ("sbcl" . lisp-mode) :mode (("\\.lisp\\'" . lisp-mode) ("\\.cl\\'" . lisp-mode))) (use-package slime-company :config (slime-setup) :after slime)
Since Elisp and Common Lisp share a common ancestry in Maclisp and
Franzlisp (more so that Scheme), it should be worthwhile to learn
CL. Additionally, the cl library for Emacs seems to be quite popular
– and what better place to learn Common Lisp than in Emacs itself
with the popular SLIME (The Superior Lisp Interaction Mode for
Emacs) environment?
Unto Tree
(use-package undo-tree :diminish undo-tree-mode :init (add-hook 'prog-mode-hook 'undo-tree-mode) :config (setq undo-tree-visualizer-timestamps t undo-tree-visualizer-diff t))
Undo-tree offers the ability to visualize ones editing history as a
tree of changes, and to jump from one "branch" to another. I use it
in every programming mode, so I "diminish" the minor mode, since it
clutters up the mode line more than it has to.
multiple-cursors
(use-package multiple-cursors :bind (("C-c m t" . mc/mark-all-like-this) ("C-c m m" . mc/mark-all-like-this-dwim) ("C-<" . mc/mark-previous-like-this) ("C->" . mc/mark-next-like-this) ("C-c m l" . mc/edit-lines) ("C-S-n" . mc/mark-next-lines) ("C-S-p" . mc/mark-previous-lines) ("C-c m e" . mc/edit-ends-of-lines) ("C-c m a" . mc/edit-beginnings-of-lines)))
It doesn't take long to adjust to multiple-cursors-mode, and it is a
feature one turns out to use surprisingly often. While it's not as
native or quick, as in other editors (I'm thinking of vis), it's for
the most part entirely sufficient for my causes.
web-mode
(use-package web-mode :init (setq web-mode-engines-alist '(("go". "\\.gtl\\'")) web-mode-enable-engine-detection t web-mode-markup-indent-offset 4 web-mode-enable-auto-quoting t web-mode-enable-auto-closing t web-mode-enable-auto-expanding t web-mode-enable-auto-pairing nil) :mode (("\\.html\\'" . web-mode) ("\\.css\\'" . web-mode) ("\\.gtl\\'" . web-mode)))
I conciser web-mode an improvement upon html-mode in nearly all
aspects, which for the first time gave me a comfortable environment
to edit HTML and related code. I require no additional
configuration, besides informing Emacs about my preferences.
Geiser
(use-package geiser :init (setq geiser-repl-use-other-window nil geiser-active-implementations '(mit guile chicken chez mit)) (add-hook 'scheme-mode-hook 'geiser-mode) :mode ("\\.scm\\'" . scheme-mode))
When properly set up, geiser gives an MIT Scheme-like editing experience. It's not perfect, and it sometimes drags the whole editor down, but for the amount of Scheme programming I do it's entirely sufficient.
ace-jump-mode
(use-package ace-jump-mode :init (setq ace-jump-allow-invisible t) :diminish ace-jump-mode :bind (("C-c SPC" . ace-jump-mode)))
When rewriting my configuration, I took the time to reread a lot of
other Emacs configurations published online. One of the things I
often saw people use was ace-jump-mode – something I was conscious
that it existed, but never used myself.
ace-window
(use-package ace-window
:bind ("M-o" . ace-window))
For easy and quick window navigation, ace-window in installed and
bound to C-o (not the recommended default) without any further
configuration.
diff-hl
(use-package diff-hl
:config
(global-diff-hl-mode)
(add-hook 'dired-mode-hook 'diff-hl-dired-mode))
To display changes in version controlled files, diff-hl highlights
the parts of the file that have been changed.
GUD/GDB
(setq gdb-display-io-nopopup t)
Currently my only option is to disable a "dedicated" I/O buffer, when running a debugger.
Yasnipppets
(use-package yasnippet :init (add-hook 'prog-mode-hook 'yas-minor-mode) (setq yas-prompt-functions '(yas-dropdown-prompt yas-ido-prompt) yas-wrap-around-region t) :config (define-key yas-minor-mode-map (kbd "<tab>") (lambda () (interactive) (if (and (eq last-command 'self-insert-command) (not (nth 3 (syntax-ppss))) ; in string (not (nth 4 (syntax-ppss)))) ; in comment (yas-expand) (indent-for-tab-command)))))
While I have previously had problems with yasnippets, mainly due to
snippets expanding when I don't want them to, recent experience has
made me long for a snippet system again. The current system, could
work: on <tab> snippets are only expanded if the last command was
self-insert-command, i.e. user input. Otherwise, code will be
aligned.
(use-package yasnippet-snippets :after yasnippet)
Furthermore, make sure a few extra major modes as supported.
Projectile
(use-package projectile :diminish projectile-mode :init (projectile-mode t) :config (setq projectile-enable-caching t projectile-keymap-prefix (kbd "M-p") projectile-switch-project-action 'projectile-dired) :bind (("C-c v" . projectile-ag)))
While I for the most part dislike using global modes, it seems like the project management package projectile works best this way, hence it is set up to work globally.
Dumb Jump
(use-package dumb-jump
:init
(add-hook 'prog-mode-hook 'dumb-jump-mode))
In addition to projectile, and to avoid using TAGS files, dumb-jump
offers clean and simple say to navigate a project, and find places
where variables were declare and used.
Markdown
(use-package markdown-mode :init (setq markdown-italic-underscore t) (add-hook 'markdown-mode-hook 'turn-on-auto-fill))
Markdown is probably one of the most popular markup languages around
nowadays, and tools like Pandoc really bring out it's inner
potential (or rather create it in the first place). Markdown-mode
offers nice support for quite a few Pandoc features, so it's usually
my default choice when I have to work with medium to longer sized
documents.
For simple previews, I've set lowdown as my markdown processor, due
to it's speed (as compared to markdown.pl or Pandoc).
c-mode
(setq-default c-electric-flag t c-auto-newline nil c-delete-function 'backward-delete-char c-default-style "k&r" c-cleanup-list '(set-from-style empty-defun-braces defun-close-semi one-liner-defun brace-else-brace brace-elseif-brace) c-tab-always-indent t) (add-hook 'c-mode-hook 'zge/autoformat-on-save)
From what one can see, it is obvious that I still have to get around to properly set up my C editing environment.
Haskell
(use-package haskell-mode :init (setq haskell-process-show-debug-tips nil haskell-process-type 'ghci haskell-process-suggest-hoogle-imports t haskell-process-suggest-remove-import-lines t haskell-process-auto-import-loaded-modules t haskell-process-log t haskell-process-log t) (add-hook 'haskell-mode-hook (lambda () (haskell-doc-mode) (interactive-haskell-mode))) (add-hook 'haskell-interactive-mode-hook 'haskell-doc-mode) :mode "\\.hs\\'" :interpreter "ghci" :bind (:map haskell-mode-map ("C-," . haskell-move-nested-left) ("C-." . haskell-move-nested-right) ("C-c C-." . haskell-mode-format-imports) ("C-c C-l" . haskell-process-load-or-reload) ("C-c C-t" . haskell-process-do-type) ("C-c C-i" . haskell-process-do-info) ("C-c C-c" . haskell-process-cabal-build) ("C-c C-k" . haskell-interactive-mode-clear) ("C-c c" . haskell-process-cabal)))
Programming Haskell can be a very nice experience in Emacs, but as always, it has to be properly set up. The keybindings have been copied from here.
(use-package company-ghc :config (add-to-list 'company-backends 'company-ghc) :after haskell-mode)
For improved interaction, intelligent and informative auto completion is always appreciated.
Ediff
(setq ediff-window-setup-function 'ediff-setup-windows-multiframe)
When using Ediff, don't create a new window.
PDF-Tools
(use-package pdf-tools :config (pdf-tools-install) :mode ("\\.pdf\\'" . pdf-view-mode))
Adding PDF-Tools let's me use emacs properly for opening PDFs, making me less dependant on external tools and window managers.
go-mode
(use-package go-mode :init (add-hook 'go-mode-hook (lambda () (add-hook 'before-save-hook 'gofmt-before-save t t) (setq-local compile-command "go generate && go build -v && go test -v && go vet"))) :config (setenv "GOPATH" "/home/phi/code/go/") (setenv "PATH" (concat (getenv "PATH") ":/home/phi/code/go/bin")) :mode "\\.go\\'" :bind (:map go-mode-map ("M-." . godef-jump) ("C-c ." . godoc-at-point) ("C-c C-r" . go-remove-unused-imports))) (use-package company-go :after go-mode :config (add-to-list 'company-backends 'company-go)) (use-package go-eldoc :after go-mode :config (add-hook 'go-mode-hook 'go-eldoc-setup))
Go can be very fragile, but after having have set up the right files and installed the right extensions, my setup gives a fairly smooth editing experience.
Currently, the following packages are installed
company
(use-package company :config (setq company-begin-commands '() company-transformers '(company-sort-by-occurrence) company-tooltip-align-annotations t company-tooltip-minimum-width 30 company-echo-delay 0 company-idle-delay 0 company-minimum-prefix-length 2 company-tooltip-limit 20 company-selection-wrap-around t) :init (add-hook 'prog-mode-hook 'company-mode) :bind (:map company-mode-map ("M-<tab>" . company-complete)))
Generally speaking, I have had a better experiance with company as
compared to auto-complete-mode. The
magit
(use-package magit :init (setq magit-diff-options "-b --patience") :bind (("C-x g" . magit-status)))
Magit has been noted to be "a git wrapper that's better than git itself" (most definitely not sic), and from my experience, this is true, for the most part. Generally speaking, I do think it has a great user experience, and it uses Emacs potential far better than certain other modes. Another way to compliment it, would be to point out how minimal it's configuration needs to be (at least for me), without being in any sense annoying or otherwise inconvenient.
flycheck
(use-package flycheck :config (setq-default flycheck-disabled-checkers '(emacs-lisp-checkdoc)) :bind (("C-c <right>" . next-error) ("C-c <left>" . previous-error)))
Besides installing flycheck, also disable the Elisp warning regarding checkdoc warnings (first line must be so and so, last line must contain this and that, …).
Paredit
(use-package paredit :diminish paredit-mode :init (dolist (hook '(scheme-mode-hook lisp-mode-hook emacs-lisp-mode-hook)) (add-hook hook 'enable-paredit-mode)))
Paredit isn't easy to get used to, but after a while (and a few failed attempts) it becomes natural and one expects it. Furthermore, Smartparens is deactivated, in order to avoid conflicts between the two minor modes.
Rust
(use-package rust-mode :init (setq rust-format-on-save t) :mode "\\.rs\\'")
When playing around with Rust, having a Emacs mode installed is convenient.
(use-package cargo :after rust-mode :init (add-hook 'rust-mode-hook #'cargo-minor-mode)) (use-package racer :after rust-mode :init (add-hook 'rust-mode-hook #'racer-mode) (add-hook 'racer-mode-hook #'eldoc-mode))
Additionally, cargo and racer are lazily loaded, as soon as rust is required.
Javadoc
(use-package javadoc-lookup :init (require 'cc-mode) :bind (:map java-mode-map ("C-c C-j" . javadoc-lookup) ("C-c C-i" . javadoc-add-import)))
javadoc-lookup is a function I found far too late, and I find
terribly useful. Furthermore, I had modified the javadoc directory,
by copying it's content to /usr/local/doc/api, and removed the
unnecessary headers and footers.
Functions
All private functions and variables shall be prefixed with zge/.
Toggle dictionary
(defconst zge/dicts '("de" "en") "list of dictionaries") (defconst zge/input-alist '(("en" . nil) ("de" . "german-postfix"))) (defconst zge/dict-ring (let ((ring (make-ring (length zge/dicts)))) (mapc (lambda (l) (ring-insert ring l)) zge/dicts) ring) "ring of dictionary-codes") (defun zge/toggle-dictionary (&optional lang) "Toggle the Ispell dictionary from English to German and vice versa." (interactive) (let* ((next-dict (or lang (ring-remove zge/dict-ring))) (next-im (assoc next-dict zge/input-alist))) (ispell-change-dictionary next-dict) (ring-insert zge/dict-ring next-dict) (when (and next-im (or (derived-mode-p 'text-mode))) (set-input-method (cdr next-im)))) (save-excursion (flyspell-large-region (point-min) (point-max))))
Since I regularly have to switch between English and German, and I am
a horrible speller, having a quick function to toggle between just
the two (using flyspell-mode) had been very nice. Additionally, my
input method is changed based on zge/input-alist.
Toggle theme
(defconst zge/light-theme 'tango "constant holding my perfered light theme") (defconst zge/dark-theme 'tango-dark "constant holding my perfered light theme") (defvar zge/current-theme zge/dark-theme "variable holding my current theme") (defun zge/toggle-theme nil "Toggle the current theme from light to dark and vice versa" (interactive) (let* ((next-theme (if (eq zge/current-theme zge/light-theme) zge/dark-theme zge/light-theme))) (disable-theme zge/current-theme) (setf zge/current-theme next-theme) (load-theme next-theme t)))
Analogously to toggle-dictionary, this function is a quick way to
switch between the two variations of the theme I use (see
Appearance).
(load-theme zge/current-theme)
Finally, load the current theme, while Emacs is still starting.
Swap keybindings
(defun swap-keys (kb1 kb2 &optional map) "Swap the functions behind KB1 and KB2 in MAP" (interactive "kFirst key: \nkSecond key: ") (let* ((m (or map (current-global-map))) (f1 (lookup-key m kb1)) (f2 (lookup-key m kb2))) (define-key m kb1 f2) (define-key m kb2 f1)))
First mentioned here, to argue for elisp v.s. vim script, I don't need this function that often, nevertheless I keep in here, just in case.
Curl to buffer
(defun zge/curl (url) "Paste the content behind URL into a new buffer." (interactive "Murl: ") (let ((buf (get-buffer-create (file-name-base url)))) (shell-command (concat "curl --silent " url) buf) (with-current-buffer buf (set-auto-mode)) (switch-to-buffer buf)))
Sometimes I just want to easily view some code in emacs (eg. a raw github gist), and this functions just makes it easier.
Wicd configuration
(defvar wicd-curses "wicd-curses" "Name of the binary that `wicd' should call") (defun wicd nil "Start a terminal session to configure the WiFi connection" (interactive) (term (executable-find wicd-curses)))
If my device uses Wicd for networking, this auxiliary function makes it easier to set up connections.
Timestamp
(defun zge/add-timestamp (arg) "Prepend a UNIX timestamp to buffer, if it doesn't alreay exits. Force prepending timestamp when ARG is non-nil." (interactive "P") (save-excursion (goto-char (point-min)) (if arg (kill-line 2) (uncomment-region (line-beginning-position) (line-end-position))) (unless (and (string-match-p "^[[:digit:]]+$" (string-trim (thing-at-point 'line t))) (not arg)) (insert (format-time-string "%s")) (newline 2) (previous-line 2)) (comment-line 1)))
For my ad-hoc blog, I insert a UNIX timestamp
Autoformat on save
(defvar zge/dont-autoformat t "Prevent a buffer from formatting before saving") (defun zge/autoformat-on-save (&optional arg) "Mark the current paragraph and indent it." (interactive) (when (not zge/dont-autoformat) (save-excursion (if arg (progn (push-mark (point)) (push-mark (point-max) nil t) (goto-char (point-min))) (mark-paragraph)) (indent-region (point-min) (point-max)))))
Under some programming modes, it is convenient to have Emacs format
the buffer before saving it. If this function is added to the
before-save-hook (as is done in the [[%3Dc-mode%3D][c-mode]] section), Emacs will do
this.
In case the feature is not wished for, since the file is too big or
has a specific formatting, this can be disabled by locally setting
zge/dont-autoformat.
Global Keybindings
(dolist (bind '(("M-\"" . eshell) ("C-x p" . proced) ("<f5>" . zge/toggle-dictionary) ("<f6>" . zge/toggle-theme) ("<f7>" . toggle-truncate-lines) ("<f8>" . org-agenda-list) ("C-x M-k" . kill-buffer-and-window) ("C-c M-k" . recompile) ("C-x w" . man) ("C-x j" . jump-to-register) ("C-M-<backspace>" . delete-region) ("C-c f" . find-file-other-window) ("C-x x" . calendar))) (global-set-key (kbd (car bind)) (cdr bind)))
These are juts a few self-explanatory global, personal keybindings, I
find useful. All of this is done using the dolist macro, to keep
everything cleaner and easier to read.
(dolist (bind '(("C-x C-b" . ibuffer) ("C-z" . repeat) ("M-z" . ignore) ("M-l" . downcase-dwim) ("M-c" . capitalize-dwim) ("M-u" . upcase-dwim) ("M-SPC" . cycle-spacing) ("M-/" . hippie-expand))) (global-set-key (kbd (car bind)) (cdr bind)))
These on the other hand, overrride existing, default keybindings with
different (eg. C-z to repeat), or better (eg. M-SPC to cycle-spacing)
commands.
Hooks
Most of the mode specific hooks were already set up in the Packages and Other Configurations section, so this part only adds a few more general hooks, which apply to more than just one mode.
Programming
(add-hook 'prog-mode-hook
(lambda ()
(add-hook 'before-save-hook
'delete-trailing-whitespace t t)
(local-set-key (kbd "C-;") 'comment-dwim)
(local-set-key (kbd "RET") 'newline-and-indent)
(local-set-key (kbd "C-:") 'indent-region)
(local-set-key (kbd "C-c C-k") 'compile)
(local-set-key (kbd "C-c w") 'whitespace-mode)
(hs-minor-mode t)
(electric-indent-mode t)
(electric-pair-mode t)
(flycheck-mode t)
(flyspell-prog-mode)))
This lambda function is turned on for every programming mode, and specially enables a few keybindings I find useful only when programming.
Writing
(add-hook 'text-mode-hook 'turn-on-flyspell)
The only minor-mode I really use when writing text is flyspell. If I do need something else, I turn it on manually.
(add-hook 'text-mode 'abbrev-mode)
Currently experimental: use abbrev-mode when writing.