my emacs configuration

I thought I'd test the ox-gemini package for Emacs by having it convert my configuration org file. :)

source repository

As you can see below, the conversion isn't perfect.

GNU Emacs configuration

Use `C-c C-v t' to generate the following files if you've cloned this repository and made changes:

When defining custom functions or variables for my `~/.emacs', I've been prefixing them with `emacs-init/' to keep them in a kind of namespace (since Emacs Lisp doesn't actually provide built-in namespacing). You're welcome to use this prefix yourself if using this config and improving on it, or use your own prefix.


# GNU Emacs Configuration

I'm tired of my GNU Emacs configuration being a mess, so it's time to organize it. It's available under [GPL-3][1] if you want to use it yourself and you're worried about licensing.

## Installation

This repository comes with a [makefile][2]. If you have GNU Make installed, you can just run `make install` in your terminal to build the config and install it if you've modified your copy. You can also run `make` to just generate the config.

Otherwise, you can manually run the following commands in your terminal after moving to where you cloned this repository:

mkdir -p ~/.emacs.d

cp init.el ~/.emacs.d/

## Extending the Config
Add source blocks as needed. Just copy and paste:

#+BEGIN_SRC emacs-lisp :tangle yes


## Credits

I stole bits and pieces of my config from various sources, listed below:

- [System Crafters][3]
- [Howardism][4]
- [Emacs Redux][5]

[1]: ./LICENSE
[2]: ./Makefile


Run this in the repository's directory to install.

.DEFAULT: tangle

  emacs -Q --batch --eval "(progn (require 'ob-tangle) (dolist (file command-line-args-left) (with-current-buffer (find-file-noselect file) (org-babel-tangle))))"

install: tangle
  install -m 644 config.el ${DEST}

Garbage Collection Adjustments

Let's adjust the garbage collection threshold, and have Emacs do

garbage collection when it loses focus.

(setq gc-cons-threshold 100000000)
(add-hook 'focus-out-hook 'garbage-collect)

Package Initialization

Let's get the package system set up first.

Initialize Package Sources

(require 'package)

(setq package-archives '(("melpa" . "")
                         ("org" . "")
                         ("elpa" . "")))

Initialize the Package Mangler


Update Installed Packages

(unless package-archive-contents

Set up use-package

I want to set up package using `use-package' and make sure it works

even if I end up going back to BSD.


(unless (package-installed-p 'use-package)
  (package-install 'use-package))

(require 'use-package)
(setq use-package-always-ensure t)

Using `use-package-always-ensure' saves me some typing and guarantees


External Secret Storage

Rather than put credentials, API keys, and location information here,

I'm using a separate file called `secrets.el'.

(load "~/.emacs.d/secrets.el")

Incidentally, this is what `secrets.el' looks like:

(setq user-full-name "YOUR NAME"
    user-mail-address "YOUR EMAIL"
    erc-nick "YOUR IRC NICK"
    erc-password "YOUR IRC NICK PASSWORD"
    sunshine-location "CITY,STATE/PROVINCE,COUNTRY"
    sunshine-appid "YOUR OPEN WEATHER MAP API KEY")

Basic/Built-in Settings

These are settings that don't require external packages or Elisp


External Secret Storage

Let's load credentials from a separate file.

Default Font Families

I'm going to define some font family variables so that I can set them

once and use them wherever I need them. Gotta stay DRY, you know?

(defvar emacs-init/default-font "Fira Code Retina")
(defvar emacs-init/default-variable-font "Noto Serif")

To install these fonts on a Debian-style distro, use the following


sudo apt install fonts-firacode fonts-noto-hinted

Default Font Sizes

These font-sizes made sense on my Thinkpad T60, but you may want to

bump them up for a higher-resolution display.

(defvar emacs-init/default-font-size 120)
(defvar emacs-init/default-variable-font-size 140)

Set Default, Fixed-Pitch, and Variable-Pitch Faces

Now we'll use the variables I defined earlier to set my fonts.

(set-face-attribute 'default nil :font emacs-init/default-font :height emacs-init/default-font-size :weight 'regular)
(set-face-attribute 'fixed-pitch nil :font emacs-init/default-font :height emacs-init/default-font-size :weight 'regular)
(set-face-attribute 'variable-pitch nil :font emacs-init/default-variable-font :height emacs-init/default-variable-font-size :weight 'regular)

No Splash Screen

I know I'm using Emacs. Just gimme a scratch buffer.

(setq inhibit-startup-message t)

Suppress Unnecessary UI Elements

I don't want a scrollbar, a toolbar, or tooltips.

(scroll-bar-mode -1)
(tool-bar-mode -1)
(tooltip-mode -1)

The menu comes in handy on occasion, though, so I'll refrain from

suppressing it for now. If you disagree, change the tangle property on

the block below to 'yes'.

(menu-bar-mode -1)

Make ESC quit prompts

In case I'm too drunk to remember to use C-g to back out of

something—or have spent too long using vi.

(global-set-key (kbd "<escape>") 'keyboard-escape-quit)

Wider Fringes

Let's have a little breathing room on the sides. There's no need for

buffers to be flush with frame borders.

(set-fringe-mode 15)

Visual Bell

If I screw up, I don't want to hear it. Just flash the screen. Not

like I've got epilepsy.

(setq visible-bell t)

Unicode Settings

I used this on OpenBSD to ensure that Emacs consistently used UTF-8. I

don't think it does any harm to use it on GNU/Linux.

(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)

Column Display in Modeline

By default, the modeline only shows the current line. I want to see

the current column, too.

(column-number-mode t)

File Size in Modeline

Emacs doesn't display the file/buffer size in the modeline,

either. Let's change that.

(size-indication-mode t)

Line Number Display

I want to show line numbers on the sides when coding, but not in

certain text and shell modes.

(global-display-line-numbers-mode t)

(dolist (mode '(org-mode-hook
  (add-hook mode (lambda () (display-line-numbers-mode 0))))

Buffer Identification

How do we tell buffers apart if they have the same name? Fortunately,

uniquify comes with GNU Emacs by default and doesn't require a


(require 'uniquify)
(setq uniquify-buffer-name-style 'forward)

Frame Title Based on Current Buffer

I want the Emacs frame (window for all you normies) to reflect the

filename of the current buffer.

(setq frame-title-format
      '((:eval (if (buffer-file-name)
           (abbreviate-file-name (buffer-file-name))

Scroll Behavior Adjustments

These settings seem to smooth out scrolling for me, but I could be

wrong and might have [misread the manual]. Make adjustments as needed.

(setq scroll-margin 0
  scroll-conservatively 100000
  scroll-preserve-screen-position 1)

misread the manual

ERC (Emacs Relay Chat)

I want to use Emacs as my IRC client. Yes, I know how crazy that


(require 'erc)

However, because Libera Chat uses SSL, we'll need TLS support.

(require 'tls)

Set up a keybinding to connect to Libera Chat

I want to use `C-c e i' to start ERC and connect to Libera.Chat

(Freenode's successor)

(global-set-key "\C-cel" (lambda () (interactive)
                           (erc-tls :server "" :port "6697"
                                    :nick "starbreaker")))

Don't forget to change the nick here.

Automatically join certain channels on Libera Chat

When I join, I want in on the following channels:

I'll also join these, just in case.

(setq erc-autojoin-channels-alist '(("" "#gemini" "#midnight-pub" "#callahans" "#emacs" "#erc" "#debian")))

Other Options

Here are some quality-of-life settings I got out of the ERC manual.

(setq erc-rename-buffers t
      erc-interpret-mirc-color t)

Fun with Dired

[Dired] is another sweet tool built into GNU Emacs. It's a file

manager in your editor.

First, let's use Dired-X when loading Dired to extend its


(eval-after-load "dired"
  '(require 'dired-x))

Next, let's tweak a few settings. I want dired to trash files by

default, and put them in the standard trash location. I also want

recursive copies and deletes.

(setq dired-recursive-deletes 'always
      dired-recursive-copies 'always
      dired-deletion-confirmer 'y-or-n-p
      dired-clean-up-buffers-too nil
      delete-by-moving-to-trash t
      trash-directory "~/.local/share/Trash/files/"
      dired-dwim-target t
      dired-listing-switches "-alv")

I'm going to bind a couple of keys to make Dired work with EMMS; I

like to play entire albums by feeding EMMS a directory since I'm anal

about keeping my music organized on disk.

I also have an alternate keybinding to change to wdired; I prefer `C-c

w' to the default `C-x C-q'.

(add-hook 'dired-mode-hook
      (lambda ()
      (local-set-key "E" 'emms-play-dired)
      (local-set-key "A" 'emms-add-dired)
      (local-set-key (kbd "C-c w") 'wdired-change-to-wdired-mode)))

I only want to tangle the following when running OpenBSD. On most

GNU/Linux distributions, the default ls from GNU coreutils is

compatible with dired. If you're on a BSD whose ls doesn't provide GNU

extensions, or you're using busybox as your shell/coreutils, your ls

might not work right with dired. Installing GNU coreutils and enabling

this setting should sort you out.

(setq insert-directory-program "/usr/local/bin/gls")

Just make sure you adjust the path as needed.


Using gtkLP to provide a print dialog

I sometimes like to print from Emacs, especially while writing, so my

wife can read rough cuts without squinting at a screen. Having Emacs

talk to gtklp allows me to take advantage of CUPS.

(setq lpr-command "/usr/bin/gtklp")
(setq ps-lpr-command "/usr/bin/gtklp")

Since it's an external tool, install it through your package

mangler. In my case that's either `sudo apt install gtklp' or `doas

pkg_add -iv gtklp'.

Putting backups and auto-saves in /tmp

I don't like having to do `rm *~' to purge backup files, let alone `rm

-rf *~', because if I'm drunk enough to forget that '~' at the end I'm

stuck restoring from backups. Instead, let's put that stuff in /tmp

where it belongs.

(setq backup-directory-alist
      `((".*" . ,temporary-file-directory))
      `((".*" ,temporary-file-directory t)))

y/n instead of yes/no

I'm lazy. I shouldn't have to type 'yes' at a prompt when 'y' will do.

(fset 'yes-or-no-p 'y-or-n-p)

Automatically reload buffer when file is changed on disk

If a file I have open is changed on disk, I want the buffer

automatically refreshed. Emacs calls this "reverting" a buffer, most

likely for reasons that made sense when Emacs was an extension of TECO

in the 1970s.

(global-auto-revert-mode t)

Indentation settings

By default, I want to indent with spaces, with a tab width of 2. I

should be able to override this using the editorconfig package if a

given project has an .editorconfig file. Using hard tabs by default

causes headaches when manually editing YAML and JSON files

(setq-default tab-width 2
        indent-tabs-mode nil)

Kill the Current Buffer

Here's a keybinding to get rid of the current buffer once I'm done

with a file.

(global-set-key (kbd "C-c k") 'kill-this-buffer)

Print the Current Region and Buffer

Here are keybindings to print the current region and buffer since

Emacs doesn't provide one. This will convert the current region/buffer

to monochrome PostScript and send it to CUPS via gtkLP.

(global-set-key (kbd "C-c p r") 'ps-print-region)
(global-set-key (kbd "C-c p b") 'ps-print-buffer)

Elisp Functions

Emacs Lisp functions used later on get defined here.

Get track info from file tags.

(defun emacs-init/emms-track-description (track)
  (let ((artist (emms-track-get track 'info-artist))
        (year (emms-track-get track 'info-year))
        (album (emms-track-get track 'info-album))
        (tracknumber (emms-track-get track 'info-tracknumber))
        (title (emms-track-get track 'info-title)))
     ((or artist title)
      (concat (if (> (length artist) 0) artist "Unknown Artist") " - "
              (if (> (length year) 0) year "XXXX") " - "
              (if (> (length album) 0) album "Unknown Album") " - "
              (if (> (length tracknumber) 0)
                  (format "%02d" (string-to-number tracknumber))
                "XX") " - "
              (if (> (length title) 0) title "Unknown Title")))
      (emms-track-simple-description track)))))

Make eww use elpher for gopher and gemini URLs

When using eww, if I hit a gopher or gemini URL, I want eww to call

elpher. We'll install elpher later.

(defun emacs-init/eww-browse-url (original url &optional new-window)
  "Handle gemini links."
  (cond ((string-match-p "\\`\\(gemini\\|gopher\\)://" url)
     (require 'elpher)
     (elpher-go url))
    (t (funcall original url new-window))))

Org Mode Functions

These are some functions I cribbed from System Crafters. First is a

basic setup function that enables `org-indent', `variable-pitch-mode',

and `visual-line-mode'. It makes Org work more like a word processor.

(defun emacs-init/org-mode-setup ()
  (variable-pitch-mode 1)
  (visual-line-mode 1))

Next, we need to set up fonts for Org mode. This function is more

involved since we're using different font sizes for various heading

levels, and also want to replace the hyphen used in lists with a

bullet point.

(defun emacs-init/org-font-setup ()
  (dolist (face '((org-level-1 . 1.5)
                  (org-level-2 . 1.4)
                  (org-level-3 . 1.3)
                  (org-level-4 . 1.2)
                  (org-level-5 . 1.1)
                  (org-level-6 . 1.05)))
    (set-face-attribute (car face) nil 
    :font emacs-init/default-variable-font 
    :weight 'regular 
    :height (cdr face)))

  (set-face-attribute 'org-block nil :foreground nil :inherit 'fixed-pitch)
  (set-face-attribute 'org-code nil   :inherit '(shadow fixed-pitch))
  (set-face-attribute 'org-table nil   :inherit '(shadow fixed-pitch))
  (set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch))
  (set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch))
  (set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch))
  (set-face-attribute 'org-checkbox nil :inherit 'fixed-pitch)

  (font-lock-add-keywords 'org-mode
                          '(("^ *\\([-]\\) "
                             (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•")))))))

Visual Fill Setup

Let's set up visual fill and centering for text modes. This was

originally just for org mode, but I bet it work work nicely when

writing Gemini text or Markdown. I'll rename the function accordingly.

(defun emacs-init/visual-fill-setup ()
  (setq visual-fill-column-width 80
        visual-fill-column-center-text t)
  (visual-fill-column-mode 1))

When we set up the `visual-fill-column' package, we'll add hooks that

call this function for Org mode, Gemini mode, and Markdown mode.

Elfeed Shortcuts

These are shortcut functions I can use to jump around in Elfeed

(defun emacs-init/elfeed-show-all ()
  (bookmark-jump "elfeed-all"))
(defun emacs-init/elfeed-show-emacs ()
  (bookmark-jump "elfeed-emacs"))
(defun emacs-init/elfeed-show-misc ()
  (bookmark-jump "elfeed-misc"))
(defun emacs-init/elfeed-show-debian ()
  (bookmark-jump "elfeed-debian"))



This is basically the killer app for a lot of GNU Emacs people. It's

an outliner, a journaling app, a todo list, a more powerful markup

language than Markdown, and a literate programming tool. It's what I'm

using to generate this configuration.

(use-package org
  :hook (org-mode . emacs-init/org-mode-setup)
  (setq org-ellipsis " ▾")

I also want to have prettier bullets in Org mode, so we'll use


(use-package org-bullets
  :after org
  :hook (org-mode . org-bullets-mode)
  (org-bullets-bullet-list '("◉" "○" "●" "○" "●" "○" "●")))

Visual Fill Column

Let's make Org and other text markup modes look a little nicer using


(use-package visual-fill-column
  :hook (org-mode . emacs-init/visual-fill-setup)
  :hook (markdown-mode . emacs-init/visual-fill-setup)
  :hook (gemini-mode . emacs-init/visual-fill-setup))


When I want to edit Markdown directly, let's have the appropriate

mode. `markdown-mode' will give me syntax highlighting, a handy menu,

preview support, and works with `pandoc'.

(use-package markdown-mode
  :init (setq markdown-command "/usr/bin/pandoc")
  :mode (("README\\.md\\'" . gfm-mode)
     ("\\.md\\'" . markdown-mode)
     ("\\.markdown\\'" . markdown-mode)))

Gemini Text

Since I've gotten into using Gemini protocol (and prefer it over the

Web and HTML when I'm not getting paid to put up with webshit), I want

support for writing Gemtext (Gemini markup) in Emacs.

(use-package gemini-mode)

Being able to export from org mode to gemini might be nice, too.

(use-package ox-gemini
  :after org
  (require 'ox-gemini))

Command Log Mode

If for some reason I want to be able to log commands in an Emacs

session, this package will make it possible.

(use-package command-log-mode)

unfill: a nicer fill mode for hard-wrapping (or un-wrapping) text

This has come in pretty handy.

(use-package unfill
  :ensure t
  (global-set-key (kbd "<f8>") 'toggle-fill-unfill))

Async mode for Dired

Let's extend Dired further to allow asynchronous operations (thus

improving responsiveness).

(use-package async
  :diminish dired-async-mode
  :init (dired-async-mode 1))

Elpher: Smol Net Browsing in Emacs

The `elpher' package is a complement to the built-in `eww' tool; the

latter handles web browsing in emacs, and the former also lets you

view sites via the gopher and gemini protocols. We're going to install

it here, and set up a hook that allows `eww' to call `elpher' as


(use-package elpher
  (set browse-url-browser-function 'eww-browse-url)
  (advice-add 'eww-browse-url :around 'emacs-init/eww-browse-url))

EMMS (Emacs Multimedia System)

Let's use Emacs to rock out. We won't need a package since EMMS is

included in GNU Emacs. We'll also configure EMMS to cache album covers

embedded in tracks, and use Python's Tinytag library to get track


(use-package emms
 (require 'emms-setup)
 (require 'emms-info-metaflac)
 (require 'emms-info-mp3info)
 (require 'emms-info-ogginfo)
 (setq emms-source-file-default-directory "~/Music/")
 (setq emms-browser-covers 'emms-browser-cache-thumbnail-async)
 (setq emms-playlist-default-major-mode 'emms-playlist-mode)
 (setq emms-track-description-function 'emacs-init/emms-track-description)
 (add-to-list 'emms-info-functions 'emms-info-libtag)
 (add-to-list 'emms-info-functions 'emms-info-mp3info)
 (add-to-list 'emms-info-functions 'emms-info-ogginfo)
 (global-set-key (kbd "C-c e p") 'emms-playlist-mode-go)
 (global-set-key (kbd "C-c e r") 'emms-toggle-repeat-playlist)
 (global-set-key (kbd "C-c e s") 'emms-toggle-random-playlist))

Tinytag is a Python package, so we'll need to install it. This is how

I did it on Debian.

sudo apt install python3-pip
pip install tinytag

EMMS Keybindings

Here's a list of keybindings for EMMS, so I don't have to dig through

the manual. Also, I've got custom bindings that aren't in the

manual. 🐱

* Open the EMMS Playlist buffer.

* Toggle *repeat* mode on current playlist

* Toggle *shuffle* on current playlist

* next track

* previous track

* stop playback

* pause playback (and unpause)

* show track info in minibuffer

* center current track

* play track under cursor

In case I find myself doing webshit again...

I'm trying not to do webshit unless I'm getting paid (in which case I

have other computers for that) but if I find myself messing with HTML

and friends for a personal project I should probably have `web-mode'

and `emmet-mode' handy. The latter makes typing out tags a /little/

less tedious.

(use-package web-mode
  (add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.shtml\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.tpl\\.php\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.[agj]sp\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.as[cp]x\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.mustache\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.njk\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode)))

Now it's time to install `emmet-mode'...

(use-package emmet-mode
  (add-hook 'sgml-mode-hook 'emmet-mode)
  (add-hook 'html-mode-hook 'emmet-mode)
  (add-hook 'css-mode-hook  'emmet-mode))

Elfeed: reading RSS/Atom feeds in Emacs

I want to use Emacs as my feed reader, so we'll install

`elfeed'. While installing, I'll map my shortcut functions to keys for

convenience. As I add categories, I'll need new functions and


I'll also pull `elfeed-org' because I want to store my feeds list in

an org file.

(use-package elfeed-org
  (setq rmh-elfeed-org-files (list "/home/starbreaker/git/srht/elfeed-org/")))

Since we're forcing elfeed to update during init, I want to make sure

elfeed-org is set up first. We'll also have elfeed update every 8


(use-package elfeed
  :init (elfeed-update)
  :bind (:map elfeed-search-mode-map
              ("A" . emacs-init/elfeed-show-all)
              ("E" . emacs-init/elfeed-show-emacs)
              ("D" . emacs-init/elfeed-show-debian)
              ("M" . emacs-init/elfeed-show-misc))
  (run-at-time nil (* 8 60 60) #'elfeed-update))

Smart Parentheses

When I open a set of parentheses, it would be handy to have the closed

automatically. Yeah, I'm lazy.

(use-package smartparens
  (require 'smartparens-config)
  (show-paren-mode t))

Rainbow Delimiters

This should make it easier to spot matching parentheses and brackets.

(use-package rainbow-delimiters
  :hook (prog-mode . rainbow-delimiters-mode))

Weather Forecasts With Sunshine

I'm going to use Aaron Bieber's sunshine package to get weather when I

don't feel like using eww to hit . :)

(use-package sunshine
  (setq sunshine-show-icons t)
  (global-set-key (kbd "C-c s f") 'sunshine-forecast))

Improved Help Buffers with Helpful

Using the `helpful' package should improve Emacs' help buffers by

providing more contextual information.

(use-package helpful
  (counsel-describe-function-function #'helpful-callable)
  (counsel-describe-variable-function #'helpful-variable)
  ([remap describe-function] . counsel-describe-function)
  ([remap describe-command] . helpful-command)
  ([remap describe-variable] . counsel-describe-variable)
  ([remap describe-key] . helpful-key))

Keybinding Completion with which-key

Emacs has a shitload of keybindings, and I still don't have them all

in my head. Maybe which-key can help?

(use-package which-key
  :init (which-key-mode)
  :diminish which-key-mode
  (setq which-key-idle-delay 0.3))

Learning Emacs Keybindings with Guru Mode

I still tend to use arrow keys in Emacs, so maybe having Guru Mode to

nudge me will help me get better at Emacs. But I won't use it in text


(use-package guru-mode
  :diminish guru-mode
  (add-hook 'prog-mode-hook 'guru-mode))

If this annoys you, just disable tangling.

Completion Setup

If I want to use Ivy and Ivy-Rich, I need to start by installing


(use-package counsel
  :bind (("M-x" . counsel-M-x)
         ("C-x b" . counsel-ibuffer)
         ("C-x C-f" . counsel-find-file)
         :map minibuffer-local-map
         ("C-r" . 'counsel-minibuffer-history)))

Basic Completion with Ivy

The Ivy package provides "incremental vertical completion", and is a

more convenient version of Emacs' default completion. It's also

lighter than Helm.

(use-package ivy
  :bind (("C-s" . swiper)
         :map ivy-minibuffer-map
         ("TAB" . ivy-alt-done)	
         ("C-l" . ivy-alt-done)
         ("C-j" . ivy-next-line)
         ("C-k" . ivy-previous-line)
         :map ivy-switch-buffer-map
         ("C-k" . ivy-previous-line)
         ("C-l" . ivy-done)
         ("C-d" . ivy-switch-buffer-kill)
         :map ivy-reverse-i-search-map
         ("C-k" . ivy-previous-line)
         ("C-d" . ivy-reverse-i-search-kill))
  (ivy-mode 1))

This config also replaces the default find bound to `C-s' with Ivy's


Beautifying Completions with Ivy-Rich

Adding Ivy-Rich will make Ivy more comfortable to use.

(use-package ivy-rich
  (ivy-rich-mode 1)
  (setq ivy-format-function #'ivy-format-function-line)
  (setq ivy-rich-display-transformers-list
        (plist-put ivy-rich-display-transformers-list
                     ((ivy-rich-candidate (:width 40))
                      (ivy-rich-switch-buffer-indicators (
                       :width 4 
                       :face error 
                       :align right))
                      (ivy-rich-switch-buffer-major-mode (
                       :width 12 
                       :face warning))
                      (ivy-rich-switch-buffer-project (
                       :width 15 
                       :face success))
                      (ivy-rich-switch-buffer-path (
                       :width (lambda (x) (ivy-rich-switch-buffer-shorten-path x (ivy-rich-minibuffer-width 0.3)))))) 
                     (lambda (cand)
                       (if-let ((buffer (get-buffer cand)))
                           ;; Don't mess with EXWM buffers
                           (with-current-buffer buffer
                             (not (derived-mode-p 'exwm-mode)))))))))

Ivy + EMMS?

Using Ivy with EMMS might make it more pleasant to use, and might make

a good alternative to grabbing albums with Dired.

(use-package ivy-emms
  (global-set-key (kbd "C-c e i") 'ivy-emms))

All the Icons

I need this for Doom Themes and the Doom Modeline.

(use-package all-the-icons)

When first using this config, remember to run `M-x

all-the-icons-install-fonts'. Then everything will work properly the

next time you start Emacs.

All the Icons (Dired)

Never mind pimping my ride. Let's pimp my Dired.

(use-package all-the-icons-dired
 (add-hook 'dired-mode-hook 'all-the-icons-dired-mode))

All the Icons (Ivy-Rich)

Let's add all-the-icons to Ivy and further enrich the experience.

(use-package all-the-icons-ivy-rich
  (all-the-icons-ivy-rich-mode 1))

Doom Themes

I don't want to use Doom Emacs, but I like the themes.

(use-package doom-themes
  (setq doom-themes-enable-bold t
    doom-themes-enable-italic t)
  (load-theme 'doom-tomorrow-night t)

The config enables bold and italic fonts before loading the theme. It

also sets up visual effects on errors and fixes org mode font


The byte compiler will gripe about a bunch of stuff not being defined

when first installing the packages, but the bytecomp warning only

shows up once.

Doom Modeline

Let's have a more attractive modeline, shall we? It'll be cleaner and

take advantage of the all-the-icons package.

(use-package doom-modeline
  :init (doom-modeline-mode 1)
  :custom ((doom-modeline-height 20)))

;; everything below here is generated by GNU Emacs...

That should be everything.