Since I am re-creating an Emacs configuration from scratch, I want to use the idea that's been playing around in my mind for ages: Maintaining the full configuration in an org-mode file and generating the configuration from this file. I am using Prot's org-mode file as a reference file, so the initial work will be lots of copying from his work. Once the skeleton is in place, I will add all of my custom configuration to this file as well.
18 KiB
GNU Emacs configuration
This configuration is inspired from the work of my hero Prot. It is not as clean and well-written as his configuration, but I'll get there eventually (probably before announcing this to the world).
#+src emacs-lisp :tangle no :results none (org-babel-tangle)
#+end_src
Here is what the generated directory structure should look like:
tree -aF
./ ├── early-init.el ├── init.el └── unravel-emacs.org
1 directory, 3 files ./ └── unravel-emacs.org
1 directory, 1 file
To make a change to this Emacs configuration, edit this file and then type C-c C-v C-t
(M-x org-babel-tangle
) to republish all the relevant files.
The early-init.el
file
This is the first file that Emacs loads. This file should only contain the absolute basic stuff Emacs needs to load first, before it loads init.el
.
Basic frame settings
;;; No GUI
(dolist (mode '(menu-bar-mode tool-bar-mode scroll-bar-mode))
(when (fboundp mode) (funcall mode -1)))
Tweaking the Garbage collector for faster startup
;; A big contributor to startup times is garbage collection.
;; We up the gc threshold to temporarily prevent it from running, then
;; reset it later by enabling `gcmh-mode'. Not resetting it will cause
;; stuttering/freezes.
(setq gc-cons-threshold most-positive-fixnum)
If you have both .el and .elc files, load the newer one
;; When both .el and .elc / .eln files are available,
;; load the latest one.
(setq load-prefer-newer t)
The init.el
file
This is the main initialisation file of Emacs. Everything loads from here, even if it has been split into multiple files for convenience.
Silence native-comp warnings
These are unnecessarily scary
;; Make native compilation silent and prune its cache.
(when (native-comp-available-p)
(setq native-comp-async-report-warnings-errors 'silent) ; Emacs 28 with native compilation
(setq native-compile-prune-cache t)) ; Emacs 29
Ignore the custom file, and just rely on this config
There is no need to use the M-x customize
infrastructure. It's easier to just rely on the init file instead.
;; Disable custom.el by making it disposable.
(setq custom-file (make-temp-file "emacs-custom-"))
Enable commands disabled by default
These commands are actually useful, especially in org-mode.
;; Enable these commands which have been disabled by default
(mapc
(lambda (command)
(put command 'disabled nil))
'(list-timers narrow-to-region narrow-to-page upcase-region downcase-region))
Disable unnecessary commands enabled by default
These commands are "unsafe", in that we should be using the alternatives (like vterm
and org
)
;; Disable these commands which have been enabled by default
(mapc
(lambda (command)
(put command 'disabled t))
'(eshell project-eshell overwrite-mode iconify-frame diary))
Add the modules folder to the load-path
This is where all the custom configuration sits for all the packages I use. We write configuration on a per-file basis instead of in a giant file, because these smaller files are more readable, approachable and shareable.
(mapc
(lambda (string)
(add-to-list 'load-path (locate-user-emacs-file string)))
'("unravel-modules"))
Setup package.el
for Package Management
;;;; Packages
(setq package-vc-register-as-project nil) ; Emacs 30
(add-hook 'package-menu-mode-hook #'hl-line-mode)
;; Also read: <https://protesilaos.com/codelog/2022-05-13-emacs-elpa-devel/>
(setq package-archives
'(("gnu-elpa" . "https://elpa.gnu.org/packages/")
("gnu-elpa-devel" . "https://elpa.gnu.org/devel/")
("nongnu" . "https://elpa.nongnu.org/nongnu/")
("melpa" . "https://melpa.org/packages/")))
;; Highest number gets priority (what is not mentioned has priority 0)
(setq package-archive-priorities
'(("gnu-elpa" . 3)
("melpa" . 2)
("nongnu" . 1)))
(setq package-install-upgrade-built-in t)
Load individual modules
Now we are ready to load our per-module configuration files:
(require 'unravel-theme)
;; (require 'unravel-essentials)
;; (require 'unravel-modeline)
;; (require 'unravel-completion)
;; (require 'unravel-search)
;; (require 'unravel-dired)
;; (require 'unravel-window)
;; (require 'unravel-git)
;; (require 'unravel-org)
;; (require 'unravel-langs)
The unravel-theme.el
module
This module defines everything related to the aesthetics of Emacs.
;;; Everything related to the look of Emacs
ef-themes
for cool, modern themes
I use themes from the ef-themes
package exclusively.
Prot is the lead developer and maintainer of this package.
- Package name (GNU ELPA):
ef-themes
- Official manual: <https://protesilaos.com/emacs/ef-themes>
- Change log: <https://protesilaos.com/emacs/ef-themes-changelog>
-
Git repositories:
- GitHub: <https://github.com/protesilaos/ef-themes>
- GitLab: <https://gitlab.com/protesilaos/ef-themes>
;;; The Ef (εὖ) themes
;; The themes are customisable. Read the manual:
;; <https://protesilaos.com/emacs/ef-themes>.
(use-package ef-themes
:ensure t
:demand t
:bind
(("<f5>" . ef-themes-rotate)
("C-<f5>" . ef-themes-select))
:config
(setq ef-themes-to-toggle '(ef-elea-light ef-elea-dark)
ef-themes-variable-pitch-ui t
ef-themes-mixed-fonts t
ef-themes-headings ; read the manual's entry of the doc string
'((0 . (variable-pitch light 1.9))
(1 . (variable-pitch light 1.8))
(2 . (variable-pitch regular 1.7))
(3 . (variable-pitch regular 1.6))
(4 . (variable-pitch regular 1.5))
(5 . (variable-pitch 1.4)) ; absence of weight means `bold'
(6 . (variable-pitch 1.3))
(7 . (variable-pitch 1.2))
(agenda-date . (semilight 1.5))
(agenda-structure . (variable-pitch light 1.9))
(t . (variable-pitch 1.1))))
(ef-themes-select 'ef-elea-light))
lin
for an improvement on hl-line-mode
Prot is the lead developer and maintainer of this package.
- Package name (GNU ELPA):
lin
- Official manual: <https://protesilaos.com/emacs/lin>
- Change log: <https://protesilaos.com/emacs/lin-changelog>
-
Git repositories:
- GitHub: <https://github.com/protesilaos/lin>
- GitLab: <https://gitlab.com/protesilaos/lin>
;;;; Lin
;; Read the lin manual: <https://protesilaos.com/emacs/lin>.
(use-package lin
:ensure t
:hook (after-init . lin-global-mode) ; applies to all `lin-mode-hooks'
:config
(setopt lin-face 'lin-cyan))
spacious-padding
for a comfortable reading experience
Prot is the lead developer and maintainer of this package.
Inspiration for this package comes from Nicolas Rougier's impressive designs
and Daniel Mendler's org-modern
package.
- Package name (GNU ELPA):
spacious-padding
- Official manual: <https://protesilaos.com/emacs/spacious-padding>
-
Git repositories:
;;;; Increase padding of windows/frames
;; <https://protesilaos.com/codelog/2023-06-03-emacs-spacious-padding/>.
(use-package spacious-padding
:ensure t
:if (display-graphic-p)
:hook (after-init . spacious-padding-mode)
:init
;; These are the defaults, but I keep it here for visiibility.
(setq spacious-padding-widths
'(:internal-border-width 30
:header-line-width 4
:mode-line-width 6
:tab-width 4
:right-divider-width 30
:scroll-bar-width 8
:left-fringe-width 20
:right-fringe-width 20))
;; Read the doc string of `spacious-padding-subtle-mode-line' as
;; it is very flexible.
(setq spacious-padding-subtle-mode-line t))
cursory
for an improved Emacs cursor
The cursory
package provides a thin wrapper around built-in variables that affect the style of the Emacs cursor on graphical terminals. The intent is to allow the user to define preset configurations such as "block with slow blinking" or "bar with fast blinking" and set them on demand.
Prot is the lead developer and maintainer.
- Package name (GNU ELPA):
cursory
- Official manual: <https://protesilaos.com/emacs/cursory>
- Change log: <https://protesilaos.com/emacs/cursory-changelog>
-
Git repositories:
- GitHub: <https://github.com/protesilaos/cursory>
- GitLab: <https://gitlab.com/protesilaos/cursory>
;;; Cursor appearance (cursory)
;; Read the manual: <https://protesilaos.com/emacs/cursory>.
(use-package cursory
:ensure t
:demand t
:if (display-graphic-p)
:config
(setq cursory-presets
'((box
:blink-cursor-interval 1.2)
(box-no-blink
:blink-cursor-mode -1)
(bar
:cursor-type (bar . 2)
:blink-cursor-interval 0.8)
(bar-no-other-window
:inherit bar
:cursor-in-non-selected-windows nil)
(bar-no-blink
:cursor-type (bar . 2)
:blink-cursor-mode -1)
(underscore
:cursor-type (hbar . 3)
:blink-cursor-interval 0.3
:blink-cursor-blinks 50)
(underscore-no-other-window
:inherit underscore
:cursor-in-non-selected-windows nil)
(underscore-thick
:cursor-type (hbar . 8)
:blink-cursor-interval 0.3
:blink-cursor-blinks 50
:cursor-in-non-selected-windows (hbar . 3))
(underscore-thick-no-blink
:blink-cursor-mode -1
:cursor-type (hbar . 8)
:cursor-in-non-selected-windows (hbar . 3))
(t ; the default values
:cursor-type box
:cursor-in-non-selected-windows hollow
:blink-cursor-mode 1
:blink-cursor-blinks 10
:blink-cursor-interval 0.2
:blink-cursor-delay 0.2)))
;; I am using the default values of `cursory-latest-state-file'.
;; Set last preset or fall back to desired style from `cursory-presets'.
(cursory-set-preset (or (cursory-restore-latest-preset) 'box))
(cursory-mode 1))
theme-buffet
for automatically changing the theme based on time of day
Bruno Boal is the lead developer and Prot is a co-maintainer.
- Package name (GNU ELPA):
theme-buffet
-
Git repo on SourceHut: <https://git.sr.ht/~bboal/theme-buffet>
-
Mirrors:
- GitHub: <https://github.com/BBoal/theme-buffet>
- Codeberg: <https://codeberg.org/BBoal/theme-buffet>
-
- Mailing list: <https://lists.sr.ht/~bboal/general-issues>
;;;; Theme buffet
;; <https://git.sr.ht/~bboal/theme-buffet>
(use-package theme-buffet
:ensure t
:after (:any modus-themes ef-themes)
:defer 1
:config
(let ((modus-themes-p (featurep 'modus-themes))
(ef-themes-p (featurep 'ef-themes)))
(setq theme-buffet-menu 'end-user)
(setq theme-buffet-time-offset 5)
(setq theme-buffet-end-user
'(:night (ef-dark ef-winter ef-autumn ef-night ef-duo-dark ef-symbiosis ef-owl)
:morning (ef-light ef-cyprus ef-spring ef-frost ef-duo-light ef-eagle)
:afternoon (ef-arbutus ef-day ef-kassio ef-summer ef-elea-light ef-maris-light ef-melissa-light ef-trio-light ef-reverie)
:evening (ef-rosa ef-elea-dark ef-maris-dark ef-melissa-dark ef-trio-dark ef-dream)))
(when (or modus-themes-p ef-themes-p)
(theme-buffet-timer-hours 2))))
fontaine
for beautiful font configuration
The fontaine
package allows the user to define detailed font configurations and set them on demand. For example, one can have a regular-editing
preset and another for presentation-mode
(these are arbitrary, user-defined symbols): the former uses small fonts which are optimised for writing, while the latter applies typefaces that are pleasant to read at comfortable point sizes.
Prot is the lead developer and maintainer.
- Package name (GNU ELPA):
fontaine
- Official manual: <https://protesilaos.com/emacs/fontaine>
- Change log: <https://protesilaos.com/emacs/fontaine-changelog>
-
Git repositories:
- GitHub: <https://github.com/protesilaos/fontaine>
- GitLab: <https://gitlab.com/protesilaos/fontaine>
;;;; Fontaine (font configurations)
;; Read the manual: <https://protesilaos.com/emacs/fontaine>
(use-package fontaine
:ensure t
:if (display-graphic-p)
:hook
;; Persist the latest font preset when closing/starting Emacs and
;; while switching between themes.
((after-init . fontaine-mode)
(after-init . (lambda ()
;; Set last preset or fall back to desired style from `fontaine-presets'.
(fontaine-set-preset (or (fontaine-restore-latest-preset) 'regular)))))
:config
;; This is defined in Emacs C code: it belongs to font settings.
(setq x-underline-at-descent-line nil)
;; And this is for Emacs28.
(setq-default text-scale-remap-header-line t)
;; This is the default value. Just including it here for
;; completeness.
(setq fontaine-latest-state-file (locate-user-emacs-file "fontaine-latest-state.eld"))
(setq fontaine-presets
'((small
:default-height 80)
(regular) ; like this it uses all the fallback values and is named `regular'
(medium
:default-weight semilight
:default-height 115
:bold-weight extrabold)
(large
:inherit medium
:default-height 150)
(live-stream
:default-family "Iosevka Comfy Wide Motion"
:default-height 150
:default-weight medium
:fixed-pitch-family "Iosevka Comfy Wide Motion"
:variable-pitch-family "Iosevka Comfy Wide Duo"
:bold-weight extrabold)
(presentation
:default-height 180)
(jumbo
:default-height 260)
(t
;; I keep all properties for didactic purposes, but most can be
;; omitted. See the fontaine manual for the technicalities:
;; <https://protesilaos.com/emacs/fontaine>.
:default-family "Iosevka Comfy"
:default-weight regular
:default-slant normal
:default-width normal
:default-height 100
:fixed-pitch-family "Iosevka Comfy"
:fixed-pitch-weight nil
:fixed-pitch-slant nil
:fixed-pitch-width nil
:fixed-pitch-height 1.0
:fixed-pitch-serif-family nil
:fixed-pitch-serif-weight nil
:fixed-pitch-serif-slant nil
:fixed-pitch-serif-width nil
:fixed-pitch-serif-height 1.0
:variable-pitch-family "Iosevka Comfy Motion Duo"
:variable-pitch-weight nil
:variable-pitch-slant nil
:variable-pitch-width nil
:variable-pitch-height 1.0
:mode-line-active-family nil
:mode-line-active-weight nil
:mode-line-active-slant nil
:mode-line-active-width nil
:mode-line-active-height 1.0
:mode-line-inactive-family nil
:mode-line-inactive-weight nil
:mode-line-inactive-slant nil
:mode-line-inactive-width nil
:mode-line-inactive-height 1.0
:header-line-family nil
:header-line-weight nil
:header-line-slant nil
:header-line-width nil
:header-line-height 1.0
:line-number-family nil
:line-number-weight nil
:line-number-slant nil
:line-number-width nil
:line-number-height 1.0
:tab-bar-family nil
:tab-bar-weight nil
:tab-bar-slant nil
:tab-bar-width nil
:tab-bar-height 1.0
:tab-line-family nil
:tab-line-weight nil
:tab-line-slant nil
:tab-line-width nil
:tab-line-height 1.0
:bold-family nil
:bold-slant nil
:bold-weight bold
:bold-width nil
:bold-height 1.0
:italic-family nil
:italic-weight nil
:italic-slant italic
:italic-width nil
:italic-height 1.0
:line-spacing nil))))