text/gemini
# my emacs configuration
I thought I'd test the ox-gemini package for Emacs by having it convert my configuration org file. :)
=> https://git.sr.ht/~starbreaker/emacs.d 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:
* README.md
* Makefile
* config.el
* secrets.el
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.
# README
```
# 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:
```bash
mkdir -p ~/.emacs.d
cp init.el ~/.emacs.d/
```
## Extending the Config
Add source blocks as needed. Just copy and paste:
```org
#+BEGIN_SRC emacs-lisp :tangle yes
#+END_SRC
```
## 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
[3]: https://systemcrafters.cc
[4]: https://howardism.org
[5]: https://emacsredux.com/blog/2013/05/09/keep-backup-and-auto-save-files-out-of-the-way/
```
# Makefile
Run this in the repository's directory to install.
```
.DEFAULT: tangle
DEST=~/.emacs
tangle: config.org
emacs -Q --batch --eval "(progn (require 'ob-tangle) (dolist (file command-line-args-left) (with-current-buffer (find-file-noselect file) (org-babel-tangle))))" config.org
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" . "https://melpa.org/packages/")
("org" . "https://orgmode.org/elpa/")
("elpa" . "https://elpa.gnu.org/packages/")))
```
## Initialize the Package Mangler
```
(package-initialize)
```
## Update Installed Packages
```
(unless package-archive-contents
(package-refresh-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.
use-package
```
(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
consistency.
# 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
functions.
## 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
commands.
```
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 "") '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
markdown-mode-hook
gemini-mode-hook
term-mode-hook
shell-mode-hook
eshell-mode-hook
eww-mode-hook
elpher-mode-hook
emms-mode-hook
erc-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
package.
```
(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))
"%b"))))
```
## 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)
```
=> https://www.gnu.org/software/emacs/manual/html_node/emacs/Auto-Scrolling.html misread the manual
## ERC (Emacs Relay Chat)
I want to use Emacs as my IRC client. Yes, I know how crazy that
sounds.
```
(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 "irc.libera.chat" :port "6697"
:nick "starbreaker")))
```
Don't forget to change the nick here.
### Automatically join certain channels on Libera Chat
When I join irc.libera.chat, I want in on the following channels:
* midnight-pub
* gemini
* callahans (if it got transferred from freenode)
I'll also join these, just in case.
* emacs
* erc
* debian
```
(setq erc-autojoin-channels-alist '(("libera.chat" "#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
capabilities.
```
(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.
=> https://www.gnu.org/software/emacs/manual/html_node/emacs/Dired.html Dired
## 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))
auto-save-file-name-transforms
`((".*" ,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)))
(cond
((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")))
(t
(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 ()
(org-indent-mode)
(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 ()
(interactive)
(bookmark-maybe-load-default-file)
(bookmark-jump "elfeed-all"))
(defun emacs-init/elfeed-show-emacs ()
(interactive)
(bookmark-maybe-load-default-file)
(bookmark-jump "elfeed-emacs"))
(defun emacs-init/elfeed-show-misc ()
(interactive)
(bookmark-maybe-load-default-file)
(bookmark-jump "elfeed-misc"))
(defun emacs-init/elfeed-show-debian ()
(interactive)
(bookmark-maybe-load-default-file)
(bookmark-jump "elfeed-debian"))
```
# Packages
## ORG MODE
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)
:config
(setq org-ellipsis " ▾")
(emacs-init/org-font-setup))
```
I also want to have prettier bullets in Org mode, so we'll use
`org-bullets'
```
(use-package org-bullets
:after org
:hook (org-mode . org-bullets-mode)
:custom
(org-bullets-bullet-list '("◉" "○" "●" "○" "●" "○" "●")))
```
## Visual Fill Column
Let's make Org and other text markup modes look a little nicer using
`visual-fill-column'.
```
(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))
```
## Markdown
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
:config
(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
:config
(global-set-key (kbd "") '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
needed.
```
(use-package elpher
:config
(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
metadata.
```
(use-package emms
:config
(require 'emms-setup)
(require 'emms-info-metaflac)
(require 'emms-info-mp3info)
(require 'emms-info-ogginfo)
(emms-all)
(emms-default-players)
(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. 🐱
* #### Custom Bindings
* Open the EMMS Playlist buffer.
* Toggle *repeat* mode on current playlist
* Toggle *shuffle* on current playlist
* #### Default Bindings for EMMS Playlist buffer
* 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
:config
(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
:init
(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
mappings.
I'll also pull `elfeed-org' because I want to store my feeds list in
an org file.
```
(use-package elfeed-org
:config
(elfeed-org)
(setq rmh-elfeed-org-files (list "/home/starbreaker/git/srht/elfeed-org/feed.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
hours.
```
(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))
:config
(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
:config
(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
:config
(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
:custom
(counsel-describe-function-function #'helpful-callable)
(counsel-describe-variable-function #'helpful-variable)
:bind
([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
:config
(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
modes.
```
(use-package guru-mode
:diminish guru-mode
:config
(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
Counsel.
```
(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
:diminish
: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))
:config
(ivy-mode 1))
```
This config also replaces the default find bound to `C-s' with Ivy's
"swiper".
## Beautifying Completions with Ivy-Rich
Adding Ivy-Rich will make Ivy more comfortable to use.
```
(use-package ivy-rich
:init
(ivy-rich-mode 1)
:config
(setq ivy-format-function #'ivy-format-function-line)
(setq ivy-rich-display-transformers-list
(plist-put ivy-rich-display-transformers-list
'ivy-switch-buffer
'(:columns
((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))))))
:predicate
(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
:config
(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
:config
(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
:config
(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
:config
(setq doom-themes-enable-bold t
doom-themes-enable-italic t)
(load-theme 'doom-tomorrow-night t)
(doom-themes-visual-bell-config)
(doom-themes-org-config))
```
The config enables bold and italic fonts before loading the theme. It
also sets up visual effects on errors and fixes org mode font
rendering.
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.
This content has been proxied by September (ba2dc).