UP | HOME

Emacs Configuration

Table of Contents


Welcome to my Emacs configuration! This file contains the code along with documentation for customizing my Emacs with all the options that I prefer to use by default.

About this Document

This file was written using Emacs Org Mode. This makes navigating and modifying my Emacs configuration much simpler as I can place different elements of my configuration under separate headings. The code in this file is placed in source code blocks that are tangled to the init.el file that Emacs will look for upon starting. When this file is saved, the source code blocks that are marked for tangling will write their contents to init.el.

Tags

Tags are used in this document to help make navigation of the packages easier and to provide additional information about piecing together this Emacs configuration. Below are descriptions of the tags and their meanings:

deprecated
This package has been "deprecated" in favor of another package that better integrates with this Emacs configuration or produces a better workflow.
disabled
Any package marked with this tag has been disabled due to it causing issues or the package was deprecated.
GUIX
Packages managed by GUIX are marked with this tag. There are a number of reasons why a package might be managed by GUIX over using package managers in Emacs:
  1. The package requires compilation on the host system (e.g. Pdf Tools and Org-roam). Using the GUIX package manager will manage the compilation automatically. Also, packages that need to be compiled are difficult to run on portable Emacs so they will be left out when Emacs is used as a portable app.
  2. The package is only run on a Linux System with GUIX installed or on the GUIX System Distribution so there is no need to have Emacs manage this package.
  3. The package relies on another program installed on the host system (e.g. Mu4e requires Mu).
testing
A package or function that is added and is being tested for use is marked with this tag.
Windows
Customizations exclusively for the use on the Windows operating system are marked with this tag.

Header for init.el

The following code block will add a header to the init.el file when it is generated on saving:

;;; init.el --- Emacs initialization file -*- lexical-binding: t -*-

;; Copyright (C) 2022 Thomas Freeman

;; Author: Thomas Freeman
;; Maintainer: Thomas Freeman
;; Keywords: lisp
;; Version: 0.0.1
;; Created: 09 Jan 2022

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:

;; This file is an init file for Emacs.
;;
;; This file is NOT a part of Emacs.
;;
;; This file IS NOT intended to be edited! It was generated by init.org.

;;; URL: https://github.com/tfree87/.emacs.d

;; For documentation and for editing this file, see the init.org in the
;; github repository tfree87/.emacs.d
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;; Code:

Performance Optimization Start

In order to slightly reduce the load time for Emacs, the whole init.el file can be wrapped in the following let statement to speed up the load process. This can help a little when Emacs is run as a portable app from a flash drive as I often do.See this Reddit post for more information.

(let ((file-name-handler-alist nil))

Load Path

Since all of the Emacs configuration is in modules, the modules directory and all of its sub-directories must be added to the Emacs load-path.

;; Add modules to Emacs load path

(let ((default-directory "~/.emacs.d/modules/"))
  (normal-top-level-add-subdirs-to-load-path))

Running Emacs as a Portable App

I like to use Emacs at work and at home to boost my productivity, but I often find when I am at work or using another computer using Windows and I cannot always install Emacs to the host system. In this case, I run Emacs from a USB thumb drive so that I can still have access to the power of Emacs even when I am not working on my home personal computer. Running Emacs from a thumb drive has some caveats. For instance, if you are running Emacs from a thumb drive on a work computer and you do not have administrator access, then a lot of features will break. This section contains code that can be used to run Emacs.

Check for Portable Emacs Instance

When runemacs.bat is executed, it will set the environment variable EMACS_PORTABLE to "Y". By checking for this, we can tell that Emacs that it was executed to be run from a flash drive.

(defun freemacs/isportable-p ()
  "A function to check whether Emacs was executed as a portable application in Windows by the runemacs.bat script."
  (string= (getenv "EMACS_PORTABLE") "Y"))

Set Location of Portable Git

Straight.el cannot operate without access to Git. Luckily, there is a portable version of Git (sheabunge/GitPortable) for Windows that can be installed on the PortableApp platform to provide access to Git without having it installed on the host system. After downloading GitPortable, we need to tell Emacs where it can find the binary executable so that Emacs programs can call Git when needed.

The following line code will check to see if Emacs is being run as a portable app and, if it is, then add the path where git.exe can be found to the exec-path list:

(when (freemacs/isportable-p)
  (add-to-list 'exec-path "~/PortableApps/GitPortable/App/Git/bin"))

Custom Set Variables

In order to keep variables set by the customize interface or set during Emacs at runtime from being placed at the top of init.el, I set the variables set from Emacs customize to be put into a separate file ./custom.el.

;; Set the location of variables set using Emacs customize interface

(setq custom-file "~/.emacs.d/custom.el")

Once the file location has been set, Emacs needs to load the custom file. This needs to be done early in the loading process because it contains the addresses for the package repositories. If this is not loaded before refreshing packages and making calls to use-package, then the :ensure command will not be able to pull the packages and install them.

;; Load the file custom.el file containing variables from Emacs customize

(load custom-file)

Package Management

In this section, I have included customization to replace the default Emacs package manager with straight.el. Some reasons for making this switch are:

  1. It is easier to avoid conflicts with different package repositories such as duplicates packages in ELPA and MELPA.
  2. I can define a specific fork to use for a specific package to get bug fixes or modifications.
  3. The entire package repository is cloned, which, while it takes up a lot of space, allows for editing the source code directly if desired.
  4. Github repositories that are not included in ELPA, MELPA, or marmalade can be pulled used in use-package statements.

Straight.el

Instead of using the built-in package manager, use straight.el to pull all the packages straight from their repositories.

;; Install Straight.el to manage packages

(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))

Install use-package

Use straight.el to install use-package to manage Emacs packages.

;; Set up use-package to manage package loading

(straight-use-package 'use-package)

Straight can be configured as the default manager for use-package using the following option:

(setq straight-use-package-by-default t)

However, as I have started using the GUIX System Distribution I have found that it can be beneficial to pick and choose which packages are managed by straight and which are managed by GUIX . Packages that I want to use across Linux and Windows operating systems can be managed by straight, and those that I only use on GUIX or require compiling on the host system (such as EXWM and pdf-tools) can be managed by GUIX.

Startup Tools

This section contains many of the tools used at Emacs startup that are helpful when other packages are initialized.

No-littering

The no-littering package will put Emacs configuration files for many third-party packages into separate folders under .emacs.d/etc/ to help keep the .emacs.d/ from getting to cluttered with different configuration files. This needs to be run before the other packages are initialized in order to ensure that when the pacakges are loaded that their configuration files will be put into the correct location.

;; Load No-littering module

(require 'freemacs-no-littering)

Whicher

Whicher provides a quick tool to check for missing executable dependencies without much cost to Emacs startup time. This needs to be loaded before the rest of init.el so that as init.el is loaded, it can look for missing executables on the host system.

;; Load Whicher module

(require 'freemacs-whicher)

Defaults

Emacs has many default options that can be changed to make Emacs more productive in a modern computing environment. Changes to the default settings of Emacs can be found in the defaults module.

;; Load Defaults module

(require 'freemacs-defaults)

Coding

Modifications to the coding modes for Emacs are defined in the coding module.

;; Load the coding module

(require 'freemacs-project)

(require 'freemacs-coding)

Completion

While Emacs has built-in completion systems, the combination of the following tools makes Emacs completion very powerful:

  • Vertico
  • Orderless
  • Cape
  • Consult
  • Marginalia
  • Embark

The configuration of these elements can be found in the completion module.

;; Load the completion module

(require 'freemacs-completion)

Docker

Tools for working with Docker and Docker files are included in the docker module. It configures the following packages:

Docker
Manage Docker containers from within Emacs
Docker Compose
Edit docker-compose files in Emacs
;; Load the Docker module

(require 'freemacs-docker)

Editing Tools

General editing tools are configured in the Emacs editing module. This includes:

Multiple Cursors
Edit text in multiple locations in the buffer simulaneously
YASnippet
Insert small predefined templates into Emacs
;; Load the editing module

(require 'freemacs-editing)

Elfeed

Elfeed is a news and RSS reader for Emacs. The configuration for Elfeed can be found in the Elfeed module.

;; Load Elfeed newsreader module

(require 'freemacs-elfeed)

Email

Email is managed using the Mu4e package that uses the Mu backend to search through emails that are stored using the Maildir format. The configuration can be found at email module.

;; Load email module

(require 'freemacs-email)

EXWM

EXWM is a window manager that runs entirely wihtin Emacs. With EXWM, Emacs frames and windows can be used to manage X11 applications. Each X11 application runs in a separate window and can be accessed as a separate buffer using Emacs commands.

;; Load the EXWM module

(require 'freemacs-exwm)

File Management

This section contains tools for working with the file system from within Emacs.

Dired

The Dired module contains changes and improvements to the Dired (directory editor) package in Emacs.

;; Load file tools module

(require 'freemacs-dired)

Sunrise Commander

Sunrise Commander is a two-pane orthodox file manager similar to Midnight Commander. The configuration for Sunrise Commander is in the sunrise module.

;; Load sunrise module

(require 'freemacs-sunrise)

Graphing

Emacs can be used as an environment to create graphs, plots, and diagrams. Configuration for these are found in the graphing module.

Gnuplot
Create plots using Gnuplot in Emacs
PlantUML
Create UML diagrams with PlantUML
;; Load graphing module

(require 'freemacs-graphing)

Math and Finance

Ledger

Ledger is a plain-text accounting system that is very fast, powerful and safe. The configuration for ledger in Emacs can be found in the ledger module.

;; Load the Ledger module

(require 'freemacs-ledger)

Org

;; Load the Org Mode module

(require 'freemacs-org)

Session

This section contains customizations for controlling how to navigate between Emacs windows, frames, and buffers.

;; Load session module

(require 'freemacs-session)

Shells and Terminals

This section contains configuration options for terminals in Emacs.

Eshell

Eshell is a shell written entirely in Emacs Lisp. It has a lot of great advantages over ihell mode in Emacs because:

  • Since many shell functions are written entirely in Emacs Lisp, many of the common *nix commands can work even in Windows as they are implemented entirely in Emacs
  • Output of shell commands can be redirected to an Emacs buffer as opposed to just a file or stdout
  • Emacs Lisp functions can be called from within the shell and aliased
;; Load the Eshell module

(require 'freemacs-eshell)

PowerShell   Windows

Powershell.el can launch an inferior shell that will run the Windows PowerShell tool. It is configured in the PowerShell module.

;; Load PowerShell module

(require 'freemacs-powershell)

VTerm

The VTerm package used a compiled terminal written in C that is faster than other terminal emulators in Emacs.

;; Load the VTerm module

(require 'freemacs-vterm)

Theme

Changes to Emacs appearance and theme can be found in the theme module.

;; Load theme module

(require 'freemacs-theme)

All the Icons

All the Icons adds icons that can improve the look of the Emacs interface. For more information on the configuration, check out the all the icons module.

;; Load All the Icons module

(require 'freemacs-alltheicons)

Writing/Publishing/Reading

This section contains customizations for Emacs to improve the environment for writing papers, publishing paper and websites, and reading documents.

Academic Writing

The academic writing module contains configurations to improve the environment for writing academic papers in Emacs. It contains configuration for the following packages:

Academic Phrases
A package that inserts common template phrases into academic papers
Citar
A citation tool that simplifies adding citations to documents
Org Cite
The built-in Org Mode citation management system
;; Load Academic Writing module

(require 'freemacs-academic-writing)

Spellchecking

The spellchecking module configures the spell checking environment in Emacs. A few of the changes made:

  • Flyspell is on be default so that you do not need to remember to call ispell.
  • Hunspell is used as the default spellchecking backend as it is more modern and works on multiple operating systems.
;; Load Spellchecking module

(require 'freemacs-spellcheck)

\LaTeX{}

Configuration for working with \LaTeX documents can be found in the \LaTeX{} module.

;; Load the LaTeX module

(require 'freemacs-latex)

Markdown

The markdown module adds additional features to improve editing markdown files in Emacs.

;; Load the markdown module

(require 'freemacs-markdown)

Ox-publish

ox-publish.el makes it easy to create multi-page websites from Org Mode files by defining a publishing project. The configuration for this package can be found in the ox-publish module.

;; Load the ox-publish module

(require 'freemacs-ox-publish)

PDF

To improve the speed and to extend the ability to view PDF files in Emacs, the PDF module can be loaded.

;; Load the pdf module

(require 'freemacs-pdf)

Help

The help module contains configuration that adds additional tools for help tools in Emacs:

Helpful
Adds extra information to Emacs help buffers
Which-key
Shows a list of key bindings in Emacs for the current major mode
;; Load the help module

(require 'freemacs-help)

Emacs Server

Emacs can be run as a server where all other instances of Emacs can connect to it and have access to the same buffers. This also greatly increases the load time of new Emacs instances as Emacs does not have to go through the initialization process again. The configuration of the Emacs server can be found in the server module.

;; Load server module

(require 'freemacs-server)

Custom Functions

This section contains custom functions that I have either created myself or borrowed from others to accomplish small tasks.

;; Custom Function Definitions

Sudo Find File

This function creates a sudo-find-file command that can be used to open files as the super user. This can be really useful when combined with Embark. This function was copied from https://karthinks.com/software/fifteen-ways-to-use-embark/.

(whicher "sudo")
(defun sudo-find-file (file)
  "Open FILE as root."
  (interactive "FOpen file as root: ")
  (when (file-writable-p file)
    (user-error "File is user writeable, aborting sudo"))
  (find-file (if (file-remote-p file)
                 (concat "/" (file-remote-p file 'method) ":"
                         (file-remote-p file 'user) "@" (file-remote-p file 'host)
                         "|sudo:root@"
                         (file-remote-p file 'host) ":" (file-remote-p file 'localname))
               (concat "/sudo:root@localhost:" file))))

Update Org Files on Portable App Startup

When running Emacs as a portable app, I want to pull down the latest versions of my org-agenda-files and other Org Mode files onto my USB flash drive (which has been set as the home directory). I also want to make sure to update the remote location when Emacs is killed so that all of my changes will be synced with the cloud and available for use on other systems.

;; Sync Dropbox containing org agenda files on load and close

(when (freemacs/isportable-p)
  (setq rclone-path "~/rclone/rclone.conf")
  (rclone-run-remote-to-local "sync" "~/Dropbox" "dropbox:")
  (add-hook 'kill-emacs-hook (rclone-run-local-to-remote "sync"
                                                         "~/Dropbox"
                                                         "dropbox:")))

Performance Optimization End

Close off the let statement at the beginning of the init file.

(setq gc-cons-threshold 800000)
)

End

Add a final comment to indicate the end of the file.

(provide 'init)

;;; init.el ends here

Date: Time-stamp: <2022-07-21 Thu 19:05>

Author: Thomas Freeman

Created: 2022-07-21 Thu 19:05

Validate