Michael's Emacs Config
1 Preamble
This is my Emacs config, which is almost a single file thanks to org-babel.
Although GitHub does render .org
files nicely, I recommend viewing it in Emacs, as GitHub isn't fully compatible. Using org-mode gives a nice overview and makes it quick and easy to navigate and make changes.
2 Beginning config
2.1 Personal information
(setq user-full-name "Michael Englehorn") (setq user-mail-address "michael@englehorn.com")
3 Package related
Setup general package related settings.
3.1 package.el
Initialize package.el, the built-in package manager.
(package-initialize)
These are the package repositories I use:
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
3.2 use-package
Install/activate use-package, basically a wrapper for package.el
.
- makes installing and configuring other packages nicer and easier.
- helps with autoloading packages to greatly reduce initial startup time.
(unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package)) (require 'use-package) (setq use-package-always-ensure t)
3.3 Quelpa
(unless (package-installed-p 'quelpa) (with-temp-buffer (url-insert-file-contents "https://raw.githubusercontent.com/quelpa/quelpa/master/quelpa.el") (eval-buffer) (quelpa-self-upgrade))) ;; Install and load `quelpa-use-package'. (quelpa '(quelpa-use-package :fetcher git :url "https://github.com/quelpa/quelpa-use-package.git")) (require 'quelpa-use-package)
3.4 Emacs String Manipulation Library
This is required for some plugins.
(use-package s)
4 Appearance related
Setup appearance early so that if something goes wrong with the init, Emacs is still looking good.
4.1 Maximize Emacs on startup
This snippet works in *nix and all (relevant) versions of Windows.
(if (eq system-type 'windows-nt) (with-no-warnings (defun w32-maximize-frame () "Maximize the current frame (windows only)" (interactive) (w32-send-sys-command 61488)) (add-hook 'windows-setup-hook 'w32-maximize-frame t)) (set-frame-parameter nil 'fullscreen 'maximized))
4.2 Minimal GUI
Remove unnecessary GUI elements: menu-bar, tool-bar, and scroll-bar.
(if (fboundp 'menu-bar-mode) (menu-bar-mode -1)) (if (fboundp 'tool-bar-mode) (tool-bar-mode -1)) (if (fboundp 'scroll-bar-mode) (scroll-bar-mode -1))
4.3 No splash screen
I prefer loading up to the scratch buffer on initial startup.
(setq inhibit-splash-screen t)
4.4 Initial scratch buffer message
(setq initial-scratch-message "")
4.5 Theme
4.5.1 Hook make-frame
to detect if we're in a TTY or GUI
(load-theme 'wheatgrass t) (enable-theme 'wheatgrass)
4.6 RainbowDelimiters
Highlight matching delimiters with unique colors. It's virtually necessary with emacs-lisp.
(use-package rainbow-delimiters :commands (rainbow-delimiters-mode) :init (add-hook 'prog-mode-hook #'rainbow-delimiters-mode))
4.7 Highlight matching parenthesis
Specifically under the cursor
(defvar show-paren-delay) (setq show-paren-delay 0.0) (show-paren-mode t)
4.8 Highlight trailing whitespace
Trailing whitespace is really annoying, especially when pasting from certain terminals.
(defun my/buf-show-trailing-whitespace () (interactive) (setq show-trailing-whitespace t)) (add-hook 'prog-mode-hook 'my/buf-show-trailing-whitespace) (custom-set-faces '(trailing-whitespace ((t (:background "dim gray")))))
4.9 Prettify symbols
Convert certain words into symbols. Prime example: lambda
becomes λ
.
(global-prettify-symbols-mode)
4.10 Show column number in modeline
(column-number-mode t)
4.11 Prettify source code in org-mode
Org mode should have pretty highlighting for source code.
(setq org-src-fontify-natively t) (setq org-src-tab-acts-natively t) (setq org-edit-src-content-indentation 0) (use-package htmlize)
5 General settings
These settings don't belong to any specific mode or package. Some packages are exceptional for being very simple.
5.1 Optimize org-babel config for faster startup
Running org-babel-load-file
increases startup time, so only do it when there
are changes to update. Only run it when config.el
is missing, and delete
config.el
when config.org
changes. (see init.el)
(require 's) (defun my/delete-config-el () "Delete ~/.emacs.d/config.el when the current buffer is ~/.emacs.d/config.org" (defvar my-configel) (setq my-configel "~/git/menglehorn-linux-dotfiles/configs/emacs/config.el") (if (s-suffix? "emacs/config.org" buffer-file-name) (if (file-exists-p my-configel) (progn (delete-file "~/git/menglehorn-linux-dotfiles/configs/emacs/config.el") (delete-file "~/git/menglehorn-linux-dotfiles/configs/emacs/config.elc"))))) (add-hook 'after-save-hook 'my/delete-config-el)
5.2 Set up org-babel
We need to allow SH scripts to be executed by org-babel.
;(require 'ob-sh)
5.3 Start server if it isn't started
Turn the first Emacs process into a server, which allows reuse of a that process
through the shell command emacsclient
.
(require 'server) (if (not (server-running-p)) (server-start))
5.4 Backup & auto-save files in one place
These files are useful if something goes wrong, but they're also annoying in how
they clutter directories. Put them in ~/.emacs.d/tmp
to remedy this.
(setq backup-directory-alist `((".*" . "~/.emacs.d/tmp")) auto-save-file-name-transforms `((".*" , "~/.emacs.d/tmp" t)))
5.5 Scroll smoothly
(setq scroll-margin 0) (setq scroll-conservatively 10000) (setq scroll-preserve-screen-position t)
5.6 Sentences end with a single period
(setq sentence-end-double-space nil)
5.7 y/n instead of yes/no
(fset 'yes-or-no-p 'y-or-n-p)
5.8 Wrap text at 80 characters
(setq-default fill-column 80)
5.9 Auto-detect indent settings
I prefer to follow a file's indenting style instead of enforcing my own, if
possible. dtrt-indent
does this and works for most mainstream languages.
(use-package dtrt-indent)
5.10 Auto-update changed files
If a file is changed outside of Emacs, automatically load those changes.
(global-auto-revert-mode t)
5.11 Auto-executable scripts in *nix
When saving a file that starts with #!
, make it executable.
(add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p)
5.12 Enable HideShow in programming modes
Useful for getting an overview of the code. It works better in some languages and layouts than others.
(defun my/enable-hideshow () (interactive) (hs-minor-mode t)) (add-hook 'prog-mode-hook 'my/enable-hideshow)
5.13 Recent Files
Enable recentf-mode
and remember a lot of files.
(recentf-mode 1) (defvar recentf-max-saved-items) (setq recentf-max-saved-items 200)
5.14 Better same-name buffer distinction
When two buffers are open with the same name, this makes it easier to tell them apart.
(require 'uniquify) (setq uniquify-buffer-name-style 'forward)
5.15 Remember last position for reopened files
(if (version< emacs-version "25.0") (progn (require 'saveplace) (setq-default save-place t)) (save-place-mode 1))
5.16 Disable garbage collection in minibuffer
See this article for more info.
(defun my/minibuffer-setup-hook () (setq gc-cons-threshold most-positive-fixnum)) (defun my/minibuffer-exit-hook () (setq gc-cons-threshold 800000)) (add-hook 'minibuffer-setup-hook #'my/minibuffer-setup-hook) (add-hook 'minibuffer-exit-hook #'my/minibuffer-exit-hook)
5.17 Configure default web browser
I use Chrome as my default browser.
(defvar browse-url-generic-program) (if (eq system-type 'darwin) (setq browse-url-browser-function 'browse-url-generic browse-url-generic-program "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome")) (if (eq system-type 'gnu/linux) (setq browse-url-browser-function 'w3m-browse-url))
5.18 Use plink on windows
Windows doesn't have the ssh command.
(when (eq window-system 'w32) (setq tramp-default-method "plink"))
6 Install and Set Up packages
6.1 yaml-mode
(use-package yaml-mode :config (progn (require 'yaml-mode) (add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode))))
6.2 Ansible (ansible
) minor mode
Install the Ansible minor mode
(use-package ansible)
6.3 BBDB
Install the Big Brother Database
(use-package bbdb :config (bbdb-initialize 'gnus 'message)) (require 'bbdb)
6.4 request.el
This is an HTTP library for emacs.
(use-package request)
6.5 git
An Elisp API for programmatically using Git.
(use-package git)
6.6 el-get
I use this to grab arbitrary lisp from github.
(use-package el-get :init (require 'el-get) (add-to-list 'load-path "~/.emacs.d/el-get"))
6.7 ERC IRC Client
IRC Client for Emacs
(use-package erc-colorize) (use-package erc-crypt) (use-package erc-hl-nicks) (use-package erc-image) ;(use-package erc-social-graph) (use-package erc-youtube) ;(require 'tls) (make-variable-buffer-local 'erc-fill-column) (add-hook 'window-configuration-change-hook '(lambda () (save-excursion (walk-windows (lambda (w) (let ((buffer (window-buffer w))) (set-buffer buffer) (when (eq major-mode 'erc-mode) (setq erc-fill-column (- (window-width w) 2)))))))))
6.8 Magit
Easy Git management
(use-package magit) (use-package magit-popup)
6.9 Smex
Smart M-x for Emacs
(use-package smex :init (global-set-key (kbd "M-x") 'smex))
6.10 Git Commit Mode
Mode for Git Commits
(use-package git-commit)
6.11 JSON Formatter
Command to clean up and prettify json.
(use-package json-mode)
6.12 EMMS
Emacs Multimedia System
(use-package emms) (use-package emms-info-mediainfo) (require 'emms-setup) (emms-all) (emms-default-players) ;; After loaded ;(require 'emms-info-mediainfo) ;(add-to-list 'emms-info-functions 'emms-info-mediainfo) (require 'emms-info-metaflac) (add-to-list 'emms-info-functions 'emms-info-metaflac) (require 'emms-player-simple) (require 'emms-source-file) (require 'emms-source-playlist) (setq emms-source-file-default-directory "~/Music/")
6.13 w3m
Web browser for Emacs
(cond ((string-equal system-type "windows-nt") (progn )) ((string-equal system-type "gnu/linux") (progn (use-package w3m :ensure t :init (setenv "PATH" (concat (getenv "PATH") ":/usr/local/bin")) (setq exec-path (append exec-path '("/usr/local/bin"))) (autoload 'w3m-browse-url "w3m") (global-set-key "\C-xm" 'browse-url-at-point) (setq w3m-use-cookies t) (setq w3m-default-display-inline-images t)))))
6.14 multi-term
Multiple terminal manager for Emacs
(use-package multi-term :init (setq multi-term-program "/bin/bash")) (require 'multi-term)
6.15 web-mode
web-mode.el is an emacs major mode for editing web templates aka HTML files embedding parts (CSS/JavaScript) and blocks (pre rendered by client/server side engines).
(use-package web-mode :init (require 'web-mode) (add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.php\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.tpl\\.php\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.[agj]sp\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.as[cp]x\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.mustache\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode)))
6.16 exec-path-from-shell
This is used to grab envirtonment variables from the shell.
(use-package exec-path-from-shell) (require 'exec-path-from-shell)
6.17 Company-mode
Company is a text completion framework for Emacs. The name stands for "complete anything". It uses pluggable back-ends and front-ends to retrieve and display completion candidates.
(use-package company :init (add-hook 'after-init-hook 'global-company-mode))
6.18 govc
VMware Integration
A VMware integration script
(use-package govc)
6.19 helm-spotify-plus
I enjoy listening to spotify, bonus points for emacs integration.
(use-package helm-spotify-plus :init (global-set-key (kbd "C-c s s") 'helm-spotify-plus))
6.20 helm-bbdb
Using helm to access and use the BBDB is nice too.
(use-package helm-bbdb :init (global-set-key (kbd "C-c s b") 'helm-bbdb))
6.21 helm-pass
Pass is pretty nice password manager
(use-package helm-pass :init (global-set-key (kbd "C-c s p") 'helm-pass))
6.22 helm-emms
This package makes using emms super easy!
(use-package helm-emms :init (global-set-key (kbd "C-c s e") 'helm-emms))
6.23 vagrant
(use-package vagrant)
6.24 Golang
All the packages associated with golang.
(use-package go-mode) (use-package go-stacktracer) (use-package go-complete) (use-package go-eldoc)
6.25 markdown-mode
Package for editing markdown.
(use-package markdown-mode :ensure t :commands (markdown-mode gfm-mode) :mode (("README\\.md\\'" . gfm-mode) ("\\.md\\'" . markdown-mode) ("\\.markdown\\'" . markdown-mode)) :init (setq markdown-command "multimarkdown"))
6.26 blockdiag-mode
I need blockdiag-mode for ob-blockdiag
(use-package blockdiag-mode)
6.27 cmake-mode
Provides syntax highlighting and indentation for CMakeLists.txt and *.cmake source files.
(use-package cmake-mode)
6.28 Rust cargo
(use-package cargo-mode)
6.29 Rust rustic
(use-package rustic :config (setq rustic-format-on-save t) (setq rustic-lsp-server 'rls))
6.30 Matrix client
;; Install `plz' HTTP library (not on MELPA yet). (use-package plz :quelpa (plz :fetcher github :repo "alphapapa/plz.el")) ;; Install Ement. (use-package ement :quelpa (ement :fetcher github :repo "alphapapa/ement.el")) (setq ement-save-sessions 't) (setq ement-sessions-file "~/.emacs.d/ement-sessions.el") ;(ement-connect :uri-prefix "http://localhost:8008")
7 Org-mode
7.1 Install org-mode
(use-package org) (require 'org)
7.2 Todo Keywords
Here are my TODO
states and color settings.
(setq org-todo-keywords (quote ((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)") (sequence "WAITING(W@/!)" "HOLD(h@/!)" "|" "CANCELLED(c@/!)" "PHONE" "MEETING" "EVENT")))) (setq org-todo-keyword-faces (quote (("TODO" :foreground "red" :weight bold) ("NEXT" :foreground "blue" :weight bold) ("DONE" :foreground "forest green" :weight bold) ("WAITING" :foreground "orange" :weight bold) ("HOLD" :foreground "magenta" :weight bold) ("CANCELLED" :foreground "forest green" :weight bold) ("MEETING" :foreground "forest green" :weight bold) ("PHONE" :foreground "forest green" :weight bold) ("EVENT" :foreground "goldenrod" :weight bold))))
7.3 Todo Selection
(setq org-use-fast-todo-selection t)
Changing a task state is done with C-c C-t KEY
7.4 Todo State Triggers
Trigger breakdown
- Moving a task to
CANCELLED
adds aCANCELLED
tag - Moving a task to
WAITING
adds aWAITING
tag - Moving a task to
HOLD
addsWAITING
andHOLD
tags - Moving a task to a done state removes
WAITING
andHOLD
tags - Moving a task to
TODO
removesWAITING
,CANCELLED
, andHOLD
tags - Moving a task to
NEXT
removesWAITING
,CANCELLED
, andHOLD
tags - Moving a task to
DONE
removesWAITING
,CANCELLED
, andHOLD
tags
(setq org-todo-state-tags-triggers (quote (("CANCELLED" ("CANCELLED" . t)) ("WAITING" ("WAITING" . t)) ("HOLD" ("WAITING") ("HOLD" . t)) (done ("WAITING") ("HOLD")) ("TODO" ("WAITING") ("CANCELLED") ("HOLD")) ("NEXT" ("WAITING") ("CANCELLED") ("HOLD")) ("DONE" ("WAITING") ("CANCELLED") ("HOLD")))))
7.5 Remove empty LOGBOOK
drawers
;; Remove empty LOGBOOK drawers on clock out (defun bh/remove-empty-drawer-on-clock-out () (interactive) (save-excursion (beginning-of-line 0) (org-remove-empty-drawer-at "LOGBOOK" (point)))) (add-hook 'org-clock-out-hook 'bh/remove-empty-drawer-on-clock-out 'append)
7.6 Refile captured
Any file in org-agenda-files
are valid refile targets.
; Targets include any file contributing to the agenda - up to 9 levels deep (setq org-refile-targets (quote ((org-agenda-files :maxlevel . 9)))) ; Use full outline paths for refile targets - we file directly with IDO (setq org-refile-use-outline-path t) ; Targets complete directly with IDO (setq org-outline-path-complete-in-steps nil) ; Allow refile to create parent tasks with confirmation (setq org-refile-allow-creating-parent-nodes (quote confirm)) ;;;; Refile settings ; Exclude DONE state tasks from refile targets (defun bh/verify-refile-target () "Exclude todo keywords with a done state from refile targets" (not (member (nth 2 (org-heading-components)) org-done-keywords))) (setq org-refile-target-verify-function 'bh/verify-refile-target)
7.7 Org-bullets
I don't see a reason why you wouldn't want this.
(use-package org-bullets :commands (org-bullets-mode) :init (setq org-bullets-bullet-list '("●")) (add-hook 'org-mode-hook 'org-bullets-mode))
7.8 Set up notes and todos
Org-mode
is great for project management, and I use it quite a bit for that.
(setq org-default-notes-file "~/Nextcloud/org-mode/personal.org") (setq org-agenda-files '("~/Nextcloud/org-mode/personal.org" "~/Nextcloud/org-mode/jblc.org")) ;; Org-Mode Capture Templates (defvar org-capture-templates) (setq org-capture-templates '(("w" "Work") ("wt" "Todo" entry (file+headline "~/Nextcloud/org-mode/jblc.org" "Tasks") "* TODO %?\n%U\n%a\n" :clock-in nil :clock-resume nil) ("wr" "Respond" entry (file "~/Nextcloud/org-mode/jblc.org") "* NEXT Respond to %:from %:subject\nSCHEDULED: %t\n%U\n%a\n" :clock-in t :clock-resume t :immediate-finish t) ("wj" "Journal" entry (file+datetree "~/Nextcloud/org-mode/jblc.org") "* %? %?\n%U\n" :clock-in t :clock-resume t) ("wm" "Meeting" entry (file "~/Nextcloud/org-mode/jblc.org") "* MEETING with %? :MEETING:\n%U" :clock-in t :clock-resume t) ("wp" "Phone call" entry (file "~/Nextcloud/org-mode/jblc.org") "* PHONE %? :PHONE:\n%U" :clock-in t :clock-resume t) ("p" "Personal") ("pt" "Todo" entry (file+headline "~/Nextcloud/org-mode/personal.org" "Tasks") "* TODO %?\n%U\n%a\n" :clock-in nil :clock-resume nil) ("pr" "Respond" entry (file "~/Nextcloud/org-mode/personal.org") "* NEXT Respond to %:from %:subject\nSCHEDULED: %t\n%U\n%a\n" :clock-in t :clock-resume t :immediate-finish t) ("pj" "Journal" entry (file+datetree "~/Nextcloud/org-mode/personal.org") "* %? %?\n%U\n" :clock-in t :clock-resume t) ("pm" "Meeting" entry (file "~/Nextcloud/org-mode/personal.org") "* MEETING with %? :MEETING:\n%U" :clock-in t :clock-resume t) ("pp" "Phone call" entry (file "~/Nextcloud/org-mode/personal.org") "* PHONE %? :PHONE:\n%U" :clock-in t :clock-resume t))) (global-set-key (kbd "C-c c") 'org-capture) (global-set-key (kbd "C-c a") 'org-agenda) (global-set-key (kbd "C-c l") 'org-store-link) (setq org-log-done 'time)
7.9 ox-twbs
Twitter Bootstrap
or just Bootstrap
is prettier than out of the box Org-mode
.
Let's get it installed!
(use-package ox-twbs)
7.10 ox-latex
ox-latex
allows syntax highlighted output. Just make sure to run the following code.
sudo pip install pygments
And set up ox-latex
(require 'ox-latex) (add-to-list 'org-latex-packages-alist '("" "minted")) (add-to-list 'org-latex-packages-alist '("" "tabularx")) (setq org-latex-minted-options '(("breaklines" "true") ("breakanywhere" "true"))) (setq org-latex-listings 'minted) (setq org-latex-pdf-process '("xelatex -shell-escape -interaction nonstopmode -output-directory %o %f"))
7.11 ox-mediawiki
ox-mediawiki
allows exporting org-mode documents to Mediawiki
(use-package ox-mediawiki :init (require 'ox-mediawiki))
7.12 ox-gfm
ox-gfm
allows exporting org-mode documents to GitHub Markdown
(use-package ox-gfm :init (require 'ox-gfm))
7.13 ob-dot
Let's set up capacity to create pretty diagrams
(require 'ob-dot)
7.14 ob-ledger
Org Babel Ledger Blocks!
(use-package ob-ledger :quelpa (ob-ledger :fetcher url :url "https://git.sr.ht/~bzg/org-contrib/blob/master/lisp/ob-ledger.el")) (require 'ob-ledger)
7.15 ob-sql
ob-sql
allows me to add MySQL queries to org-mode and execute them.
(use-package sql :init (require 'sql)) (require 'ob-sql)
7.16 ob-blockdiag
Create diagrams in org-mode.
(use-package ob-blockdiag :init (require 'ob-blockdiag))
7.17 ob-http
Perform HTTP requests in org-mode source blocks.
(use-package ob-http :init (require 'ob-http))
7.18 ob-restclient
Perform REST operations in org-mode source blocks.
(use-package ob-restclient :init (require 'ob-restclient))
7.19 Disable org-confirm-babel-evaluate
for some code types
dot
(defun my-org-confirm-babel-evaluate (lang body) (not (member lang '("dot")))) ;don't ask for dot (setq org-confirm-babel-evaluate #'my-org-confirm-babel-evaluate)
7.20 org-publish
I have a website to publish!
(setq org-publish-project-alist '( ("org-notes" :base-directory "~/Nextcloud/org/" :base-extension "org" :publishing-directory "/ssh:michael@websites01.lan.productionservers.net:/mnt/sites/michael.englehorn.com/public_html/" :recursive t :publishing-function org-twbs-publish-to-html :headline-levels 4 :auto-preamble t) ("org-static" :base-directory "~/Nextcloud/org/" :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf\\|php\\|txt\\|asc" :publishing-directory "/ssh:michael@websites01.lan.productionservers.net:/mnt/sites/michael.englehorn.com/public_html/" :recursive t :publishing-function org-publish-attachment) ("org" :components ("org-notes" "org-static")))) (require 's) (defun my/publish-work () "Publish ~/Nextcloud/org-mode/work/ whenever work.org is saved." (if (equal "~/Nextcloud/org-mode/work/work.org" buffer-file-truename) (progn (setq org-confirm-babel-evaluate nil) (setq org-export-use-babel t) (org-publish "org-work") (org-publish "org-work-static") (setq org-confirm-babel-evaluate t)))) (add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook 'my/publish-work nil nil)))
8 Customizations
8.1 Load SSH Agent from environment
(when (not (eq window-system 'w32)) (exec-path-from-shell-copy-env "SSH_AGENT_PID") (exec-path-from-shell-copy-env "PATH") (exec-path-from-shell-copy-env "SSH_AUTH_SOCK"))
8.2 Powerline
Initialize the Powerline.
(require 'powerline)
8.3 Powerline theme
Set up the powerline theme
(powerline-default-theme)
8.4 Load secrets
I keep slightly more sensitive information in a separate file so that I can easily publish my main configuration.
(el-get-bundle menglehorn-emacs-secret :url "git@gitlab.com:K0HAX/menglehorn-emacs-secret.git" :feature "menglehorn-emacs-secret" :submodule nil (load-file "~/.emacs.d/el-get/menglehorn-emacs-secret/menglehorn-emacs-secret.el"))
8.5 Restart Emacs
It's useful to be able to restart emacs from inside emacs. Configure restart-emacs to allow this.
(use-package restart-emacs)
8.6 Ledger Reports
Some custom and shorter keywords for ledger reports (C-r r in ledger-mode)
(setq ledger-reports (quote (("register" "ledger ") ("bal" "ledger -f %(ledger-file) --price-db ./prices.db -V bal Assets Liabilities") ("bigbal" "ledger -f %(ledger-file) bal Assets Liabilities") ("reg" "ledger -f %(ledger-file) reg") ("payee" "ledger -f %(ledger-file) reg @%(payee)") ("account" "ledger -f %(ledger-file) reg %(account)"))))
8.7 Newsticker List
Set up RSS feeds
(setq newsticker-url-list-defaults (quote (("NY Times" "http://partners.userland.com/nytRss/nytHomepage.xml") ("The Register" "http://www.theregister.co.uk/tonys/slashdot.rdf") ("slashdot" "http://slashdot.org/index.rss" nil 3600))))
8.8 Mail Processing
Set up the mail sending function
(setq send-mail-function 'smtpmail-send-it)
8.9 Customizations file
Move the customizations file out from init.el so we don't break the Git repo.
(setq custom-file "~/.emacs.d/emacs-custom.el") (load custom-file)
8.10 Disable blinking and flashing
Disable the annoying bell
(setq ring-bell-function 'ignore)
8.11 M-s s to SSH to a host.
I wanted to by able to easily SSH from Emacs, so I wrote some elisp.
(defun ssh-to-host (x) "Ask for host." (interactive "sHost: ") (let* ((buffer-name (format "*SSH %s*" x)) (buffer (get-buffer buffer-name))) (if buffer (switch-to-buffer buffer) (multi-term) (term-send-string (get-buffer-process (rename-buffer buffer-name)) (format "ssh %s\r" x))))) (global-set-key (kbd "M-s s") 'ssh-to-host)
8.12 Ask to open as root if I lack permission to edit
Very useful. If I try to open a file I don't have write permissions to, ask if I want to open it as root using tramp.
Note: if you're experiencing problems using this (like tramp hanging), check that you can open them "manually" in the first place, C-x C-f /sudo::/path/to/file. Check the tramp troubleshooting section at emacs wiki.
(defun th-rename-tramp-buffer () (when (file-remote-p (buffer-file-name)) (rename-buffer (format "%s:%s" (file-remote-p (buffer-file-name) 'method) (buffer-name))))) (add-hook 'find-file-hook 'th-rename-tramp-buffer) (defadvice find-file (around th-find-file activate) "Open FILENAME using tramp's sudo method if it's read-only." (if (and (not (file-writable-p (ad-get-arg 0))) (not (file-remote-p default-directory)) (y-or-n-p (concat "File " (ad-get-arg 0) " is read-only. Open it as root? "))) (th-find-file-sudo (ad-get-arg 0)) ad-do-it)) (defun th-find-file-sudo (file) "Opens FILE with root privileges." (interactive "F") (set-buffer (find-file (concat "/sudo::" file))))
8.13 Dired customizations
- Human readable sizes in Dired
- Sort by size
(setq dired-listing-switches "-alh")
8.14 Key bindings
Set up custom global key bindings.
(global-set-key (kbd "<f12>") 'org-agenda) (global-set-key (kbd "<f8>") 'org-cycle-agenda-files) (global-set-key (kbd "<f9> b") 'bbdb) (global-set-key (kbd "<f9> c") 'my-open-calendar) (global-set-key (kbd "<f9> g") 'gnus) (global-set-key (kbd "<f11>") 'org-clock-goto) (global-set-key (kbd "C-c c") 'org-capture)
8.15 Cisco Router Mode
;;; cisco-router-mode.el --- Major mode for editing Cisco router configuration files ;; ;; Copyright (C) 2022 Michael Englehorn <michael at englehorn stop com> ;; Copyright (C) 2004 Noufal Ibrahim <nkv at hcoop period net> ;; ;; This program is not part of Gnu Emacs ;; ;; cisco-router-mode.el is free software; you can ;; redistribute it and/or modify it under the terms of the GNU General ;; Public License as published by the Free Software Foundation; either ;; version 2 of the License, or (at your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. (defgroup cisco-router nil "Cisco Router Mode" :group 'text) (defcustom cisco-router-mode-hook nil "Hook called by \"cisco-router-mode\"" :type 'hook :group 'cisco-router) (defcustom cisco-router-mode-map (let ((cisco-router-mode-map (make-keymap))) (define-key cisco-router-mode-map "\C-j" 'newline-and-indent) cisco-router-mode-map) "Keymap for Cisco router configuration major mode" :group 'cisco-router) ;; Font locking definitions. (defcustom cisco-router-command-face 'cisco-router-command-face "Face for basic router commands" :group 'cisco-router) (defcustom cisco-router-toplevel-face 'cisco-router-toplevel-face "Face for top level commands" :group 'cisco-router) (defcustom cisco-router-no-face 'cisco-router-no-face "Face for \"no\"" :group 'cisco-router) (defcustom cisco-router-ipadd-face 'cisco-router-ipadd-face "Face for IP addresses" :group 'cisco-router) ;; End Font locking definitions. (defface cisco-router-ipadd-face '( (((type tty) (class color)) (:foreground "yellow")) (((type graphic) (class color)) (:foreground "LightGoldenrod")) (t (:foreground "LightGoldenrod" )) ) "Face for IP addresses") (defface cisco-router-command-face '( (((type tty) (class color)) (:foreground "cyan")) (((type graphic) (class color)) (:foreground "cyan")) (t (:foreground "cyan" )) ) "Face for basic router commands") (defface cisco-router-toplevel-face '( (((type tty) (class color)) (:foreground "blue")) (((type graphic) (class color)) (:foreground "lightsteelblue")) (t (:foreground "lightsteelblue" )) ) "Face for basic router commands") (defface cisco-router-no-face '( (t (:underline t)) ) "Face for \"no\"") ;; (regexp-opt '("interface" "ip vrf" "controller" "class-map" "redundancy" "line" "policy-map" "router" "access-list" "route-map") t) ;; (regexp-opt '("diagnostic" "hostname" "logging" "service" "alias" "snmp-server" "boot" "card" "vtp" "version" "enable") t) (defconst cisco-router-font-lock-keywords (list '( "\\<\\(access-list\\|c\\(?:lass-map\\|ontroller\\)\\|i\\(?:nterface\\|p vrf\\)\\|line\\|policy-map\\|r\\(?:edundancy\\|oute\\(?:-map\\|r\\)\\)\\)\\>". cisco-router-toplevel-face) '( "\\<\\(alias\\|boot\\|card\\|diagnostic\\|^enable\\|hostname\\|logging\\|s\\(?:ervice\\|nmp-server\\)\\|v\\(?:ersion\\|tp\\)\\)\\>" . cisco-router-command-face) '("\\<\\(no\\)\\>" . cisco-router-no-face) '("\\<\\([0-9]\\{1,3\\}\\.[0-9]\\{1,3\\}\\.[0-9]\\{1,3\\}\\.[0-9]\\{1,3\\}\\)\\>" . cisco-router-ipadd-face) ) "Font locking definitions for cisco router mode") ;; Imenu definitions. (defcustom cisco-router-imenu-expression '( ("Interfaces" "^[\t ]*interface *\\(.*\\)" 1) ("VRFs" "^ip vrf *\\(.*\\)" 1) ("Controllers" "^[\t ]*controller *\\(.*\\)" 1) ("Routing protocols" "^router *\\(.*\\)" 1) ("Class maps" "^class-map *\\(.*\\)" 1) ("Policy maps" "^policy-map *\\(.*\\)" 1) ) "Cisco Router imenu Expression" :group 'cisco-router) ;; Indentation definitions. (defun cisco-router-indent-line () "Indent current line as cisco router config line" (let ((indent0 "^interface\\|redundancy\\|^line\\|^ip vrf \\|^controller\\|^class-map\\|^policy-map\\|router\\|access-list\\|route-map") (indent1 " *main-cpu\\| *class\\W")) (beginning-of-line) (let ((not-indented t) (cur-indent 0)) (cond ((or (bobp) (looking-at indent0) (looking-at "!")) ; Handles the indent0 and indent1 lines ; (message "Indent0") (setq not-indented nil cur-indent 0)) ((looking-at indent1) ; (message "Indent1") (setq not-indented nil cur-indent 1))) (save-excursion ; Indents regular lines depending on the block they're in. (while not-indented (forward-line -1) (cond ((looking-at indent1) ; (message "Indent1 block") (setq cur-indent 2 not-indented nil)) ((looking-at indent0) ; (message "Indent0 block") (setq cur-indent 1 not-indented nil)) ((looking-at "!") ; (message "Reached !") (setq cur-indent 0 not-indented nil)) ((bobp) ; (message "Buffer beginning reached") (setq cur-indent 0 not-indented nil))))) (indent-line-to cur-indent)))) ;; Custom syntax table (defcustom cisco-router-mode-syntax-table (make-syntax-table) "Syntax table for cisco router mode" :group 'cisco-router) (modify-syntax-entry ?_ "w" cisco-router-mode-syntax-table) ;All _'s are part of words. (modify-syntax-entry ?- "w" cisco-router-mode-syntax-table) ;All -'s are part of words. (modify-syntax-entry ?! "<" cisco-router-mode-syntax-table) ;All !'s start comments. (modify-syntax-entry ?\n ">" cisco-router-mode-syntax-table) ;All newlines end comments. (modify-syntax-entry ?\r ">" cisco-router-mode-syntax-table) ;All linefeeds end comments. ;; Entry point (defun cisco-router-mode () "Major mode for editing Cisco router configuration files" (interactive) (kill-all-local-variables) (set-syntax-table cisco-router-mode-syntax-table) (use-local-map cisco-router-mode-map) (set (make-local-variable 'font-lock-defaults) '(cisco-router-font-lock-keywords)) (set (make-local-variable 'indent-line-function) 'cisco-router-indent-line) (set (make-local-variable 'comment-start) "!") (set (make-local-variable 'comment-start-skip) "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\)!+ *") (setq imenu-case-fold-search nil) (set (make-local-variable 'imenu-generic-expression) cisco-router-imenu-expression) (imenu-add-to-menubar "Imenu") (setq major-mode 'cisco-router-mode mode-name "Cisco router configuration") (run-hooks cisco-router-mode-hook)) (add-to-list 'auto-mode-alist '("\\.cfg\\'" . cisco-router-mode)) (provide 'cisco-router-mode) ;;; cisco-router-mode.el ends here
8.16 Fix gnus large groups
(setq gnus-large-newsgroup nil)
8.17 Fix tramp for ZSH
(add-to-list 'tramp-connection-properties (list (regexp-quote "/ssh:michael@asterisk:") "remote-shell" "/bin/zsh"))
8.18 nws-weather
custom function
(defun nws-weather (station) (interactive "sNWS Station? ") (let ((current-observation (car (with-current-buffer (url-retrieve-synchronously (format "https://w1.weather.gov/xml/current_obs/%s.xml" station)) (xml-parse-region (point-min) (point-max)))))) (message "Location: %s\nTemperature: %s℉\nRelative Humidity: %s%%\nWind: %s\nDew Point: %s\nVisibility: %s miles" (car (xml-node-children (car (xml-get-children current-observation 'location)))) (car (xml-node-children (car (xml-get-children current-observation 'temp_f)))) (car (xml-node-children (car (xml-get-children current-observation 'relative_humidity)))) (car (xml-node-children (car (xml-get-children current-observation 'wind_string)))) (car (xml-node-children (car (xml-get-children current-observation 'dewpoint_string)))) (car (xml-node-children (car (xml-get-children current-observation 'visibility_mi)))))))
9 BBDB
9.1 Automatically add people to the bbdb
(bbdb-initialize 'gnus 'message) (bbdb-mua-auto-update-init 'message) (setq bbdb-mua-auto-update-p 'query)
10 Mutt
10.1 Emacs as external editor
(add-to-list 'auto-mode-alist '("/mutt" . mail-mode))
10.2 Autofill for Mail
(add-hook 'mail-mode-hook 'turn-on-auto-fill)
10.3 Replace C-x # with C-x k
(defun my-mail-mode-hook () (auto-fill-mode 1) (abbrev-mode 1) (local-set-key "\C-Xk" 'server-edit)) (add-hook 'mail-mode-hook 'my-mail-mode-hook)
11 Evil Mode
11.1 Enable evil mode
(setq evil-want-keybinding nil) (use-package evil) (use-package evil-leader) (use-package evil-org) (require 'evil) (evil-mode 1)
11.2 Set up global key-bindings, and make evil my leader.
(eval-after-load "evil" '(progn (define-key evil-normal-state-map (kbd "M-h") 'evil-window-left) (define-key evil-normal-state-map (kbd "M-j") 'evil-window-down) (define-key evil-normal-state-map (kbd "M-k") 'evil-window-up) (define-key evil-normal-state-map (kbd "M-l") 'evil-window-right) (define-key evil-motion-state-map ";" 'smex) (define-key evil-motion-state-map ":" 'evil-ex)))
11.3 Evil Powerline
Powerline for Evil mode
(use-package powerline) (use-package powerline-evil)
11.4 Ledger Mode
I use ledger-cli for my personal finances, here I make it evil friendly.
(use-package ledger-mode :ensure t :init (setq ledger-clear-whole-transactions 1) :config (add-to-list 'evil-emacs-state-modes 'ledger-report-mode) :mode "\\.ldg\\'")
11.5 Set up key-bindings for ledger-mode
(with-eval-after-load 'ledger-mode (define-key ledger-mode-map (kbd "C-c n") 'ledger-add-transaction) (define-key ledger-mode-map (kbd "C-c c") 'ledger-mode-clean-buffer) (define-key ledger-mode-map (kbd "C-c r") 'ledger-report))
11.6 Set up key-bindings for BBDB
Set up the Key Bindings for the Big Brother Database. This code was pulled from github/tarleb
(evil-define-key 'motion bbdb-mode-map "\C-k" 'bbdb-delete-field-or-record "\C-x\C-s" 'bbdb-save "\C-x\C-t" 'bbdb-transpose-fields "\d" 'bbdb-prev-field ; DEL "\M-d" 'bbdb-dial "\t" 'bbdb-next-field ; TAB "+" 'bbdb-append-display "*" 'bbdb-do-all-records ";" 'bbdb-edit-foo "?" 'bbdb-help "!" 'bbdb-search-invert "=" 'delete-other-windows "a" 'bbdb-add-mail-alias "A" 'bbdb-mail-aliases "C" 'bbdb-copy-records-as-kill "c" 'bbdb-create "d" 'bbdb-delete-field-or-record "e" 'bbdb-edit-field "h" 'bbdb-info "i" 'bbdb-insert-field "J" 'bbdb-next-field "j" 'bbdb-next-record "K" 'bbdb-prev-field "k" 'bbdb-prev-record "m" 'bbdb-mail "M" 'bbdb-mail-address "N" 'bbdb-next-field "n" 'bbdb-next-record "o" 'bbdb-omit-record "P" 'bbdb-prev-field "p" 'bbdb-prev-record "s" 'bbdb-save "T" 'bbdb-display-records-completely "t" 'bbdb-toggle-records-layout "u" 'bbdb-browse-url ;; Search keys "b" 'bbdb "/1" 'bbdb-display-records "/n" 'bbdb-search-name "/o" 'bbdb-search-organization "/p" 'bbdb-search-phone "/a" 'bbdb-search-address "/m" 'bbdb-search-mail "/N" 'bbdb-search-xfields "/x" 'bbdb-search-xfields "/c" 'bbdb-search-changed "/d" 'bbdb-search-duplicates "\C-xnw" 'bbdb-display-all-records "\C-xnd" 'bbdb-display-current-record ) (evil-set-initial-state 'bbdb-mode 'motion)
11.7 Fix term-mode
Term-mode shouldn't have evil bindings.
(evil-set-initial-state 'term-mode 'emacs)
11.8 Fix govc-mode
Govc shouldn't have evil bindings.
(evil-set-initial-state 'govc-mode 'emacs) (evil-set-initial-state 'govc-mode-major-mode 'emacs)
11.9 Fix twittering-mode
Twittering should have some evil bindings.
(eval-after-load 'twittering-mode '(progn (evil-define-key 'motion twittering-mode-map "g" nil "g g" 'twittering-goto-first-status "c" 'twittering-current-timeline "C-u" 'twittering-scroll-down "/" 'evil-search-forward "?" 'evil-search-backward "n" 'evil-search-next "N" 'evil-search-previous [escape] 'twittering-edit-cancel-status "<tab>" 'twittering-goto-next-uri) (evil-set-initial-state 'twittering-mode 'motion)))
11.10 evil-collection
evil-collection
is a collection of Evil mode bindings for parts of Emacs that Evil does not cover properly by default.
(use-package evil-collection :init (evil-collection-init))
12 Disabled Configs
This section is where bad sections of this config can go if they break Emacs. It's only used for debugging purposes.
12.1 graphviz-dot-mode
(use-package graphviz-dot-mode :ensure t :config (setq graphviz-dot-indent-width 4)) (use-package company-graphviz-dot)
12.2 calfw
Package for org-mode calendar
(use-package calfw :custom-face (cfw:face-toolbar ((t (:background "midnight blue" :foreground "Steelblue4")))) (cfw:face-toolbar-button-off ((t (:foreground "gray30" :weight bold))))) (use-package calfw-org) (use-package calfw-ical) (use-package calfw-cal)
12.3 Twitter Mode
Browse Twitter from Emacs
(use-package twittering-mode :init (if (executable-find "convert") (setq twittering-convert-fix-size 32)) (if (executable-find "gzip") (setq twittering-use-icon-storage t)))
12.4 nnreddit
A Reddit backend for the Gnus newsreader.
;(el-get-bundle nnredit ; :url "https://github.com/paul-issartel/nnreddit.git" ; (add-to-list 'gnus-secondary-select-methods '(nnreddit "")))