diff options
| author | cashmere <cashmere@autistici.org> | 2026-09-04 01:47:51 +0200 |
|---|---|---|
| committer | cashmere <cashmere@autistici.org> | 2026-09-04 01:48:05 +0200 |
| commit | 9b1fd26d28a02c108c986a68b98ab885d1893742 (patch) | |
| tree | b546ff606143ad9af901024543fe1329c746606f /lisp/my-tinty.el | |
| parent | bb95be8487700bfc14389f224dd59ec7d5b9883b (diff) | |
| download | emacs-9b1fd26d28a02c108c986a68b98ab885d1893742.tar.gz | |
md: 2026-09-04T01:47:55+02:00
Diffstat (limited to 'lisp/my-tinty.el')
| -rw-r--r-- | lisp/my-tinty.el | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/lisp/my-tinty.el b/lisp/my-tinty.el new file mode 100644 index 0000000..3780b26 --- /dev/null +++ b/lisp/my-tinty.el @@ -0,0 +1,85 @@ +;;; my-tinty.el --- Follow Tinty changes in this Emacs -*- lexical-binding: t; -*- + +(require 'filenotify) + +(defgroup my/tinty nil + "Automatic Tinty theme updates." + :group 'faces) + +(defcustom my/tinty-theme-file + (expand-file-name "themes/tinty-theme.el" user-emacs-directory) + "Shared theme source to watch in every Emacs process." + :type 'file + :group 'my/tinty) + +(defcustom my/tinty-reload-delay 0.15 + "Seconds to combine filesystem events before loading the theme." + :type 'number + :group 'my/tinty) + +(defvar my/tinty-auto-reload-mode nil) +(defvar my/tinty--watch nil) +(defvar my/tinty--timer nil) +(defvar my/tinty--loaded-content nil) + +(defun my/tinty--reload () + "Reload only changed theme content, without success messages." + (setq my/tinty--timer nil) + (when (and my/tinty-auto-reload-mode (file-readable-p my/tinty-theme-file)) + (condition-case err + (let* ((content (with-temp-buffer + (insert-file-contents-literally my/tinty-theme-file) + (secure-hash 'sha256 (current-buffer)))) + (inhibit-message t) + (message-log-max nil)) + (unless (equal content my/tinty--loaded-content) + (load my/tinty-theme-file nil 'nomessage 'nosuffix) + (enable-theme 'tinty) + (setq my/tinty--loaded-content content))) + (error + (let ((inhibit-message t)) + (message "Tinty theme: %s" (error-message-string err))))))) + +(defun my/tinty--watch-start () + "Watch the theme directory, retrying if it is temporarily unavailable." + (setq my/tinty--timer nil) + (when my/tinty-auto-reload-mode + (condition-case nil + (unless (and my/tinty--watch (file-notify-valid-p my/tinty--watch)) + (setq my/tinty--watch + (file-notify-add-watch + (file-name-directory (expand-file-name my/tinty-theme-file)) + '(change attribute-change) #'my/tinty--changed)) + (my/tinty--reload)) + (file-notify-error + (setq my/tinty--timer (run-at-time 2 nil #'my/tinty--watch-start)))))) + +(defun my/tinty--changed (event) + "React only to events for the theme file or a stopped directory watch." + (when (and my/tinty-auto-reload-mode (equal (car event) my/tinty--watch)) + (cond + ((eq (cadr event) 'stopped) + (setq my/tinty--watch nil) + (when (timerp my/tinty--timer) (cancel-timer my/tinty--timer)) + (setq my/tinty--timer (run-at-time 2 nil #'my/tinty--watch-start))) + ((member (expand-file-name my/tinty-theme-file) (cddr event)) + (when (timerp my/tinty--timer) (cancel-timer my/tinty--timer)) + (setq my/tinty--timer + (run-at-time my/tinty-reload-delay nil #'my/tinty--reload)))))) + +;;;###autoload +(define-minor-mode my/tinty-auto-reload-mode + "Keep this Emacs's theme synchronized with Tinty, independently of config reloads." + :global t + :group 'my/tinty + (if my/tinty-auto-reload-mode + (unless (and my/tinty--watch (file-notify-valid-p my/tinty--watch)) + (when (timerp my/tinty--timer) (cancel-timer my/tinty--timer)) + (my/tinty--watch-start)) + (when (timerp my/tinty--timer) (cancel-timer my/tinty--timer)) + (let ((watch my/tinty--watch)) + (setq my/tinty--timer nil my/tinty--watch nil my/tinty--loaded-content nil) + (when watch (file-notify-rm-watch watch))))) + +(provide 'my-tinty) +;;; my-tinty.el ends here |
