I started using Emacs in the fall of 2010 after a few years of Vim. I use GNU Emacs 25.1+ on Ubuntu for Org-Mode, Ruby, LaTeX, sh, and a host of miscellaneous other languages.
(load "server")
(unless (server-running-p) (server-start))
You can clone directly as $HOME/.emacs.d
:
git clone git://github.com/jmdeldin/.emacs.d.git ~/.emacs.d/
Key | Description |
---|---|
C-q TAB | Insert literal tab |
M-y | Traverse kill-ring (after C-y) |
C-u C-SPC | Jump to last mark |
M-n | (In cua-mode ) Increment digit |
C-M \ | Indent according to major mode |
C-c C-s | Start IRB |
C-c C-r | Send region to IRB (C-c C-s first) |
C-x v = | Diff against HEAD |
C-u C-x v = | Diff against other branch |
C-x v u | Discard changes |
C-x v ~ | Checkout another rev |
C-x v l | View commit log |
C-Shift BS | Kill whole line |
C-c ’ | Edit code block (org-babel) |
C-x r m | Bookmark the current loc in a file |
C-x r b | Jump to bookmark |
C-x r l | List bookmarks |
C-x C-n | Narrow region |
C-x C-w | Widen region |
C-x r w | Save window configuration |
C-x r j | Restore configuration |
M-& | Execute shell command asynchronously |
C-x r t | Removes the content in a rectangle (mark first) |
M-0 .. M-9 | Prefix argument |
M– M-c | Capitalize last word (M-dash for back) |
M-e | Forward sentence |
M-a | Backward sentence |
C-M-f | Move forward by a balanced expr (e.g., “,’, []) |
C-M-b | Move backward by a balanced expr |
M-m | back-to-indentation (^ in Vim) |
M-r | move the point w/o scrolling |
M-g M-g | goto-line |
M-o M-s | Center text |
C-x r N | Number lines |
Key | Description |
---|---|
M-p | previous search term |
M-n | next search term |
M-c | toggle case-sensitivity |
C-s C-w | search with the word at point (* inv Vim) |
These keys work inside the Ido minibuffer (C-x C-f).
Key | Description |
---|---|
C-d | Open a dired buffer in the current directory |
C-a | Toggles showing ignored files |
C-c | Toggles case-sensitivity |
C-s & C-r | Move to the next/prev match |
C-SPC | Restrict to an expr (C-x C-b .org C-SPC for just org) |
Function | Description |
---|---|
follow-mode | Browse splits like they’re one window |
ielm-mode | Elisp REPL |
hexl-mode | Hex viewer |
bury-buffer | Send buffer to end of list |
highlight-changes-mode | Show newly changed text in red |
info-apropos | full-text search of info |
Command | Decription |
---|---|
C-c C-n | next heading |
C-c C-p | previous heading |
C-c C-f | next heading (same level) |
C-c C-b | previous heading (same level) |
C-c C-u | back to a higher heading |
C-c / | Sparse tree |
M-S-RET | Insert new item with checkbox |
M-S-UP/DOWN | Move items including subitems up/down |
C-c - | Cycle list level through different bullets |
Command | Description |
---|---|
% u | uppercase filename |
% l | lowercase filename |
% R | regex rename |
;; dependency issue - these defuns should not bother with install crap
(load-file (concat user-emacs-directory "site-lisp/defuns.el"))
On clean installs, some packages will try to append custom vars to
init.el, breaking installation. The custom-file
must be set before
trying to install packages.
(setq custom-file (concat user-emacs-directory "local/emacs-custom.el"))
(load custom-file 'noerror)
(setq package-archives '(("gnu" . "https://elpa.gnu.org/packages/")
("melpa-stable" . "https://stable.melpa.org/packages/")
("melpa-unstable" . "https://melpa.org/packages/")))
We can declare the origin of our packages with the
package-pinned-packages
variable:
(setq package-pinned-packages '((use-package . "melpa-unstable")
(diminish . "melpa-unstable")))
(setq use-package-verbose t)
(setq jm/packages (mapcar 'car package-pinned-packages))
(jm/install-all-packages jm/packages)
(setq use-package-verbose t)
(eval-when-compile
(require 'use-package))
(require 'diminish)
(require 'bind-key)
(use-package tiny
:pin melpa-unstable
:ensure t
:defer t)
(use-package s
:pin melpa-stable
:ensure t
:defer t)
Only load the server if it isn’t running:
(load "server")
(unless (server-running-p)
(server-start))
This section is dedicated to all of the turd files Emacs leaves all over your machine.
Disable lockfiles – there’s only one user on this machine. This prevents guard from re-running specs everytime the file is edited (but not saved).
(setq create-lockfiles nil)
Place backups in ~/.emacs.d/local/backups
:
(setq backup-by-copying t)
(setq backup-directory-alist
(list (cons "." (jm/local-path "backups"))))
(setq delete-old-versions t)
(setq kept-new-versions 6)
(setq kept-old-versions 2)
(setq version-control t)
Keep auto-save files together. Test with M-x do-auto-save
.
(let ((new-dir (jm/local-path "auto-saves/")))
(setq auto-save-list-file-prefix new-dir)
(setq auto-save-file-name-transforms
`((".*" ,new-dir t))))
Use ~/.emacs.d/local/.emacs.bmk
for bookmarks:
(setq bookmark-default-file (jm/local-path "bookmarks"))
Prevent auto-joining #erc
(setq erc-autojoin-channels-alist '())
Spell-check ERC:
(with-eval-after-load 'erc
(erc-spelling-mode 1))
Ignore noise:
(setq erc-network-hide-list '("JOIN" "PART" "QUIT" "NICK" "MODE"))
(setq erc-track-exclude-server-buffer t)
Highlight nick:
(setq erc-current-nick-highlight-type 'nick)
;; Once =mu= is installed, run =mu init --my-address="foo@example.com"
;; --my-address="bar@example.com"= and =mu index=
;;
;; sudo apt install mu4e gnutls-bin
(use-package mu4e
:bind ("<f8>" . mu4e)
:init
(defun jm/email (user domain)
"Builds an email address to dodge some spam bot harvesting
for public config."
(combine-and-quote-strings (list user domain) "@"))
(defun jm/match-mu4e-context (email msg)
(when msg
(mu4e-message-contact-field-matches msg :to email)))
:config
(add-hook 'message-send-hook
(lambda ()
(unless (yes-or-no-p "Are you sure you want to send this?")
(signal 'quit nil))))
;; when viewing a message, hit `a V' to view message in browser
(add-to-list 'mu4e-view-actions
'("ViewInBrowser" . mu4e-action-view-in-browser) t)
(setq mu4e-get-mail-command "offlineimap")
(setq send-mail-function 'smtpmail-send-it)
(setq message-send-mail-function 'smtpmail-send-it)
;; enable inline images:
(setq mu4e-view-show-images t)
(when (fboundp 'imagemagick-register-types)
(imagemagick-register-types))
(setq mu4e-compose-dont-reply-to-self t)
(setq message-kill-buffer-on-exit t)
(setq mu4e-context-policy 'ask-if-none)
(setq mu4e-compose-context-policy 'ask-if-none)
;; the backquote is needed to evaluate the alist values
(setq mu4e-contexts `(
(make-mu4e-context
:name "Personal"
:match-func (lambda (msg)
(when msg
(string-prefix-p "/Personal" (mu4e-message-field msg :maildir))))
:vars `( (user-mail-address . ,(jm/email "jm" "deldin.us"))
(smtpmail-smtp-user . ,(jm/email "jm" "deldin.us"))
(smtpmail-smtp-server . "smtp.fastmail.com")
(smtpmail-smtp-service . 587)
(smtpmail-stream-type . starttls)
(mu4e-drafts-folder . "/Personal/Drafts")
(mu4e-sent-folder . "/Personal/Sent")
(mu4e-trash-folder . "/Personal/Trash")
)))))
Elfeed is a really nice RSS reader for Emacs that’s easy to use and fast.
(use-package elfeed
:pin melpa-unstable
:ensure t
:preface
(defun jm/elfeed ()
"Download feed updates before using elfeed."
(interactive)
(elfeed-update)
(elfeed))
:bind ("<f9>" . jm/elfeed)
:config
(setq elfeed-db-directory (concat user-emacs-directory "local/elfeed")))
(setq elfeed-feeds
'(
("http://nullprogram.com/feed/" emacs)
("http://planet.emacsen.org/atom.xml" emacs)
("http://sachachua.com/blog/feed/" emacs)
("https://www.masteringemacs.org/feed" emacs)
("https://www.matthewkirk.com/news?format=rss" friends)
("http://nelsonware.com/feed.xml" friends)
("https://goto10line.net/feed/" friends)
("https://www.lyonwj.com/atom.xml" friends)
("http://www.jmdeldin.com/atom.xml" personal)
("https://jvns.ca/atom.xml" programming)
("https://toolguyd.com/feed/" tools)
("https://slickdeals.net/newsearch.php?src=SearchBarV2&q=tools&searcharea=deals&searchin=first&rss=1" tools)
("https://slickdeals.net/newsearch.php?src=SearchBarV2&q=knipex&searcharea=deals&searchin=first&rss=1" tools)
("https://slickdeals.net/newsearch.php?src=SearchBarV2&q=eneloop&searcharea=deals&searchin=first&rss=1" tools)
("https://blog.lostartpress.com/feed/" woodworking)
("https://www.reddit.com/r/everett.xml" news)))
Default to 72 column width for plain text
(add-hook 'text-mode-hook
'(lambda ()
(set-fill-column 72)))
Match parens and quotes
(electric-pair-mode t)
Enable on-the-fly reindentation
(electric-indent-mode t)
Insert a newline around special characters
(electric-layout-mode t)
Use single spaces between sentences for fill-paragraph
(M-q
)
(setq sentence-end-double-space nil)
Use Unicode everywhere, as per Mastering Emacs’ post:
(set-language-environment "UTF-8")
(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(setq-default buffer-file-coding-system 'utf-8)
;; clipboard as UTF-8
(setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING))
Changing a region’s case is useful
(put 'upcase-region 'disabled nil)
(put 'downcase-region 'disabled nil)
Remember last edit position
(require 'saveplace)
(setq-default save-place t)
(setq save-place-file (jm/local-path "places"))
(use-package yasnippet
:pin melpa-stable
:ensure t
:config
(yas-global-mode t))
(use-package yasnippet-snippets
:pin melpa-stable
:ensure t)
(use-package auto-complete-config
:ensure auto-complete
:pin melpa-stable
:defer 2
:diminish auto-complete-mode
:config
(ac-config-default)
(ac-flyspell-workaround)
(setq ac-ignore-case nil)
(setq ac-comphist-file (jm/local-path "ac-comphist.dat")))
Use aspell
instead of ispell
, use list
for faster region checking, and
use a faster suggestion mode.
(setq ispell-program-name "aspell")
(setq ispell-list-command "list")
(setq ispell-extra-args '("--sug-mode=ultra"))
Turn it on for some modes:
(mapcar (lambda (mode)
(add-hook mode (lambda () (flyspell-mode t))))
'(org-mode-hook markdown-mode mu4e-compose-mode-hook text-mode))
(add-hook 'git-commit-mode-hook 'turn-on-flyspell)
Wrap lines at column 78
(setq-default fill-column 78)
Highlight right-margin when whitespace-mode is on
(setq whitespace-line-column fill-column)
Highlight empty lines
(setq-default indicate-empty-lines t)
Hard-wrap lines all the time
(add-hook 'text-mode-hook 'turn-on-auto-fill)
Use spaces, not tabs (C-q C-i to insert a hard-tab)
(setq-default indent-tabs-mode nil)
2-space tabs
(setq-default tab-width 2)
Insert tabs when appropriate
(setq indent-line-function 'insert-tab)
Insert a newline at the EOF
(setq-default require-final-newline t)
Delete trailing whitespace on save
(add-hook 'before-save-hook 'delete-trailing-whitespace)
(use-package highlight-indent-guides
:ensure t
:pin melpa-unstable
:config
(setq highlight-indent-guides-method 'fill)
(mapcar (lambda (hook) (add-hook hook 'highlight-indent-guides-mode))
'(prog-mode-hook yaml-mode-hook)))
Hide the {menu,tool,scroll}bars
(if window-system
(progn
(scroll-bar-mode -1)
(tool-bar-mode -1)))
(menu-bar-mode -1)
Hide the startup messages
(setq inhibit-startup-message t)
(setq inhibit-startup-echo-area-message t)
“y or n” instead of “yes or no”
(fset 'yes-or-no-p 'y-or-n-p)
Show line & column number in the mode line
(column-number-mode t)
Show file size
(size-indication-mode t)
Highlight parens
(show-paren-mode t)
(setq show-paren-delay 0.0)
Highlight current line
(global-hl-line-mode 1)
Use ibuffer
instead of list-buffers
(defalias 'list-buffers 'ibuffer)
No bells
(setq ring-bell-function 'ignore)
Restore window configuration with C-c LEFT
(winner-mode)
Enable windmove – default binding is shift
(windmove-default-keybindings)
(setq windmove-wrap-around t)
Make windmove work in org-mode:
(add-hook 'org-shiftup-final-hook 'windmove-up)
(add-hook 'org-shiftleft-final-hook 'windmove-left)
(add-hook 'org-shiftdown-final-hook 'windmove-down)
(add-hook 'org-shiftright-final-hook 'windmove-right)
Interactively-do-things is the greatest Emacs extension.
(setq ido-enable-flex-matching t)
(setq ido-everywhere t)
(setq ido-show-dot-for-dired t)
(setq ido-save-directory-list-file (jm/local-path "ido.last"))
(setq ido-use-virtual-buffers t)
(ido-mode 1)
Use part of the directory to distinguish between identically-named files:
(use-package uniquify
:config
(setq uniquify-buffer-name-style 'forward))
Save minibuffer history:
(savehist-mode 1)
(setq savehist-additional-variables '(kill-ring search-ring regexp-search-ring))
(setq savehist-file (jm/local-path "savehist"))
Enable recent files:
(use-package recentf
:defer 1
:config
(setq recentf-save-file (jm/local-path "recentf"))
(setq recentf-max-saved-items 1000)
(recentf-mode 1))
M-x
– ido-like completion for functions:
(use-package smex
:pin melpa-stable
:ensure t
:bind ("M-x" . smex)
:config
(setq smex-save-file (jm/local-path "smex-items")))
Enable mouse support in a terminal (from StackOverflow):
(unless window-system
(require 'mouse)
(xterm-mouse-mode t)
(global-set-key [mouse-4] '(lambda ()
(interactive)
(scroll-down 1)))
(global-set-key [mouse-5] '(lambda ()
(interactive)
(scroll-up 1)))
(defun track-mouse (e))
(setq mouse-sel-mode t))
Arguably the best Vim ever, but sometimes, I still want Emacs keys.
(use-package undo-tree
:ensure t
:init
(global-undo-tree-mode)
(setq undo-tree-history-directory-alist (list (cons "." (jm/local-path "backups")))))
(use-package evil
:pin melpa-unstable
:ensure t
:demand t
:diminish undo-tree-mode
:bind (
:map evil-insert-state-map
("C-a" . beginning-of-line)
("C-e" . end-of-line)
("C-d" . delete-forward-char)
("C-k" . kill-line)
("C-p" . evil-previous-line)
("C-p" . evil-previous-line)
("C-n" . evil-next-line)
("C-z" . suspend-emacs)
:map evil-normal-state-map
("C-n" . evil-next-line)
("C-p" . evil-previous-line)
("C-z" . suspend-emacs))
:config
;; disable evil in some buffers:
(mapc (lambda (mode) (evil-set-initial-state mode 'emacs))
'(elfeed-show-mode elfeed-search-mode Info-mode-hook ledger-report-mode))
(evil-set-undo-system 'undo-tree)
(evil-mode t))
;; Jump between tags with %
(use-package evil-matchit
:pin melpa-stable
:ensure t
:defer 1
:config (global-evil-matchit-mode t))
;; increment/decrement numbers like Vim (just not with C-a/C-x)
(use-package evil-numbers
:pin melpa-stable
:ensure t
:bind (("C-c +" . evil-numbers/inc-at-pt)
("C-c -" . evil-numbers/dec-at-pt)))
(use-package evil-surround
:pin melpa-stable
:ensure t
:defer 1
:config
(global-evil-surround-mode 1)
)
M-/
– use a more powerful expansion
(global-set-key (kbd "M-/") 'hippie-expand)
C-c C-r
– Revert buffer
(global-set-key (kbd "C-c C-r") 'revert-buffer)
Swap C-j
and RET
(global-set-key (kbd "RET") 'reindent-then-newline-and-indent)
(global-set-key (kbd "C-j") 'newline)
C-c C-d
– Remove trailing whitespace
(global-set-key (kbd "C-c C-d") 'delete-trailing-whitespace)
C-w
– delete the previous word (like most shells)
(global-set-key (kbd "C-w") 'backward-kill-word)
C-x C-k – kill region (since we just unbound it with C-w)
(global-set-key (kbd "C-x C-k") 'kill-region)
C-x C-j
– join line
(global-set-key (kbd "C-x C-j") 'join-line)
C-c w
– toggle whitespace mode
(global-set-key (kbd "C-c w") 'whitespace-mode)
better commenting (replaces the original comment-dwim)
(global-set-key (kbd "M-;") 'comment-or-uncomment-region)
C-x m
– recompile
(global-set-key (kbd "C-x m") 'recompile)
C-x x
– jm/shell
(global-set-key (kbd "C-x x") 'jm/shell)
M-#
– jm/reload-init
(global-set-key (kbd "M-#") 'jm/reload-init)
F12
– calculate and insert result in buffer
(global-set-key (kbd "<f12>") (lambda ()
(interactive)
(quick-calc t)))
M-s/M-S
– switch windows
(use-package ace-window
:bind (("M-s" . ace-window))
:ensure t
:pin melpa-stable)
Make the Cmd and Opt keys work for M-x
(when system-type "darwin"
(setq-default mac-command-modifier 'super)
(setq-default mac-option-modifier 'meta))
VC mode does not need to show more than the branch. The following code from Malabrba does just that:
(setcdr (assq 'vc-mode mode-line-format)
'((:eval (replace-regexp-in-string "^ Git" " " vc-mode))))
For dumb terminals:
(if (and (not window-system) (string= (getenv "TERM") "dumb"))
(progn
(set-face-background 'hl-line "#666")
(set-face-foreground 'hl-line "#fff")))
For GUIs:
(defvar jm/font-size
150
"Default font size. #pixels height * 10.")
(defun font/old-man ()
"Increase the font size of all buffers."
(interactive)
(font/default (+ 100 jm/font-size)))
(defun font/standing-desk ()
"Drop the font size down for my external monitor."
(interactive)
(font/default 110))
(defun font/default (size)
"Scale things back down. Optionally invoke with C-u SIZE to set
the global size. Remember that the font size is pixels*10, e.g.,
150 == 15 px."
(interactive "P")
(set-face-attribute 'default nil :height (if size size jm/font-size)))
(if (and window-system (eq system-type 'gnu/linux))
(let ((jm/font "Source Code Pro-13"))
(set-face-attribute 'default nil :font jm/font)
(set-frame-font jm/font)))
The only way to program.
(setq c-default-style "k&r")
Use four spaces for tabs.
(setq-default c-basic-offset 4)
Many-windows mode makes Emacs into a more traditional IDE for GDB. See
C-h f gdb
for details. NOTE: This doesn’t work on OS 10.8 (non-stop
mode isn’t supported).
(setq gdb-many-windows t)
(use-package cider
:pin melpa-stable
:ensure t
:mode ("\\.clj\\'" . clojure-mode))
Turn on rainbow-mode
for colored hex values
(use-package rainbow-mode
:pin gnu
:ensure t
:defer t
:init
(add-hook 'prog-mode-hook 'rainbow-mode))
Associate less and scss:
(associate-file-type '(".less" ".scss" ".sass") 'css-mode)
Prevent SCSS from compiling at save time:
(setq scss-compile-at-save nil)
Two spaces:
(setq css-indent-offset 2)
(use-package graphviz-dot-mode
:pin melpa-stable
:ensure t
:mode ("\\.gv\\'" "\\.dot\\'"))
(use-package go-mode
:pin melpa-stable
:ensure t
:mode "\\.go\\'")
2 space indent:
(setq js-indent-level 2)
(setq js2-basic-offset 2)
(setq js2-bounce-indent-p t)
Show errors immediately:
(setq flycheck-display-errors-delay 0)
(use-package json-mode
:pin melpa-stable
:ensure t
:mode (".babelrc" "\\.json\\'"))
(use-package rjsx-mode
:pin melpa-unstable
:ensure t
:mode (("\\.jsx" . rjsx-mode))
:bind (:map rjsx-mode-map ("<" . nil)))
Produce PDFs instead of DVIs
(setq TeX-PDF-mode t)
(define-key lisp-mode-shared-map (kbd "C-c e") 'eval-buffer)
; probably not needed with 25+ 4
(add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode)
(use-package markdown-mode
:pin melpa-stable
:ensure t
:mode ("\\.md\\'" "\\.markdown\\'"))
(use-package nginx-mode
:pin melpa-stable
:ensure t
:mode "nginx.conf")
Support editing mixed mode files, like ERB templates.
(use-package mmm-auto
:ensure mmm-mode
:pin melpa-stable
:mode ((".rhtml" . html-erb-mode)
(".html.erb" . html-erb-mode)
(".erb" . html-erb-mode))
:config
(setq mmm-global-mode 'auto)
(setq mmm-submode-decoration-level 2)
(setq mmm-parse-when-idle t))
(use-package org
:pin gnu
:ensure t
:mode ("\\.org" . org-mode)
:bind (
("C-c l" . org-store-link)
("C-c a" . org-agenda)
("C-c c" . org-capture)
("C-c b" . org-iswitchb)
("C-c C-x h" . org-html-export-to-html)
;; for terminals -- TAB does not work
("C-x t" . org-cycle))
:config
(org-babel-do-load-languages
'org-babel-load-languages (mapcar (lambda (l) (cons l t))
'(C calc emacs-lisp gnuplot latex ledger perl python ruby screen shell))))
;; for org-html export
(use-package htmlize
:pin melpa-stable
:ensure t
:defer t)
Include the org-habit module for the agenda:
(setq org-modules (quote (org-habit)))
Use Org-Mode for the *scratch*
buffer:
(setq initial-major-mode 'org-mode)
(setq initial-scratch-message nil)
This configuration assumes org files live in the ~/org
directory. You can
customize it by setting these variables in ../local/local.el
:
(setq org-directory "~/org")
(setq org-default-notes-file "~/org/capture.org")
(setq org-journal-file "~/org/journal.org.gpg")
(setq org-work-journal-file "~/org/work.org")
(setq org-log-file "~/org/log.org")
(setq org-notes-file "~/org/notes.org")
(setq org-archive-location "archive/%s_archive::")
(setq org-agenda-files (filter (lambda (fn)
(not (string-match (rx "#") fn)))
(file-expand-wildcards org-directory)))
Hit C-c c
to trigger these:
(defun jm/find-org-headline (&optional heading)
"Prompts for and finds a heading.
Adapted from URL `http://emacs.stackexchange.com/a/5931'."
(let* ((target (save-excursion
(org-refile-get-location heading nil t t)))
(file (nth 1 target))
(pos (nth 3 target)))
(with-current-buffer (find-file-noselect org-notes-file)
(goto-char pos)
(org-end-of-subtree)
(org-return))))
(setq org-capture-templates
'(("t" "TODO" entry (file+headline org-default-notes-file "Tasks")
"* TODO %^{Task} %^g \n%U \n%?")
("w" "Work Journal" entry (file+datetree org-work-journal-file)
"* %^{Title}\n%U \n%?\n")
("j" "Journal" entry (file+datetree org-journal-file)
"* %^{Title}\n%U \n%?\n")
("n" "Notes" entry (file+function org-notes-file jm/find-org-headline)
"* %^{Title}\n%U \n%?"
:empty-lines 1)
("d" "Appointment" entry (file+headline org-default-notes-file "Tasks")
"* TODO %^{Description} %^g\n%?\nSCHEDULED: %t\n%i\n%a")
("l" "Log" entry (file+datetree+prompt org-log-file)
"* %^{Task} %^g\n%?" :clock-in t :clock-resume t)
))
(define-skeleton orgmode-skeleton
"Inserts orgmode defaults into the current buffer."
"Title: "
"#+TITLE: " str | (file-name-nondirectory buffer-file-name) \n
"#+DESCRIPTION: " (skeleton-read "Description: ") \n
"#+STARTUP: align hidestars indent lognotedone" \n
\n _)
Highlight src blocks
(setq org-src-fontify-natively t)
(defun jm/org-confirm-babel-evaluate (lang body)
"Don't ask to confirm evaluating a ledger block."
(not (string= lang "ledger")))
(setq org-confirm-babel-evaluate 'jm/org-confirm-babel-evaluate)
Hide some holidays:
(setq holiday-bahai-holidays nil)
(setq holiday-hebrew-holidays nil)
(setq holiday-islamic-holidays nil)
Show the agenda from the current day:
(setq org-agenda-start-on-weekday nil)
Show all habits
(setq org-habit-show-habits-only-for-today nil)
Set the location for showing the sunrise/sunset in the agenda:
(setq calendar-latitude 47.9790)
(setq calendar-longitude -122.2021)
(setq calendar-location-name "Everett, WA")
Remove “Valid XHTML” link
(setq org-export-html-validation-link nil)
Minted latex export
(setq org-export-latex-minted-options
'(("fontsize" "\\scriptsize")))
Use the more modern cperl-mode
(defalias 'perl-mode 'cperl-mode)
Use cperl-mode
for .t
tests
(associate-file-type '(".t") 'cperl-mode)
Use four-space indents
(setq cperl-indent-level 4)
Indent only four-spaces in broken-up calls like
someCall(
$var,
$var2
)
(setq cperl-indent-parens-as-block t)
(setq cperl-close-paren-offset -4)
Fix indentation for lines not starting statements (e.g., hash members)
(setq cperl-continued-statement-offset 0)
(use-package plantuml-mode
:pin melpa-unstable
:ensure t
:mode ("\\.plantuml" . plantuml-mode)
:config
(setq plantuml-default-exec-mode 'jar)
(setq plantuml-jar-path "/usr/share/plantuml/plantuml.jar")
)
; default for Ruby 2+ is UTF-8, so no need for this anymore
(setq ruby-insert-encoding-magic-comment nil)
(use-package rspec-mode
:pin melpa-stable
:ensure t
:bind (:map ruby-mode-map ("C-c , x" . rspec-verify-single))
:config
(setq rspec-use-rake-when-possible nil)
(setq rspec-use-spring-when-possible t))
(use-package ruby-mode
:mode
("\\.rb\\'" "\\.rake\\'" "Capfile" "Gemfile" "Guardfile" "Rakefile" "\\.ru\\'")
:preface
(defun jm/run-ruby-buffer ()
"Run the current Ruby script and switch focus back to the script."
(interactive)
(ruby-compilation-this-buffer)
(other-window -1))
:bind (:map ruby-mode-map ("C-c C-c" . jm/run-ruby-buffer))
:interpreter "ruby"
:config
(rspec-mode t))
(use-package ruby-compilation
:pin melpa-stable
:ensure t
:defer t)
(use-package inf-ruby
:pin melpa-stable
:defer t
:ensure t
:init
;; for binding.pry to work
(add-hook 'after-init-hook 'inf-ruby-switch-setup))
(setq scheme-program-name "scheme")
(defun scheme-run-buffer ()
"Runs the current buffer through scheme and switches focus back to the script."
(interactive)
(scheme-send-region (point-min) (point-max)))
(add-hook 'scheme-mode-hook
(lambda ()
(local-set-key (kbd "C-c C-c") 'scheme-run-buffer)
(local-set-key (kbd "C-j") 'scheme-send-last-sexp)))
(use-package yaml-mode
:pin melpa-stable
:ensure t
:mode ("\\.yml\\'" "\\.yaml\\'")
:bind (:map yaml-mode-map ("C-m" . newline-and-indent)))
(use-package dockerfile-mode
:mode ("Dockerfile.*" ".*\\.docker'"))
There are far too many ways to configure which browser to use in emacs. xdg-open should be the default but alas, we need this:
(setq shr-external-browser 'browse-url-xdg-open)
(setq browse-url-browser-function 'browse-url-generic
browse-url-generic-program "sensible-browser")
Customize M-x display-time-world
:
(setq display-time-world-list
'(("America/Los_Angeles" "Seattle")
("America/Denver" "Cascade")
; coworkers:
("America/Chicago" "Ann Arbor")
("America/New_York" "New York")
("America/Sao_Paulo" "Brazil")
("America/Bogota" "Columbia")
("Asia/Karachi" "Karachi")
("Asia/Manila" "Manila")
("UTC" "UTC")))
Make it so hitting C
on a filename in a dired window defaults to the
other dired window:
(setq dired-dwim-target t)
(use-package avy
:init
(bind-key "M-S" 'avy-goto-char-2))
(use-package editorconfig
:pin melpa-stable
:ensure t
:config (editorconfig-mode t))
(use-package ledger-mode
:pin melpa-unstable
:ensure t
:defer t
:config
(define-skeleton monthly-interest-skeleton
"Inserts an interest accrued entry into ledger."
"" (insert (replace-regexp-in-string "-" "/" (org-read-date))) " * Monthly Interest Paid" \n
" Assets:"(skeleton-read "Account: ") " " (skeleton-read "Amount: ") \n
"Income:Interest:CapitalOne" \n
\n _)
(defun ledger-toggle-cleared ()
"Toggle --cleared flag on an open ledger report."
(interactive)
(setq ledger-report-cmd
(if (string-match-p "--cleared" ledger-report-cmd)
(replace-regexp-in-string "--cleared" "" ledger-report-cmd)
(replace-regexp-in-string "$" " --cleared" ledger-report-cmd)))
(ledger-report-redo))
(define-key ledger-report-mode-map (kbd "C-c C-c") 'ledger-toggle-cleared)
(defun jm/ledger-format ()
"Clean up a ledger buffer automatically."
(interactive)
(ledger-sort-buffer)
(ledger-post-align-postings (point-min) (point-max)))
;; for consistency with ledger-mode:
(define-key ledger-report-mode-map (kbd "C-c C-o C-r") 'ledger-report-select-report)
(setq ledger-reports
'(
("bal" "%(binary) -f %(ledger-file) bal")
("biz" "%(binary) -f %(ledger-file) bal Biz")
("biz-income" "%(binary) -f %(ledger-file) equity Revenue Biz:Receivable")
("cash" "%(binary) -f %(ledger-file) bal Assets:Checking Assets:Savings --cleared")
("cat" "%(binary) -f %(ledger-file) reg Assets:Reimbursements:Catherine --dc --cleared")
("cc-rewards" "%(binary) -f %(ledger-file) bal Income:Rebate --cleared")
("cc-spending" "%(binary) -f %(ledger-file) bal Liabilities:Credit -l 'amount < 0'")
("checking-cap1" "%(binary) -f %(ledger-file) reg Assets:Checking:CapitalOne --display 'd>=[last month]' --cleared")
("credit-cap1" "%(binary) -f %(ledger-file) reg Liabilities:Credit:CapitalOne --display 'd>=[last month]' --cleared")
("donations" "%(binary) -f %(ledger-file) bal Expenses:Donations Liabilities:Donations")
("exp-nonessential" "%(binary) -f %(ledger-file) bal Expenses:Entertainment Expenses:Sports Expenses:Travel Expenses:Woodworking")
("mortgage" "%(binary) -f %(ledger-file) bal Virtual:Home Assets:Home")
("net" "%(binary) -f %(ledger-file) bal Assets Liabilities --cleared")
("payee" "%(binary) -f %(ledger-file) reg @%(payee)")
("reg" "%(binary) -f %(ledger-file) reg")
("savings-goals" "%(binary) -f %(ledger-file) bal Virtual:Goals Assets:Savings:Buffer Assets:Savings:Emergency ")
("savings-emergency" "%(binary) -f %(ledger-file) reg Assets:Savings:Emergency --display 'd>=[last month]' --cleared")
("savings-buffer" "%(binary) -f %(ledger-file) reg Assets:Savings:Buffer --display 'd>=[last month]' --cleared")
("savings-taxes" "%(binary) -f %(ledger-file) reg Assets:Savings:Taxes --display 'd>=[last month]' --cleared")
("taxes" "%(binary) -f %(ledger-file) bal --cleared Liabilities:Taxes Savings:Taxes")
("uncleared" "%(binary) -f %(ledger-file) reg --uncleared")
("year-spending" "%(binary) -f %(ledger-file) --monthly --empty --collapse reg Expenses")
)))
Open man pages in a different window
(setq Man-notify-method 'friendly)
I tend to keep man pages pretty narrow
(setenv "MANWIDTH" "72")
(use-package magit
:pin melpa-stable
:ensure t
:bind (("C-x g" . magit-status)
("C-x G" . magit-blame-addition)))
(defun motd ()
"Inspirational quotes and such."
(interactive)
(let ((quotes '(("Victor Frankl" . "Between stimulus and response there is a space. In that space is our power to choose our response. In our response lies our growth and our freedom.")
("Steve Jobs" . "If today were the last day of my life, would I want to do what I am about to do today? And whenever the answer has been ``no'' for too many days in a row, I know I need to change something."))))
(let ((record (nth (random (length quotes)) quotes)))
(message "> %s\n> —%s" (cdr record) (car record)))))
Run the above every few hours:
(setq my-timer (run-with-idle-timer 14400 t 'motd))
Find files in a project:
(use-package projectile
:pin melpa-stable
:ensure t
:bind ("C-x p" . projectile-find-file)
:bind-keymap ("C-x P" . projectile-command-map)
:config
(projectile-mode t)
(setq projectile-enable-caching t)
(setq projectile-cache-file (jm/local-path "projectile-cache")))
(setq projectile-known-projects-file (jm/local-path "projectile-bookmarks.eld"))
Set $PAGER
to cat
to avoid WARNING: terminal is not fully
functional
messages.
(setenv "PAGER" "cat")
Ensure eshell garbage stays in ~/.emacs.d/local
:
(setq eshell-directory-name (concat user-emacs-directory "local/eshell"))
(use-package ag
:ensure t
:pin melpa-stable
:bind ("C-x a" . ag-project-regexp)
:config
(setq ag-highlight-search t))
Load local config to override any of the above settings
(load (jm/local-path "local") 'noerror)