summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortdback <tyler@tdback.net>2025-02-05 22:22:29 -0500
committertdback <tyler@tdback.net>2025-02-05 22:22:29 -0500
commit5c590db7901f6e0f0a089bcf71401d6a4c9ba1d3 (patch)
treea764c99cff33a29ba61fd1d54a956aa5013ff4a7
initial: we are SO back
-rw-r--r--.gitignore6
-rw-r--r--early-init.el14
-rw-r--r--init.el99
-rw-r--r--lisp/td-common.el145
-rw-r--r--lisp/td-dired.el27
-rw-r--r--lisp/td-evil.el33
-rw-r--r--lisp/td-functions.el64
-rw-r--r--lisp/td-mu4e.el63
-rw-r--r--lisp/td-org.el172
-rw-r--r--lisp/td-present.el27
-rw-r--r--lisp/td-programming.el123
-rw-r--r--lisp/td-writing.el22
12 files changed, 795 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d9aac78
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+/auto-save-list/
+/eln-cache/
+/elpa/
+/etc/
+/places
+/var/
diff --git a/early-init.el b/early-init.el
new file mode 100644
index 0000000..ffc24a2
--- /dev/null
+++ b/early-init.el
@@ -0,0 +1,14 @@
+;; Raise GC limits for a faster startup.
+(setq gc-cons-threshold most-positive-fixnum
+ gc-cons-percentage 0.6)
+
+(add-hook 'after-init-hook (lambda ()
+ (setq gc-cons-threshold 100000000
+ gc-cons-percentage 0.1)))
+
+;; Disable additional toolbars, scrollbars, etc.
+(menu-bar-mode -1)
+(scroll-bar-mode -1)
+(tool-bar-mode -1)
+(tooltip-mode -1)
+(set-fringe-mode 10)
diff --git a/init.el b/init.el
new file mode 100644
index 0000000..ae96934
--- /dev/null
+++ b/init.el
@@ -0,0 +1,99 @@
+;;; -*- lexical-binding: t; -*-
+
+;; Setup package.el and `use-package'.
+(require 'package)
+(setq package-archives '(("melpa" . "https://melpa.org/packages/")
+ ("elpa" . "https://elpa.gnu.org/packages/")
+ ("nongnu" . "https://elpa.nongnu.org/nongnu/")))
+
+(when (version< emacs-version "27")
+ (package-initialize)
+ (load (concat user-emacs-directory "early-init.el")))
+
+;; Bootstrap `use-package'.
+(unless (package-installed-p 'use-package)
+ (package-refresh-contents)
+ (package-install 'use-package))
+
+(require 'use-package)
+(setq use-package-always-ensure t)
+
+;;; ----- Package Imports -----
+
+;; Load custom modules.
+(add-to-list 'load-path '"~/.emacs.d/lisp")
+
+(require 'td-common)
+(require 'td-dired)
+(require 'td-evil)
+(require 'td-functions)
+(require 'td-mu4e)
+(require 'td-org)
+(require 'td-present)
+(require 'td-programming)
+(require 'td-writing)
+
+;;; ----- Sane Defaults -----
+
+(column-number-mode) ; Display columns in our modeline.
+(global-display-line-numbers-mode t) ; Display line numbers in the buffer/modeline.
+(prefer-coding-system 'utf-8) ; Always default to `utf-8'.
+(save-place-mode 1) ; Save our place in the file.
+(fset 'yes-or-no-p 'y-or-n-p) ; Do I even have to explain this one?
+(setq-default indent-tabs-mode nil) ; Disable tab indentation.
+(setq-default tab-width 2) ; Set tabs to two spaces.
+(setq inhibit-startup-message t) ; Don't show a startup message.
+(setq echo-keystrokes 0.1) ; Don't wait long before showing keystrokes.
+(setq ring-bell-function 'ignore) ; Don't make a sound when something goes south.
+(setq use-dialog-box nil) ; Get rid of the dialog box.
+(setq native-comp-async-report-warnings-errors nil) ; Silence compiler warnings.
+(setq large-file-warning-threshold nil) ; Don't warn when opening large files.
+(setq vc-follow-symlinks t) ; Always follow symlinks.
+(setq async-shell-command-display-buffer nil) ; Only display a buffer if the command returns something.
+(setq inhibit-x-resources t) ; Fix emacsclient issues.
+(setq frame-resize-pixelwise t) ; Pixel perfect window resize.
+(setq make-pointer-invisible t) ; This should hide the mouse... doesn't always work.
+(setq word-wrap t) ; Don't wrap in the middle of a word.
+(setq save-place-forget-unreadable-files nil) ; Always save our place in the file.
+(setq display-line-numbers-type 'relative) ; Show relative line numbers.
+
+;;; ----- Keybinds -----
+
+;; Make escape quit prompts.
+(global-set-key (kbd "<escape>") 'keyboard-escape-quit)
+
+;; Increment/decrement a number at point, similar to vim's `C-a' and `C-x'.
+(global-set-key (kbd "C-x n a") 'td/increment-number-at-point)
+(global-set-key (kbd "C-x n x") 'td/decrement-number-at-point)
+
+;;; ----- Hooks -----
+
+;; Display startup stats.
+(add-hook 'emacs-startup-hook #'td/display-startup-time)
+
+;; Delete all trailing whitespace.
+(add-hook 'before-save-hook #'delete-trailing-whitespace)
+
+;; Fix font issues when running as a daemon.
+(if (daemonp)
+ (add-hook 'after-make-frame-functions (lambda (frame)
+ (with-selected-frame frame
+ (td/set-font))))
+ (td/set-font))
+
+;; Disable line numbers for some modes.
+(dolist (mode '(eshell-mode-hook
+ dired-mode-hook
+ olivetti-mode-hook
+ org-mode-hook
+ shell-mode-hook
+ term-mode-hook
+ vterm-mode-hook))
+ (add-hook mode (lambda ()
+ (display-line-numbers-mode 0))))
+
+;; Prettify the lambda symbol.
+(dolist (mode '(emacs-lisp-mode-hook
+ lisp-mode-hook
+ scheme-mode-hook))
+ (add-hook mode 'prettify-symbols-mode))
diff --git a/lisp/td-common.el b/lisp/td-common.el
new file mode 100644
index 0000000..7e71f1b
--- /dev/null
+++ b/lisp/td-common.el
@@ -0,0 +1,145 @@
+;;; -*- lexical-binding: t; -*-
+
+(use-package async
+ :ensure t
+ :config
+ (async-bytecomp-package-mode 1))
+
+(use-package beframe
+ :ensure t
+ :config
+ (global-set-key (kbd "C-c b") 'beframe-prefix-map)
+ (beframe-mode 1))
+
+(use-package consult
+ :ensure t
+ :demand t
+ :bind (("C-s" . consult-ripgrep)
+ ("C-M-l" . consult-imenu)
+ ("C-M-j" . consult-buffer)
+ ("C-x C-b" . consult-buffer)
+ :map minibuffer-local-map
+ ("C-r" . consult-history)))
+
+(use-package consult-dir
+ :ensure t
+ :bind (("C-x C-d" . consult-dir)
+ :map vertico-map
+ ("C-x C-d" . consult-dir)
+ ("C-x C-j" . consult-dir-jump-file))
+ :custom
+ (consult-dir-project-list-function nil))
+
+(use-package doom-modeline
+ :ensure t
+ :init
+ (doom-modeline-mode 1)
+ :custom
+ (doom-modeline-height 10)
+ (doom-modeline-buffer-encoding nil)
+ (doom-modeline-modal-icon nil))
+
+(use-package ef-themes
+ :ensure t
+ :config
+ ;; By default start with a light theme.
+ (load-theme 'ef-day t))
+
+(use-package embark
+ :ensure t
+ :bind (("C-." . embark-act)
+ ("M-." . embark-dwim)
+ ("C-h B" . embark-bindings))
+ :config
+ ;; Remove mixed indicator to prevent popup from being displayed automatically.
+ (delete #'embark-mixed-indicator embark-indicators)
+ (add-to-list 'embark-indicators 'embark-minimal-indicator)
+
+ ;; Use embark to show command prefix help.
+ (setq prefix-help-command #'embark-prefix-help-command))
+
+(use-package embark-consult
+ :ensure t
+ :after embark)
+
+(use-package helpful
+ :ensure t
+ :custom
+ (counsel-describe-function-function #'helpful-callable)
+ (counsel-describe-variable-function #'helpful-variable)
+ :bind
+ ([remap describe-function] . helpful-function)
+ ([remap describe-command] . helpful-command)
+ ([remap describe-symbol] . helpful-symbol)
+ ([remap describe-variable] . helpful-variable)
+ ([remap describe-key] . helpful-key))
+
+(use-package marginalia
+ :ensure t
+ :after vertico
+ :custom
+ (marginalia-annotators '(marginalia-annotators-heavy
+ marginalia-annotators-light
+ nil))
+ :config
+ (marginalia-mode))
+
+(use-package no-littering
+ :ensure t
+ :demand t
+ :config
+ ;; Set custom-file to a file that won't be tracked by git.
+ (setq custom-file
+ (let ((custom-file "custom.el"))
+ (if (boundp 'server-socket-dir)
+ (expand-file-name custom-file server-socket-dir)
+ (no-littering-expand-etc-file-name custom-file))))
+ (when (file-exists-p custom-file)
+ (load custom-file t))
+
+ ;; Don't litter project folders with backup files.
+ (let ((backup-dir (no-littering-expand-var-file-name "backup/")))
+ (make-directory backup-dir t)
+ (setq backup-directory-alist
+ `(("\\`/tmp/" . nil)
+ ("\\`/dev/shm/" . nil)
+ ("." . ,backup-dir))))
+
+ ;; Tidy up auto-save files.
+ (setq auto-save-default nil)
+ (let ((auto-save-dir (no-littering-expand-var-file-name "auto-save/")))
+ (make-directory auto-save-dir t)
+ (setq auto-save-file-name-transforms
+ `(("\\`/[^/]*:\\([^/]*/\\)*\\([^/]*\\)\\'" ,(concat temporary-file-directory "\\2") t)
+ ("\\`\\(/tmp\\|/dev/shm\\)\\([^/]*/\\)*\\(.*\\)\\'" "\\3")
+ ("." ,auto-save-dir t)))))
+
+(use-package savehist
+ :ensure t
+ :init
+ (savehist-mode))
+
+(use-package vertico
+ :ensure t
+ :demand t
+ :bind (:map vertico-map
+ ("C-j" . vertico-next)
+ ("C-k" . vertico-previous)
+ ("C-f" . vertico-exit-input)
+ :map minibuffer-local-map
+ ("M-h" . vertico-directory-up))
+ :custom
+ (vertico-cycle t)
+ :config
+ (require 'vertico-directory)
+ (vertico-mode))
+
+(use-package which-key
+ :ensure t
+ :defer 0
+ :diminish which-key-mode
+ :config
+ (setq which-key-idle-delay 0.5)
+ (which-key-mode))
+
+(provide 'td-common)
diff --git a/lisp/td-dired.el b/lisp/td-dired.el
new file mode 100644
index 0000000..d1a6b72
--- /dev/null
+++ b/lisp/td-dired.el
@@ -0,0 +1,27 @@
+;;; -*- lexical-binding: t; -*-
+
+(use-package dired
+ :ensure nil
+ :commands (dired dired-jump)
+ :hook ((dired-mode . dired-hide-details-mode))
+ :bind (:map dired-mode-map ("C-x C-j" . dired-jump))
+ :config
+ (setq dired-listing-switches "-Agho --group-directories-first"
+ dired-omit-files "^\\.[^.].*"
+ dired-omit-verbose nil
+ dired-hide-detailes-hide-symlink-targets nil
+ dired-kill-when-opening-new-dired-buffer t
+ delete-by-moving-to-trash t))
+
+(use-package all-the-icons-dired
+ :ensure t
+ :hook (dired-mode . all-the-icons-dired-mode))
+
+(use-package dired-hide-dotfiles
+ :ensure t
+ :hook (dired-mode . dired-hide-dotfiles-mode)
+ :config
+ (evil-collection-define-key 'normal 'dired-mode-map
+ "H" 'dired-hide-dotfiles-mode))
+
+(provide 'td-dired)
diff --git a/lisp/td-evil.el b/lisp/td-evil.el
new file mode 100644
index 0000000..afa92a7
--- /dev/null
+++ b/lisp/td-evil.el
@@ -0,0 +1,33 @@
+;;; -*- lexical-binding: t; -*-
+
+(use-package evil
+ :init
+ (setq evil-want-integration t)
+ (setq evil-want-keybinding nil)
+ (setq evil-want-C-u-scroll t)
+ (setq evil-want-C-i-jump nil)
+ (setq evil-insert-state-cursor t)
+ :config
+ (evil-mode 1)
+
+ ;; Fix keybindings.
+ (define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state)
+ (define-key evil-insert-state-map (kbd "C-h") 'evil-delete-backward-char-and-join)
+
+ ;; Use visual line motions even outside of visual-line-mode buffers.
+ (evil-global-set-key 'motion "j" 'evil-next-visual-line)
+ (evil-global-set-key 'motion "k" 'evil-previous-visual-line)
+
+ ;; Ensure some buffers start in normal mode.
+ (evil-set-initial-state 'messages-buffer-mode 'normal)
+ (evil-set-initial-state 'dashboard-mode 'normal))
+
+(use-package evil-collection
+ :after evil
+ :config
+ (evil-collection-init))
+
+(use-package evil-nerd-commenter
+ :bind ("M-/" . evilnc-comment-or-uncomment-lines))
+
+(provide 'td-evil)
diff --git a/lisp/td-functions.el b/lisp/td-functions.el
new file mode 100644
index 0000000..4475037
--- /dev/null
+++ b/lisp/td-functions.el
@@ -0,0 +1,64 @@
+;;; -*- lexical-binding: t; -*-
+
+(defun td/display-startup-time ()
+ (message (if (daemonp)
+ "emacs daemon loaded in %s with %d garbage collections."
+ "emacs loaded in %s with %d garbage collections.")
+ (format "%.2f seconds"
+ (float-time
+ (time-subtract after-init-time before-init-time)))
+ gcs-done))
+
+(defun td/set-font ()
+ (when (display-graphic-p)
+ (message "Setting font...")
+ (set-face-attribute 'default nil
+ :font "Iosevka Comfy Motion Fixed"
+ :weight 'normal
+ :height 200)
+ (set-face-attribute 'fixed-pitch nil
+ :font "Iosevka Comfy Motion Fixed"
+ :weight 'normal
+ :height 200)
+ (set-face-attribute 'variable-pitch nil
+ :font "Iosevka Comfy Motion Fixed"
+ :weight 'normal
+ :height 200)))
+
+(defun td/increment-number-at-point (&optional increment)
+ "Increment number at point like vim's `C-a'."
+ (interactive "p")
+ (td/change-number-at-point '+ (or increment 2)))
+
+(defun td/decrement-number-at-point (&optional decrement)
+ "Decrement number at point like vim's `C-x'."
+ (interactive "p")
+ (td/change-number-at-point '- (or decrement 2)))
+
+(defun td/change-number-at-point (change operation)
+ "The generic logic for incrementing and decrementing numbers at point."
+ (search-forward-regexp (rx digit))
+ (let ((number (number-at-point))
+ (point (point)))
+ (when number
+ (forward-word)
+ (search-backward (number-to-string number))
+ (replace-match (number-to-string (funcall change number operation)))
+ (goto-char (- point 1)))))
+
+(defun td/disable-theme ()
+ "Disable all themes."
+ (interactive)
+ (dolist (theme custom-enabled-themes)
+ (disable-theme theme)))
+
+(defun td/toggle-theme ()
+ "Toggle between light and dark modes."
+ (interactive)
+ (let ((theme (if (eq (car custom-enabled-themes) 'ef-dark)
+ 'ef-day
+ 'ef-dark)))
+ (td/disable-theme)
+ (load-theme theme t)))
+
+(provide 'td-functions)
diff --git a/lisp/td-mu4e.el b/lisp/td-mu4e.el
new file mode 100644
index 0000000..6e45fbb
--- /dev/null
+++ b/lisp/td-mu4e.el
@@ -0,0 +1,63 @@
+;;; -*- lexical-binding: t; -*-
+
+(use-package mu4e
+ :ensure nil
+ :bind (("C-c m m" . mu4e)
+ ("C-c m c" . 'mu4e-compose-new)
+ ("C-c m u" . 'mu4e-update-mail-and-index))
+ :config
+ (setq mu4e-maildir "~/Mail")
+
+ ;; IMAP options.
+ (setq mu4e-update-interval (* 5 60))
+ (setq mu4e-get-mail-command "mbsync -a")
+ (setq mu4e-change-filenames-when-moving t)
+
+ ;; SMTP options.
+ (setq message-send-mail-function 'message-send-mail-with-sendmail)
+ (setq sendmail-program "/etc/profiles/per-user/tdback/bin/msmtp")
+
+ ;; Compose options.
+ (setq mu4e-compose-format-flowed t)
+ (setq mu4e-compose-dont-reply-to-self t)
+ (setq message-kill-buffer-on-exit t)
+
+ ;; Display options.
+ (setq mu4e-view-show-images t)
+ (setq mu4e-view-show-addresses t)
+ (setq mu4e-modeline-show-global nil)
+
+ (setq mu4e-contexts
+ (list
+ ;; Personal account.
+ (make-mu4e-context
+ :name "Personal"
+ :vars '((user-mail-address . "tyler@tdback.net")
+ (user-full-name . "Tyler Dunneback")
+ (mu4e-compose-signature . "Tyler Dunneback")
+ (mu4e-drafts-folder . "/tdback/Drafts")
+ (mu4e-sent-folder . "/tdback/Sent")
+ (mu4e-refile-folder . "/tdback/Archive")
+ (mu4e-trash-folder . "/tdback/Trash")))))
+
+ (setq mu4e-maildir-shortcuts
+ '(("/tdback/Inbox" . ?i)
+ ("/tdback/Sent" . ?s)
+ ("/tdback/Trash" . ?t)
+ ("/tdback/Drafts" . ?d)
+ ("/tdback/Archive" . ?a)
+ ("/tdback/All Mail" . ?m))))
+
+(use-package org-mime
+ :ensure t
+ :config
+ (setq org-mime-export-options (list :section-numbers nil
+ :with-author nil
+ :with-toc nil))
+ (add-hook 'org-mime-html-hook (lambda ()
+ (org-mime-change-element-style
+ "pre" (format "color: %s; background-color: %s; padding: 0.5em;"
+ "#E6E1DC" "#232323"))))
+ (add-hook 'message-send-hook 'org-mime-confirm-when-no-multipart))
+
+(provide 'td-mu4e)
diff --git a/lisp/td-org.el b/lisp/td-org.el
new file mode 100644
index 0000000..d9ca50e
--- /dev/null
+++ b/lisp/td-org.el
@@ -0,0 +1,172 @@
+;;; -*- lexical-binding: t; -*-
+
+;;; ----- Bootstrapping Functions -----
+
+(defun td/org-font-setup ()
+ (font-lock-add-keywords 'org-mode
+ '(("^ *\\([-]\\) "
+ (0 (prog1 ()
+ (compose-region (match-beginning 1)
+ (match-end 1)
+ "•"))))))
+ (dolist (face '((org-level-1 . 1.2)
+ (org-level-2 . 1.15)
+ (org-level-3 . 1.1)
+ (org-level-4 . 1.0)))
+ (set-face-attribute (car face)
+ nil
+ :font "Iosevka Comfy Motion Fixed"
+ :weight 'regular
+ :height (cdr face)))
+ (set-face-attribute 'org-block
+ nil
+ :foreground nil
+ :inherit 'fixed-pitch)
+ (set-face-attribute 'org-code
+ nil
+ :foreground nil
+ :inherit '(shadow fixed-pitch))
+ (set-face-attribute 'org-table
+ nil
+ :foreground nil
+ :inherit '(shadow fixed-pitch))
+ (set-face-attribute 'org-verbatim
+ nil
+ :foreground nil
+ :inherit '(shadow fixed-pitch))
+ (set-face-attribute 'org-special-keyword
+ nil
+ :foreground nil
+ :inherit '(font-lock-comment-face fixed-pitch))
+ (set-face-attribute 'org-meta-line
+ nil
+ :foreground nil
+ :inherit '(font-lock-comment-face fixed-pitch))
+ (set-face-attribute 'org-checkbox
+ nil
+ :inherit 'fixed-pitch))
+
+(defun td/org-mode-setup ()
+ (org-indent-mode)
+ (variable-pitch-mode 1)
+ (visual-line-mode 1)
+ (setq evil-auto-indent nil))
+
+;;; ----- Package Declaration -----
+
+(use-package org
+ :ensure t
+ :hook (org-mode . td/org-mode-setup)
+ :bind (("C-c c" . org-capture)
+ ("C-c a" . org-agenda))
+ :config
+ (setq org-ellipsis " ▾"
+ org-hide-emphasis-markers t
+ org-agenda-start-with-log-mode t
+ org-log-done 'time
+ org-fontify-whole-heading-line t
+ org-fontify-quote-and-verse-blocks t
+ org-src-tab-acts-natively t
+ org-edit-src-content-indentation 2
+ org-hide-block-startup nil
+ org-log-into-drawer t
+ org-agenda-files '("~/Documents/org/tasks.org"
+ "~/Documents/org/ideas.org")
+ org-agenda-custom-commands '(("d" "Dashboard"
+ ((agenda ""
+ ((org-deadline-warning-days 7)))
+ (todo "NEXT"
+ ((org-agenda-overriding-header "Next Tasks")))))
+ ("n" "Next Tasks"
+ ((todo "NEXT"
+ ((org-agenda-overriding-header "Next Tasks")))))
+ ("s" "Status"
+ (todo "ACTIVE"
+ ((org-agenda-overriding-header "In Progress")
+ (org-agenda-files org-agenda-files)))
+ ((todo "BACKLOG"
+ ((org-agenda-overriding-header "Backlog")
+ (org-agenda-todo-list-sublevels nil)
+ (org-agenda-files org-agenda-files)))
+ (todo "CANCELED"
+ ((org-agenda-overriding-header "Canceled")
+ (org-agenda-files org-agenda-files)))
+ (todo "COMPLETED"
+ ((org-agenda-overriding-header "Completed")
+ (org-agenda-files org-agenda-files)))
+ ((todo "PLAN"
+ ((org-agenda-overriding-header "In Planning")
+ (org-agenda-todo-list-sublevels nil)
+ (org-agenda-files org-agenda-files)))
+ (todo "READY"
+ ((org-agenda-overriding-header "Ready for Work")
+ (org-agenda-files org-agenda-files)))))))
+ org-capture-templates '(("t" "Tasks")
+ ("tt" "New Task" entry (file+olp (car org-agenda-files))
+ "* TODO %?\n %i" :empty-lines 1)
+ ("i" "Ideas")
+ ("ii" "New Idea" entry (file+olp (cadr org-agenda-files))
+ "* %^{Idea}\n %U\n %?\n %i" :empty-lines 1))
+ org-todo-keywords '((sequence "TODO(t)"
+ "NEXT(n)"
+ "|"
+ "DONE(d!)")
+ (sequence "BACKLOG(b)"
+ "PLAN(p)"
+ "READY(r)"
+ "ACTIVE(a)"
+ "|"
+ "COMPLETED(c)"
+ "CANCELED(k@)"))
+ org-refile-targets '(("archive.org" :maxlevel . 1)
+ ("tasks.org" :maxlevel . 1)))
+ (advice-add 'org-refile :after 'org-save-all-org-buffers)
+ (td/org-font-setup))
+
+(use-package org-appear
+ :ensure t
+ :after org
+ :custom
+ (org-hide-emphasis-markers t)
+ (org-appear-autolinks t)
+ (org-appear-inside-latex t)
+ (org-appear-autoentities t)
+ (org-appear-autosubmarkers t)
+ :config
+ (add-hook 'org-mode-hook 'org-appear-mode))
+
+(use-package org-modern
+ :ensure t
+ :hook ((org-mode . org-modern-mode)
+ (org-agenda-finalize-hook . org-modern-agenda))
+ :custom ((org-modern-todo t)
+ (org-modern-table nil)
+ (org-modern-variable-pitch nil)
+ (org-modern-block-fringe nil))
+ :commands
+ (org-modern-mode org-modern-agenda)
+ :init
+ (global-org-modern-mode))
+
+(use-package org-timeline
+ :ensure t
+ :commands org-agenda
+ :init
+ (add-hook 'org-agenda-finalize-hook 'org-timeline-insert-timeline :append))
+
+;; Code block execution and template expansion.
+(with-eval-after-load 'org
+ (org-babel-do-load-languages 'org-babel-load-languages
+ '((emacs-lisp . t)
+ (python . t)))
+
+ (push '("conf-unix" . conf-unix) org-src-lang-modes)
+
+ (require 'org-tempo)
+ (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
+ (add-to-list 'org-structure-template-alist '("py" . "src python"))
+ (add-to-list 'org-structure-template-alist '("rs" . "src rust"))
+ (add-to-list 'org-structure-template-alist '("sh" . "src shell"))
+ (add-to-list 'org-structure-template-alist '("sq" . "src sqlite")))
+
+(provide 'td-org)
diff --git a/lisp/td-present.el b/lisp/td-present.el
new file mode 100644
index 0000000..72cd901
--- /dev/null
+++ b/lisp/td-present.el
@@ -0,0 +1,27 @@
+;;; -*- lexical-binding: t; -*-
+
+(use-package org-present
+ :ensure t
+ :hook ((org-present-mode . td/org-present-start)
+ (org-present-mode-quit . td/org-present-end)
+ (org-present-after-navigate-functions . td/org-present-prepare-slide)))
+
+(defun td/org-present-start ()
+ (setq-local face-remapping-alist
+ '((default (:height 1.5) variable-pitch)
+ (header-line (:height 4.0) variable-pitch)
+ (org-document-title (:height 1.75) org-document-title)
+ (org-code (:height 1.55) org-code)
+ (org-verbatim (:height 1.55) org-verbatim)
+ (org-block (:height 1.25) org-block)
+ (org-block-begin-line (:height 0.7) org-block))))
+
+(defun td/org-present-end ()
+ (setq-local face-remapping-alist '((default variable-pitch default))))
+
+(defun td/org-present-prepare-slide (buffer-name heading)
+ (org-overview)
+ (org-show-entry)
+ (org-show-children))
+
+(provide 'td-present)
diff --git a/lisp/td-programming.el b/lisp/td-programming.el
new file mode 100644
index 0000000..eee8d67
--- /dev/null
+++ b/lisp/td-programming.el
@@ -0,0 +1,123 @@
+;;; -*- lexical-binding: t; -*-
+
+;;; ----- Completion -----
+
+(use-package cape
+ :defer 10
+ :init
+ ;; Add `completion-at-point-functions', used by `completion-at-point'.
+ (add-to-list 'completion-at-point-functions #'cape-file)
+ ;; Nice completion to have available everywhere.
+ (add-to-list 'completion-at-point-functions #'cape-dabbrev)
+ :config
+ ;; Silence then pcomplete capf, no errors or messages.
+ (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent)
+ ;; Ensure that pcomplete does not write to the buffer and behaves as a pure
+ ;; `completion-at-point-function'.
+ (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-purify))
+
+(use-package corfu
+ :ensure t
+ :custom
+ (corfu-cycle t) ; Cycle through candidates
+ (corfu-auto t) ; Enable auto completion.
+ (corfu-auto-prefix 2) ; Display completion options after two characters.
+ (corfu-auto-delay 0.0) ; Don't delay.
+ (corfu-quit-at-boundary 'separator) ; Quit if no separator has been inserted at the boundary.
+ (corfu-echo-documentation 0.25) ; Echo docs shortly after options.
+ (corfu-preview-current 'insert) ; Auto-insert the current completion.
+ (corfu-preselect-first nil) ; Don't select a completion right away.
+ :bind (:map corfu-map
+ ("M-SPC" . corfu-insert-separator)
+ ("C-n" . corfu-next)
+ ([tab] . corfu-next)
+ ("C-p" . corfu-previous)
+ ([backtab] . corfu-previous)
+ ("S-<return>" . corfu-insert)
+ ("RET" . nil))
+ :init
+ ;; Use corfu everywhere.
+ (global-corfu-mode)
+ ;; Save completion history for better sorting.
+ (corfu-history-mode))
+
+(use-package eglot
+ :ensure t
+ :defer t
+ :config
+ (setq eglot-autoshutdown t
+ elgot-ignored-server-capabilities '(:inlayHintProvider))
+ (add-to-list 'eglot-server-programs '(c-mode . ("clangd")))
+ (add-to-list 'eglot-server-programs '(c++-mode . ("clangd")))
+ (add-to-list 'eglot-server-programs '(nix-mode . ("nixd")))
+ (add-to-list 'eglot-server-programs '(python-mode . ("pylsp")))
+ (add-to-list 'eglot-server-programs '(rust-mode . ("rust-analyzer")))
+ :hook
+ ((c-mode . eglot-ensure)
+ (c++-mode . eglot-ensure)
+ (nix-mode . eglot-ensure)
+ (python-mode . eglot-ensure)
+ (rust-mode . eglot-ensure)))
+
+(use-package orderless
+ :ensure t
+ :commands (orderless)
+ :custom
+ (completion-styles '(orderless flex)))
+
+;;; ----- Modes -----
+
+(use-package dockerfile-mode
+ :ensure t
+ :defer t)
+
+(use-package markdown-mode
+ :ensure t
+ :defer t)
+
+(use-package nix-mode
+ :ensure t
+ :defer t)
+
+(use-package python-mode
+ :ensure t
+ :defer t)
+
+(use-package rust-mode
+ :ensure t
+ :defer t
+ :config
+ (setq rust-format-on-save nil))
+
+(use-package toml-mode
+ :ensure t
+ :defer t)
+
+(use-package yaml-mode
+ :ensure t
+ :defer t)
+
+;;; ----- Tooling & Enhancements -----
+
+(use-package compile
+ ;; Using `C-u' before recompile acts like `M-x compile'.
+ :bind (("C-x C-m" . recompile))
+ :custom
+ (compilation-scroll-output t))
+
+(use-package magit
+ :ensure t
+ :commands magit-status)
+
+(use-package paren-face
+ :ensure t
+ :hook ((prog-mode
+ eshell-mode
+ inferior-lisp-mode
+ inferior-emacs-lisp-mode
+ lisp-interaction-mode
+ sly-mrepl-mode
+ scheme-mode)
+ . paren-face-mode))
+
+(provide 'td-programming)
diff --git a/lisp/td-writing.el b/lisp/td-writing.el
new file mode 100644
index 0000000..df9989f
--- /dev/null
+++ b/lisp/td-writing.el
@@ -0,0 +1,22 @@
+;;; -*- lexical-binding: t; -*-
+
+(use-package jinx
+ :ensure t
+ :hook ((org-mode . jinx-mode)
+ (text-mode . jinx-mode))
+ :bind (("M-$" . jinx-correct)
+ ("C-M-$" . jinx-languages)))
+
+(use-package olivetti
+ :ensure t
+ :defer t
+ :hook ((markdown-mode . olivetti-mode)
+ (org-mode . olivetti-mode))
+ :init
+ (setq olivetti-body-width 80))
+
+(use-package writegood-mode
+ :ensure t
+ :hook (jinx-mode . writegood-mode))
+
+(provide 'td-writing)