Started work on making the configuration modular.

This commit is contained in:
Micheal Smith
2025-09-25 03:12:04 -05:00
parent fb76f3767e
commit 8e0e2c63ec
3 changed files with 539 additions and 39 deletions

View File

@@ -7,19 +7,23 @@
#+LATEX_HEADER: \lstset{breaklines=true, breakatwhitespace=true, basicstyle=\ttfamily\footnotesize, columns=fullflexible}
#+begin_src emacs-lisp :exports none :tangle no
;; This asks for a file which it uses to store the processed org
;; data with the includes into. It can be anything and can safely
;; be deleted afterwards. I think README.org is a good file to
;; pick if using a repository.
(defun tangle-literate-config ()
"Tangle all my literate configuration files."
"Tangle config files with proper include handling."
(interactive)
(let ((org-confirm-babel-evaluate nil)
(files '("config.org"
"extra/feed.org"
"extra/email.org"
"extra/social.org")))
(dolist (file files)
(when (file-exists-p file)
(message "Tangling %s..." (file-name-nondirectory file))
(org-babel-tangle-file file)))
(message "All configuration files tangled!")))
(let ((org-confirm-babel-evaluate nil))
;; Create a temporary buffer with expanded includes
(with-temp-buffer
(insert-file-contents "config.org")
(org-mode)
;; This expands all #+INCLUDE directives
(org-export-expand-include-keyword)
;; Now tangle from this buffer which has everything in one place
(org-babel-tangle nil "init.el"))
(message "Configuration tangled!")))
#+end_src
#+BEGIN_SRC emacs-lisp :exports none
@@ -480,11 +484,254 @@ on a system by system basis.
# For now I'm not using headers here and letting them be defined in the org files
# themselves.
#+INCLUDE: "extra/email.org" :minlevel 1
#+PROPERTY: header-args :tangle email.el
#+INCLUDE: "extra/feed.org" :minlevel 1
Incoming email is handled by [[https://notmuchmail.org][notmuch]]. Outgoing is via [[https://github.com/marlam/msmtp][msmtp]]
#+INCLUDE: "extra/social.org" :minlevel 1
This is a pretty simple implementation without a lot of search queries, and
list handling. As I get more comfortable with using emacs as an email client
I'll try to get fancier.
#+BEGIN_SRC emacs-lisp
;; Email/notmuch settings -*- lexical-binding: t; -*-
(use-package notmuch
:init
(autoload 'notmuch "notmuch" "notmuch mail" t)
:config
(define-key notmuch-show-mode-map "d"
(lambda ()
"toggle deleted tag for message"
(interactive)
(if (member "deleted" (notmuch-show-get-tags))
(notmuch-show-tag (list "-deleted"))
(notmuch-show-tag (list "+deleted")))))
(define-key notmuch-search-mode-map "d"
(lambda ()
"toggle deleted tag for message"
(interactive)
(if (member "deleted" (notmuch-search-get-tags))
(notmuch-search-tag (list "-deleted"))
(notmuch-search-tag (list "+deleted")))))
(define-key notmuch-tree-mode-map "d"
(lambda ()
"toggle deleted tag for message"
(interactive)
(if (member "deleted" (notmuch-tree-get-tags))
(notmuch-tree-tag (list "-deleted"))
(notmuch-tree-tag (list "+deleted"))))))
;; Saved searches
(setq notmuch-saved-searches '((:name "cheapbsd"
:query "tag:inbox and tag:cheapbsd"
:count-query "tag:inbox and tag:cheapbsd and tag:unread")
(:name "icloud"
:query "tag:inbox and tag:icloud"
:count-query "tag:inbox and tag:icloud and tag:unread")
(:name "sdf"
:query "tag:inbox and tag:sdf"
:count-query "tag:inbox and tag:sdf and tag:unread")))
(setq mml-secure-openpgp-sign-with-sender t)
;; Sign messages by default.
(add-hook 'message-setup-hook 'mml-secure-sign-pgpmime)
;; Use msmtp
(setq send-mail-function 'sendmail-send-it
sendmail-program "msmtp"
mail-specify-envelope-from t
message-sendmail-envelope-from 'header
mail-envelope-from 'header)
(defun message-recipients ()
"Return a list of all recipients in the message, looking at TO, CC and BCC.
Each recipient is in the format of `mail-extract-address-components'."
(mapcan (lambda (header)
(let ((header-value (message-fetch-field header)))
(and
header-value
(mail-extract-address-components header-value t))))
'("To" "Cc" "Bcc")))
(defun message-all-epg-keys-available-p ()
"Return non-nil if the pgp keyring has a public key for each recipient."
(require 'epa)
(let ((context (epg-make-context epa-protocol)))
(catch 'break
(dolist (recipient (message-recipients))
(let ((recipient-email (cadr recipient)))
(when (and recipient-email (not (epg-list-keys context recipient-email)))
(throw 'break nil))))
t)))
(defun message-sign-encrypt-if-all-keys-available ()
"Add MML tag to encrypt message when there is a key for each recipient.
Consider adding this function to `message-send-hook' to
systematically send encrypted emails when possible."
(when (message-all-epg-keys-available-p)
(mml-secure-message-sign-encrypt)))
(add-hook 'message-send-hook #'message-sign-encrypt-if-all-keys-available)
(setq notmuch-crypto-process-mime t)
(defvar notmuch-hello-refresh-count 0)
(defun notmuch-hello-refresh-status-message ()
(let* ((new-count
(string-to-number
(car (process-lines notmuch-command "count"))))
(diff-count (- new-count notmuch-hello-refresh-count)))
(cond
((= notmuch-hello-refresh-count 0)
(message "You have %s messages."
(notmuch-hello-nice-number new-count)))
((> diff-count 0)
(message "You have %s more messages since last refresh."
(notmuch-hello-nice-number diff-count)))
((< diff-count 0)
(message "You have %s fewer messages since last refresh."
(notmuch-hello-nice-number (- diff-count)))))
(setq notmuch-hello-refresh-count new-count)))
(add-hook 'notmuch-hello-refresh-hook 'notmuch-hello-refresh-status-message)
(defun color-inbox-if-unread () (interactive)
(save-excursion
(goto-char (point-min))
(let ((cnt (car (process-lines "notmuch" "count" "tag:inbox and tag:unread"))))
(when (> (string-to-number cnt) 0)
(save-excursion
(when (search-forward "inbox" (point-max) t)
(let* ((overlays (overlays-in (match-beginning 0) (match-end 0)))
(overlay (car overlays)))
(when overlay
(overlay-put overlay 'face '((:inherit bold) (:foreground "green")))))))))))
(add-hook 'notmuch-hello-refresh-hook 'color-inbox-if-unread)
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(notmuch-search-oldest-first nil))
(custom-set-faces)
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
#+end_src
#+PROPERTY: header-args :tangle "feed.el" :noweb yes
I get a lot of my news, and updates via Atom/RSS feeds. If I'm going to
browse them in emacs I use elfeed.
#+name: header
#+begin_src emacs-lisp :exports none
;;; elfeed -- Just my elfeed config. -*- lexical-binding: t; -*-
;;; Commentary:
;;; Nothing yet.
;;; Code:
#+end_src
#+name: footer
#+begin_src emacs-lisp :exports none
(provide 'feed)
;;; feed.el ends here
#+end_src
#+name: feed-src
#+begin_src emacs-lisp :exports code
(use-package elfeed
:defer t
:bind
(("C-c F" . elfeed)))
(use-package elfeed-org
:after (elfeed)
:config
(elfeed-org)
(setq rmh-elfeed-org-files (list "~/.emacs.d/extra/elfeed.org")))
(use-package elfeed-tube
:after (elfeed)
:config
(elfeed-tube-setup)
:bind (:map elfeed-show-mode-map
("F" . elfeed-tube-fetch)
([remap save-buffer] . elfeed-tube-save)
:map elfeed-search-mode-map
("F" . elfeed-tube-fetch)
([remap save-buffer] . elfeed-tube-save)))
(use-package mpv
:ensure (:host github :repo "kljohann/mpv.el"))
(use-package elfeed-tube-mpv
:after (elfeed-tube mpv)
:bind (:map elfeed-show-mode-map
("C-c C-f" . elfeed-tube-mpv-follow-mode)
("C-c C-w" . elfeed-tube-mpv-where)))
(use-package elfeed-goodies
:after (elfeed)
:config
(elfeed-goodies/setup))
<<footer>>
#+end_src
#+RESULTS: feed-src
: feed
#+PROPERTY: header-args :tangle "social.el" :exports code
* Mastodon, and other tidbits
#+name: header
#+begin_src emacs-lisp :exports none
;;; social -- Provides social features -*- lexical-binding: t; -*-
;;; Commentary:
;;; Only provides Mastodon, and discord presence currently.
;;; Code:
#+end_src
#+RESULTS: header
** Mastodon
Just a little package for browsing mastodon. I don't use it much, but
it's deferred and doesn't take much space.
#+begin_src emacs-lisp
<<header>>
(use-package mastodon
:defer t
:config
(setq mastodon-instance-url "https://mastodon.social"
mastodon-active-user "xulfer"))
#+end_src
#+name: footer
#+begin_src emacs-lisp :exports none
;;; social.el ends here
(provide 'social)
#+end_src
* Hail Hydra?!
@@ -1287,6 +1534,7 @@ the package.
(c-ts-mode . lsp-deferred)
(clojure-ts-mode . lsp-deferred)
(elixir-ts-mode . lsp-deferred)
(gleam-ts-mode . lsp-deferred)
(rust-ts-mode . lsp-deferred)
(slint-mode . lsp-deferred)
(zig-mode . lsp-deferred)
@@ -1360,6 +1608,10 @@ bother with an explanation on each.
(clojure-ts-mode . rainbow-delimiters-mode)
(clojure-ts-mode . clj-refactor-mode)))
;; Gleam
(use-package gleam-ts-mode
:mode (rx ".gleam" eos))
(use-package cider
:ensure t
:defer t)