376 lines
13 KiB
EmacsLisp
376 lines
13 KiB
EmacsLisp
;; -*- lexical-binding: t; -*-
|
|
|
|
;;; This file is generated from the Emacs.org file in my dotfiles repository!
|
|
|
|
;;; ----- Basic Configuration -----
|
|
|
|
;; Core settings
|
|
(setq ;; Flash the UI instead of beeping
|
|
visible-bell nil
|
|
|
|
;; Yes, this is Emacs
|
|
inhibit-startup-message t
|
|
;; inhibit-startup-screen t
|
|
initial-scratch-message nil
|
|
;; initial-buffer-choice nil
|
|
frame-title-format nil
|
|
use-file-dialog nil
|
|
|
|
indicate-empty-lines t
|
|
|
|
;; Instruct auto-save-mode to save to the current file, not a backup file
|
|
auto-save-default nil
|
|
auto-save-timeout 3 ; number of seconds idle time before auto-save
|
|
; (default: 30)
|
|
auto-save-interval 200 ; number of keystrokes between auto-saves
|
|
; (default: 300)
|
|
x-select-enable-primary t
|
|
x-select-enable-clipboard t
|
|
mouse-drag-copy-region t
|
|
|
|
;; No backup files, please
|
|
make-backup-files nil
|
|
|
|
;; Make it easy to cycle through previous items in the mark ring
|
|
set-mark-command-repeat-pop t
|
|
|
|
;; Don't warn on large files
|
|
large-file-warning-threshold nil
|
|
|
|
;; Follow symlinks to VC-controlled files without warning
|
|
;; vc-follow-symlinks t
|
|
|
|
;; Don't warn on advice
|
|
ad-redefinition-action 'accept
|
|
|
|
;; Revert Dired and other buffers
|
|
global-auto-revert-non-file-buffers t
|
|
|
|
;; Silence compiler warnings as they can be pretty disruptive
|
|
native-comp-async-report-warnings-errors nil)
|
|
|
|
|
|
;; No scroll bars
|
|
(if (fboundp 'scroll-bar-mode) (set-scroll-bar-mode nil))
|
|
|
|
;; No toolbar
|
|
(if (fboundp 'tool-bar-mode) (tool-bar-mode -1))
|
|
|
|
(dolist (mode '(scroll-bar-mode
|
|
horizontal-scroll-bar-mode
|
|
menu-bar-mode
|
|
tooltip-mode
|
|
tool-bar-mode))
|
|
(when (fboundp mode)
|
|
(funcall mode 0)))
|
|
|
|
|
|
;; Core modes
|
|
(repeat-mode 1) ;; Enable repeating key maps
|
|
(menu-bar-mode 0) ;; Hide the menu bar
|
|
(tool-bar-mode 0) ;; Hide the tool bar
|
|
(savehist-mode 1) ;; Save minibuffer history
|
|
(scroll-bar-mode 0) ;; Hide the scroll bar
|
|
(xterm-mouse-mode 1) ;; Enable mouse events in terminal Emacs
|
|
(display-time-mode 1) ;; Display time in mode line / tab bar
|
|
(fido-vertical-mode 1) ;; Improved vertical minibuffer completions
|
|
(column-number-mode 1) ;; Show column number on mode line
|
|
(tab-bar-history-mode 1) ;; Remember previous tab window configurations
|
|
(auto-save-visited-mode 1) ;; Auto-save files at an interval
|
|
(global-visual-line-mode 1) ;; Visually wrap long lines in all buffers
|
|
(global-auto-revert-mode 1) ;; Refresh buffers with changed local files
|
|
|
|
(icomplete-mode 0)
|
|
;; (blink-cursor-mode 0)
|
|
|
|
(show-paren-mode t)
|
|
|
|
;; Tabs to spaces
|
|
(setq-default indent-tabs-mode nil
|
|
tab-width 2)
|
|
(fset 'yes-or-no-p 'y-or-n-p)
|
|
|
|
;; Display line numbers in programming modes
|
|
(add-hook 'prog-mode-hook #'display-line-numbers-mode)
|
|
(add-hook 'before-save-hook 'delete-trailing-whitespace)
|
|
|
|
;; Make icomplete slightly more convenient
|
|
;; (keymap-set icomplete-fido-mode-map "M-h" 'icomplete-fido-backward-updir)
|
|
;; (keymap-set icomplete-fido-mode-map "TAB" 'icomplete-force-complete)
|
|
|
|
;; Delete trailing whitespace before saving buffers
|
|
(add-hook 'before-save-hook 'delete-trailing-whitespace)
|
|
|
|
;; Move customization settings out of init.el
|
|
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
|
|
(when (file-exists-p custom-file)
|
|
(load custom-file t))
|
|
|
|
;; Match completion substrings that may be out of order
|
|
(defun fn/override-fido-completion-styles ()
|
|
(setq-local completion-styles '(substring partial-completion emacs22)))
|
|
|
|
;; (add-hook 'icomplete-minibuffer-setup-hook 'fn/override-fido-completion-styles)
|
|
|
|
|
|
(prefer-coding-system 'utf-8)
|
|
(set-default-coding-systems 'utf-8)
|
|
(set-terminal-coding-system 'utf-8)
|
|
(set-keyboard-coding-system 'utf-8)
|
|
(set-language-environment 'utf-8)
|
|
|
|
(set-default 'cursor-type '(hbar . 2))
|
|
|
|
;;; ----- System Identification -----
|
|
|
|
(defvar fn/is-termux
|
|
(string-suffix-p "Android" (string-trim (shell-command-to-string "uname -a"))))
|
|
|
|
(defvar fn/current-distro (or (and (eq system-type 'gnu/linux)
|
|
(file-exists-p "/etc/os-release")
|
|
(with-temp-buffer
|
|
(insert-file-contents "/etc/os-release")
|
|
(search-forward-regexp "^ID=\"?\\(.*\\)\"?$")
|
|
(intern (or (match-string 1)
|
|
"unknown"))))
|
|
'unknown))
|
|
|
|
(defvar fn/is-guix-system (eql fn/current-distro 'guix))
|
|
|
|
;;; ----- Package Management -----
|
|
|
|
;; Automatically install packages (when not on Guix) but don't load
|
|
;; them until requested
|
|
(setq use-package-always-ensure (not fn/is-guix-system)
|
|
use-package-always-defer t)
|
|
|
|
;;; ----- Configuration Management -----
|
|
|
|
(defvar fn/use-config-modules '()
|
|
"A list of module symbols to load once init.el is finished.")
|
|
|
|
(defvar fn/common-config-modules '(
|
|
fn-core
|
|
fn-present
|
|
fn-writing
|
|
fn-workflow
|
|
fn-coding
|
|
fn-interface
|
|
fn-vc
|
|
)
|
|
"Configuration modules most commonly used across my machines.")
|
|
|
|
|
|
|
|
;; Add configuration modules to load path
|
|
(add-to-list 'load-path '"~/.config/emacs/modules")
|
|
|
|
;; Load system-specific configuration
|
|
(let ((config-path
|
|
(format "~/.config/emacs/systems/%s.el" system-name)))
|
|
(if (file-exists-p config-path)
|
|
(load-file config-path)
|
|
(message "No per-system configuration found for %s!" system-name)))
|
|
|
|
|
|
|
|
|
|
;;; ----- Appearance -----
|
|
|
|
(defun fn/set-terminal-title (title)
|
|
(send-string-to-terminal (format "\e]0;%s\a" title)))
|
|
|
|
(defun fn/clear-background-color (&optional frame))
|
|
;; (interactive)
|
|
;; (or frame (setq frame (selected-frame)))
|
|
;; "unsets the background color in terminal mode"
|
|
;; (unless (display-graphic-p frame)
|
|
;; Set the terminal to a transparent version of the background color
|
|
;; (send-string-to-terminal
|
|
;; (format "\033]11;[90]%s\033\\"
|
|
;; (face-attribute 'default :background)))
|
|
;; (set-face-background 'default "unspecified-bg" frame)))
|
|
|
|
;; Clear the background color for transparent terminals
|
|
(unless (display-graphic-p)
|
|
(add-hook 'after-make-frame-functions 'fn/clear-background-color)
|
|
(add-hook 'window-setup-hook 'fn/clear-background-color)
|
|
(add-hook 'ef-themes-post-load-hook 'fn/clear-background-color))
|
|
|
|
(use-package modus-themes
|
|
:custom
|
|
(modus-themes-italic-constructs t)
|
|
(modus-themes-bold-constructs t)
|
|
(modus-themes-mixed-fonts t)
|
|
(modus-themes-variable-pitch-ui t)
|
|
(modus-themes-to-toggle '(modus-vivendi-tinted modus-operandi-tinted))
|
|
(modus-themes-common-palette-overrides
|
|
`((bg-mode-line-active bg-lavender)
|
|
(fg-mode-line-active fg-main)
|
|
(border-mode-line-active bg-magenta-warmer)))
|
|
:init
|
|
(load-theme 'modus-vivendi-tinted t)
|
|
(add-hook 'modus-themes-after-load-theme-hook #'fn/clear-background-color))
|
|
;;
|
|
;; Make vertical window separators look nicer in terminal Emacs
|
|
(set-display-table-slot standard-display-table 'vertical-border (make-glyph-code ?│))
|
|
|
|
;; Clean up the mode line
|
|
(setq-default mode-line-format
|
|
'("%e" " "
|
|
(:propertize
|
|
("" mode-line-mule-info mode-line-client mode-line-modified mode-line-remote))
|
|
mode-line-frame-identification
|
|
mode-line-buffer-identification
|
|
" "
|
|
mode-line-position
|
|
mode-line-format-right-align
|
|
" "
|
|
(project-mode-line project-mode-line-format)
|
|
" "
|
|
(vc-mode vc-mode)
|
|
" "
|
|
mode-line-modes
|
|
mode-line-misc-info
|
|
" ")
|
|
project-mode-line t
|
|
mode-line-buffer-identification '(" %b")
|
|
mode-line-position-column-line-format '(" %l:%c"))
|
|
|
|
;; Move global mode string to the tab-bar and hide tab close buttons
|
|
(setq tab-bar-close-button-show nil
|
|
tab-bar-separator " "
|
|
tab-bar-format '(tab-bar-format-menu-bar
|
|
tab-bar-format-tabs-groups
|
|
tab-bar-separator
|
|
tab-bar-format-align-right
|
|
tab-bar-format-global))
|
|
|
|
;; Turn on the tab-bar
|
|
(tab-bar-mode 1)
|
|
|
|
;; Customize time display
|
|
(setq display-time-load-average nil
|
|
display-time-format "%H:%M %b %d W%U")
|
|
|
|
;; ----- Special Buffers as Popup Window -----
|
|
|
|
(setq display-buffer-alist
|
|
'(("\\*\\(shell\\|.*term\\|.*eshell\\|help\\|compilation\\|Async Shell Command\\|Occur\\|xref\\).*\\*"
|
|
(display-buffer-reuse-window display-buffer-in-side-window)
|
|
(side . bottom) ; Popups go at the bottom
|
|
(slot . 0) ; Use the first slot at the bottom
|
|
(post-command-select-window . t) ; Select the window upon display
|
|
(window-height . 0.3)))) ; 30% of the frame height
|
|
|
|
(defun fn/toggle-popup-window ()
|
|
(interactive)
|
|
(if-let ((popup-window
|
|
(get-window-with-predicate
|
|
(lambda (window)
|
|
(eq (window-parameter window 'window-side)
|
|
'bottom)))))
|
|
|
|
;; Focus the window if it is not selected, otherwise close it
|
|
(if (eq popup-window (selected-window))
|
|
(delete-window popup-window)
|
|
(select-window popup-window))
|
|
|
|
;; Find the most recent buffer that matches the rule and show it
|
|
;; NOTE: This logic is somewhat risky because it makes the assumption
|
|
;; that the popup rule comes first in `display-buffer-alist'.
|
|
;; I chose to do this because maintaining a separate variable
|
|
;; for this rule meant I had to re-evaluate 2 different forms
|
|
;; to update my rule list.
|
|
(if-let ((popup-buffer
|
|
(seq-find (lambda (buffer)
|
|
(buffer-match-p (caar display-buffer-alist)
|
|
(buffer-name buffer)))
|
|
(if (project-current)
|
|
(project-buffers (project-current))
|
|
(buffer-list (selected-frame))))))
|
|
(display-buffer popup-buffer (cdar display-buffer-alist))
|
|
(message "No popup buffers found."))))
|
|
|
|
;; TODO: This binding may need to change
|
|
(keymap-global-set "C-c p" #'fn/toggle-popup-window)
|
|
(with-eval-after-load 'term
|
|
(keymap-set term-raw-map "C-c p" #'fn/toggle-popup-window))
|
|
|
|
;;; ----- Essential Org Mode Configuration -----
|
|
|
|
(setq org-ellipsis " ▾"
|
|
org-startup-folded 'content
|
|
org-cycle-separator-lines 2
|
|
org-fontify-quote-and-verse-blocks t)
|
|
|
|
;; Indent org-mode buffers for readability
|
|
(add-hook 'org-mode-hook #'org-indent-mode)
|
|
|
|
;; Set up Org Babel languages
|
|
(org-babel-do-load-languages
|
|
'org-babel-load-languages
|
|
'((emacs-lisp . t)
|
|
(shell . t)))
|
|
|
|
;; Use org-tempo
|
|
(use-package org-tempo
|
|
:straight (:type built-in)
|
|
:ensure nil
|
|
:demand t
|
|
:config
|
|
(dolist (item '(("sh" . "src sh")
|
|
("el" . "src emacs-lisp")
|
|
("li" . "src lisp")
|
|
("sc" . "src scheme")
|
|
("ts" . "src typescript")
|
|
("py" . "src python")
|
|
("yaml" . "src yaml")
|
|
("json" . "src json")
|
|
("einit" . "src emacs-lisp :tangle emacs/init.el")
|
|
("emodule" . "src emacs-lisp :tangle emacs/modules/dw-MODULE.el")))
|
|
(add-to-list 'org-structure-template-alist item)))
|
|
|
|
;;; ----- Document Centering -----
|
|
|
|
(defvar center-document-desired-width 90
|
|
"The desired width of a document centered in the window.")
|
|
|
|
(defun center-document--adjust-margins ()
|
|
;; Reset margins first before recalculating
|
|
(set-window-parameter nil 'min-margins nil)
|
|
(set-window-margins nil nil)
|
|
|
|
;; Adjust margins if the mode is on
|
|
(when center-document-mode
|
|
(let ((margin-width (max 0
|
|
(truncate
|
|
(/ (- (window-width)
|
|
center-document-desired-width)
|
|
2.0)))))
|
|
(when (> margin-width 0)
|
|
(set-window-parameter nil 'min-margins '(0 . 0))
|
|
(set-window-margins nil margin-width margin-width)))))
|
|
|
|
(define-minor-mode center-document-mode
|
|
"Toggle centered text layout in the current buffer."
|
|
:lighter " Centered"
|
|
:group 'editing
|
|
(if center-document-mode
|
|
(add-hook 'window-configuration-change-hook #'center-document--adjust-margins 'append 'local)
|
|
(remove-hook 'window-configuration-change-hook #'center-document--adjust-margins 'local))
|
|
(center-document--adjust-margins))
|
|
|
|
(add-hook 'org-mode-hook #'center-document-mode)
|
|
|
|
;; Make sure ripgrep is used everywhere
|
|
(setq xref-search-program 'ripgrep
|
|
grep-command "rg -nS --noheading")
|
|
|
|
;; Load requested configuration modules
|
|
(dolist (module fn/use-config-modules)
|
|
(require module))
|
|
|
|
(dashboard-open)
|
|
(treemacs-start-on-boot)
|