My Emacs Configuration

Table of Contents

Copyright

Copyright 2025 Harry Thompson

This file is part of the Ox Ranch.

The Ox Ranch 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.

The Ox Ranch 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

You should have received a copy of the GNU General Public License along with the Ox Ranch. If not, see https://www.gnu.org/licenses/.

Introduction

Welcome to my Emacs config. This is literate configuration written in Org-mode using source code blocks tangled with a collection of .el files. These files include various modules, custom libraries, an early-init.el file and an init.el file. The setup is modular: modules are made up of use-package macros for the purposes of standardisation and autoloading. These modules are loaded by the init.el file at startup along with any necessary libraries.

To learn more about literate programming in Org-mode, or indeed literate programming in general, visit https://orgmode.org/manual/Working-with-Source-Code.html (Accessed: 29 April 2025) or read Literate Programming by Donald Knuth.

Startup

Early Initialisation

Prior to searching for a .emacs, .emacs.el or a init.el file in the user’s .emacs.d directory or their home directory, Emacs will search for an early-init.el file in the .emacs.d directory, or in ~/.config/emacs/. Note that there are no alternative files for which Emacs will search for in the home directory.

The early-init.el file is meant for essential configuration prior to the initialisation of Emacs’ GUI; hence the follow source block is rather compact and primarily deals with ensuring that various GUI features remain disabled. Perhaps most interestingly, config-early-init sets the garbage collection threshold to an arbitrarily high number whilst ensuring that an anonymous function lowers the threshold back to its default value is added to emacs-startup-hook.

(package-initialize)
(setopt gc-cons-threshold most-positive-fixnum)
(add-hook 'emacs-startup-hook
          (lambda ()
            (setopt gc-cons-threshold 800000
                    gc-cons-percentage 0.2)))

(setopt frame-resize-pixelwise t
        frame-title-format "🏺 %b - ScholarMacs - %M 🏺"
        frame-inhibit-implied-resize t
        use-dialog-box t
        initial-buffer-choice t
        menu-bar-mode nil
        scroll-bar-mode nil
        tool-bar-mode nil)

Initialisation

;;; Package Management

(setopt package-archives
        '(("gnu" . "https://elpa.gnu.org/packages/")
          ("nongnu" . "https://elpa.nongnu.org/nongnu/")
          ("melpa" . "https://melpa.org/packages/")))

(setopt package-archive-priorities
        '(("gnu" . 20)
          ("nongnu" . 10)
          ("melpa" . -1)))

;; use-package settings

(use-package use-package-ensure-system-package)

;;; Module Loading

(add-to-list 'load-path "~/.emacs.d/Harry-libraries/")
(add-to-list 'load-path "~/.emacs.d/Harry-modules/")


(require 'harry-bibliography)
(require 'harry-header-line)
(require 'harry-language)
(require 'harry-mode-line)
(require 'harry-themes)
(require 'harry-org)

(require 'harry-packaging-module)
(require 'harry-bibliography-module)
(require 'harry-completion-module)
(require 'harry-dired-module)
(require 'harry-essentials-module)
(require 'harry-header-line-module)
(require 'harry-language-module)
(require 'harry-media-module)
(require 'harry-mode-line-module)
(require 'harry-news-module)
(require 'harry-org-module)
(require 'harry-shell-module)
(require 'harry-themes-module)
(require 'harry-version-control-module)
(require 'harry-web-module)
(require 'harry-window-module)
(require 'harry-maths-and-logic-module)

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

Configuration Modules

Bibliography

Biblio

(use-package biblio
  :ensure t
  :after ebib
  :pin melpa
  :custom
  (biblio-bibtex-use-autokey t))

Bibtex Mode

(use-package bibtex
  :ensure nil
  :custom
  (bibtex-dialect 'biblatex)
  (bibtex-user-optional-fields
   '(("keywords" "Keywords to describe the entry" "")
     ("file" "Link to a document file." "" )
     ("annote" "Personal annotation (ignored)")))
  (bibtex-align-at-equal-sign t))

Ebib

What does this package do?

This is an Emacs-based bibliography manager for .bib files, written by Joost Kremmers, who has authored an extensive accompanying manual. It supports both the BibTeX and BibLaTeX dialects and is well integrated with org-mode. You can find out more at http://joostkremers.github.io/ebib (Accessed: 19 April 2025).

Custom settings

This block sets a variety of user options and aesthetic tweaks. Its most interesting facet is its referencing of a custom function for setting the vertical or horizontal split (harry-set-ebib-window-split), which is invoked when Ebib is entered via the keybind C-c e. It would, of course, be more sensible to attach this directly to one of Ebib’s hooks; however, Ebib lacks a startup hook, and ebib-index-mode-hook is run only as a final step, after the variable controlling the window layout (ebib-window-layout-vertical-split) has already been set.

(use-package ebib
  :ensure t
  :pin melpa
  :custom
  (ebib-preload-bib-files '("~/Documents/Bibliography/my.bib")) 
  (ebib-file-associations 
   '(("pdf" . find-file)
     ("xopp" . "xournalpp")))     
  (ebib-keywords "~/Documents/Bibliography/keywords")
  (ebib-file-search-dirs '("~/Documents/Bibliography/PDFs+XOPPs")) 
  (ebib-bibtex-dialect 'biblatex) 
  (ebib-notes-storage 'one-file-per-note) 
  (ebib-notes-directory "~/Documents/Bibliography/Entry Notes/") 
  (ebib-reading-list-file "~/Documents/Bibliography/Reading List.org") 
  (ebib-reading-list-template
   "** %M %T :ReadingList:\n:PROPERTIES:\n:KEY: %K\n:END:\n") 
  (ebib-autogenerate-keys t) 
  (ebib-use-timestamp t)
  (ebib-modified-char "Δ") ;
  (ebib-reading-list-symbol "🔖") 
  (ebib-notes-symbol "🗒️") 
  (ebib-index-columns 
   '(("Author/Editor" 40 t)
     ("Year" 6 t)
     ("Title" 50 t)))
  :bind
  (("C-c e" . ebib)))

Ebib-biblio

(use-package ebib-biblio
  :after (ebib biblio)
  :bind (:map ebib-index-mode-map
              ("B" . ebib-biblio-import-doi)
              :map biblio-selection-mode-map
              ("e" . ebib-biblio-selection-import)))

Completion

Cape

(use-package cape
  :ensure t
  :pin gnu
  :init
  (add-hook 'completion-at-point-functions #'cape-file))

Completion Preview

(use-package completion-preview
  :ensure nil
  :custom
  (completion-preview-minimum-symbol-length 2)
  :hook
  (prog-mode . completion-preview-mode)
  (text-mode . completion-preview-mode)
  (comint-mode . completion-preview-mode)
  (eshell-mode . completion-preview-mode))

Consult

What does this package do?

Consult adds a rich set of search and navigation commands which allow for easy buffer previews, both inter and intra-file navigation, among many other features.

Custom Settings

For the time being I have used the maintainer’s recommendations.

(use-package consult
  :ensure t
  :pin gnu
  ;; Replace bindings. Lazily loaded by `use-package'.
  :bind (;; C-c bindings in `mode-specific-map'
         ("C-c M-x" . consult-mode-command)
         ("C-c h" . consult-history)
         ("C-c k" . consult-kmacro)
         ("C-c m" . consult-man)
         ("C-c i" . consult-info)
         ([remap Info-search] . consult-info)
         ;; C-x bindings in `ctl-x-map'
         ("C-x M-:" . consult-complex-command)     ;; orig. repeat-complex-command
         ("C-x b" . consult-buffer)                ;; orig. switch-to-buffer
         ("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
         ("C-x 5 b" . consult-buffer-other-frame)  ;; orig. switch-to-buffer-other-frame
         ("C-x t b" . consult-buffer-other-tab)    ;; orig. switch-to-buffer-other-tab
         ("C-x r b" . consult-bookmark)            ;; orig. bookmark-jump
         ("C-x p b" . consult-project-buffer)      ;; orig. project-switch-to-buffer
         ;; Custom M-# bindings for fast register access
         ("M-#" . consult-register-load)
         ("M-'" . consult-register-store)          ;; orig. abbrev-prefix-mark (unrelated)
         ("C-M-#" . consult-register)
         ;; Other custom bindings
         ("M-g a" . consult-theme)
         ("M-y" . consult-yank-pop)                ;; orig. yank-pop
         ;; M-g bindings in `goto-map'
         ("M-g e" . consult-compile-error)
         ("M-g f" . consult-flymake)               ;; Alternative: consult-flycheck
         ("M-g g" . consult-goto-line)             ;; orig. goto-line
         ("M-g M-g" . consult-goto-line)           ;; orig. goto-line
         ("M-g o" . consult-outline)               ;; Alternative: consult-org-heading
         ("M-g j" . consult-org-heading)
         ("M-g m" . consult-mark)
         ("M-g k" . consult-global-mark)
         ("M-g i" . consult-imenu)
         ("M-g I" . consult-imenu-multi)
         ;; M-s bindings in `search-map'
         ("M-s d" . consult-find)                  ;; Alternative: consult-fd
         ("M-s c" . consult-locate)
         ("M-s g" . consult-grep)
         ("M-s G" . consult-git-grep)
         ("M-s r" . consult-ripgrep)
         ("M-s l" . consult-line)
         ("M-s L" . consult-line-multi)
         ("M-s k" . consult-keep-lines)
         ("M-s u" . consult-focus-lines)
         ;; Isearch integration
         ("M-s e" . consult-isearch-history)
         :map isearch-mode-map
         ("M-e" . consult-isearch-history)         ;; orig. isearch-edit-string
         ("M-s e" . consult-isearch-history)       ;; orig. isearch-edit-string
         ("M-s l" . consult-line)                  ;; needed by consult-line to detect isearch
         ("M-s L" . consult-line-multi)            ;; needed by consult-line to detect isearch
         ;; Minibuffer history
         :map minibuffer-local-map
         ("M-s" . consult-history)                 ;; orig. next-matching-history-element
         ("M-r" . consult-history))                 ;; orig. previous-matching-history-element


  ;; Enable automatic preview at point in the *Completions* buffer. This is
  ;; relevant when you use the default completion UI.
  :hook (completion-list-mode . consult-preview-at-point-mode)

  ;; The :init configuration is always executed (Not lazy)
  :init

  ;; Tweak the register preview for `consult-register-load',
  ;; `consult-register-store' and the built-in commands.  This improves the
  ;; register formatting, adds thin separator lines, register sorting and hides
  ;; the window mode line.
  (advice-add #'register-preview :override #'consult-register-window)
  (setq register-preview-delay 0.5)

  ;; Use Consult to select xref locations with preview
  (setq xref-show-xrefs-function #'consult-xref
        xref-show-definitions-function #'consult-xref)

  ;; Configure other variables and modes in the :config section,
  ;; after lazily loading the package.
  :config

  ;; Optionally configure preview. The default value
  ;; is 'any, such that any key triggers the preview.
  ;; (setq consult-preview-key 'any)
  ;; (setq consult-preview-key "M-.")
  ;; (setq consult-preview-key '("S-<down>" "S-<up>"))
  ;; For some commands and buffer sources it is useful to configure the
  ;; :preview-key on a per-command basis using the `consult-customize' macro.
  (consult-customize
   consult-theme :preview-key '(:debounce 0.2 any)
   consult-ripgrep consult-git-grep consult-grep consult-man
   consult-bookmark consult-recent-file consult-xref
   consult--source-bookmark consult--source-file-register
   consult--source-recent-file consult--source-project-recent-file
   ;; :preview-key "M-."
   :preview-key '(:debounce 0.4 any))

  ;; Optionally configure the narrowing key.
  ;; Both < and C-+ work reasonably well.
  (setq consult-narrow-key "<")) ;; "C-+"

;; Optionally make narrowing help available in the minibuffer.
;; You may want to use `embark-prefix-help-command' or which-key instead.
;; (keymap-set consult-narrow-map (concat consult-narrow-key " ?") #'consult-narrow-help)

Consult-Denote

(use-package consult-denote
  :ensure t
  :pin gnu
  :bind
  (("C-c n f" . consult-denote-find)
   ("C-c n g" . consult-denote-grep))
  :config
  (consult-denote-mode 1))

Ecomplete

(use-package ecomplete
  :ensure nil
  :defer t
  :config
  (ecomplete-setup))

Embark

What does this package do?

Embark has been described as adding a feature-rich ’right-click’ to Emacs, but this does not capture its power. Embark allows for the easy collection and export of candidates to a suitable major mode (e.g. dired), among other features.

Custom Settings

For the time being I have used the maintainer’s recommendations.

(use-package embark
  :ensure t
  :pin gnu

  :bind
  (("M-o" . embark-act)         
   ("M-p" . embark-dwim)
   ("M-[" . embark-export)
   ("C-h B" . embark-bindings)) ;; alternative for `describe-bindings'
  :config
  ;; Hide the mode line of the Embark live/completions buffers
  (add-to-list 'display-buffer-alist
               '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
                 nil
                 (window-parameters (mode-line-format . none)))))

Embark-Consult

What does this package do?

This package is required to make Embark and Consult compatible.

(use-package embark-consult
  :ensure t 
  :hook
  (embark-collect-mode . consult-preview-at-point-mode))

Marginalia

What does this package do?

Marginalia provides brief marks of annotations at the margin of the minibuffer for completion candidates in order to convey more information about files and functions.

(use-package marginalia
  :ensure t
  :pin gnu
  :bind (:map minibuffer-local-map
              ("M-A" . marginalia-cycle))
  :hook
  (vertico-mode . marginalia-mode))

Orderless

What does this package do?

Orderless is a completion style which matches search candidates based on fuzzy search of space-separated components

(use-package orderless
  :ensure t
  :pin gnu
  :custom
  (completion-styles '(orderless basic))
  (completion-category-overrides '((file (styles basic partial-completion)))))  ;; Correct wrapping of the list

Vertico

What does this package do?

Vertico, or VERTical Interactive Completion, is a completion UI which replaces Emacs’ builtin completion framework with a more minimalist design based on Emacs’ built-in functions. Vertico is highly modular and can be extended with a variety of complementary packages such as Orderless and Marginalia.

(use-package vertico
  :ensure t
  :pin gnu
  :custom
  (vertico-cycle t)
  (vertico-scroll-margin 0)
  (vertico-count 5)
  (vertico-resize t)
  :hook
  (after-init . vertico-mode))  

Vertico-posframe

(use-package vertico-posframe
  :ensure t
  :pin gnu
  :after vertico
  :custom
  vertico-posframe-truncate-lines nil
  vertico-multiform-commands

  :config
  (setq vertico-multiform-commands
        '((consult-line
           posframe
           (vertico-posframe-poshandler . posframe-poshandler-frame-top-center)
           (vertico-posframe-border-width . 10)
           ;; NOTE: This is useful when emacs is used in both in X and
           ;; terminal, for posframe do not work well in terminal, so
           ;; vertico-buffer-mode will be used as fallback at the
           ;; moment.
           (vertico-posframe-fallback-mode . vertico-buffer-mode))

          (consult-outline
           posframe
           (vertico-posframe-poshandler . posframe-poshandler-frame-top-center)
           (vertico-posframe-border-width . 10)
           ;; NOTE: This is useful when emacs is used in both in X and
           ;; terminal, for posframe do not work well in terminal, so
           ;; vertico-buffer-mode will be used as fallback at the
           ;; moment.
           (vertico-posframe-fallback-mode . vertico-buffer-mode))

          (consult-org-heading
           posframe
           (vertico-posframe-poshandler . posframe-poshandler-frame-top-center)
           (vertico-posframe-border-width . 10)
           ;; NOTE: This is useful when emacs is used in both in X and
           ;; terminal, for posframe do not work well in terminal, so
           ;; vertico-buffer-mode will be used as fallback at the
           ;; moment.
           (vertico-posframe-fallback-mode . vertico-buffer-mode))

          (consult-org-agenda
           posframe
           (vertico-posframe-poshandler . posframe-poshandler-frame-top-center)
           (vertico-posframe-border-width . 10)
           ;; NOTE: This is useful when emacs is used in both in X and
           ;; terminal, for posframe do not work well in terminal, so
           ;; vertico-buffer-mode will be used as fallback at the
           ;; moment.
           (vertico-posframe-fallback-mode . vertico-buffer-mode))


          (consult-buffer
           posframe
           (vertico-posframe-poshandler . posframe-poshandler-frame-top-center)
           (vertico-posframe-border-width . 10)
           ;; NOTE: This is useful when emacs is used in both in X and
           ;; terminal, for posframe do not work well in terminal, so
           ;; vertico-buffer-mode will be used as fallback at the
           ;; moment.
           (vertico-posframe-fallback-mode . vertico-buffer-mode))

          (t posframe)))
  (vertico-multiform-mode 1)
  :hook
  (vertico-mode . vertico-posframe-mode))

undo-tree

(use-package undo-tree
  :ensure t
  :pin gnu
  :bind ("C-x u" . undo-tree-visualize)
  :hook (after-init . global-undo-tree-mode))

Which-key

(use-package which-key
  :ensure nil
  :config
  (which-key-setup-side-window-right)
  :hook (after-init . which-key-mode))

Dired

Dired-preview

(use-package dired-preview
  :ensure t
  :pin gnu
  :custom 
  (dired-preview-delay 0.7)
  (dired-preview-max-size (expt 2 20))
  (dired-preview-ignored-extensions-regexp
   (concat "\\."
           "\\(gz\\|"
           "zst\\|"
           "tar\\|"
           "xz\\|"
           "rar\\|"
           "zip\\|"
           "iso\\|"
           "epub"
           "\\)"))

  :config
  (when (string-equal system-type "windows-nt")
    (setq dired-listing-switches "/A:H /O:NG"))

  :bind
  (:map dired-mode-map
        ("M-g q" . dired-preview-mode))
  :hook (dired-load . dired-preview-global-mode))

Dired

(use-package dired
  :ensure nil
  :custom
  (dired-omit-files "^\\.[^.]+")  
  :bind
  ("M-g w" . wdired-change-to-wdired-mode)
  ("M-g b" . dired-omit-mode)
  ("M-g d" . dired-hide-details-mode)

  :hook ((dired-mode . dired-hide-details-mode)
         (dired-mode . dired-omit-mode)
         (dired-mode . turn-on-gnus-dired-mode)
         (dired-mode . hl-line-mode)))

Essentials

(use-package emacs
  :ensure nil
  :custom

  (delete-by-moving-to-trash t)                      ; Delete files to trash

  (window-combination-resize t)                      ; Take new window space from all other windows (not just current)
  (cursor-type 'bar)	   			  ; Sets cursor to the more conventional, narrow line type

  (sentence-end-double-space nil)                    ; Make Emacs view sentences as a series of words prior to a fullstop and a single space, rather than a double space
  (doc-view-continuous t)                       ; The document viewer shows content continuously, so you don’t have to flip between pages.
  (recentf-max-menu-items 10)  ; Set the maximum number of items to remember
  (line-spacing 0.1)
  (use-short-answers t)


  (pixel-scroll-precision-mode t) ; Make scrolling bearable
  (pixel-scroll-precision-interpolate-page t)
  (scroll-conservatively 101)
  (scroll-margin 3)
  (scroll-preserve-screen-position t)
  (touch-screen-display-keyboard t)
  (mouse-wheel-progressive-speed nil)  
  (mouse-wheel-scroll-amount '(3 ((shift) . 1)))


  (history-length 25)
  (shr-inhibit-images t) ; Disable images in eww
  (shr-max-width fill-column)
  (browse-url-browser-function 'browse-url-default-browser) 
  (recentf-mode t)
  (warning-minimum-level :emergency "Don't show warnings in buffer")
  (native-comp-async-report-warnings-errors 'silent)
  (default-input-method "greek-babel")
  (message-truncate-lines t)
  (confirm-kill-emacs #'yes-or-no-p)
  (keymap-substitute global-map #'suspend-frame #'quit-window)
  (tab-bar-show nil)
  (auto-save-interval 20)
  (auto-save-timeout 20)

  :config

  (defun toggle-frame-decoration ()
    "Toggle frame decoration on/off."
    (interactive)
    (let ((undecorated (frame-parameter nil 'undecorated)))
      (modify-frame-parameters nil 
                               `((undecorated . ,(not undecorated))))
      (message "Frame decoration %s" (if (not undecorated) "disabled" "enabled"))))

  (subword-mode 1)	  ; Navigate camelcase words properly
  (which-function-mode 1)
  (auto-fill-mode 1)
  (savehist-mode 1)
  (global-auto-revert-mode 1)
  (save-place-mode 1)
  (global-visual-line-mode 1)


           ;;; Mac-specific settings

  (when (string-equal system-type "darwin") 
    (setopt mac-command-key-is-meta nil
            mac-command-modifier 'super
            mac-option-key-is-meta t
            mac-option-modifier 'meta)

    (global-unset-key (kbd "s-w"))
    (global-unset-key (kbd "s-q")))


  (put 'narrow-to-region 'disabled nil)
  (put 'narrow-to-page 'disabled nil)

  :bind

  (("C-<" . undo-redo)

   ("C-x <up>" . toggle-frame-fullscreen)
   ("C-x ," . recentf-open-files)
   ("C-c o f" . harry-toggle-frame-transparency)
   ("C-c o d" . harry-toggle-frame-decoration)
   ("C-c o a" . harry-autumn-screensaver)
   ("C-c o p" .   (lambda () (interactive) (dired "~/Documents/Bibliography/PDFs+XOPPs/")))
   ("C-c o v" . variable-pitch-mode)
   ("<f12>" . org-mode)))

This block does a number of things:

  • It disables the:
    • menu-bar
    • tool-bar
    • scroll-bar
  • Renames the frame
  • Directs Emacs to put deleted items in the wastebasket rather than deleting them outright
  • Enables proportional resizing of window combinations
  • Changes the cursor to the more conventional, narrow type
  • Enables subword-mode for better navigating camel case words
  • Directs Emacs to view a sentence as a string of words before a full stop and a single space a sentence, rather than a double space
  • Enables continuous viewing mode in Emacs’ document viewer
  • Sets up a toggleable full screen mode
  • Enables recentf mode and binds it to ’C-x’ ,
  • Enables save-place-mode
  • Sets line spacing to 2
  • Enables pixel-scroll-precision-mode for smoother scrolling
  • Adds margins
  • Enables savehist-mode
  • Enables global-auto-revert-mode
  • Disables images in eww (for security purposes)
  • Enables auto-fill-mode
  • Enables spell-checking in the built-in commit message editor
  • Sets ’C-<’ as redo
  • Enables hl-line-mode in Dired and Org-agenda
  • Enables Whichkey mode
  • Defines a separate terminal function called ’ox-term’ which is identical to the default terminal function, except it loads /bin/bash by default (this is then bound to ’M-g t’)

Essentials: Cleanup keybind documentation

I might want to remove the listings for individual keybinds and instead simply state that the blocks sets up a number of keybinds.

Header Line

(use-package harry-header-line
  :ensure nil
  :bind ("C-c o z" . harry-header-line-mode))

Language

Citeproc

(use-package citeproc 
  :ensure t
  :pin melpa
  :defer t
  :after (ox))

Delsel

What does this package do?

This package provides delete-selection-mode for more intuitive editing

Custom Settings

This macro adds delete-selection-mode to the after-init hook, which incidentally defers the loading of delsel.

(use-package delsel
  :ensure nil
  :hook (after-init . delete-selection-mode))

Denote

(use-package denote
  :ensure t
  :custom
  (denote-directory (expand-file-name "~/Documents/notes/"))

  ;; Do not read keywords from files.  The only source is the `denote-known-keywords'.
  (denote-infer-keywords t)

  ;; Automatically rename Denote buffers when opening them so that
  ;; instead of their long file name they have, for example, a literal
  ;; "[D]" followed by the file's title.  Read the doc string of
  ;; `denote-rename-buffer-format' for how to modify this.
  (denote-rename-buffer-mode 1)

  (denote-templates
   `((lecture . ,(concat "* Introduction"
                         "\n\n"
                         "* Main Points"
                         "\n\n"
                         "* Summary"
                         "\n\n"
                         "* Further Reading"))))

  :hook (dired-mode . denote-dired-mode)
  :bind
  (("C-c n n" . denote)
   ("C-c n r" . denote-rename-file)
   ("C-c n l" . denote-link)
   ("C-c n b" . denote-backlinks)
   ("C-c n d" . denote-dired)
   ("C-c n g" . denote-grep)))

Ispell

(use-package ispell
  :ensure nil
  :defer t
  :custom
  (ispell-program-name "aspell")
  (ispell-dictionary "en_GB"))

jinx

(use-package jinx
  :ensure t
  :pin gnu
  :hook (emacs-startup . global-jinx-mode)
  :bind (("M-$" . jinx-correct)
         ("C-M-$" . jinx-languages)))

Logos

(use-package logos
  :ensure t
  :pin gnu

  :custom
  (logos-outlines-are-pages t)
  (logos-hide-cursor nil)
  (logos-hide-mode-line t)
  (logos-hide-header-line t)
  (logos-hide-buffer-boundaries nil)
  (logos-outline-regexp-alist '((emacs-lisp-mode . "^;;;+ ") (org-mode . "^\\*+ +")
                                (markdown-mode . "^\\#+ +") (ibuffer-mode . "^.*$")
                                (dired-mode . "^.*$")))

  :bind (("C-c o l" . logos-focus-mode)
         ([remap narrow-to-region] . logos-narrow-dwim)
         ([remap forward-page] . logos-forward-page-dwim)
         ([remap backward-page] . logos-backward-page-dwim))

  :hook ((text-mode . logos-focus-mode)
         (prog-mode . logos-focus-mode)
         (pdf-view-mode . logos-focus-mode)
         (dired-mode . logos-focus-mode)
         (wdired-mode . logos-focus-mode)
         (image-mode . logos-focus-mode)
         (eww-mode . logos-focus-mode)
         (eshell-mode . logos-focus-mode)
         (term-mode . logos-focus-mode)
         (eat-mode . logos-focus-mode)
         (shell-mode . logos-focus-mode)
         (ibuffer-mode . logos-focus-mode)
         (Info-mode . logos-focus-mode)
         (doc-view-mode . logos-focus-mode)
         (org-mode . logos-focus-mode)
         (gnus-mode . logos-focus-mode)
         (emms-playlist-mode . logos-focus-mode)
         (emms-browser-mode . logos-focus-mode)
         (logos-focus-mode . (lambda ()
                               (if (eq major-mode 'org-mode)
                                   (setopt logos-olivetti t) 
                                 (setopt logos-olivetti nil)))))) 				 

Lorem-ipsum

(use-package lorem-ipsum
  :pin nongnu
  :ensure t
  :defer t)

Olivetti

What does this package do?

Olivetti provides a simple minor mode which sets the window’s margins automatically according to the user’s preference.

Custom Settings

This block configures the widths of the margins set by Olivetti and ensures that visual-line-mode’s entry state is recalled. I have also set olivetti-style to fancy, though I am not entirely sure what this does.

(use-package olivetti
  :ensure t
  :pin melpa
  :custom
  (olivetti-body-width 75)  
  (olivetti-minimum-body-width 70)
  (olivetti-recall-visual-line-mode-entry-state nil)
  (olivetti-style nil)

  :hook
  (message-mode . olivetti-mode)
  (emms-playlist-mode . olivetti-mode)
  (emms-browser-mode . olivetti-mode)
  (gnus-mode . olivetti-mode)
  (dired-mode . olivetti-mode)
  (eshell-mode . olivetti-mode)
  :bind
  ("C-c o o" . olivetti-mode))

Pdf-Tools

(use-package pdf-tools
  :pin nongnu
  :ensure t
  :defer 2
  :custom
  (pdf-cache-image-limit 125)
  :config
  (pdf-tools-install)
  :hook
  (pdf-view-mode . pdf-view-themed-minor-mode))

writegood-mode

(use-package writegood-mode
  :ensure t
  :pin nongnu
  :custom
  (writegood-weasel-words
   (append writegood-weasel-words
           '("arguably" "essentially" "various" "certain")))  ; Add philosophy
  :bind ("C-c w" . writegood-mode))

Maths & Logic

calc

(use-package calc
  :ensure nil
  :bind ("C-c o ~" . calc))

cdlatex

(use-package cdlatex
  :pin nongnu
  :ensure
  :defer t)

Media

EMMS

(use-package emms
  :ensure-system-package (vlc mpv yt-dlp)
  :ensure t
  :pin gnu
  :custom

  (emms-player-list '(emms-player-vlc emms-player-ogg123))
  (emms-info-functions '(emms-info-native emms-info-ogginfo))
  (emms-player-vlc-parameters '("--intf=rc" "--no-dbus"))
  (emms-source-file-default-directory "~/Music/")
  (emms-browser-covers #'emms-browser-cache-thumbnail-async)
  (emms-browser-thumbnail-small-size 64)
  (emms-browser-thumbnail-medium-size 128)

  (emms-player-list '(emms-player-mpv emms-player-vlc))  ; Add mpv
  (emms-player-mpv-parameters '("--quiet" "--really-quiet" "--no-audio-display"))

  :config

  (emms-all)
  (emms-mpris-enable)

  :bind
  (("<f8>" . emms-pause)      
   ("C-c C-= g" . emms-playlist-mode-go)
   ("C-c C-= b" . emms-browser)
   ("<f9>" . emms-next)
   ("<f7>" . emms-previous)
   ("C-c C-= s" . emms-show)
   ("C-c C-= r" . emms-toggle-repeat-track)))

Mode Line

Mode Line

The block defines the mode-line format by using the variables defined in harry-modeline.el.

(use-package harry-mode-line
  :ensure nil
  :custom
  (mode-line-format
   '(:eval
     (list
      "%e 🍵✒️ "
      ;; The first part is the left-aligned portion with padding
      my-mode-line-buffer-name
      " "
      my-mode-line-file-position
      " "
      my-mode-line-file-delta-status
      " | "
      my-mode-line-lambda
      my-mode-line-mode   	 
      (or (cdr (assoc major-mode my-major-mode-line-mode-indicators)) "")
      " | "

      (if which-function-mode
          (if (which-function)

              (propertize (which-function)
                          'face '(:weight bold)))
        (concat "which-function mode is disabled 👎🏻 | "))))))

TMR

(use-package tmr
  :ensure t
  :pin gnu
  :defer t
  :config
  (define-key global-map (kbd "C-c t") #'tmr-prefix-map)
  (setq tmr-sound-file "/usr/share/sounds/freedesktop/stereo/alarm-clock-elapsed.oga"
        tmr-notification-urgency 'normal
        tmr-description-list 'tmr-description-history)
  :hook
  (org-mode . tmr-mode-line-mode))

News

SMTP

(use-package emacs
  :ensure nil
  :custom

  (message-signature "Harry G. Thompson") 
  (user-mail-address "harrygthompson@posteo.net")
  (user-full-name "Harry G. Thompson")

  (mail-user-agent 'gnus-user-agent)

  :config

  ;; SMTP (TLS)

  (setq smtpmail-servers-requiring-authorization "posteo.de")

  (setq send-mail-function    'smtpmail-send-it
        smtpmail-smtp-server  "posteo.de"
        smtpmail-stream-type  'ssl
        smtpmail-smtp-service 465
        smtpmail-auth-credentials "~/.authinfo.gpg" 
        smtpmail-smtp-user "harrygthompson@posteo.net" 
        smtpmail-debug-info t))

                                        ;   (setq mml-secure-openpgp-signers '("7DF8F8E0A52926AA9FB45CB3976A0BDD15B89B7C")) )
                                        ;(add-hook 'message-send-hook 'mml-secure-message-sign-pgpmime))

Gnus

  • Gnus Startup
    (autoload 'gnus "gnus" "Start Gnus" t)
    (with-eval-after-load 'gnus
      (require 'gnus-notifications))
    (global-set-key (kbd "C-c o g") 'gnus)
    (setopt gnus-init-file "~/.emacs.d/Gnus/.gnus")
    (setopt gnus-inhibit-startup-message t)
    
  • Gnus
    (setopt gnus-summary-default-high-score 3000
            gnus-summary-default-low-score 2000
    
            gnus-use-dribble-file nil
            gnus-select-method '(nnnil ""))
    
           ;;; IMAP (TLS)
    
    (setopt gnus-secondary-select-methods
            '((nnimap "posteo.de"
                      (nnimap-address "imap.posteo.de")
                      (nnimap-server-port 993)
                      (nnimap-stream ssl)
                      (nnimap-authinfo-file "~/.authinfo.gpg")
                      (nnimap-inbox "INBOX")        ; "Inbox" folder
                      (nnimap-sent "Sent")          ; "Sent" folder
                      (nnimap-drafts "Drafts")      ; "Drafts" folder
                      (nnimap-trash "Trash")))) ; "Deleted Items" folder
    
    ;; Archive outgoing email in Sent folder
    
    (setq gnus-message-archive-method '(nnimap "posteo.de")
          gnus-message-archive-group "Sent")
    
    ;; Set email expiry target to Trash on Posteo and wait for 30 days
    
    (setopt nnmail-expiry-target "nnimap+posteo:Trash")
    (setopt nnmail-expiry-wait 7) ; A moo moo week 🐂
    (setq nnimap-expunge t)
    (setq nnimap-record-commands t)
    
            ;;; startup
    (setopt gnus-activate-level 2)
    (add-hook 'gnus-group-mode-hook 'gnus-topic-mode)
    (add-hook 'gnus-summary-mode-hook 'hl-line-mode)
    
            ;;; Demon
    (gnus-demon-add-handler 'gnus-demon-scan-mail 1 t)
    (gnus-demon-init)
    (add-hook 'gnus-after-getting-new-news-hook 'gnus-notifications)
    (setq gnus-use-full-window nil)      ; Don't take over entire frame
    (setq gnus-summary-line-format "%U%R%z %(%&user-date;  %-15,15f  %B%s%)\n")
    (setq gnus-user-date-format-alist '((t . "%Y-%m-%d %H:%M"))) ; Clean date format
    (setq gnus-summary-thread-gap-function 'gnus-summary-insert-dummy-line)
    (setq gnus-summary-ignore-thread '("^Re:" "^Fwd:")) ; Clean up thread prefixes
    
    ;; Simplified group line format
    (setq gnus-group-line-format "%M%S%p%P%5y: %(%g%)\n")
    

Message

(use-package message
  :ensure nil
  :defer t
  :custom

  (message-mail-alias-type 'ecomplete)
  (message-self-insert-commands nil)
  (message-expand-name-standard-ui t)

  :hook (message-sent . message-put-addresses-in-ecomplete))

Org

org-cite-overlay

(use-package org-cite-overlay
  :ensure nil
  :pin melpa
  :hook (org-mode . org-cite-overlay-mode))

org-fragtog

(use-package org-fragtog
  :ensure nil
  :pin melpa
  :hook (org-mode . org-fragtog-mode))

Org Transclusion

(use-package org-transclusion
  :ensure t
  :pin gnu
  :after org)

Org General Tweaks

(use-package org
  :ensure-system-package zip
  :ensure nil
  :custom
                   ;;; Capture 

  (org-capture-templates
   '(("t" "Todo" entry (file+headline "~/Documents/Personal Files/Personal Todo.org" "Tasks")
      "* TODO  %?\n  %i\nCreated: %U")
     ("j" "Learning Journal" entry (file+datetree "~/Documents/Personal Files/Learning Journal.org")
      "* %?\nEntered on %U\n  %i\n  %a")
     ("J" "Personal Journal" entry (file+datetree "~/Documents/Personal Files/Personal Journal.org")
      "* %?\nEntered on %U\n  %i\n ")))


                   ;;; Clock

  (org-clock-idle-time 5)

                   ;;; Org bibliographic and exporter settings

  (org-export-default-language "en-gb")

  (org-cite-global-bibliography '("/home/Harry/Documents/Bibliography/my.bib")) ; Set your .bib file here
  (org-cite-csl-styles-dir "~/Documents/Bibliography/CSLFiles/") ; Set the CSL styles directory (path to where your .csl files are located)
  (org-cite-csl-locales-dir "/home/Harry/Documents/Bibliography/CSLFiles/locales/")
  (org-cite-export-processors
   '((t csl)))


  (org-format-latex-options
   '(:foreground default :background default :scale 0.5 :html-foreground
                 "Black" :html-background "Transparent" :html-scale
                 1.0 :matchers ("begin" "$1" "$" "$$" "\\(" "\\[")))

  (TeX-command-default "LaTeX")
  (TeX-clean-confirm nil)  ; Automatically clean without confirmation
  (org-odt-preferred-output-format "docx")
  (org-cite-csl-link-cites t)
  (org-latex-hyperref-template
   "\\hypersetup{
          pdfauthor={%a},
          pdftitle={%t},
          pdfkeywords={%k},
          pdfsubject={%d},
          pdfcreator={%c},
          pdflang={%L},
          colorlinks=false,   
          linkcolor=black,    
          urlcolor=black,     
          citecolor=black,    
          pdfborder={0 0 0}   
        }")

                 ;;; Org editing and visual tweaks

  (org-pretty-entities t)
  (org-use-sub-superscripts "{}")
  (org-support-shift-select t)
  (org-hide-emphasis-markers t)
  (org-startup-with-inline-images nil)
  (org-tags-column 0)

  (org-src-window-setup 'current-window)
                                        ; (org-auto-align-tags nil)

                ;;; Export settings

  (org-export-with-toc nil) ; No table of contents
  (org-export-with-section-numbers nil)  ; No section numbers
  (org-export-with-smart-quotes t)  ; Use smart quotes

                ;;; misc

  (org-log-into-drawer t)
  (org-log-done 'time)

  :config

  (require 'oc-csl)
  (add-to-list 'org-modules 'org-habit)

                   ;;; Org-babel

  ;; active Babel languages

  (org-babel-do-load-languages
   'org-babel-load-languages
   '((emacs-lisp . t)
     (shell . t)
     (gnuplot . t)))

  :bind (("C-c 9" . org-capture)
         ("M-+" . org-word-counter))

  :hook ((org-mode . variable-pitch-mode)
         (org-babel-post-tangle . harry-post-tangle-headers-elisp)
         (org-babel-post-tangle . harry-post-tangle-headers-shell)))

Org Agenda

(use-package org-agenda
  :ensure nil
  :custom
  (org-agenda-tags-column -77)
  (org-agenda-files '("~/Documents/Open University/Org mode notes/A350.org"
                      "~/Documents/Open University/Org mode notes/A340.org"
                      "~/Documents/Personal Files/Personal Todo.org"
                      "~/Documents/Bibliography/Reading List.org"
                      "~/GNU-Ranch/Literate-configs/Emacs-config.org"
                      ))

  (org-agenda-custom-commands
   '(("d" "Daily Agenda"
      ((agenda "" ((org-agenda-span 'day)))))))

  (org-agenda-remove-tags t)
  (org-agenda-scheduled-leaders
   '("[S] : " "[S] x%3d d.: "))
  (org-agenda-deadline-leaders
   '("[D] : " "[D] +%3d d.: " "[D] -%3d d.: "))

  :config

  (add-to-list 'display-buffer-alist '("\\*Agenda Commands\\*" (display-buffer-in-side-window) (side . right) (window-width . 0.4)))

  (add-to-list 'display-buffer-alist '("\\*Org Agenda\\*" (display-buffer-in-side-window) (side . right) (window-width . 0.5)))

  (setq org-latex-create-formula-image-program 'dvisvgm)


  :bind
  (("C-c a" . org-agenda)
   ("C-c t" . (lambda()
                (interactive)
                (org-agenda nil "a"))))

  :hook (org-agenda-mode . hl-line-mode))

Org Crypt

(use-package org-crypt
  :ensure nil
  :custom
  (org-tags-exclude-from-inheritance '("crypt"))

  (org-crypt-key "976A0BDD15B89B7C")

  :config 
  (org-crypt-use-before-save-magic)

  ;; Auto-saving does not cooperate with org-crypt.el: so you need to
  ;; turn it off if you plan to use org-crypt.el quite often.  Otherwise,
  ;; you'll get an (annoying) message each time you start Org.

  ;; To turn it off only locally, you can insert this:
  ;;
  ;; # -*- buffer-auto-save-file-name: nil; -*-

  :bind (("C-c o q" . org-decrypt-entry)
         ("C-c o w" . org-encrypt-entry)))

Org Habit

(use-package org-habit
  :ensure nil
  :defer t)

Org-modern

What does this package do?

Org-modern adjusts Org’s various elements (heading markers, agenda faces and the tables) in order to make them appear more modern and visually appealing.

Custom Settings

For the time being the settings are identical to the defaults except for the heading icons which are set to stars, rather than folding indicators

(use-package org-modern
  :ensure t
  :pin gnu
  :custom

  (org-modern-star 'replace)
  (org-modern-tag-faces (quote (("OU" :background "light blue"
                                 :foreground "black")
                                ("Life" :background "medium spring green" :foreground "black")
                                ("MA" :background "black" :foreground "white")
                                ("Latin" :background "salmon" :foreground "black")
                                ("Gym" :background "medium aquamarine" :foreground "black"))))
  :hook
  (org-mode . global-org-modern-mode))

Org Remark

(use-package org-remark-global-tracking-mode
  :ensure nil
  :hook after-init
  :config

  (use-package org-remark-info :ensure nil :after info :config
    (org-remark-info-mode +1))
  (use-package org-remark-eww :ensure nil :after eww :config
    (org-remark-eww-mode +1)))

(use-package org-remark
  :pin gnu
  :ensure t
  :bind (("C-c n m" . org-remark-mark)
         ("C-c n l" . org-remark-mark-line)
         :map org-remark-mode-map
         ("C-c n o" . org-remark-open)
         ("C-c n ]" . org-remark-view-next)
         ("C-c n [" . org-remark-view-prev)
         ("C-c n r" . org-remark-remove)
         ("C-c n d" . org-remark-delete)))

Packaging

(use-package system-packages
  :ensure t
  :pin gnu) 

Shells

Eat

(use-package eat
  :ensure t
  :defer t
  :pin nongnu
  :hook
  (eshell-first-time-mode . eat-eshell-visual-command-mode)
  (eshell-first-time-mode . eat-eshell-mode))

Eshell

  • Aliases
    alias u cd ..
    alias docs cd ~/Documents
    alias ranch cd ~/GNU-Ranch
    
    alias ll ls -l $@*
    
    alias autumnbonsailive cbonsai -l -k 202,3,214,11
    alias autumnbonsai cbonsai -k 202,3,214,11
    alias autumnscreensaver cbonsai -S -k 202,3,214,11
    alias autumnscreensaverslow cbonsai -S -k 202,3,214,11 -t 2
    
  • General
    (use-package eshell
      :ensure nil
      :custom
      (eshell-bad-command-tolerance 10)
      :bind ("M-g u" . eshell))
    

Term

(use-package term
  :ensure nil
  :defer t
  :bind ("M-g t" . (lambda () (interactive) (term "/bin/bash"))))

Shell

(use-package shell
  :ensure nil
  :bind ("M-g y" . shell))

Themes

Doric-themes

(use-package doric-themes
  :ensure t
  :pin gnu
  :defer nil
  :config

(doric-themes-select 'doric-obsidian))

Ef-themes

What does this package do?

This package provides a set of themes similar to Modus, but with a good deal more flair.

Custom Settings

The themes have been configured to bring them in line with the configurations for Modus Themes (see Modus Themes)

(use-package ef-themes
  :ensure nil
  :pin gnu
:defer t
:custom

(ef-themes-mixed-fonts t)
(ef-themes-variable-pitch-ui t)
(ef-themes-disable-other-themes t)

(ef-themes-headings
 (quote ((1 variable-pitch 1.4)
         (2 variable-pitch  1.3)
         (3 variable-pitch 1.2)
         (4 variable-pitch 1.1)
         (t light variable-pitch 1.1)

         ((agenda-date) 1.3)
         ((agenda-structure-variable-pitch light 1.8))))))

Fontaine

(use-package fontaine
  :ensure t
  :pin gnu
  :custom

  (fontaine-presets
   '((regular
      :default-family "Dejavu Sans Mono"
      :default-weight normal
      :default-height 140
      :fixed-pitch-family "Dejavu Sans Mono"
      :fixed-pitch-weight normal
      :fixed-pitch-height 140
      :fixed-pitch-serif-family "DejaVu Sans Mono"
      :fixed-pitch-serif-weight normal
      :fixed-pitch-serif-height 100
      :variable-pitch-family "Dejavu Sans"
      :variable-pitch-weight normal
      :variable-pitch-height 1.12
      :mode-line-active-family "Dejavu Sans"
      :mode-line-inactive-family "Dejavu Sans"
      :bold-family nil
      :bold-weight bold
      :italic-family nil
      :italic-slant italic
      :line-spacing 2)

     (regular-serif
      :inherit regular
      :variable-pitch-family "Dejavu Serif")

     (libertine
      :inherit regular
      :variable-pitch-family "Linux Libertine O")

     (biolinum
      :inherit regular
      :variable-pitch-family "Linux Biolinum O")

     (ioesvka
      :default-family "Iosevka"
      :default-weight normal
      :default-height 140
      :fixed-pitch-family "Iosevka"
      :fixed-pitch-weight normal
      :fixed-pitch-height 140
      :fixed-pitch-serif-family "Iosevka"
      :fixed-pitch-serif-weight normal
      :fixed-pitch-serif-height 100
      :variable-pitch-height 1.12
      :mode-line-active-family "Iosevka"
      :mode-line-inactive-family "Iosevka"
      :bold-family nil
      :bold-weight bold
      :italic-family nil
      :italic-slant italic
      :line-spacing 2)


     (libertine/ioesvka
      :inherit ioesvka
      :variable-pitch-family "Linux Libertine O")

     (biolinum/ioesvka
      :inherit ioesvka
      :variable-pitch-family "Linux Biolinum O")))


  :hook

  ((after-init . fontaine-mode)
   (after-init . (lambda ()
                   (fontaine-set-preset (or (fontaine-restore-latest-preset) 'regular)))))

  :bind (("C-c o i" . fontaine-set-preset)
         ("C-c o ," . fontaine-toggle-preset)))

Modus Themes

    (use-package emacs
      :ensure nil
      :custom
      (modus-themes-italic-constructs t)
      (modus-themes-mixed-fonts t)
      (modus-themes-variable-pitch-ui t)

      (modus-themes-headings
       '((0 . (1.75))
         (1 . (variable-pitch 1.4))
         (2 . (variable-pitch  1.3))
         (3 . (variable-pitch 1.2))
         (4 . (variable-pitch 1.1))
         (t . (variable-pitch light 1.1))

         ((agenda-date) 1.3)
         ((agenda-structure-variable-pitch light 1.8))))

      (modus-themes-to-toggle '(modus-operandi modus-vivendi))
      (modus-themes-disable-other-themes t)

        ;;; Overrides

      ;; Slightly nicer looking mode line

      (modus-operandi-tinted-palette-overrides
       '((bg-mode-line-active bg-ochre)
         (fg-mode-line-active fg-main)))

      ;; Invisible Fringe and source blocks

      (modus-themes-common-palette-overrides
        '((bg-prose-block-contents unspecified)
          (bg-prose-block-delimiter unspeficied)
          (fg-prose-block-delimiter fg-dim)
        (fringe unspecified)))

;      :config

 ;     (load-theme 'modus-operandi)

      :bind ("<f5>" . modus-themes-toggle))

Show Font

(use-package show-font
  :ensure t
  :pin gnu
  :bind
  (("C-c s f" . show-font-select-preview)
   ("C-c s t" . show-font-tabulated)))

Spacious Padding

What does this package do?

This package adds a global-minor-mode which increases the padding of Emacs’ UI elements.

Custom Settings

The widths have been altered slightly—largely to minimise internal-border-widths. I have also defined an interactive function which toggles spacious-padding-subtle-mode-line before refreshing spacious-padding-mode; this function is bound to ’C-c o t’.

(use-package spacious-padding
  :ensure t
  :pin gnu
  :custom
  (spacious-padding-subtle-mode-line t)

  (spacious-padding-widths
   '( :internal-border-width 15
      :header-line-width 4
      :mode-line-width 6
      :tab-width 4
      :right-divider-width 30
      :scroll-bar-width 8
      :fringe-width 8))

  :bind (("C-c o t" . set-spacious-padding-subtle-mode-line)
           ("C-c o s" . spacious-padding-mode))
  :hook (after-init . spacious-padding-mode))

Splash Screen

Here the default scratch buffer is replaced with a splash screen featuring a tasteful ASCII art GNU—credited to Vijay Kumar Bagavath Singh—and a welcome message. Both the art and the message are set to clear upon user input.

(use-package harry-splash-screen
  :ensure nil
  :hook ((emacs-startup . my-ascii-art)
         (emacs-startup . olivetti-mode)
         (post-command . clear-scratch-buffer-on-input)))

Version Control

VC

(use-package vc
  :ensure nil
  :ensure-system-package git
  :defer t
  :hook (vc-git-log-edit-mode . auto-fill-mode))

Web

Window

Ibuffer

(use-package ibuffer
  :ensure nil
  :bind ("M-g ," . ibuffer))

Libraries

Bibliography Library

Ebib

(defun harry-set-ebib-window-split ()
  "Set `ebib-window-vertical-split' based on window width."
  (if (< (window-width) 130)
      (progn
        (setq ebib-window-vertical-split nil)
        (setq ebib-index-window-size 20))
    (progn
      (setq ebib-window-vertical-split t)
      (setq ebib-index-window-size 110))))

Header Line Library

This block adds a header line which displays the current file path and vc branch. It can be enabled and disabled with ’M-x harry-header-line-mode’ or ’M-g h’.

(define-minor-mode harry-header-line-mode
  "A minor mode which displays a header line with the current file path and vc branch."
  :lighter " Harry's Header Line"
  (if harry-header-line-mode
      (setq header-line-format
            '(:eval
              (list
               (abbreviate-file-name default-directory)
               "  "
               (when vc-mode "🪵")
               vc-mode)
              ()))
    (setq-local header-line-format nil)))

Language Library

Logos

(defun harry-logos-hide-mode-line ()
  "Hides or shows the mode line while in logos-focus-mode."
  (interactive)
  logos-set-mode-arg '
  (if logos-focus-mode
      (if logos-hide-mode-line
          (progn
            (setq-local logos-hide-mode-line nil)
            (logos-focus-mode -1)
            (logos-focus-mode 1))
        (setq-local logos-hide-mode-line t)
        (logos-focus-mode -1)
        (logos-focus-mode 1))))

Mode Line Library

Mode Line Indicators

This block defines the basic variables to be used as indicators within the mode-line.

(defvar my-mode-line-buffer-name (propertize "%b" 'face 'bold)
  "The format for the buffer name in the mode line.")

(defvar my-mode-line-file-position (propertize "(%o)" 'face 'shadow)
  "The format for the file position in the mode line.")

(defvar my-mode-line-file-delta-status (propertize "Δ: %&" 'face 'shadow))

(defvar my-mode-line-lambda (propertize "λ " 'face 'shadow)
  "The format for the lambda symbol in the mode line.")

(defvar my-mode-line-mode (propertize "%m" 'face 'bold)
  "The format for the major mode in the mode line.")

(defvar my-mode-line-global-string (propertize " %M" 'face 'bold)
  "The format for the global status in the mode line.")

(dolist (construct '(my-mode-line-buffer-name
                     my-mode-line-file-position
                     my-mode-line-file-delta-status
                     my-mode-line-lambda
                     my-mode-line-mode
                     my-major-mode-line-mode-indicators))

  (put construct 'risky-local-variable t))

Mode Line Major Mode Icons

This block defines a list of UTF emojis to be associated with various major modes.

(defvar my-major-mode-line-mode-indicators
  '((org-mode . " 📚")
    (org-agenda-mode . " 🗓️")
    (bibtex-mode . " 📜")
    (lisp-mode . " 🍯")
    (python-mode . " 🐍")
    (java-mode . " ☕")
    (perl-mode . " 🐫")
    (c-mode . " 👴🏼")
    (c++-mode . " 👴🏼")
    (eww-mode . " 🧭")
    (emms-playlist-mode . " 🎹")
    (emms-browser-mode . " 💽")
    (gnus-group-mode . " 📫")
    (gnus-summary-mode . " 📬")
    (gnus-article-mode . " 📰")
    (message-mode . " 📧")
    (dired-mode . " 💾")
    (ibuffer-mode . " 🪟")
    "A list of mode-specific indicators for the mode line."))

Themes Library

Cbonsai

(defun harry-autumn-screensaver (&optional size)
  "Split frame with eshell on right running autumn screensaver.
SIZE sets the approximate width percentage for the right window (default 35)."
  (interactive "P")
  (let* ((default-size 27)
         (size-percent (or (and size (prefix-numeric-value size)) default-size))
         (left-width (round (* (frame-width) (- 1 (/ size-percent 100.0)))))
         (buffer-name "*Autumn Screensaver*"))

    ;; Kill existing Autumn Screensaver buffer if it exists
    (when (get-buffer buffer-name)
      (message "Killing existing Autumn Screensaver buffer...")
      (kill-buffer buffer-name))

    (delete-other-windows)
    (split-window-horizontally left-width)
    (other-window 1)

    ;; Error handling for eshell creation
    (condition-case err
        (progn
          (eshell)
          (rename-buffer buffer-name)
          (eshell-return-to-prompt)
          (insert "autumnscreensaverslow")
          (eshell-send-input)
          (other-window -1)
          (message "Autumn screensaver started successfully!"))

      (error 
       (message "Error starting autumn screensaver: %s" (error-message-string err))
       (other-window -1)
       (delete-window (get-buffer-window buffer-name))))))

Frame Transparency

This block adds a setting which makes the frame transparent

(defvar harry-frame-transparency 86 "Transparency value for the frame when toggled.")

(defun harry-toggle-frame-transparency ()
  "Toggle frame transparency between transparent and opaque."
  (interactive)
  (if (eq (frame-parameter nil 'alpha-background) harry-frame-transparency)
      (progn
        (set-frame-parameter nil 'alpha-background 100) ; Opaque
        (message "Frame is now opaque."))
    (progn
      (set-frame-parameter nil 'alpha-background harry-frame-transparency) ; Transparent
      (message "Frame is now transparent."))))

Frame Decoration

(defun harry-toggle-frame-decoration ()
  "Toggle frame decoration on/off."
  (interactive)
  (let ((undecorated (frame-parameter nil 'undecorated)))
    (modify-frame-parameters nil 
                             `((undecorated . ,(not undecorated))))
    (message "Frame decoration %s" (if (not undecorated) "disabled" "enabled"))))

Spacious Padding

(defun set-spacious-padding-subtle-mode-line ()
  "Toggles spacious-padding-subtle-mode-line"
  (interactive)
  (setq spacious-padding-subtle-mode-line
        (not spacious-padding-subtle-mode-line))
  (spacious-padding-mode -1)
  (spacious-padding-mode 1))

Splash Screen

(defun center-text (text)
  "Center TEXT within the entire Emacs window width."
  (let* ((window-width (window-body-width))          ; Get the width of the window
         (ascii-width (apply 'max (mapcar 'length (split-string text "\n")))))  ; Max length of any line in the ASCII art
    (if (> window-width ascii-width)
        (let ((padding (max 0 (/ (- window-width ascii-width) 2))))  ; Calculate padding
          (mapconcat (lambda (line)
                       (concat (make-string padding ?\ ) line))  ; Add padding to each line
                     (split-string text "\n" t)
                     "\n"))
      text)))  ; If the text is wider than the window, just return it unmodified

(defun my-ascii-art ()
  "Insert custom ASCII art into the *scratch* buffer."
  (flymake-mode 0)
  (interactive)
  (let ((ascii-art "

    _-`````-,            ,- '- .\n
  .'   .- - |          | - -.  `.\n
 /.'  /                     `.   \n
:/   :      _...   ..._      ``   :\n
::   :     /._ .`:'_.._\\.    ||   :\n
::    `._ ./  ,`  :    \\ . _.''   .\n
`:.      /   |  -.  \\-. \\\\_      /\n
  \:._ _/  .'   .@)  \\@) ` `\\ ,.'\n
     _/,--'       .- .\\,-.`--`.\n
       ,'/''     (( \\ `  )    
        /'/'  \\    `-'  (      
         '/''  `._,-----'\n
          ''/'    .,---'\n
           ''/'      ;:\n
             ''/''  ''/\n
               ''/''/''\n
                 '/'/'\n
                  `;"))
    (let ((welcome-message "\nWelcome to Harry's Emacs! Press any key to clear this scratch buffer. Credit for the art goes to Vijay Kumar Bagavath Singh <3"))
      (with-current-buffer "*scratch*"
        (erase-buffer)
        (insert (center-text ascii-art))  ; Centered ASCII art
        (insert (center-text welcome-message))  ; Center the welcome message
        (goto-char (point-min))))))

;; Automatically clear *scratch* buffer when you start typing
(defvar my-scratch-cleared nil "Flag to check if *scratch* has been cleared.")

(defun clear-scratch-buffer-on-input ()
  "Clear the *scratch* buffer when you start typing."
  (when (and (eq (current-buffer) (get-buffer "*scratch*"))
             (not my-scratch-cleared)
             (not (= (point) (point-min)))) ; Only clear if you are not at the beginning (start typing)
    (erase-buffer)
    (setq my-scratch-cleared t)))  ; Flag to prevent multiple clears

Org Library

General

  • An Org Friendly Word Counter
    (defun org-word-counter ()
      "Count words in region/buffer, estimate pages, and reading time.
    Excludes lines beginning with * or #. Prints result in echo area. Credit goes to Chris Maiorana"
      (interactive)
      (let* ((start (if (use-region-p) (region-beginning) (point-min)))
             (end (if (use-region-p) (region-end) (point-max)))
             (word-count
              (save-excursion
                (goto-char start)
                (let ((count 0)
                      (inhibit-field-text-motion t))
                  (while (< (point) end)
                    (beginning-of-line)
                    (unless (looking-at-p "^[*#<]")
                      (let ((line-end (line-end-position)))
                        (while (re-search-forward "\\w+\\W*" line-end t)
                          (setq count (1+ count)))))
                    (forward-line 1))
                  count)))
             (words-per-page 400)
             (reading-speed 215)
             (page-count (/ (+ word-count words-per-page -1) words-per-page))
             (reading-time (/ (+ word-count reading-speed -1) reading-speed)))
        (message "%d words, ~%d pages, ~%d min read"
                 word-count page-count reading-time)))
    

Babel

  • Post-tangle Headers
    (defun harry-post-tangle-headers-elisp ()
      (message "running in %s" (buffer-file-name))
      (cond
       ((f-ext? (buffer-file-name) "el")
        (goto-char (point-min))
        (insert ";;; -*- lexical-binding: t -*-
    ;; Copyright (C) 2025 by Harry G. Thompson
    ;; This file is part of the Ox Ranch.
    
    ;; The Ox Ranch 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.
    
    ;; The Ox Ranch 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 the Ox Ranch. If not, see <https://www.gnu.org/licenses/>.\n\n"))
       (t
        nil))
      (save-buffer))
    
      (defun harry-post-tangle-headers-shell ()
      (message "running in %s" (buffer-file-name))
      (cond
       ((f-ext? (buffer-file-name) "sh")
        (goto-char (point-min))
        (forward-line 1)
        (open-line 2)
        (insert "
    # Copyright 2025 Harry Thompson
    # This file is part of the Ox Ranch.
    
    # The Ox Ranch 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.
    
    # The Ox Ranch 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 the Ox Ranch. If not, see <https://www.gnu.org/licenses/>.\n\n"))
       (t
        nil))
      (save-buffer))