My Emacs Init - Matt Whipple

Site Nav

Overview

This file captures my evolving emacs configuration using literate programming.

I'll likely be integrating all of the content in the currently separate `mw-config` repo into literate programming files in this site and likely publish the tangled outputs separately to reduce consumption overhead.

I'm currently being very judicious about which emacs packages to use, preferring a combination of standard functionality and a slow stream of packages which I've read through.

Conventions

Parent Lists

Throughout this file I try to group some of the related lines into blocks which are always enclosed within a single parent list; this allows for easy collapsing of those sections via that parent.

Explicit Defaults

My configuration will also reflect a lot of standard behavior. Much of this is redundant but acts as a convenient vehicle for me to document things for myself. I'm likely to go back and wrap these in a comment macro so they exist in the configuration file but are not actually executed thereby acting as documentation only without introducing inadvertent side effects or costs.

Prefer Code and Keys

I prefer to manipulate emacs fairly directly through things like elisp and bound commands rather than things like the customize interface or menus.

A Tree of Consistent Bindings

I think one of the complaints often leveled against emacs is how arcane some of the key sequences are, but I am likely to make some of them seem even more arcane. There's a potential tension between making key sequences easier to type versus keeping them in a more consistent structure. My idealized pursuit is that as much as possible all of the bindings can be represented as a tree where each prefix key descends to a a cohesive grouping of bindings, and those bindings primarily carry the same intent across modes. In standard emacs configuration some keys may not fall into such a grouping or be lifted for easier input, and very often the key bindings shift to provide more convenient alternatives in some modes.

Each internal node within the tree would correspond to a well defined key map, which emphasizes the role of the contained grouping, therefore each prefix key would point to a target map rather than leaving multiple levels within the same map.

This is currently a half-baked idea which may guide some of the choices herein but is subject to change or abandonment. The idea of preferring consistent structure over ease of use is largely around easier discoverability and trying to leverage muscle memory to compensate for any short term gains. This is also likely to be tweaked to accommodate my use of a keyer if and when I start to use one of those again.

A related mostly untried convention is to prefer using the control modifier to indicate internal nodes rather than any leaf nodes (so each complete sequence would contain a sequence of C-</something/> events finished with one not of that pattern.

Installation

Installation of the init file is likely to be handled later by a build tool (make) but in the short term it can be handled directly here. The default babel behavior will be modified locally and then tangle will be called to use those defaults.

(setq-local
  org-babel-default-header-args
  (list
    '(:comment . noweb)
    (cons :tangle (format "%s/.emacs.d/init.el" (expand-file-name "~")))
    org-babel-default-header-args))

(org-babel-tangle)

TODO Replace this with a composed master block.

File Structure

Currently I'm using a single monolithic emacs config file. I'm likely to break this up over time though it will likely remain a single top-level file performing the configuration though it may call into other files which absorb some of the more specialized details.

The file itself will follow a structure along the lines of:

<<header>>
<<bootrap-and-initializaton>>

Header

As in pretty much any source file, this one will start with a descriptive block comment. I don't have much to say at the moment though I should probably borrow the typical elisp block comment structure.

;;; init.el ---- Configure my emacs. -*- lexical-binding: t; -*-

Bootstrap and Initialization

Local Variables

Some parameters may be based on fairly specific environmental information. These will be consolidated outside of the rest of the configuration so that the latter can remain relatively portable (beyond expecting these variables to exist).

These variables may also be later extracted from this file entirely as a model I tend to like is one where the variables are set in a local file which then loads further initialization files (and therefore would not be present here).

(setq                                   ; Configure local variables
  mw-docs (format "%s/Documents" (expand-file-name "~"))
  mw-hq (format "%s/hq" mw-docs)
  mw-default-org (format "%s/main.org" mw-hq)
  mw-org-src (format "%s/org-mode" mw-docs))

Tweak INFOPATH

INFOPATH should be set in the environment and loaded as needed (potentially with exec-from-shell). But until I circle back around to integrating my config management into this new process this can just be stuck in here.

(use-package info
  :custom
  Info-directory-list (cons "/usr/share/info" Info-directory-list))

org-mode source

Install org-mode from source while working through a potential issue. Ideally the source would also be checked out as needed using a build tool, but that's skipped for the time being.

(add-to-list 'load-path (format "%s/lisp" mw-org-src))
(add-to-list 'load-path (format "%s/contrib/lisp" mw-org-src))

Package

Most of the actual package retrieval will be done through use-package. Outside of that the main concern is just defining the desired archive sources.

(progn                                  ; PACKAGING
  (require 'package)
  (setq package-archives '(("gnu" . "https://elpa.gnu.org/packages/")
                           ("melpa" . "https://melpa.org/packages/"))))

use-package[emacs-use-package-github]

I like use-package primarily for the organizational aspects it introduces. In a previous emacs life I started my own set of similar macros to provide an orientation more aligned with concepts rather than packages and I may make use of some of the pluggability of use-package to provide some of that value again. My previous distinction may also have been fairly myopic as packages can ultimately be viewed as a standard means to budle up arbitrary bits of code and therefore creating packages which correspond to any other perceived concepts would be perfectly reasonable while aligning with the provided means of abstraction. In any case I'll almost certainly work with or build on top of use-package.

Automatically installing the package may be nice longer term, but since this is somewhat of a bootstrapping issue for this particular package and the invocation to install it is simple, the first pass will just whine if the package doesn't seem to be available.

(progn                                  ; USE-PACKAGE
  (or (package-installed-p 'use-package)
      (warn "use-package is not installed, expect bad things!"))
  (require 'use-package)
  (require 'bind-key))

Core

Some commands act as somewhat of the low-level building blocks of emacs or act upon a similarly low level, these are defined here.

(bind-keys :map global-map              ; CORE
           ("C-g" . keyboard-quit)
           ("M-x" . execute-extended-command))

Display

I like to try to maximize the space available for windows and remove those widgets I won't use. Some basic theming can be thrown in for good measure (currently just reversing the video).

(progn                                  ; DISPLAY
  (menu-bar-mode -1)
  (tool-bar-mode -1)
  (add-to-list 'default-frame-alist '(background-color . "black"))
  (add-to-list 'default-frame-alist '(foreground-color . "white")))

Mode-line

I'm not making particularly interesting use of the mode-line, but I've started to customize it as an inroad to introducing more advanced functionality. This configuration reflects emacs acting as a primary/fullscreen UI and so the mode-line also provides some system information that may otherwise be provided by an OS or window manager.

(progn                                  ; MODE-LINE
  (setq display-time-day-and-date t)
  (display-time-mode 1)
  (display-battery-mode 1)
  
  ;; Customize the mode line.
  (setq-default
   mode-line-format
   (list
    "%b L%l %p "
    mode-line-misc-info)))

TODO Explain some of this stuff

Inserting Characters

Let's insert some characters! These are all standard but included for completeness. This is focued on visible/printing characters although some non-printing chracters may be treated similarly.

I may come back and replace the individual pairs with applying the binding to each character in provided strings, but this seems sufficient to start.

org-mode uses its own `org-self-insert-command` and other modes may do the same. It's worth looking at what the code is doing but this type of switch could be handled by either defining all input characters (if no such variable already exists) or by defining them within a function which takes the command to bind as an argument.

TODO Switch to parameterized function

Lowercase Letters

(bind-keys :map global-map              ; INSERT LOWERS
           ("a" . self-insert-command)
           ("b" . self-insert-command)
           ("c" . self-insert-command)
           ("d" . self-insert-command)
           ("e" . self-insert-command)
           ("f" . self-insert-command)
           ("g" . self-insert-command)
           ("h" . self-insert-command)
           ("i" . self-insert-command)
           ("j" . self-insert-command)
           ("k" . self-insert-command)
           ("l" . self-insert-command)
           ("m" . self-insert-command)
           ("n" . self-insert-command)
           ("o" . self-insert-command)
           ("p" . self-insert-command)
           ("q" . self-insert-command)
           ("r" . self-insert-command)
           ("s" . self-insert-command)
           ("t" . self-insert-command)
           ("u" . self-insert-command)
           ("v" . self-insert-command)
           ("w" . self-insert-command)
           ("x" . self-insert-command)
           ("y" . self-insert-command)
           ("z" . self-insert-command))

Uppercase Letters

(bind-keys :map global-map              ; INSERT UPPERS
           ("A" . self-insert-command)
           ("B" . self-insert-command)
           ("C" . self-insert-command)
           ("D" . self-insert-command)
           ("E" . self-insert-command)
           ("F" . self-insert-command)
           ("G" . self-insert-command)
           ("H" . self-insert-command)
           ("I" . self-insert-command)
           ("J" . self-insert-command)
           ("K" . self-insert-command)
           ("L" . self-insert-command)
           ("M" . self-insert-command)
           ("N" . self-insert-command)
           ("O" . self-insert-command)
           ("P" . self-insert-command)
           ("Q" . self-insert-command)
           ("R" . self-insert-command)
           ("S" . self-insert-command)
           ("T" . self-insert-command)
           ("U" . self-insert-command)
           ("V" . self-insert-command)
           ("W" . self-insert-command)
           ("X" . self-insert-command)
           ("Y" . self-insert-command)
           ("Z" . self-insert-command))

Numbers

(bind-keys :map global-map              ; INSERT NUMBERS
           ("0" . self-insert-command)
           ("1" . self-insert-command)
           ("2" . self-insert-command)
           ("3" . self-insert-command)
           ("4" . self-insert-command)
           ("5" . self-insert-command)
           ("6" . self-insert-command)
           ("7" . self-insert-command)
           ("8" . self-insert-command)
           ("9" . self-insert-command))

Symbols

These are listed roughly in the order they appear on the keyboard used at the time, going from the top left to the bottom right row-wise.

(bind-keys :map global-map              ; INSERT SYMBOLS
           ("`" . self-insert-command)
           ("~" . self-insert-command)
           ("!" . self-insert-command)
           ("@" . self-insert-command)
           ("#" . self-insert-command)
           ("$" . self-insert-command)
           ("%" . self-insert-command)
           ("^" . self-insert-command)
           ("&" . self-insert-command)
           ("*" . self-insert-command)
           ("(" . self-insert-command)
           (")" . self-insert-command)
           ("-" . self-insert-command)
           ("_" . self-insert-command)
           ("=" . self-insert-command)
           ("+" . self-insert-command)
           ("[" . self-insert-command)
           ("]" . self-insert-command)
           ("{" . self-insert-command)
           ("}" . self-insert-command)
           ("\\" . self-insert-command)
           ("|" . self-insert-command)
           (";" . self-insert-command)
           (":" . self-insert-command)
           ("'" . self-insert-command)
           ("\"" . self-insert-command)
           ("," . self-insert-command)
           ("." . self-insert-command)
           ("<" . self-insert-command)
           (">" . self-insert-command)
           ("/" . self-insert-command)
           ("?" . self-insert-command))

Utilities

Sometimes self-insert-command isn't enough; maybe your keyboard doesn't have the needed key or maybe there's some magic that needs to be avoided or tweaked.

(bind-keys :map global-map              ; INSERT UTILITIES
           ("C-q" . quoted-insert))

Motion

These commands are focused on moving around the current buffer without making modifications.

(bind-keys :map global-map              ; MOTION
           ("C-f"   . forward-char)
           ("C-b"   . backward-char)
           ("C-n"   . next-line)
           ("C-p"   . previous-line)
           ("M-f"   . forward-word)
           ("M-b"   . backward-word)
           ("C-a"   . move-beginning-of-line)
           ("C-e"   . move-end-of-line)
           ("C-v"   . scroll-up-command)
           ("M-v"   . scroll-down-command)
           ("C-l"   . recenter-top-bottom)
           ("M-<"   . beginning-of-buffer)
           ("M->"   . end-of-buffer)
           ("C-M-n" . forward-list)
           ("C-M-p" . backward-list))

Search/Navigation

Search is somewhat a specialized variation of Motion that seems rich enough to split into its own section. Additionally, search may target the current buffer or a wider scope.

(bind-keys :map global-map              ; SEARCH
           ("C-s" . isearch-forward)
           ("C-r" . isearch-backward)
           ("M-." . xref-find-definitions))

Editing

While pretty much everything is actually editing, this section is used for relatively basic but potentially interesting behavior. This includes things like manipulation of whitespace and content in ways that may be relatively simple or may be made to be more smart or electric.

(bind-keys :map global-map      ; EDITING
           ("RET" . newline)
           ("DEL" . delete-backward-char)
           ("C-d" . delete-char)
           ("C-o" . open-line)
           ("C-w" . kill-region)
           ("M-w" . kill-ring-save)
           ("C-j" . electric-newline-and-maybe-indent)
           ("M-l" . downcase-word)
           ("M-u" . upcase-word)
           ("C-k" . kill-line)
           ("M-d" . kill-word)
           ("M-\\" . delete-horizontal-space)
           ("M-%" . query-replace)

ChromeOS produces some alternative keycodes for some combinations.

           ("<deletechar>" . backward-kill-word))

Rectangles

Rectangles are a pretty basic concept that can be used to deliver some useful functionality through a simpler mechanism than may be otherwise used.

(bind-keys :prefix "C-x C-r"
           :prefix-map rectangle-map
           :prefix-docstring "Mess with rectangles"
           ("o" . open-rectangle)
           ("k" . kill-rectangle))

Manage the Mark/Kill Ring

Make some regions and shuffle them around.

(bind-keys :map global-map              ; MARK/RING
           ("C-SPC" . set-mark-command)
           ("C-y"   . yank)
           ("M-y"   . yank-pop))

File Management

Sooner or later I'm probably going to want to save some buffers or load some files (probably sooner).

(bind-keys :map global-map
           ("C-x C-s"     . save-buffer)

`ffap` can act as a useful extended version of `find-file`, so I'm just going to use it as a replacement of the latter and see if anything breaks.

           ("C-x C-f" . ffap))

Buffer Management

I currently use a pretty simple approach to buffer management which I'll evolve into something slicker as I become more familiar with appropriate enabling features. Without tuned configuration a running emacs can quickly accrete a collection of buffers which have long since served their purpose, so I tend to normally iterate through all buffers so that I can close those that are no longer needed.

Currently I'm also tuning my use of Org agenda and am looking to collect that agenda out of assorted files which would be loaded into buffers during agenda creation or refresh, so skipping over those buffers during an iteration would help avoid agenda churn.

(setq switch-to-prev-buffer-skip
  (lambda (window buffer bury-or-kill)
    (member (buffer-file-name buffer) org-agenda-files)))

(bind-keys :map global-map
           ("C-x <right>" . next-buffer)
           ("C-x <left>"  . previous-buffer)
           :prefix "C-x C-b"
           :prefix-map buffer-map
           :prefix-docstring "Manage some buffers"
           ("b" . list-buffers)
           ("r" . rename-buffer))

Help

One of the best aspects of emacs is how discoverable all of the information is (and then how easily it can be tinkered with).

(bind-keys :prefix "C-h"                ; HELP!
           :prefix-map help-map
           :prefix-docstring "Help me!"
           ("b" . describe-bindings)
           ("f" . describe-function)
           ("i" . info)
           ("k" . describe-key)
           ("l" . view-lossage)
           ("m" . describe-mode)
           ("p" . describe-package)
           ("v" . describe-variable)
           ("w" . where-is))

Version Control

I use git pretty extensively, and I've used magit in the past which is pretty snazzy and in all likelihood I'll probably use it again. For now I'm using the built-in VC library which attempts to abstract the underlying system and therefore doesn't match git quite as well. I'm using it (complemented by the command line as necessary) until I fully run up against its limitations and am driven to dig into magit some more.

(use-package vc
  :bind (:prefix "C-x C-v"
         :prefix-map vc-map
         :prefix-docstring "Bind version control operations."
         ("v" . vc-next-action)
         ("d" . vc-dir)
         :map vc-dir-mode-map
         ("M-m" . vc-dir-mark)
         ("M-u" . vc-dir-unmark)
         ("M-=" . vc-diff)))

exec-path-from-shell[emacs-exec-from-shell-github]

exec-path-from-shell is useful to make sure forked subprocesses such as comint buffers behave as desired based on shell configuration. While this has generally been a problem on OS X it also seems to affect running emacs as a ChromeOS Linux app. The ChromeOS behavior is likely due to environment.d being a more appropriate home than the shell initialization scripts[chromium-container-environment]. It seems to be innocuous otherwise so it will just be activated consistently.

Internally this package is pretty simple. The primary functionality is built on top of some useful utility functions that revolve around evaluating the output produced by commands pass to the shell. This functionality would be suitable for generalization and elevation from the package namespace if the need arises.

(use-package exec-path-from-shell
  :ensure t
  :config
  (exec-path-from-shell-initialize)

Beyond standard needs like PATH I also want the subprocesses to make use of any running ssh-agent so things like git over ssh work.

  :custom
  (exec-path-from-shell-variables
    '("SSH_AUTH_SOCK"
      "SSH_AGENT_PID")))

Utilities

I normally try to avoid the term "utility" as it's usually overworked and tied to things that should have better names or homes…but it is a term that jumped out at me and lends itself to a decent keybinding (which some other alternatives didn't), so that's what I'll go with.

Here utility means some kind of self contained command which is likely to be executed across a wide range of contexts.

(bind-keys :prefix "C-x C-u"            ; UTILITIES
           :prefix-map global-utility-map
           :prefix-docstring
           "Provide some general global utilities."
           ("!" . shell-command)
           ("c" . compile)
           ("s" . shell))

Modes

Define some major and minor modes which are sometimes explicitly toggled.

(bind-keys :prefix "C-x C-m"            ; MODES
           :prefix-map modes-map
           :prefix-docstring
           "Provide globally toggle-able modes."
           ("h" . hexl-mode)
           ("v" . view-mode))

Org Mode

I likely use org-mode more than any other emacs functionality as I use it to coordinate other work. I'm also starting to use it for literate programming, and this Web site: both of which provide larger chunks of activity beyond the smaller more continuous stream related to supporting other activity.

Since I currently only have a single capture template, I'd like to bypass selection.

(use-package org-mode
  :mode "\\.org\\'"
  :bind (:prefix "C-x C-o"
         :prefix-map x-org
         :prefix-docstring "Globally bind org keys."
         ("a" . org-agenda)
         ("c" . (lambda (goto) (interactive "P") (org-capture goto "t")))
         ("l" . org-store-link)
         :map org-mode-map
         ("M-<RET>"     . org-meta-return)
         ("M-S-<RET>"   . org-insert-todo-heading)
         ("C-<RET>"     . org-insert-heading-respect-content)
         ("C-S-<RET>"   . org-insert-todo-heading-respect-content)
         ("M-<DOWN>"    . org-metadown)
         ("M-<UP>"      . org-metaup)
         ("M-<LEFT>"    . org-metaleft)
         ("M-S-<LEFT>"  . org-promote-subtree)
         ("M-<RIGHT>"   . org-metaright)
         ("M-S-<RIGHT>"  . org-demote-subtree)
         ("C-c @"        . org-mark-subtree)
         ("C-c C-d"     . org-deadline)
         ("C-c C-k"     . outline-show-branches)
         ("C-c C-j"     . org-goto)
         ("C-c C-r"     . org-reveal)
         ("C-c C-s"     . org-schedule)
         ("C-c C-t"     . org-todo)
         ("C-c C-w"     . org-refile)
         ("C-c C-x C-w"  . org-cut-subtree)
         ("C-c C-x M-w"  . org-copy-subtree)
         ("C-c C-x b"   . org-tree-to-indirect-buffer)
         ("C-c C-x v"   . org-copy-visible)

Some of the more structural navigation commands are bound to using the C-M- modifier with an attempt to use behavior analogous to other modifiers. In particular f/b vs n/p are flipped from what org normally provides under C-c C- as moving to a sibling feels far more similar to changing lines whereas potentially descending to a child feels more aligned with advancing a character.

         ("C-M-f"     . org-next-visible-heading)
         ("C-M-b"     . org-previous-visible-heading)
         ("C-M-n"     . org-forward-heading-same-level)
         ("C-M-p"     . org-backward-heading-same-level)
         ("C-M-^"     . outline-up-heading)

ChromeOS produces some alternative keycodes for some combinations.

         ("<next>"   . org-metadown)
         ("<prior>"  . org-metaup)

While TAB is typically used for cycling, I'd ideally like to keep TAB as an input command and have a more global folding/unfolding toggle which could be used across modes.

         ("C-M--"    . org-cycle))

Configure some general org settings. The notes file is set to support org-capture logging to the desired file without messing with the templates (though this is likely to be done later.

         :init
         (setq org-directory mw-hq)
         :custom
         (org-default-notes-file mw-default-org)
         (org-catch-invisible-edits 'error)

This allows cycling of an entire doc which does not have a single root headline by cycling at the beginning-of-buffer. This will generally be facilitated through the use of #+TITLE: which can act as a typical target for this behavior.

         (org-cycle-global-at-bob t)

My current use of literate programming involves splitting a single output across multiple blocks so that comments can be interleaved as appropriate. The subsequent blocks are indented relative to the previous blocks, and that should be preserved when tangling.

         (org-src-preserve-indentation t)

I use org agenda to organize my daily tasks, so some configuration to support that use will be defined here. There seems to be some surprising behavior or bugs around the sorting strategy such that it works mostly but not completely as configured, so I may look in to that at some point. There's also seems to be some limitations around missing/absent values in the standard strategy chaining provided which may also warrant some tweaking.

         (org-agenda-todo-ignore-with-date t)
         (org-agenda-span 'day)
         (org-agenda-sorting-strategy
          '((agenda time-up priority-down timestamp-up)
            (todo deadline-down scheduled-down)
            (tags priority-down category-keep)
            (search category-keep)))

The agenda files is defined by any matching the standard pattern under org-directory, only a subset of these files is likely to be relevant but this feels like a good, dumb, starting point to allow things to work flexibly without requiring fiddling.

         (org-agenda-files 
           (directory-files-recursively org-directory org-agenda-file-regexp t))

I'd like to not show the time-grid since it takes up a fair amount of real estate and I like to mix agenda with TODOs.

         (org-agenda-time-grid
           '((daily today require-timed)
             () "" "")))

org-ref[emacs-org-ref-github]

org-ref is currently used so that I can manage my sources in BibTeX and reference them from org files.

(use-package org-ref
  :ensure t)

TODO Move away from org-ref

Global Style

Pretty much any file that would be edited should end in a newline as per the POSIX specification. I'm not sure of any files I'd edit in emacs for which this wouldn't apply but these can just be added as exceptions.

(progn                                  ; GLOBAL STYLE
  (setq-default require-final-newline t))

State Retention

(use-package desktop
  :init
  (desktop-save-mode))

Link/Location Management

I'm hoping to gravitate towards some form of unified approach of tracking assorted locations across systems, but for now I have the basics.

(use-package bookmark
  :bind (:prefix "C-x C-l"
         :prefix-map state-keeper-map
         :prefix-docstring "Stash some state away for re-entry."
         ("m" . bookmark-set)

ChromeOS URL Management

Running Emacs on ChromeOS means that the application itself will be run inside of a container within a VM[chromium-containers-and-vms]. Opening URLs in Chrome outside of the container therefore requires passing a message to the host OS, which is supported in ChromeOS through Garcon[chromium-garcon]. While I was prepared to have to fiddle to this, I unsuprisingly didn't have to since browse-url-default-browser seems to already detect and work with garcon-url-handler; someone else (likely from Google) has already taken care of that.

         ("b" . browser-url-at-point))

  :custom
  (bookmark-save-flag 1))

Development

General

This will define some configuration to support development in general rather than being oriented towards any particular language. Some of these may be further specialized by more specific modes.

TODO The lambda hook handler can likely be replaced by

use-pacakage, but the invocation or required supporting code isn't immediately obvious.

(progn                                  ; DEV
  (add-hook
   'prog-mode-hook
   (lambda ()

Support hiding/showing blocks of code.

     (hs-minor-mode)
     (bind-keys :map prog-mode-map
                ("C-M--" . hs-toggle-hiding))))
  (bind-keys ("M-SPC" . complete-symbol)
             ("M-;"   . comment-dwim)))

Emacs Lisp

(progn                                  ; ELISP
  (add-to-list 'auto-mode-alist '("\\.el\\'" . emacs-lisp-mode))
  (bind-keys ("C-x C-e" . eval-last-sexp)

The general pattern of being able to navigate through program structure should be available across languages, so this is likely to need revisiting: but the starting point will be the standard defined lisp list navigation.

             ("C-M-n" . forward-list)
             ("C-M-p" . backward-list)))

C

(progn                                  ; C
  (add-to-list 'auto-mode-alist '("\\.c\\'" . c-mode)))

Mail

I was using Gnus for email and plan to again, but I'm currently using my browser until I'm willing to dedicate time to tuning some specific behaviors around everything that may be associated with the gmail account.

(defun mw-gnus-read-forward ()
  (interactive)
  (gnus-group-read-group 50))

(use-package gnus
  :bind (:map global-utility-map
         ("g" . gnus)
         ("m" . gnus-summary-mail-other-window)
         :map gnus-group-mode-map
         ("M-g" . gnus-group-get-new-news-this-group)
         ("M-<down>" . mw-gnus-read-forward)
         :map gnus-summary-mode-map
         ("M-<down>" . gnus-summary-next-page)
         ("C-c m" . gnus-summary-move-article))
         
  :custom
  (gnus-select-method
    '(nnimap "imap.gmail.com" (nnimap-server-port "imaps"))))
    

Web

(use-package eww
  :bind (:map global-utility-map
         ("w" . eww)
         :map eww-mode-map
         ("C-c w" . eww-copy-page-url)))

Music

Among other outputs, I'll be looking to use Emacs to manage some music related documents.

<<configure-lilypond>>

LilyPond

I use LilyPond to create sheet music. It provides emacs support as part of its source bundle but it does not seem to be readily consumable as a package. I'll look at figuring out a more preferable way to integrate this but in the meantime I'd started to embed some of the logic into my emacs init file which I'll copy forward for now (and re-evaluate later).

(progn                                  ; MUSIC
  (defvar LilyPond-mode-map()
    "Keymap used in `LilyPond-mode' buffers.")

  (defun LilyPond-mode ()
    "Major mode for editing LilyPond music files.

This mode knows about LilyPond keywords and line comments, not about
indentation or block comments.  It features easy compilation, error
finding and viewing of a LilyPond source buffer or region.

COMMANDS
\\{LilyPond-mode-map}
VARIABLES

LilyPond-command-alist\t\talist from name to command"
    (interactive)

    ;; set up local variables
    (kill-all-local-variables))

  (add-to-list 'auto-mode-alist '("\\.ly$" . LilyPond-mode))
  (add-to-list 'auto-mode-alist '("\\.ily%" . LilyPond-mode)))

Sources

Bibliography

  • [emacs-use-package-github] @miscemacs-use-package-github, title = use-package (GitHub), url = https://github.com/jwiegley/use-package, status = wip,
  • [emacs-exec-from-shell-github] @miscemacs-exec-from-shell-github, title = exec-path-from-shell (GitHub), url = https://github.com/purcell/exec-path-from-shell, notes = This package delivers solid functionality in nice lightweightcode., status = done,
  • [chromium-container-environment] @miscchromium-container-environment, title = Chromium OS Docs - Running Custom Containers Under Chrome OS: Can I set environment variables for my container?, url = https://chromium.googlesource.com/chromiumos/docs/+/master/containers_and_vms.md#can-i-set-environment-variables-for-my-container, notes = This provides a decent high level overview of Chrome OS'es use of containers with relatively user-centric information., status = done,
  • [emacs-org-ref-github] @miscemacs-org-ref-github, title = org-ref (GitHub), url = https://github.com/jkitchin/org-ref, status = wip,
  • [chromium-containers-and-vms] @miscchromium-containers-and-vms, title = Chromium OS Docs - Running Custom Custom Containers Under Chrome OS, url = https://chromium.googlesource.com/chromiumos/docs/+/master/containers_and_vms.md, status = done,
  • [chromium-garcon] @miscchromium-garcon, title = Garcon, url = https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/vm_tools/garcon/, notes = Gracon is one of the main channels between the host and containers. The README provides some high-level functional descriptions without much detail., status = done,

Author: mwhipple

Created: 2020-10-27 Tue 19:37

Validate