so
  • This post is part of a thread:
  • Dotfiles, 29 Feb 2020

My .emacs

Volume 4, Issue 16; 29 Feb 2020

Configuring emacs is part art, part science. I’m carrying around customizations that date back more than 20 years.

This posting is the “woven” version of my Emacs configuration. It occurred to me that since I can publish Org mode files as weblog postings, I could post it directly. That amused me. It’ll be more useful to you from the repository. One obvious deficiencyAlso, this posting contains a lot of third-level headings. Those are formatted as “run in” heads which usually work fine because I write the prose so that they do. Some of them look a bit odd in this posting; that’s another deficiency I’m not motivated to fix. in this posting is that many of the code fragment are too wide. Given that the weblog is secondary and actually understanding the code in my Org file is primary, I’m not motivated to try to fix that.

The relevant point is, I maintain my Emacs configuration in a documented Org-mode file and that feels good.

This document represents and attempt to both document and clean up my configuration. This is, obviously, an Org-mode file. The code snippets it contains are woven together with their documentation (prose like this) and tangled together into my ~/.emacs.d/init.el file by Org-Babel.

One consequence of this approach is that I’m free to document code fragments in any order I want. Mostly, this file documents things from top-to-bottom, but the actual order is determined by the tangle, not the weave, as it were.

There’s still room for improvement:

  • A few big chunks of this file are still mostly verbatim copies from my old configuration file with little by way of new documentation.
  • There’s still a bunch of undocumented configuration in libraries in ~/.emacs.d/personal/*.el that would benefit from greater documentation.

The sincerest form of flattery

Insert witty quote about imitation, theft, and plagiarism here. Many of the ideas in this file are stolen from inspired by the works of others:

(Note to self: update this list, there are surely others.)

Startup

Lexical binding · Use lexical-binding. Why?

;;; init.el --- -*- lexical-binding: t -*-

Early Init · Emacs 27 introduces early-init.el, which is run before init.el, before package and UI initialization happens.

Compatibility with Emacs 26

Ensure emacs-version>=26, manually require early-init configurations if emacs-version<27.

(cond ((version< emacs-version "26.1")
       (warn "M-EMACS requires Emacs 26.1 and above!"))
      ((let* ((early-init-f (expand-file-name "early-init.el" user-emacs-directory))
              (early-init-do-not-edit-d (expand-file-name "early-init-do-not-edit/" user-emacs-directory))
              (early-init-do-not-edit-f (expand-file-name "early-init.el" early-init-do-not-edit-d)))
         (and (version< emacs-version "27")
              (or (not (file-exists-p early-init-do-not-edit-f))
                  (file-newer-than-file-p early-init-f early-init-do-not-edit-f)))
         (make-directory early-init-do-not-edit-d t)
         (copy-file early-init-f early-init-do-not-edit-f t t t t)
         (add-to-list 'load-path early-init-do-not-edit-d)
         (require 'early-init))))

Defer garbage collection

Defer garbage collection further back in the startup process, according to hlissner:

The GC eats up quite a bit of time, easily doubling startup time. The trick is to turn up the memory threshold as early as possible.

(setq gc-cons-threshold 100000000)

Disable package-enable-at-startup

Package initialize occurs automatically, before user-init-file is loaded, but after early-init-file. We handle package initialization, so we must prevent Emacs from doing it early!

(setq package-enable-at-startup nil)

Unset file-name-handler-alist

Every file opened and loaded by Emacs will run through this list to check for a proper handler for the file, but during startup, it won’t need any of them.

(defvar file-name-handler-alist-original file-name-handler-alist)
(setq file-name-handler-alist nil)

Disable site-run-file

(setq site-run-file nil)

Disable unnecessary interfaces

It will be faster to disable them here before they've been initialized.

;;(menu-bar-mode -1)
(unless (and (display-graphic-p) (eq system-type 'darwin))
  (push '(menu-bar-lines . 0) default-frame-alist))
(push '(tool-bar-lines . 0) default-frame-alist)
(push '(vertical-scroll-bars) default-frame-alist)

Garbage Collection

Set gc-cons-threshold smaller for interactive use

A large gc-cons-threshold may cause freezing and stuttering during long-term interactive use.

(defvar better-gc-cons-threshold 67108864 ; 64mb
  "The default value to use for `gc-cons-threshold'.
If you experience freezing, decrease this. If you experience stuttering, increase this.")

(add-hook 'emacs-startup-hook
          (lambda ()
            (setq gc-cons-threshold better-gc-cons-threshold)
            (setq file-name-handler-alist file-name-handler-alist-original)
            (makunbound 'file-name-handler-alist-original)))

Garbage collect when emacs is out of focus

Note: Since Emacs 27.1, focus-out-hook is obsolete.

(add-hook 'emacs-startup-hook
          (lambda ()
            (if (boundp 'after-focus-change-function)
                (add-function :after after-focus-change-function
                              (lambda ()
                                (unless (frame-focus-state)
                                  (garbage-collect))))
              (add-hook 'after-focus-change-function 'garbage-collect))

Avoid garbage collection when using minibuffer

(defun gc-minibuffer-setup-hook ()
  (setq gc-cons-threshold (* better-gc-cons-threshold 2)))

(defun gc-minibuffer-exit-hook ()
  (garbage-collect)
  (setq gc-cons-threshold better-gc-cons-threshold))

(add-hook 'minibuffer-setup-hook #'gc-minibuffer-setup-hook)
(add-hook 'minibuffer-exit-hook #'gc-minibuffer-exit-hook)))

Use the garbage collector magic hack

The garbage collector magic hack.

(straight-use-package
 '(gcmh
   :type git
   :host github
   :repo "emacsmirror/gcmh"))
(require 'gcmh)
(gcmh-mode 1)

Load Path · I’m storing some functions in ~/.emacs.d/personal, so make sure that gets added to the load path. For good measure, add its subdirectories as well.

(defun update-to-load-path (folder)
  "Update FOLDER and its subdirectories to `load-path'."
  (let ((base folder))
    (unless (member base load-path)
      (add-to-list 'load-path base))
    (dolist (f (directory-files base))
      (let ((name (concat base "/" f)))
        (when (and (file-directory-p name)
                   (not (equal f ".."))
                   (not (equal f ".")))
          (unless (member base load-path)
            (add-to-list 'load-path name)))))))

(update-to-load-path (expand-file-name "personal" user-emacs-directory))

Define constants · I nicked these from somewhere. They seem like a good idea, but I’m not actually using most of them just at the moment.

(defconst *sys/gui*
  (display-graphic-p)
  "Are we running on a GUI Emacs?")

(defconst *sys/win32*
  (eq system-type 'windows-nt)
  "Are we running on a WinTel system?")

(defconst *sys/linux*
  (eq system-type 'gnu/linux)
  "Are we running on a GNU/Linux system?")

(defconst *sys/mac*
  (eq system-type 'darwin)
  "Are we running on a Mac system?")

(defconst *sys/root*
  (string-equal "root" (getenv "USER"))
  "Are you a ROOT user?")

(defconst *rg*
  (executable-find "rg")
  "Do we have ripgrep?")

(defconst *python*
  (executable-find "python")
  "Do we have python?")

(defconst *python3*
  (executable-find "python3")
  "Do we have python3?")

(defconst *mvn*
  (executable-find "mvn")
  "Do we have Maven?")

(defconst *gcc*
  (executable-find "gcc")
  "Do we have gcc?")

(defconst *git*
  (executable-find "git")
  "Do we have git?")

(defconst *pdflatex*
  (executable-find "pdflatex")
  "Do we have pdflatex?")

Where is our custom file?

I’m not really a fan of the custom framework; I’d rather edit the sources and save my configurations by hand. But some packages use it, so let’s get this out of the way early.

;;; Tell custom to put its crap somewhere else, but load it early
(setq custom-file (concat user-emacs-directory "custom.el"))
(load custom-file 'noerror)

Remove built-in Org

I want to install a version of Org-Mode that’s more recent than the version that ships with Emacs. To do that safely, I first move the built-in version out of my class path.

;; Remove the built-in version of Org from the load-path
(require 'cl-seq)
(setq load-path
      (cl-remove-if
       (lambda (x)
         (string-match-p "org$" x))
       load-path))

Load the package manager

I’ve been using straight.el for a while and I really like it.

;; Bootstrap straight.el
(defvar bootstrap-version)
(let ((bootstrap-file
       (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
      (bootstrap-version 5))
  (unless (file-exists-p bootstrap-file)
    (with-current-buffer
        (url-retrieve-synchronously
         "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
         'silent 'inhibit-cookies)
      (goto-char (point-max))
      (eval-print-last-sexp)))
  (load bootstrap-file nil 'nomessage))

Load up the straight.el version of use-package.

;; Load the straight.el version of use-package
(defvar straight-use-package-by-default)
(straight-use-package 'use-package)
;; Tell straight to use use-package by default
(setq straight-use-package-by-default t)

;; Tell straight to use ssh by default, instead of https.
(setq straight-vc-git-default-protocol 'ssh)

System configuration

Configure the keyboard · What kind of a system is this? Do the bare requirements necessary to make the keyboard usable.

  (if *sys/mac*
      (progn
        (setq mac-command-modifier 'meta) ; command = Meta
        (setq mac-option-modifier 'super) ; (left) option = Super
        (setq mac-control-modifier 'control) ; control = Control
        (setq mac-right-option-modifier 'hyper) ; (right) opton = Hyper
        (setq x-select-enable-clipboard 't)))

Load my custom functions · Load my custom functions.

;; Some custom functions.
(require 'ndw-defuns)

(define-key global-map "\M-j" 'ndw/fill-paragraph)

Grab bag of my general settings · This needs to be cleaned up.

;; This is me.
(setq user-mail-address "ndw@nwalsh.com")
(setq user-full-name "Norman Tovey-Walsh")
(setq add-log-mailing-address "ndw@nwalsh.com")

; Allow some things that emacs would otherwise confirm.
(put 'eval-expression  'disabled nil)
(put 'downcase-region  'disabled nil)
(put 'upcase-region    'disabled nil)
(put 'narrow-to-region 'disabled nil)
(put 'set-goal-column  'disabled nil)

;; No flashing, please.
(setq visible-bell nil)

;; Also, I’ve seen the startup message
(setq inhibit-startup-message t)

;; Show me errors
(setq debug-on-error t)

;; Show me more log messages
(setq message-log-max 500)

;; WTF? If I don't define this, I get weird warnings when byte compiling
(setq warning-suppress-types nil)

(unless *sys/win32*
  (set-selection-coding-system 'utf-8)
  (prefer-coding-system 'utf-8)
  (set-language-environment "UTF-8")
  (set-default-coding-systems 'utf-8)
  (set-terminal-coding-system 'utf-8)
  (set-keyboard-coding-system 'utf-8)
  (setq locale-coding-system 'utf-8))
;; Treat clipboard input as UTF-8 string first; compound text next, etc.
(when *sys/gui*
  (setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)))

(setq electric-indent-mode nil)
(setq case-fold-search t)
; Character folding in searches!
(if (boundp 'search-default-mode)
    (setq search-default-mode 'char-fold-to-regexp))

(setq line-number-mode t)
(setq auto-save-interval 2048)
(setq blink-matching-paren-distance 100000)

;; Updates from [[https://github.com/alhassy/emacs.d][alhassy]].
;; Move auto save and backup files out of the way
(setq backup-directory-alist '(("." . "~/.emacs.d/backups")))
;; Silently delete execess backup versions
(setq delete-old-versions t)
;; Only keep the last 100 backups of a file.
(setq kept-old-versions 000)
;; Even version controlled files get to be backed up.
(setq vc-make-backup-files t)
;; Use version numbers for backup files.
(setq version-control t)

;; Make emacs backup every time I save.
(defun ndw/force-backup-of-buffer ()
  "Lie to Emacs, telling it the current buffer has yet to be backed up."
  (setq buffer-backed-up nil))
(add-hook 'before-save-hook  'ndw/force-backup-of-buffer)

;; Follow symlinks automatically
(setq vc-follow-symlinks t)

;; Ignore .rtf files
;; (Does anyone remember .rtf files? I don’t think I’ve seen
;; one since the last millenium.)
(setq completion-ignored-extensions
      (append completion-ignored-extensions '(".rtf")))

;; Use python3
(setq python-shell-interpreter "python3"
      python-shell-interpreter-args "-i")

;; Location things
(setq calendar-latitude 30.3102244)
(setq calendar-longitude -97.7528019)
(setq calendar-location-name "Austin, TX")

;; Bookmarks (which I never think to use)
(autoload 'create-bookmark "bookmark" "Bookmark utility" t)
(autoload 'locate-bookmark "bookmark" "Boomkark utility" t)
(autoload 'query-delete-bookmarks "bookmark" "Boomkark utility" t)

;; Emerge
(autoload 'emerge-files "emerge" "File merging utility" t)
(autoload 'emerge-files-with-ancestor "emerge" "File merging utility" t)

;; Activate transparent GnuPG encryption.
(require 'epa-file)
(epa-file-enable)

;; Save minibuffer history
(require 'savehist)
(savehist-mode t)

;; Save the place in files
(require 'saveplace)
(setq-default save-place t)
(setq save-place-file "~/.emacs.d/saved-places")

;; Setup authinfo
(require 'auth-source)
(if (file-exists-p "~/.authinfo.gpg")
    (setq auth-sources '((:source "~/.authinfo.gpg" :host t :protocol t)))
    (setq auth-sources '((:source "~/.authinfo" :host t :protocol t))))

Immortal buffers · Some buffers should never be deleted. Even if you type C-x k in them.

;; Make some buffers immortal
(defun ndw-immortal-buffers ()
  (if (or (eq (current-buffer) (get-buffer "*scratch*"))
          (eq (current-buffer) (get-buffer "*Messages*")))
      (progn (bury-buffer)
             nil)
    t))

(add-hook 'kill-buffer-query-functions 'ndw-immortal-buffers)

Prettify things · These settings “prettify” some things in the buffer. For example, the string “l-a-m-b-d-a” is replaced by the “λ” character. This has no effect on the underlying data, it only effects the presentation. This is a little bit like using a programming font with ligatures, an approach not universally admired.

I’m on the fence about it. In some contexts, I think it’s fine. In others, it really does look a bit odd.

(global-prettify-symbols-mode 1)

(defun add-pretty-lambda ()
  "Make some word or string show as pretty Unicode symbols.
See https://unicodelookup.com for more."
  (setq prettify-symbols-alist
        '(
          ("lambda" . ?λ)
          ("->" . ?⟶)
          ("<=" . ?≤)
          (">=" . ?≥)
          ("#+BEGIN_SRC" . ?✎)
          ("#+END_SRC"    . ?□)
          ("#+BEGIN_EXAMPLE" . (?ℰ (Br . Bl) ?⇒)) ;; ℰ⇒
          ("#+END_EXAMPLE"    . ?⇐)               ;; ⇐
          ("#+BEGIN_QUOTE" . (?𝒬 (Br . Bl) ?⇒))   ;; 𝒬⇒
          ("#+END_QUOTE"    . ?⇐)                 ;; ⇐
          )))

;; Alternatively, rendering begin/end src as icons can be improved:
;; https://pank.eu/blog/pretty-babel-src-blocks.html#coderef-symbol

(add-hook 'text-mode-hook 'add-pretty-lambda)
(add-hook 'prog-mode-hook 'add-pretty-lambda)
(add-hook 'org-mode-hook 'add-pretty-lambda)

Whitespace · I’m fussy about whitespace.

(require 'whitespace)
;; 17 October 2019, removed "face" here because it makes colored backgrounds
;; in other modes, such as Org and Markdown, ugly and distracting.
;; 3 November 2019, removed trailing because too many menus have it
(setq whitespace-style
      '(tabs trailing spaces space-before-tab newline space-after-tab space-mark tab-mark))
(setq whitespace-display-mappings
      '(
;        (space-mark   ?\    [?\x2423]   [?·] [?\ ])  ; space
        (space-mark   ?\xA0 [?\xA4]     [?_])        ; hard space
        ))
(global-whitespace-mode)
(setq-default show-trailing-whitespace nil)

(setq-default fill-column 70)
(setq sentence-end-double-space nil)
(setq-default indicate-empty-lines t)
(setq-default indent-tabs-mode nil)

Custom key bindings · I have a set of custom keybindings. There’s a school of thought that says custom bindings are bad because they limit your ability to be productive on an Emacs not configured your way. That almost never happens to me, so I’m not going to worry about it.

Control T bindings

I bind a bunch of random things to “​C-t​” because I learned Emacs in graduate school and this is what my advisor did. I do not assert that I know and remember all of these bindings all of the time.

  ;; The principal of the lab where I was introduced to Emacs
  ;; installed extensions on C-t. So I do too.
  (defvar ctl-t-map nil "Norm's extensions key map.")
  (progn
    (setq ctl-t-map (lookup-key global-map "\C-t"))
    (if (not (keymapp ctl-t-map))
        (setq ctl-t-map (make-sparse-keymap)))
    (define-key ctl-t-map "AT"   'ndw/agenda-template)
    (define-key ctl-t-map "AM"   'ndw/minutes-template)
    (define-key ctl-t-map "RC"   'clear-rectangle)
    (define-key ctl-t-map "RD"   'delete-rectangle)
    (define-key ctl-t-map "RO"   'open-rectangle)
    (define-key ctl-t-map "RW"   'kill-rectangle)
    (define-key ctl-t-map "RY"   'yank-rectangle)
    (define-key ctl-t-map "\C-[" 'backward-paragraph)
    (define-key ctl-t-map "\C-]" 'forward-paragraph)
    (define-key ctl-t-map "\C-a" 'beginning-of-buffer)
    (define-key ctl-t-map "\C-b" 'bury-buffer)
    (define-key ctl-t-map "\C-c" 'ndw/open-calendar)
    (define-key ctl-t-map "\C-e" 'end-of-buffer)
    (define-key ctl-t-map "\C-g" 'keyboard-quit)
    (define-key ctl-t-map "\C-k" 'kill-buffer)
    (define-key ctl-t-map "\C-l" 'ndw/goto-line-with-feedback)
    (define-key ctl-t-map "\C-n" 'next-error)
    (define-key ctl-t-map "\C-r" 'all)
    (define-key ctl-t-map "\C-s" 'sort-lines)
    (define-key ctl-t-map "\C-t" 'wwtime)
    (define-key ctl-t-map "\C-w" 'ispell-word)
    (define-key ctl-t-map "\C-z" 'wwtime-convert)
    (define-key ctl-t-map "b"    'org-brain-visualize)
    (define-key ctl-t-map "c"    'helm-org-contacts)
    (define-key ctl-t-map "d"    'dired)
    (define-key ctl-t-map "e"    'insert-euro)
    (define-key ctl-t-map "f"    'set-fill-prefix)
    (define-key ctl-t-map "l"    'insert-pound)
    (define-key ctl-t-map "m"    'mu4e)
    (define-key ctl-t-map "p"    'ndw-blog:post)
    (define-key ctl-t-map "q"    'xml-quotes-add-mail-signature)
    (define-key ctl-t-map "s"    'ispell-buffer)
    (define-key ctl-t-map "u"    'xmlunicode-character-insert-helm)
    (define-key ctl-t-map "z"    'insert-zero-width-space)
    (define-key ctl-t-map "ox"   'om-to-xml)
    (define-key ctl-t-map "yi"   'yankpad-insert)
    (define-key ctl-t-map "yy"   'yankpad-insert)
    (define-key ctl-t-map "ye"   'yankpad-expand)
    (define-key ctl-t-map "ym"   'yankpad-map)
    (define-key ctl-t-map "ys"   'yankpad-set-category)
    )
  (defvar Control-T-prefix ctl-t-map "Norm's extension prefix.")

Control X bindings

  ;; Changes to Control-X map
  (define-key ctl-x-map "\C-]" 'save-buffer)

Global bindings

;; Changes to global map
(define-key global-map "\C-t" Control-T-prefix)
(define-key global-map "\ej"  'fill-paragraph)
(define-key global-map "\eq"  'query-replace-regexp)
(define-key global-map "\er"  'replace-regexp)
(define-key global-map "#"    'quoted-insert)
(define-key global-map "\eOC" 'forward-word)
(define-key global-map "\eOD" 'backward-word)
(global-set-key "\C-\\" 'call-last-kbd-macro)
(global-set-key "\C-Z"  'undo)
(global-set-key [M-left] 'backward-sexp)
(global-set-key [M-right] 'forward-sexp)

(global-set-key (kbd "M-z") nil)
(global-set-key (kbd "C-x C-z") nil)
(global-set-key (kbd "M-/") nil)

;; Move up/down paragraph
(global-set-key (kbd "M-n") #'forward-paragraph)
(global-set-key (kbd "M-p") #'backward-paragraph)

;; This doesn’t work and I don’t know why
(global-set-key [M-a] 'copy-whole-buffer)

Mode bindings

xmlunicode provides some convenience methods for inserting Unicode characters (in particular for what have traditionally been SGML XML named character entities).

(use-package xmlunicode
  :init
  ;; set Unicode data file location. (used by what-cursor-position and describe-char)
  (let ((x "~/.emacs.d/UnicodeData.txt"))
    (when (file-exists-p x)
      (setq describe-char-unicodedata-file x))))

(require 'xmlunicode)
(setq xmlunicode-default-single-quote xmlunicode-rsquo)

I bind them in several modes.

  (defun bind-smart-characters (mode-map)
    "Add bindings for special punctuation handling to MODE-MAP."
    (define-key mode-map "\"" 'xmlunicode-smart-double-quote)
    (define-key mode-map "'" 'xmlunicode-smart-single-quote)
    (define-key mode-map "-" 'xmlunicode-smart-hyphen)
    (define-key mode-map "." 'xmlunicode-smart-period))

  (defun bind-nxml-mode-keys ()
    "Special support for `nxml-mode'."
    (set-language-environment "utf-8")
    (define-key nxml-mode-map (kbd "<C-return>") 'completion-at-point)
    (define-key nxml-mode-map ";" 'xmlunicode-smart-semicolon)
    ; Now that I have C-t C-u, I never use this
    ;(define-key nxml-mode-map [menu-bar unichar]
    ;  (cons "UniChar" xmlunicode-character-menu-map))
    (set-input-method 'xml)
    (bind-smart-characters nxml-mode-map))

  (defun bind-adoc-mode-keys ()
    "Use smart insert characters in `adoc-mode'."
    (bind-smart-characters adoc-mode-map))

  (defun bind-markdown-mode-keys ()
    "Use smart insert characters in `markdown-mode'."
    (bind-smart-characters markdown-mode-map))

  (defun bind-text-mode-keys ()
    "Use smart insert characters in `text-mode'."
    (bind-smart-characters text-mode-map))

  (add-hook 'markdown-mode-hook 'bind-markdown-mode-keys)
  (add-hook 'nxml-mode-hook 'bind-nxml-mode-keys)
  (add-hook 'adoc-mode-hook 'bind-adoc-mode-keys)
  (add-hook 'text-mode-hook 'bind-text-mode-keys)

Org-mode

At the beginning of 2019, I made a decision to seriously embrace Org-mode. Lots of my config is about tinkering with Org-mode. It’s great, except for the parts I really wish were different. :-)

This section sets up Org-mode, it’s prerequisites, and the extensions I’m using.

doct · doct provies “Declarative Org-mode Capture Templates” for Emacs. I find them a little easier to reason about than the standard form.

(straight-use-package
 '(doct :type git :host github :repo "progfolio/doct"))

Org-mode · I use org-mode for a lot of things. Let’s make sure it’s loaded and configured.

(use-package org-plus-contrib
  :mode (("\\.org$" . org-mode)))
  :config
  (require 'ndw-org)

;; Load my LaTeX customizations if we ever load ox-latex.
(with-eval-after-load 'ox-latex
   (require 'ndw-org-latex))

Org-sticky-header · org-sticky-header keeps headings at the top of the buffer. Updates from alhassy.

I actually find this a little distracting and probably won’t continue using it. YMMV.

(use-package org-sticky-header
 :hook (org-mode . org-sticky-header-mode)
 :config
 (setq-default
  org-sticky-header-full-path 'full
  ;; Child and parent headings are seperated by a /.
  org-sticky-header-outline-path-separator " / "))

org-jira · org-jira claims to bring Jira and OrgMode together.

(straight-use-package
 '(org-jira :type git :host github :repo "ahungry/org-jira"))

(with-eval-after-load 'org-jira
  ;; I use auth-source to conceal “secrets” from publication.
  ;; I don’t think the MarkLogic JIRA URL is especially secret,
  ;; but the mechanism exists, so…
  (setq jiralib-url
        (let ((found
               (nth 0
                    (auth-source-search :max 1
                                        :host "jiralib"
                                        :require '(:url)
                                        :create nil))))
          (plist-get found :url))))

org-bullets · org-bullets provides UTF-8 bullets for Org-mode.

(use-package org-bullets
  :init
  (setq org-bullets-bullet-list '("●" "○" "●" "○" "●" "◉" "○" "◆"))
  :config
  (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))))

org-cliplink · org-cliplink inserts Org-mode links from the clipboard.

(use-package org-cliplink)

org-context · org-context provides contextual agenda and capture for Org-mode.

(use-package org-context)

org-tree-slide · org-tree-slide is a presentation tool for Org-mode based on the visibility of outline trees.

Ultimately, I’m not happy with the way this works and I’ve cobbled together my own set of functions for presentations from Emacs.

(use-package org-tree-slide)

org-journal · org-journal is a simple Org-mode based journaling mode.

(straight-use-package
 '(org-journal :type git :host github :repo "ndw/org-journal"))

(defun ndw/org-journal-monday (&optional time)
  "Return the TIME cast back to the previous Monday.
If TIME isn’t specified, the (current-time) is assumed.
If today is Monday, return today."
  (let* ((now    (if time time (current-time)))
         (dow    (string-to-number (format-time-string "%u" now)))
         (delta  (if (= dow 1)
                     0
                   (* (- dow 1) (* 24 3600)))))
    (seconds-to-time (- (time-to-seconds now) delta))))

(customize-set-variable 'org-journal-file-type 'weekly)
(customize-set-variable 'org-journal-dir "~/Dropbox/Org/Journal/")
(customize-set-variable 'org-journal-file-format "%Y/%m/%d.org")
(customize-set-variable 'org-journal-date-format "%A, %d %B %Y")
(customize-set-variable 'org-journal-date-prefix "* ")
(customize-set-variable 'org-journal-time-prefix "** ")
(customize-set-variable 'org-journal-enable-agenda-integration t)

(customize-set-variable 'org-journal-file-header
   (lambda ()                        
     (let ((monday (ndw/org-journal-monday)))
       (insert "#+TITLE: ")
       (insert (format-time-string org-journal-date-format monday))
       (insert "\n#+STARTUP: content\n#+FILETAGS: :Journal:\n\n"))))

(require 'org-journal)

(define-key org-mode-map (kbd "C-c C-j") 'org-journal-new-entry)

org-ref · org-ref is a set of Org-mode modules for citations, cross-references, and bibliographies in Org-mode and useful BibTeX tools to go with it.

I have not figured out org-ref yet.

;; Files to look at when no “╲bibliography{⋯}” is not present in a file.
;; Most useful for non-LaTeX files.
(setq reftex-default-bibliography '("~/etc/bibliography.bib"))
(setq bibtex-completion-bibliography (car reftex-default-bibliography))

(use-package org-ref
  :config (setq org-ref-default-bibliography reftex-default-bibliography)
  :requires (org-bibtex))

;; Quick BibTeX references, sometimes.
(use-package helm-bibtex)
(use-package biblio)

org-mac-iCal · org-mac-iCal allows you to imports events from iCal.app to the Emacs diary.

(straight-use-package
 '(org-mac-iCal :type git :host github :repo "ndw/org-mac-iCal"))

(require 'org-mac-iCal)
(setq org-mac-iCal-import-exchange t)
(setq org-mac-iCal-calendar-names
      '("Norman Walsh" "Family" "Home" "Calendar" "US Holidays"))

yankpad · yankpad provides the ability to paste snippets from an Org-mode file.

(straight-use-package
 '(yankpad :type git :host github :repo "Kungsgeten/yankpad"))

org-ql · org-ql is an Org-mode query language, including search commands and saved views.

;(use-package org-ql)

org-super-agenda · org-super-agenda is an Org-mode enhancement to make the agenda view more organized.

;(use-package org-super-agenda)

org-msg · org-msg is a global minor mode for mixing Org mode and Message mode to compose and reply to emails in an Outlook HTML friendly style.

;(use-package org-msg
;  :requires (emacs-htmlize))

(straight-use-package
 '(org-msg :type git :host github :repo "jeremy-compostella/org-msg"
           :branch "experimental"
           :requires (emacs-htmlize)))

org-screenshot (org-attach-screenshot) · org-screenshot (org-attach-screenshot) provides screenshots integrated with emacs org mode attachments.

(straight-use-package
'(org-attach-screenshot :type git :host github :repo "dfeich/org-screenshot"))
(setq org-attach-screenshot-command-line "screencapture -m %f")    

org-brain · org-brain provides Org-mode wiki + concept-mapping.

;; Load org-brain after my personal org settings...
(use-package org-brain
  :init
  (setq org-brain-path "~/Dropbox/Org/brain")
  :config
  (setq org-id-track-globally t)
  (setq org-id-locations-file "~/.emacs.d/.org-id-locations")

  (push (car (doct '(("Brain" :keys "b"
                      :type plain
                      :function org-brain-goto-end
                      :template "** %i%?"))))
        org-capture-templates)

;  (push '("b" "Brain" plain (function org-brain-goto-end)
;          "* %i%?" :empty-lines 1)
;        org-capture-templates)

;  (push (doct '(("Brain" :keys "b"
;         :type plain
;         :function org-brain-goto-end
;         :template "** %i%?")))
;         org-capture-templates)

  (setq org-brain-visualize-default-choices 'all)
  (setq org-brain-title-max-length 12)
  (setq org-brain-include-file-entries nil)
  (setq org-brain-file-entries-use-title nil))

code-library · code-library supports using Org-mode to manage code snippets.

(use-package code-library)

Packages

This is the beginning of an attempt to untangle the “unsorted bag of stuff” below.

Let me be clear up front: there are a lot of packages here that I probably tried once or twice and forgot about. The trick is figuring out which ones. And of course, when I try, I’m reminded that they’re kind of cool so I decide to leave them, try them once or twice, and then forget about them again.

Avy · Avy, a nice way to move around text.

(use-package avy
  :defer t
  :bind
  (("M-z c" . avy-goto-char-timer)
   ("M-z l" . avy-goto-line))
  :custom
  (avy-timeout-seconds 0.3)
  (avy-style 'pre)
  :custom-face
  (avy-lead-face ((t (:background "#51afef" :foreground "#870000" :weight bold)))));

Crux · Crux, a Collection of Ridiculously Useful eXtensions for Emacs.

(use-package crux
  :bind
  (("C-x 4 t" . crux-transpose-windows)
   ("C-x K" . crux-kill-other-buffers))
  :config
  (crux-with-region-or-buffer indent-region)
  (crux-with-region-or-buffer untabify)
  (crux-with-region-or-point-to-eol kill-ring-save)
  (defalias 'rename-file-and-buffer #'crux-rename-file-and-buffer))

Disk usage · disk-usage is a file system analyzer: it offers a tabulated view of file listings sorted by size. Directory sizes are computed recursively.

(use-package disk-usage
  :commands (disk-usage))

Atomic Chrome · Atomic Chrome allows you to use Emacs to edit textarea elements in the browser

(use-package atomic-chrome)

Zel · Zel tracks files by “frecency” of access. Basically a port of z in Emacs.

(use-package zel
  :bind (("C-x C-r" . zel-find-file-frecent))
  :config
  (zel-install))

Diminsh · Dimish removes (certain) minor modes from the mode-line.

(use-package diminish)

Visual line mode tweaks · Visual line mode has been the default since Emacs 23, but I don’t like it.

(setq line-move-visual nil)
(setq visual-line-fringe-indicators '(left-curly-arrow right-curly-arrow))
(use-package visual-fill-column)
(add-hook 'visual-line-mode-hook #'visual-fill-column-mode)
(add-hook 'visual-line-mode-hook #'ndw/adaptive-fill-paragraph-mode)
; On further consideration, no.
;(add-hook 'org-mode-hook 'visual-line-mode) 

(straight-use-package
 '(virtual-auto-fill
   :type git
   :host github
   :repo "luisgerhorst/virtual-auto-fill"))

; On further consideration, no.
;(add-hook 'org-mode-hook #'virtual-auto-fill-mode)

om · om is a functional library for org-mode.

(straight-use-package
 '(om :type git :host github :repo "ndwarshuis/om.el"))

org-to-xml · org-to-xml is a library to convert Emacs org-mode files to XML.

(straight-use-package
 '(om-to-xml :type git :host github :repo "ndw/org-to-xml"))

(require 'ndw-om-to-xml)

ack

  • ack is an Emacs interface to ack-like tools.
  • full-ack is an Emacs front-end for ack.

Do I need both of these?

(use-package ack)
(use-package full-ack)

deadgrep · deadgrep provides fast, friendly searching with ripgrep and Emacs.

(use-package deadgrep)

bbdb · bbdb is the Insideous Big Brother Database.

(use-package bbdb
  :init
  (defadvice bbdb-read-string (before bbdb-read-string-no-ivy activate) (ivy-mode 0))
  (defadvice bbdb-read-string (after bbdb-read-string-yes-ivy activate) (ivy-mode 1)))

bind-key · The bind-key package is a simple way to manage personal keybindings. It appears to be part of use-package.

(use-package bind-key)

charmap · charmap provides Unicode tables in Emacs. M-x charmap.

(use-package charmap)

color-theme-modern · color-theme-modern is part of replace-colorthemes which replaces color-theme with the Emacs 24 theme framework.

(use-package color-theme-modern)

company · company-mode is a modular in-buffer completion framework. Updates from alhassy.

I’ve turned off global-company-mode it was much too intrusive in non-programming contexts. It may be too intrusive in programming contexts as well.

(use-package company
  :diminish
  :config
  (global-company-mode 0)
  (setq ;; Only 2 letters required for completion to activate.
        company-minimum-prefix-length 2

        ;; Search other buffers for completion candidates
        company-dabbrev-other-buffers t
        company-dabbrev-code-other-buffers t

        ;; Allow (lengthy) numbers to be eligible for completion.
        company-complete-number t

        ;; M-⟪num⟫ to select an option according to its number.
        company-show-numbers t

        ;; Edge of the completion list cycles around.
        company-selection-wrap-around t

        ;; Do not downcase completions by default.
        company-dabbrev-downcase nil

        ;; Even if I write something with the ‘wrong’ case,
        ;; provide the ‘correct’ casing.
        company-dabbrev-ignore-case t

        ;; Immediately activate completion.
        company-idle-delay 0))

(add-hook 'prog-mode-hook 'company-mode)

company-emoji

(use-package company-emoji
  :config (add-to-list 'company-backends 'company-emoji))

cperl-mode · cperl-mode is an advanced mode for programming in Perl.

(use-package cperl-mode)

rainbow-mode · rainbow-mode is a minor mode sets background color to strings that match color names, e.g. #0000ff is displayed in white with a blue background.

(use-package rainbow-mode
  :config
  (add-hook 'emacs-lisp-mode-hook 'rainbow-mode))

css-mode · css-mode is a mode for editing CSS stylesheets.

(use-package css-mode
  :requires (rainbow-mode)
  :init
  (add-hook 'css-mode-hook 'rainbow-mode))

dash · dash is a modern list library for Emacs.

;; Modern list library
(use-package dash)

magit · magit is a git porcelain inside Emacs.

With the default tramp-ssh-controlmaster-options, tramp takes a long time to start and consequently magit takes a long time.

(defvar tramp-ssh-controlmaster-options)
(defvar magit-last-seen-setup-instructions)
(use-package magit
  :init
  (setq tramp-ssh-controlmaster-options "")
  (setq magit-last-seen-setup-instructions "1.4.0"))

Docker-related packages

(use-package docker)
(use-package docker-api)
(use-package docker-compose-mode)
(use-package dockerfile-mode)

emojify · emojify displays emojiy in Emacs. Don’t bother loading it unless we’re running in a window system.

(use-package emojify
  :if window-system
  :init
  (defun --set-emoji-font (frame)
    "Adjust the font settings of FRAME so Emacs can display emoji properly."
    (if (eq system-type 'darwin)
        ;; For NS/Cocoa
        (set-fontset-font t 'symbol (font-spec :family "Apple Color Emoji") frame 'prepend)
      ;; For Linux
      (set-fontset-font t 'symbol (font-spec :family "Symbola") frame 'prepend)))
  ;; For when Emacs is started in GUI mode:
  (--set-emoji-font nil)
  (add-hook 'after-make-frame-functions '--set-emoji-font)
  (add-hook 'org-mode-hook 'emojify-mode))

exec-path-from-shell · exec-path-from-shell makes Emacs use the $PATH set up by the user's shell

(use-package exec-path-from-shell)

ledger-mode · ledger-mode is a major mode for editing “Ledger CLI” files.

(use-package ledger-mode)

Flycheck-related packages

(use-package flycheck
  :config
  (global-flycheck-mode))
(use-package flycheck-ledger)
(use-package flycheck-package)

graphviz-dot-mode · graphviz-dot-mode is an Emacs mode for Graphviz DOT files.

(use-package graphviz-dot-mode)

git-gutter · git-gutter shows git changes in the fringe.

(use-package git-gutter
  :init
  (setq git-gutter:deleted-sign "▁")
  (setq git-gutter:added-sign "▌")
  (setq git-gutter:modified-sign "▌")
  :config
  (global-git-gutter-mode +1))

Hydra · hydra shortens key bindings by allowing you to type the prefix only once. Updates from alhassy.

Use Hydra to navigate through version control changes. I’ve commented out revert and stage because it feels like it would be too easy to do them accidentally.

(use-package hydra)

(defhydra hydra-version-control (global-map "C-x v")
  "Version control"
  ;; Syntax: (extension method description)
  ("n" git-gutter:next-hunk      "Next hunk")
  ("p" git-gutter:previous-hunk  "Previous hunk")
  ("d" git-gutter:popup-hunk     "Show hunk diff")
;  ("r" git-gutter:revert-hunk    "Revert hunk\n")
;  ("c" git-gutter:stage-hunk     "Stage hunk")
  ("s" git-gutter:statistic      "How many added & deleted lines"))

Groovy- and Gradle-related packages

  • groovy-mode is a major mode for editing Groovy files. Also included in the package: REPL integration with run-groovy and Grails project navigation with grails-mode.
(use-package groovy-mode
  :init
  (setq groovy-indent-offset 2)
  :mode (("\\.groovy$" . groovy-mode)
         ("\\.gradle$" . groovy-mode)))

projectile · projectile is the Project Interaction Library for Emacs.

(use-package projectile)

restclient · restclient is an HTTP REST client tool for emacs.

(use-package restclient)

helm · helm is an incremental completion and selection narrowing framework for Emacs.

(use-package helm
  :init
  (setq helm-split-window-inside-p            t
        helm-move-to-line-cycle-in-source     t
        helm-ff-search-library-in-sexp        t
        helm-scroll-amount                    8
        helm-ff-file-name-history-use-recentf t)
  ;; Remove helm-source-info-cl which I don't seem to have
  (setq helm-info-default-sources
        '(helm-source-info-elisp
          helm-source-info-eieio
          helm-source-info-pages))
  :bind (("<f1>" .      helm-resume)
         ("<f2>" .      helm-execute-kmacro)
         ("C-," .       helm-calcul-expression)
         ("C-:" .       helm-eval-expression-with-eldoc)
         ("C-c <SPC>" . helm-all-mark-rings)
         ("C-c f" .     helm-recentf)
         ("C-c g" .     helm-gid)
         ("C-c i" .     helm-imenu)
         ("C-c I" .     helm-imenu-in-all-buffers)
         ("C-h C-s" .   helm-occur)
         ("C-h a" .     helm-apropos)
         ("C-h f" .     helm-find)
         ("C-h g" .     helm-google-suggest)
         ("C-h i" .     helm-info-at-point)
         ("C-h r" .     helm-info-emacs)
         ("C-h s" .     helm-swoop)
         ("C-x C-d" .   helm-browse-project)
         ("C-x C-f" .   helm-find-files)
         ("C-x b" .     helm-mini)
         ("C-x r b" .   helm-filtered-bookmarks)
         ("C-x c b" .   helm-chrome-bookmarks)
         ("M-x" .       helm-M-x)
         ("M-y" .       helm-show-kill-ring)
         ("M-g a" .     helm-do-grep-ag)
         ([remap jump-to-register] . helm-register)
         ([remap list-buffers]     . helm-buffers-list)
         ([remap dabbrev-expand]   . helm-dabbrev)
         ([remap find-tag]         . helm-etags-select)
         ([remap xref-find-definitions] . helm-etags-select))
  :config
  (require 'ndw-helm)
  (require 'xmlunicode-helm)
)

helm-projectile · helm-projectile is a Helm UI for projectile.

(use-package helm-projectile
  :requires (helm)
  :init
  (setq projectile-enable-caching t)
  (setq projectile-completion-system 'helm)
  :bind-keymap
  ("C-c p" . projectile-command-map)
  :config
  (projectile-mode)
  (helm-projectile-on))

helm-wordnet · helm-wordnet is a helm interface to WordNet.

(use-package helm-wordnet
  :requires (helm)
  :init
  (setq helm-wordnet-wordnet-location "/usr/local/Cellar/wordnet/3.1")
  :bind (:map ctl-t-map
              ("w" . helm-wordnet-suggest)))

restclient-helm · restclient is a tool to manually explore and test HTTP REST webservices. Runs queries from a plain-text query sheet, displays results as a pretty-printed XML, JSON and even images.

(use-package restclient-helm
  :requires (helm))

all-ext · all-ext is an extension-of/replacement for all.

(use-package all-ext
  :requires (helm))

helm-ag · helm-ag is a helm interface to the silver searcher.

(use-package helm-ag
  :requires (helm))

helm-bbdb · helm-bbdb is a helm interface to BBDB.

(use-package helm-bbdb
  :requires (helm))

helm-flycheck · helm-flycheck shows flycheck errors within helm.

(use-package helm-flycheck
  :requires (helm))

helm-swoop · helm-swoop efficiently hops squeezed lines powered by Emacs helm interface .

(use-package helm-swoop
  :requires (helm))

helm-company · helm-company is a helm interface to company-mode.

(use-package helm-company
  :requires (helm))

hyperspace · hyperspace - get there from here.

(use-package hyperspace
  :init
  (setq hyperspace-actions
        '(("ddg" . "https://duckduckgo.com/?q=%s")
          ("dis" . "https://duckduckgo.com/?q=%s&iax=images&ia=images")
          ("g"   . "https://www.google.com/search?q=%s")
          ("gi"  . "https://www.google.com/search?tbm=isch&q=%s")
          ("bb"  . bbdb-search-name)
          ("el"  . (apply-partially #'hyperspace-action->info "(elisp)Top"))
          ("av"  . apropos-variable)
          ("ac"  . apropos-command)
          ("af"  . (lambda (query) (apropos-command query t)))

          ("gh"   . "https://github.com/%s")
          ("wiki" . "https://en.wikipedia.org/wiki/%s")
          ("gm"   . "http://maps.google.com/maps?q=%s")))
  :bind (:map hyperspace-minor-mode-map
              ("C-c s" . hyperspace))
  :config
  (hyperspace-minor-mode))

multiple-cursors · multiple-cursors gives Emacs…multiple, parallel cursors

(use-package multiple-cursors
  :bind (("C-S-c C-S-c" . mc/edit-lines)
         ("C->" . mc/mark-next-like-this)
         ("C-<" . mc/mark-previous-like-this)
         ("C-c C-<" . mc/mark-all-like-this)))

markdown-related packages · Mostly I work in Org-mode these days, so I don’t use these as often as I once did.

  • markdown-mode is a major mode for editing Markdown files.
  • markdown-mode+ adds additional functions for Emacs markdown-mode. Default support for [pandoc]. Much of the functionality is tailored to OS X, with the end goal to extend markdown-mode in useful ways for all platforms.
  • markdown-preview-mode is a minor mode to preview Markdown files as you save.
(use-package markdown-mode)
(use-package markdown-mode+)
(use-package markdown-preview-mode)

markup-faces · markup-faces is a collection of faces for markup language modes.

(use-package markup-faces)

rainbow-delimiters · rainbow-delimiters marks nested delimeters (parenthesis, brackets, etc.) in different colors.

(use-package rainbow-delimiters
  :init
  (add-hook 'prog-mode-hook #'rainbow-delimiters-mode))

recentf · recentf maintains a list of recently edited files.

(use-package recentf
  :init
  (setq recentf-max-menu-items 100)
  :config
  (recentf-mode 1))

rnc-mode · rnc-mode is a major mode for editing RELAX NG compact syntax files.

(use-package rnc-mode
  :init
  (setq rnc-indent-level 3))

s · s is the long lost Emacs string manipulation library.

(use-package s)

sass-mode · sass-mode is a major mode for editing SASS files.

(use-package sass-mode)

Javascript and JSON-related packages

(use-package indium)
(use-package js2-mode
  :init
  (setq js-indent-level 2)
  :mode (("\\.js" . js2-mode)
         ("\\.sjs" . js2-mode))
  :config
  (add-hook 'js2-mode-hook #'js2-imenu-extras-mode)) ;; Better imenu
(use-package xref-js2)
(use-package json-mode
  :mode (("\\.json\\'" . json-mode)
         ("\\manifest.webapp\\'" . json-mode )
         ("\\.tern-project\\'" . json-mode)))

Typescript-related packages

  • typescript-mode is a major mode for editing typescript files.
  • tide is the TypeScript Interactive Development Environment for Emacs.

Do I need both of these?

(use-package typescript-mode)
(use-package tide)

web · web is a useful HTTP client in Emacs Lisp

(use-package web)

yaml-mode · yaml-mode is a major mode for editing YAML files.

(use-package yaml-mode)

htmlize · htmlize converts a buffer of text and decorations into HTML.

(use-package htmlize)

calfw-related packages · calfw is a calendar framework for Emacs.

(use-package calfw
  :init
  (setq cfw:fchar-junction ?╋
        cfw:fchar-vertical-line ?┃
        cfw:fchar-horizontal-line ?━
        cfw:fchar-left-junction ?┣
        cfw:fchar-right-junction ?┫
        cfw:fchar-top-junction ?┯
        cfw:fchar-top-left-corner ?┏
        cfw:fchar-top-right-corner ?┓))
(use-package calfw-org)
(use-package calfw-ical)
(use-package calfw-cal)

;;; My calfw customizations
(defun ndw/open-calendar ()
  "CFW config for my calendars."
  (interactive)
  (cfw:open-calendar-buffer
   :contents-sources
   (list
    (cfw:org-create-source "Green")
    ;(cfw:cal-create-source "Orange")
    (cfw:ical-create-source "Home" "~/Documents/Home.ics" "Gray")
    (cfw:ical-create-source "Family" "~/Documents/Family.ics" "Orange")
   )))

wwtime · wwtime is an emacs library to insert time-of-day with appropriate world-wide localization.

(use-package wwtime
  :init
  ;(setq wwtime-display '("EST" "PST" "GMT" "CET" "JST" "India"))
  ;(setq wwtime-display '("EDT" "PDT" "GMT" "BST" "CEST" "JST" "India"))
  ;(setq wwtime-display '("CDT" "PDT" "GMT" "India"))
  (setq wwtime-display '("CST" "PST" "GMT" "India"))
  ;(setq wwtime-display '("CDT" "PDT" "GMT" "India"))
  (setq wwtime-ampm '("EST" "CST" "MST" "PST" "AKST"
                      "EDT" "CDT" "MDT" "PDT" "AKDT"
                      "India"))
  :config
  (setq wwtime-time-zones (append wwtime-time-zones '(("India" +5.5 "India")))))

xml-quotes · xml-quotes provides macros for generating quotations from an XML document.

(defvar signature-quote-number t)
(use-package xml-quotes
  :config
  (setq xml-quotes-message-signature-file "~/.signatures/default")
  (setq xml-quotes-closing-name "norm")
  (setq xml-quotes-closing-text-alist '(("#default" "Be seeing you," "Cheers,")))
  ;; These are “gnus” groups.
  (setq xml-quotes-group-no-closing '("docbook.admin"
                                      "list-admin"
                                      "docbook-apps.admin"
                                      "spam.missed"
                                      "spam.caught"))
  (setq xml-quotes-default-signature-function 'xml-quotes-gnus-default-signature)
  (defun set-signature-quote (&optional prefixarg)
    (interactive "P")
    (if prefixarg
        (if (numberp prefixarg)
            (setq signature-quote-number prefixarg)
          (setq signature-quote-number t)))
    (if (numberp signature-quote-number)
        (message "Next signature quote is #%d" signature-quote-number)
      (message "Next signature quote is random"))))

synosaurus · synosaurus is an extensible thesuarus mode for Emacs.

(use-package synosaurus)

powerthesaurus · powerthesaurus is a PowerThesaurus integration for Emacs.

(use-package powerthesaurus)

websocket · websocket is an Emacs Lisp implementation of websockets.

(use-package websocket)

writegood-mode · writegood-mode is a minor mode to aid in finding common writing problems.

I’m not wholly satisfied with this mode, to be honest. In particular, it tends (IMHO) to be overly aggressive about passive voice. Or maybe my technical writing just uses too much passive voice.

(use-package writegood-mode
  :config
  (add-hook 'nxml-mode-hook 'writegood-mode)
  (add-hook 'org-mode-hook 'writegood-mode))

beacon · beacon highlights the line the cursor is on whenever the window scrolls.

(use-package beacon
  :config
  (beacon-mode 1))

wsd-mode · wsd-mode is a major-mode for Emacs and websequencediagrams.com.

(use-package wsd-mode)

jdee · jdee is an add-on software package that turns Emacs into a comprehensive system for creating, editing, debugging, and documenting Java applications.

I confess, I’ve never really been able to set this up well enough. I mostly use IntelliJ for Java and Scala.

(use-package jdee)

git-timemachine · git-timemachine allows you to step through historic versions of git controlled files.

(use-package git-timemachine)

tldr · tldr is a tldr client for Emacs.

(use-package tldr)

python-mode · python-mode is a major mode for editing Python.

(use-package python-mode
  :requires (flycheck-mode)
  :init
  (setq py-shell-name "python3")
  :config
  (setq flycheck-python-pylint-executable "/Users/ndw/.pyenv/shims/pylint"))

plantuml-mode · plantuml-mode is a major mode for editing PlantUML diagrams.

(use-package plantuml-mode
  :config
  (setq plantuml-jar-path "/Users/ndw/java/plantuml.1.2019.9.jar"))

elpy · elpy is the Emacs Python Development Environment.

(use-package elpy
  :config
  (elpy-enable))

company-restclient · company-restclient is a company-mode completion back-end for restclient.

(use-package company-restclient)

emacs-request · emacs-request is a library that simplifies HTTP interactions from Emacs.

(straight-use-package
 '(emacs-request :type git :host github :repo "tkf/emacs-request"))

ob-restclient · ob-restclient is an Org-mode extension for restclient.

(use-package ob-restclient)

ob-ml-marklogic · ob-ml-marklogic provides org-babel integration with MarkLogic XQuery and (server side) JavaScript code blocks

(straight-use-package
 '(ob-ml-marklogic :type git :host github :repo "ndw/ob-ml-marklogic"))
(require 'ndw-ob-ml-marklogic)

xproc-mode · xproc-mode provides a trivial variant of nxml-mode that supports org-babel evaluation.

(straight-use-package
 '(xproc-mode :type git :host github :repo "ndw/xproc-mode"))
(require 'xproc-mode)
(setq xproc-processor "/Users/ndw/bin/meerschaum")

minions · minions is a minor-mode menu for the mode-line.

(use-package minions
  :config
  (minions-mode))

annotate · annotate provides a minor mode which can add annotations to arbitrary files without changing the files themselves. This is very useful for code reviews. When annotate-mode is active, C-c C-a will create, edit, or delete annotations.

I haven’t established the habit of using it.

(use-package annotate)

sparql-mode · sparql-mode is a major-mode for editing SPARQL files.

(use-package sparql-mode)

undo-propose · undo-propose allows you to navigate the emacs undo history by staging undo's in a temporary buffer.

(use-package undo-propose)

dimmer · dimmer interatively highlights which buffer is active by dimming the others.

(use-package dimmer
  :config
  (dimmer-mode))

dashboard · dashboard presents an extensible Emacs dashboard.

(use-package dashboard
  :config
  (dashboard-setup-startup-hook))

company-marklogic · company-marklogic is a company backend for MarkLogic functions.

(require 'company)
(straight-use-package
 '(company-marklogic :type git :host github
                     :repo "fgeorges/company-marklogic"
                     :files (:defaults "src/*.el")))

(require 'company-marklogic)
(add-to-list 'company-backends 'company-marklogic-sjs)
(add-to-list 'company-backends 'company-marklogic-xqy)
(add-hook 'xquery-mode-hook 'company-mode)

helm-org-contacts · helm-org-contacts is a helm source for Org contacts.

(straight-use-package
 '(helm-org-contacts :type git :host github :repo "tmalsburg/helm-org-contacts"))

(require 'org-contacts)

(setq org-contacts-email-property "EMAIL")
(setq org-contacts-tel-property "PHONE")
(setq org-contacts-address-property "ADDRESS")
(setq org-contacts-birthday-property "BIRTHDAY")
(setq org-contacts-note-property "NOTE")
(setq org-contacts-alias-property "ALIAS")
(setq org-contacts-ignore-property "IGNORE")

(setq org-contacts-files
      '("/Users/ndw/Documents/Notes/contacts/contacts.org"
        "/Users/ndw/Documents/Notes/contacts/businesses.org"
        "/Users/ndw/Documents/Notes/contacts/lodging.org"
        "/Users/ndw/Documents/Notes/contacts/marklogic.org"
        "/Users/ndw/Documents/Notes/contacts/restaurants.org"
        "/Users/ndw/Documents/Notes/contacts/random.org"))

xquery-mode · xquery-mode is a major mode for editing XQuery files.

(straight-use-package
 '(xquery-mode :type git :host github :repo "ndw/xquery-mode"))

poet-theme · poet-theme is an emacs theme that's well suited for modes using variable pitch: particularly org-mode and markdown-mode.

(use-package poet-theme)
(require 'ndw-theme)
(require 'ndw-fonts)

emacs-gfs · emacs-gfs is a “global face scaling” library.

(straight-use-package
 '(emacs-gfs :type git :host github :repo "ndw/emacs-gfs"))

(require 'emacs-gfs)
;; Adjust face sizes with +/-
(global-set-key (kbd "C-+") #'gfs/magnify-faces)
(global-set-key (kbd "C--") #'gfs/shrink-faces)

emacs-htmlize · emacs-htmlize converts buffer text and decorations into HTML.

(straight-use-package
 '(emacs-htmlize :type git :host github :repo "hniksic/emacs-htmlize"))

perspective · perspective lets you group sets of buffers and navigate between them distinctly from the whole buffer list. From alhassy.

Also something I haven’t really incorporated into daily use.

(use-package perspective
  :config ;; Activate it.
          (persp-mode)
          ;; In the modeline, tell me which workspace I'm in.
          (persp-turn-on-modestring))

flyspell · From alhassy.

(use-package flyspell
  :diminish
  :hook ((prog-mode . flyspell-prog-mode)
         (org-mode . flyspell-mode)
         (text-mode . flyspell-mode)))

(setq ispell-list-command "list")
(setq ispell-program-name "/usr/local/bin/aspell")
(setq ispell-dictionary "en_US") ;; set the default dictionary

(setq  ispell-extra-args '("--sug-mode=ultra"))

;; This run-together option causes a whole bunch of
;; misspellings to be treated as correct. WTF?
;;                            "--run-together"
;;                            "--run-together-limit=5"
;;                            "--run-together-min=2"))

(eval-after-load "flyspell"
  ' (progn
     (define-key flyspell-mouse-map [down-mouse-3] #'flyspell-correct-word)
     (define-key flyspell-mouse-map [mouse-3] #'undefined)))

;; (custom-set-faces '(flyspell-incorrect ((t (:inverse-video t)))))

(setq ispell-silently-savep t)

(add-hook          'c-mode-hook 'flyspell-prog-mode)
(add-hook 'emacs-lisp-mode-hook 'flyspell-prog-mode)

(use-package synosaurus
  :diminish synosaurus-mode
  :init    (synosaurus-mode)
  :config  (setq synosaurus-choose-method 'popup) ;; 'ido is default.
           (global-set-key (kbd "M-#") 'synosaurus-choose-and-replace))

(use-package wordnut
 :bind ("M-!" . wordnut-lookup-current-word))

goto-chg · goto-chg moves through a buffer based on the location of the last changes.

; M-. can conflict with etags tag search. But C-. can get overwritten
; by flyspell-auto-correct-word. And goto-last-change needs a fast key.
(use-package goto-chg
  :bind (("C-." . goto-last-change)   
         ("M-." . goto-last-change-reverse)))

(defhydra hydra-edits (global-map "C-c e")
  ("p" goto-last-change "Goto nᵗʰ last change")
  ("n" goto-last-change-reverse "Goto more recent change"))

mu4e · mu4e is installed with brew. It’s an alternative to gnus. I’m playing with it.

;; commented out here because it requires additional config
;;(add-to-list 'load-path "/usr/local/ndw/share/emacs/site-lisp/mu4e")
;;(require 'ndw-mu4e)

Unsorted bag of stuff

More work required here!

;; Make a custom -primary command line argument
;; http://edward.oconnor.cx/2010/08/standalone-gnus
(add-to-list
 'command-switch-alist
 '("primary" . (lambda (&rest ignore)
                 (server-start)
                 (atomic-chrome-start-server))))

;; Make a custom -resize command line argument. I don’t
;; find this very effective on the Mac so I’ve mostly stopped
;; using it.
(add-to-list
 'command-switch-alist
 '("resize" . (lambda (&rest ignore)
                (add-to-list 'default-frame-alist '(top . 0))
                (add-to-list 'default-frame-alist '(left . 0))
                (add-to-list 'default-frame-alist '(width . 108))
                (add-to-list 'default-frame-alist ' (height . 43)))))


;; Autoloads
(setq auto-mode-alist
      (append
       (list (cons "\\.txt$" 'text-mode)
             (cons "\\.tex$" 'latex-mode)
             (cons "\\.sli$" 'latex-mode)
             (cons "\\.bib$" 'bibtex-mode)

             (cons "\\.dss?s?l$" 'dsssl-mode)
             (cons "\\.css$" 'css-mode)

             (cons "\\.pl$" 'perl-mode)
             (cons "\\.cls$" 'perl-mode)
             (cons "\\.sup$" 'perl-mode)

             (cons "\\.py$" 'python-mode)

             (cons "\\.rb$" 'ruby-mode)

             (cons "\\.3l$" 'nroff-mode)

             (cons "\\.ttl$" 'ttl-mode)
             (cons "\\.n3$" 'ttl-mode)

             (cons "\\.ts$" 'ng2-ts-mode)

             (cons "\\.rdf$" 'nxml-mode)
             (cons "\\.rnc$" 'rnc-mode)
             (cons "\\.rng$" 'nxml-mode)
             (cons "\\.xpd$" 'nxml-mode)
             (cons "\\.xml$" 'nxml-mode)
             (cons "\\.xpl$" 'nxml-mode)
             (cons "\\.xsd$" 'nxml-mode)
             (cons "\\.xqy$" 'xquery-mode)
             (cons "\\.html$" 'nxml-mode)
             (cons "\\.htm$" 'nxml-mode)
             (cons "\\.xsl$" 'nxml-mode)
             )
       auto-mode-alist)
      )

(setq magic-mode-alist '(("<\\?xml " . nxml-mode)
                         ("%![^V]" . ps-mode)
                         ("# xmcd " . conf-unix-mode)))

;; for viewing lines matching regexps
(autoload 'all "all" nil t)

;; for RFCs
(autoload 'rfc "rfc" nil t)

;; Various modes
(autoload 'tar-mode "tar-mode.elc" "Tar archive mode." t)
(autoload 'ruby-mode "ruby-mode.elc" "Ruby mode" t)
(autoload 'xquery-mode "xquery-mode.elc" "XQuery mode" t)
(autoload 'python-mode "python-mode" "Mode for editing Python programs" t)
(autoload 'n3-mode "n3-mode" "Mode for editing N3" t)

;; Setup encryption
(setq password-cache-expiry (* 60 60 4)) ; 4 hours

;; Make buffer names unique
(require 'uniquify)

(setq c-mode-hook
      '(lambda ()
         (setq case-fold-search nil)))

(setq term-setup-hook
      '(lambda ()
         (progn
           (defvar CSI-map nil)
           (and CSI-map (enable-arrow-keys))
           (define-key global-map "\eOR" 'start-xon-isearch))))

;;

(straight-use-package
 '(ttl-mode :type git :host github
            :repo "jeeger/ttl-mode"))

(straight-use-package
 '(n3-mode :type git :host github
           :repo "kurtjx/n3-mode-for-emacs"))

(use-package poet-theme)

;; Now that all the packages are setup; do some more config

(require 'ndw-nxml)

;;; init.el ends here

Tangled files

early-init.el

;;; early-init.el --- -*- lexical-binding: t -*-
;;
;; N.B. This file is generated automatically from literate sources.
;; Do not edit this file directly. Your changes will be lost
;; the next time the sources are tangled.
;;
;; Filename: early-init.el
;; Description: Early initialization
;; Author: Norman Walsh
;; Original Author: Mingde (Matthew) Zeng
;; URL: https://github.com/MatthewZMD/.emacs.d
;; Compatibility: emacs-version >= 27
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Commentary:
;;
;; Emacs 27 introduces early-init.el, which is run before init.el,
;; before package and UI initialization happens.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Code:

<<early-defer-gc>>

<<early-disable-package-startup>>

<<early-file-name-handler-alist>>

<<early-site-run-file>>

<<early-interfaces>>

(provide 'early-init)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; early-init.el ends here

init.el

<<lexical-binding>>

;; This is Norm’s Emacs init.el file.

;; N.B. This file is generated automatically from literate sources.
;; Do not edit this file directly. Your changes will be lost
;; the next time the sources are tangled.

;; package.el and to use use-package in a more idiomatic fashion.

;;; Commentary:

;;; Code:

<<early-init-26>>

<<gc-cons-threshold>>

<<gc—out-of-focus>>

<<gc-avoid-in-minubuffer>>

<<load-path>>

<<constants>>

<<custom-file>>

<<remove-org>>

<<bootstrap-straight>>

<<gc-magic>>

<<use-package>>

<<system-type>>

<<my-defuns>>

<<my-settings>>

<<immortality>>

<<prettify>>

<<white-space>>

<<ctl-t-bindings>>

<<ctl-x-bindings>>

<<global-bindings>>

<<xmlunicode>>

<<mode-bindings>>

<<package-doct>>

<<org-mode>>

<<package-org-sticky-header>>

<<package-org-jira>>

<<package-avy>>

<<package-crux>>

<<package-disk-usage>>

<<package-atomic-chrome>>

<<package-zel>>

<<package-diminish>>

<<package-om>>

<<package-visual-lines>>

<<package-org-to-xml>>

<<package-ack>>

<<package-deadgrep>>

<<package-bbdb>>

<<package-bind-key>>

<<package-charmap>>

<<package-replace-colorthemes>>

<<package-company-mode>>

<<package-company-emoji>>

<<package-cperl-mode>>

<<package-rainbow-mode>>

<<package-css-mode>>

<<package-dash>>

<<package-magit>>

<<package-docker-related>>

<<package-emojify>>

<<package-exec-path-from-shell>>

<<package-ledger-mode)>>

<<package-flycheck-related>>

<<package-graphviz-dot-mode>>

<<package-hydra>>

<<package-git-gutter>>

<<package-groovy-mode>>

<<package-projectile>>

<<package-restclient>>

<<package-helm>>

<<package-helm-projectile>>

<<package-helm-wordnet>>

<<package-restclient-helm>>

<<package-all-ext>>

<<package-helm-ag>>

<<package-helm-bbdb>>

<<package-helm-flycheck>>

<<package-helm-swoop>>

<<package-helm-company>>

<<package-hyperspace>>

<<package-multiple-cursors>>

<<package-markdown-related>>

<<package-markup-faces>>

<<package-rainbow-delimiters>>

<<package-recentf>>

<<package-rnc-mode>>

<<package-s>>

<<package-sass-mode>>

<<package-javascript-related>>

<<package-typescript-related>>

<<package-web>>

<<package-xmlunicode>>

<<package-yaml-mode>>

<<package-org-bullets>>

<<package-org-cliplink)>>

<<package-org-context>>

<<package-org-tree-slide>>

<<package-htmlize>>

<<package-org-journal>>

<<package-calfw>>

<<package-code-library)>>

<<package-wwtime>>

<<package-xml-quotes>>

<<package-synosaurus>>

<<package-powerthesaurus>>

<<package-websocket>>

<<package-writegood-mode>>

<<package-beacon>>

<<package-wsd-mode>>

<<package-jdee>>

<<package-git-timemachine>>

<<package-tldr>>

<<package-python-mode>>

<<package-plantuml-mode>>

<<package-elpy>>

<<package-company-restclient>>

<<package-emacs-request>>

<<package-ob-restclient>>

<<package-ob-ml-marklogic>>

<<package-xproc-mode>>

<<package-minions>>

<<package-annotate>>

<<package-sparql-mode>>

<<package-org-ref>>

<<package-undo-propose>>

<<package-dimmer>>

<<package-dashboard>>

<<package-yankpad>>

<<package-org-mac-iCal>>

<<package-company-marklogic>>

<<package-helm-org-contacts>>

<<package-xquery-mode>>

<<package-poet-theme>>

<<package-org-ql>>

<<package-org-super-agenda>>

<<package-emacs-gfs>>

<<package-emacs-htmlize>>

<<package-org-msg>>

<<package-org-brain>>

<<package-perspective>>

<<package-flyspell>>

<<package-goto-chg>>

<<package-org-screenshot>>

<<package-org-brain>>

<<package-mu4e>>

<<unsorted-bag-of-stuff>>

Web mentions

Please provide your name and email address. Your email address will not be displayed and I won’t spam you, I promise. Your name and a link to your web address, if you provide one, will be displayed.

Your name:

Your email:

Homepage:

Do you comprehend the words on this page? (Please demonstrate that you aren't a mindless, screen-scraping robot.)

What is ten plus six?  (e.g. six plus two is 8)

Enter your comment in the box below. You may style your comment with the CommonMark flavor of Markdown.

All comments are moderated. I don’t promise to preserve all of your formatting and I reserve the right to remove comments for any reason.