diff options
-rw-r--r-- | attic/elisp/misc.el | 6 | ||||
-rwxr-xr-x | bin/notmuch-tags.sh | 10 | ||||
-rw-r--r-- | custom/jao-custom-browse.el | 66 | ||||
-rw-r--r-- | custom/jao-custom-completion.el | 4 | ||||
-rw-r--r-- | custom/jao-custom-email.el | 2 | ||||
-rw-r--r-- | custom/jao-custom-eww.el | 17 | ||||
-rw-r--r-- | custom/jao-custom-gnus.el | 114 | ||||
-rw-r--r-- | custom/jao-custom-notmuch.el | 7 | ||||
-rw-r--r-- | custom/jao-custom-org.el | 3 | ||||
-rw-r--r-- | custom/jao-custom-pdf.el | 2 | ||||
-rw-r--r-- | custom/jao-custom-programming.el | 45 | ||||
-rw-r--r-- | custom/jao-custom-w3m.el | 2 | ||||
-rw-r--r-- | init.el | 21 | ||||
-rw-r--r-- | lib/eos/jao-afio.el | 2 | ||||
-rw-r--r-- | lib/eos/jao-r2e.el | 206 | ||||
-rw-r--r-- | lib/net/jao-eww-session.el | 19 | ||||
-rw-r--r-- | lib/net/jao-notmuch.el | 8 | ||||
-rw-r--r-- | lib/net/jao-url.el | 36 | ||||
-rw-r--r-- | lib/prog/jao-clojure.el | 101 | ||||
-rw-r--r-- | lib/themes/jao-light-theme.el | 6 | ||||
-rw-r--r-- | lib/themes/jao-themes.el | 12 |
21 files changed, 520 insertions, 169 deletions
diff --git a/attic/elisp/misc.el b/attic/elisp/misc.el index d8c2610..2213646 100644 --- a/attic/elisp/misc.el +++ b/attic/elisp/misc.el @@ -1075,3 +1075,9 @@ It should be the title of the web page as returned by `rdrview'" (if eww-rdrview-mode (eww-rdrview-mode -1) (eww-rdrview-mode 1)) (eww-reload)) + +(defun jao-eww-readable (rdrview) + (interactive "P" eww-mode) + (if rdrview + (eww-rdrview-toggle-and-reload) + (eww-readable))) diff --git a/bin/notmuch-tags.sh b/bin/notmuch-tags.sh index 3a6cbef..03afc82 100755 --- a/bin/notmuch-tags.sh +++ b/bin/notmuch-tags.sh @@ -92,11 +92,11 @@ killfile "subject:prefclean from:apt-listbugs" killfile "subject:open-thread AND Rss:astralcodexten" +1d killfile "subject:hidden-thread AND Rss:astralcodexten" +deleted -# gfeeds="grep -o -e feeds.*@localhost $HOME/.config/rss2email.cfg" -# for f in $($gfeeds | sort | uniq); do -# ftag=$(echo $f | sed 's/feeds.\(.*\)@localhost/\1/'); -# notmuch tag +rss +feeds +$ftag -- tag:new AND folder:feeds AND to:$f -# done +gfeeds="grep -o -e feeds.*@localhost $HOME/.config/rss2email.cfg" +for f in $($gfeeds | sort | uniq); do + ftag=$(echo $f | sed 's/feeds.\(.*\)@localhost/\1/'); + notmuch tag +rss +feeds +$ftag -- tag:new AND folder:feeds AND to:$f +done notmuch tag +write +jao -words -drivel -feeds \ -- "tag:new AND from:/campusdee?scrip?tura/" diff --git a/custom/jao-custom-browse.el b/custom/jao-custom-browse.el index 2787518..ec5a000 100644 --- a/custom/jao-custom-browse.el +++ b/custom/jao-custom-browse.el @@ -1,5 +1,8 @@ ;; -*- lexical-binding: t -*- +;;; Deps +(require 'jao-url) + ;;; Browsing ;;;; variables (defvar jao-browse-doc-use-emacs-p (jao-is-linux)) @@ -7,14 +10,6 @@ (defvar jao-browse-url-external-function nil) ;;;; url around point -(defun jao-url-around-point (&optional current-url) - (or (and (fboundp 'w3m-anchor) (w3m-anchor)) - (shr-url-at-point nil) - (ffap-url-at-point) - (thing-at-point 'url) - (when current-url - (or (and (fboundp 'w3m-anchor) (w3m-anchor)) - (and (derived-mode-p 'eww-mode) (plist-get eww-data :url)))))) (defun jao--url-prompt (&optional prefix) (let* ((def (jao-url-around-point t)) @@ -108,7 +103,7 @@ ;;;; browse-url (require 'browse-url) -(setq browse-url-generic-program "firefox") +(setq browse-url-generic-program (jao-d-l "open" "firefox")) (defun jao-browse-with-external-browser (&rest url) "Browse with external hogging" @@ -191,59 +186,6 @@ (,(jao-wget--regexp) . jao-download) ("." . jao-browse-url-browse)))) -;;;; subscribe to rss using r2e -(autoload 'View-quit "view") - -(defun jao-rss--find-url () - (save-excursion - (when (derived-mode-p 'w3m-mode 'eww-mode) - (if (fboundp 'w3m-view-source) (w3m-view-source) (eww-view-source))) - (goto-char (point-min)) - (when (re-search-forward - "type=\"application/\\(?:atom\\|rss\\)\\+xml\" +" nil t) - (let ((url (save-excursion - (when (re-search-forward - "href=\"\\([^\n\"]+\\)\"" nil t) - (match-string-no-properties 1)))) - (title (when (re-search-forward - "\\(?:title=\"\\([^\n\"]+\\)\" +\\)" nil t) - (match-string-no-properties 1)))) - (cond ((derived-mode-p 'w3m-view-mode) (w3m-view-source)) - ((string-match-p ".*\\*eww-source\\b.*" (buffer-name)) - (View-quit))) - (when url (cons url (or title ""))))))) - -(defun jao-rss2e-append (name url mbox) - (with-current-buffer (find-file-noselect "~/.config/rss2email.cfg") - (goto-char (point-max)) - (insert "[feed." name "]\nurl = " url) - (insert "\nto = " mbox "+" name "@localhost") - (insert "\nmaildir-mailbox = " mbox "\n\n") - (save-buffer))) - -(defun jao-rss--feeds-dirs () - (mapcar (lambda (d) (cadr (split-string d "\\."))) - (directory-files "~/.emacs.d/gnus/Mail/" nil "^feeds"))) - -(defun jao-rss-subscribe (url) - "Subscribe to a given RSS URL. If URL not given, look for it." - (interactive (list (or (jao-url-around-point) - (jao-rss--find-url) - (read-string "Feed URL: ")))) - (let* ((url+title (ensure-list url)) - (url (car url+title)) - (title (cdr url+title))) - (unless url (error "No feeds found")) - (let ((url (if (string-match "^feed:" url) (substring url 5) url))) - (when (y-or-n-p (format "Subscribe to <%s>? " url)) - (let* ((name (read-string "Feed name: " title)) - (cats (cons "prog" (jao-notmuch--subtags "feeds"))) - (cat (completing-read "Category: " cats nil t)) - (subs (format "r2e add %s '%s' feeds.%s@localhost" - name url cat))) - ;; (jao-rss2e-append name url cat) - (shell-command-to-string subs) - (shell-command (format "r2e run %s" name))))))) (provide 'jao-custom-browse) ;;; jao-custom-browse.el ends here diff --git a/custom/jao-custom-completion.el b/custom/jao-custom-completion.el index 436a4db..98b853c 100644 --- a/custom/jao-custom-completion.el +++ b/custom/jao-custom-completion.el @@ -1,5 +1,7 @@ ;; -*- lexical-binding: t; -*- +(require 'jao-r2e) + ;;; builtin completion (setq tab-always-indent 'complete read-extended-command-predicate #'command-completion-default-include-p @@ -308,7 +310,7 @@ (define-key embark-url-map (kbd "RET") #'jao-embark-url) (define-key embark-url-map (kbd "f") #'browse-url-firefox) -(define-key embark-url-map (kbd "x") #'jao-rss-subscribe) +(define-key embark-url-map (kbd "x") #'jao-r2e-subscribe) (define-key embark-url-map (kbd "m") 'jao-browse-with-external-browser) (define-key embark-url-map (kbd "p") 'jao-mpc-add-or-play-url) diff --git a/custom/jao-custom-email.el b/custom/jao-custom-email.el index 534b342..b9e4ba9 100644 --- a/custom/jao-custom-email.el +++ b/custom/jao-custom-email.el @@ -11,7 +11,7 @@ (defvar jao-mails) (defvar jao-extra-mails nil) (defvar jao-mails-regexp (regexp-opt jao-mails)) - +(defvar jao-maildir (jao-d-l "~/Documents/mail" "~/var/mail")) ;;; gnus (setq gnus-init-file "~/.emacs.d/gnus.el" gnus-home-directory "~/.emacs.d/gnus" diff --git a/custom/jao-custom-eww.el b/custom/jao-custom-eww.el index cdd5c8d..beeb97e 100644 --- a/custom/jao-custom-eww.el +++ b/custom/jao-custom-eww.el @@ -1,5 +1,7 @@ ;; -*- lexical-binding: t -*- +(require 'jao-r2e) + ;;; integration with browse-url and afio (defun jao-eww-browse-url (url &rest _r) "Browse URL using eww." @@ -159,7 +161,10 @@ ;;; auto-readable (defvar jao-eww-auto-readable-urls - (regexp-opt '("guardian.co.uk" "theguardian.com" "github.com" "eldiario.es"))) + (regexp-opt '("guardian.co.uk" + "theguardian.com" + "github.com" + "eldiario.es"))) (defun jao-eww-autoread () (when (string-match-p jao-eww-auto-readable-urls (or (eww-current-url))) @@ -195,12 +200,6 @@ (when (not (string-blank-p s)) (format "%s" s)))) (setq eww-auto-rename-buffer #'jao-eww-buffer-name) - (defun jao-eww-readable (rdrview) - (interactive "P" eww-mode) - (if rdrview - (eww-rdrview-toggle-and-reload) - (eww-readable))) - :bind (:map eww-mode-map (("b" . eww-back-url) ("B" . eww-forward-url) ("d" . jao-download) @@ -211,7 +210,7 @@ ("o" . jao-eww-browse) ("O" . jao-eww-browse-new) ("r" . jao-eww-reload) - ("R" . jao-eww-readable) + ("R" . eww-readable) ("s" . eww-search-words) ("S" . jao-eww-browse-new) ("T" . jao-mastodon-toot-url) @@ -219,7 +218,7 @@ ("U" . jao-eww-reopen-new) ("w" . jao-eww-to-org) ("q" . jao-eww-close) - ("x" . jao-rss-subscribe) + ("x" . jao-r2e-subscribe) ("y" . jao-eww-copy-link) ("\\" . eww-view-source) ("C-c C-w" . jao-eww-close) diff --git a/custom/jao-custom-gnus.el b/custom/jao-custom-gnus.el index 3165372..ec6c761 100644 --- a/custom/jao-custom-gnus.el +++ b/custom/jao-custom-gnus.el @@ -30,11 +30,13 @@ nndraft-directory (jao-gnus-dir "drafts") nnrss-directory (jao-gnus-dir "rss")) +(setq gnus-uncacheable-groups "^nnml") + ;;; looks ;;;; verbosity (setq gnus-verbose 4) ;;;; geometry -(defvar jao-gnus-use-three-panes t) +(defvar jao-gnus-use-three-panes (not jao-notmuch-enabled)) (defvar jao-gnus-groups-width 50) (defvar jao-gnus-wide-width 190) @@ -44,37 +46,76 @@ (setq calendar-left-margin 6) -(let ((wide-len jao-gnus-wide-width) - (groups-len jao-gnus-groups-width) - (summary-len (- jao-gnus-wide-width jao-gnus-groups-width))) - (gnus-add-configuration - `(article - (horizontal 1.0 - (vertical ,groups-len (group 1.0)) - (vertical 1.0 - (summary 0.25 point) - (article 1.0))))) - - ;; (gnus-add-configuration - ;; `(group (horizontal 1.0 (group ,wide-len point)))) - - (gnus-add-configuration - `(message (horizontal 1.0 (message ,wide-len point)))) - - (gnus-add-configuration - `(reply-yank (horizontal 1.0 (message ,wide-len point)))) - - (gnus-add-configuration - `(summary - (horizontal 1.0 - (vertical ,groups-len (group 1.0)) - (vertical 1.0 (summary 1.0 point))))) - - (gnus-add-configuration - `(reply - (horizontal 1.0 - (message ,(- wide-len 100) point) - (article 100))))) +(if jao-gnus-use-three-panes + (let ((side-bar '(vertical 1.0 + ("inbox.org" 0.4) + ("*Org Agenda*" 1.0) + ("*Calendar*" 8))) + (wide-len jao-gnus-wide-width) + (groups-len jao-gnus-groups-width) + (summary-len (- jao-gnus-wide-width jao-gnus-groups-width))) + (gnus-add-configuration + `(article + (horizontal 1.0 + (vertical ,groups-len (group 1.0)) + (vertical ,summary-len + (summary 0.25 point) + (article 1.0)) + ,side-bar))) + + (gnus-add-configuration + `(group (horizontal 1.0 (group ,wide-len point) ,side-bar))) + + (gnus-add-configuration + `(message (horizontal 1.0 (message ,wide-len point) ,side-bar))) + + (gnus-add-configuration + `(reply-yank (horizontal 1.0 (message ,wide-len point) ,side-bar))) + + (gnus-add-configuration + `(summary + (horizontal 1.0 + (vertical ,groups-len (group 1.0)) + (vertical ,summary-len (summary 1.0 point)) + ,side-bar))) + + (gnus-add-configuration + `(reply + (horizontal 1.0 + (message ,(- wide-len 100) point) + (article 100) + ,side-bar)))) + (let ((wide-len jao-gnus-wide-width) + (groups-len jao-gnus-groups-width) + (summary-len (- jao-gnus-wide-width jao-gnus-groups-width))) + (gnus-add-configuration + `(article + (horizontal 1.0 + (vertical ,groups-len (group 1.0)) + (vertical 1.0 + (summary 0.25 point) + (article 1.0))))) + + ;; (gnus-add-configuration + ;; `(group (horizontal 1.0 (group ,wide-len point)))) + + (gnus-add-configuration + `(message (horizontal 1.0 (message ,wide-len point)))) + + (gnus-add-configuration + `(reply-yank (horizontal 1.0 (message ,wide-len point)))) + + (gnus-add-configuration + `(summary + (horizontal 1.0 + (vertical ,groups-len (group 1.0)) + (vertical 1.0 (summary 1.0 point))))) + + (gnus-add-configuration + `(reply + (horizontal 1.0 + (message ,(- wide-len 100) point) + (article 100)))))) ;;;; no blue icon (advice-add 'gnus-mode-line-buffer-identification :override #'identity) @@ -185,7 +226,7 @@ (setq mail-sources (let* ((pwd (auth-source-pick-first-password :host "proton-bridge")) (mds (mapcar (lambda (f) - `(maildir :path ,(expand-file-name f "~/var/mail/"))) + `(maildir :path ,(expand-file-name f jao-maildir))) '("local/" "feeds/"))) (ims (mapcar (lambda (b) `(imap :server "127.0.0.1" :port 1143 @@ -308,12 +349,13 @@ "\n")) (defun jao-gnus--set-summary-line (&optional w) - (let* ((d (if jao-gnus-use-three-panes (+ jao-gnus-groups-width 11) 12)) + (let* ((d (if jao-gnus-use-three-panes + (+ jao-gnus-groups-width 11) + (+ jao-gnus-groups-width 12))) (w (- (or w (window-width)) d))) (setq gnus-summary-line-format (format jao-gnus--summary-line-fmt w)))) -;; (add-hook 'gnus-select-group-hook 'jao-gnus--set-summary-line) -;; (jao-gnus--set-summary-line 150) +(add-hook 'gnus-select-group-hook 'jao-gnus--set-summary-line) (add-to-list 'nnmail-extra-headers 'Cc) (add-to-list 'nnmail-extra-headers 'BCc) diff --git a/custom/jao-custom-notmuch.el b/custom/jao-custom-notmuch.el index 30b0976..a0dba56 100644 --- a/custom/jao-custom-notmuch.el +++ b/custom/jao-custom-notmuch.el @@ -185,11 +185,6 @@ '("new" "unread" "flagged" "signed" "sent" "attachment" "forwarded" "inbox" "encrypted" "gmane" "gnus" "feeds" "rss" "mce" "trove" "prog" "emacs")) -(defun jao-notmuch--subtags (tag &rest excl) - (let* ((cmd (concat "notmuch search --output=tags tag:" tag)) - (ts (split-string (shell-command-to-string cmd)))) - (seq-difference ts (append jao-notmuch--shared-tags (cons tag excl))))) - (setq notmuch-archive-tags '("+trove" "-new" "-drivel" "-words" "-inbox") notmuch-show-mark-read-tags '("-new" "-unread") notmuch-tag-formats @@ -245,7 +240,7 @@ (when jao-notmuch-enabled (define-key message-mode-map (kbd "C-c C-d") #'notmuch-draft-postpone) - (setq message-directory "~/var/mail/" + (setq message-directory (file-name-as-directory jao-maildir) message-auto-save-directory "/tmp" mail-user-agent 'message-user-agent)) diff --git a/custom/jao-custom-org.el b/custom/jao-custom-org.el index cd4ec25..f4e84a8 100644 --- a/custom/jao-custom-org.el +++ b/custom/jao-custom-org.el @@ -30,6 +30,9 @@ org-modules '(bibtex info eww eshell git-link) org-odd-levels-only t org-outline-path-complete-in-steps nil + org-persist-directory (jao-d-l + "~/Tmp/org-persist" + "/tmp/org-persist") org-refile-allow-creating-parent-nodes 'confirm org-refile-targets '((nil :maxlevel . 5) (org-agenda-files :maxlevel . 5)) diff --git a/custom/jao-custom-pdf.el b/custom/jao-custom-pdf.el index 4ebd7f1..5e2c27d 100644 --- a/custom/jao-custom-pdf.el +++ b/custom/jao-custom-pdf.el @@ -78,6 +78,7 @@ ;;;; doc-view (use-package doc-view + :if (jao-is-linux) :init (setq doc-view-cache-directory "~/.emacs.d/cache/docview" doc-view-resolution 110 @@ -95,6 +96,7 @@ (use-package jao-doc-session :demand t) (use-package jao-doc-view + :if (jao-is-linux) :demand t :bind (:map doc-view-mode-map ("b" . jao-doc-view-back) diff --git a/custom/jao-custom-programming.el b/custom/jao-custom-programming.el index 4028f3d..b88c43c 100644 --- a/custom/jao-custom-programming.el +++ b/custom/jao-custom-programming.el @@ -239,32 +239,37 @@ ;;;; Clojure (use-package clojure-mode :ensure t + :hook (clojure-mode . jao-clojure--fix-things) :config (defun jao-clojure--fix-things () (setq-local completion-styles '(basic partial-completion emacs22)) (eldoc-mode 1) (setq mode-name "λ")) - :hook (clojure-mode . jao-clojure--fix-things)) -(defun jao-cider-test-ns (ns) - (let ((parts (string-split ns "\\."))) - (if (string= "test" (cadr parts)) - ns - (mapconcat #'identity (cons (car parts) (cons "test" (cdr parts))) ".")))) - -(defun jao-kaocha-file-name () - (let* ((filename (match-string 2)) - (path (replace-regexp-in-string "\\." "/" (match-string 1)))) - (substring-no-properties (concat "test/" path filename)))) - -(defconst jao-kaocha-compilation-error - '(kaocha-error "^FAIL in \\(.+\\.\\)[^ ]+ (\\([^:]+\\.clj[cs]?\\):\\([0-9]+\\))" - jao-kaocha-file-name 3)) - -(use-package compile - :config - (add-to-list 'compilation-error-regexp-alist-alist - jao-kaocha-compilation-error)) + (defun jao-cider-test-ns (ns) + (let ((parts (string-split ns "\\."))) + (if (string= "test" (cadr parts)) + ns + (mapconcat #'identity + (cons (car parts) (cons "test" (cdr parts))) ".")))) + + (defun jao-kaocha-file-name () + (let* ((filename (match-string 2)) + (path (replace-regexp-in-string "\\." "/" (match-string 1)))) + (substring-no-properties (concat "test/" path filename)))) + + (defconst jao-kaocha-compilation-error + '(kaocha-error + "^FAIL in \\(.+\\.\\)[^ ]+ (\\([^:]+\\.clj[cs]?\\):\\([0-9]+\\))" + jao-kaocha-file-name 3)) + + (use-package compile + :config + (add-to-list 'compilation-error-regexp-alist-alist + jao-kaocha-compilation-error))) + +(use-package jao-clojure + :bind (:map clojure-mode-map (("C-c o" . jao-clojure-other-file)))) (use-package cider :ensure t diff --git a/custom/jao-custom-w3m.el b/custom/jao-custom-w3m.el index 43b9e2d..f532e8b 100644 --- a/custom/jao-custom-w3m.el +++ b/custom/jao-custom-w3m.el @@ -198,7 +198,7 @@ ("v" . jao-view-video) ("q" . w3m-delete-buffer) ("w" . org-w3m-copy-for-org-mode) - ("x" . jao-rss-subscribe) + ("x" . jao-r2e-subscribe) ("y" . w3m-print-current-url)))) ;;; textsec @@ -110,7 +110,8 @@ (dolist (p '("/Applications/Emacs.app/Contents/MacOS/bin-arm64-11" "/Applications/Emacs.app/Contents/MacOS/libexec-arm64-11" "/opt/homebrew/sbin" - "/opt/homebrew/bin")) + "/opt/homebrew/bin" + "~/.local/bin")) (jao-exec-path p)) (add-to-list 'Info-directory-list "/opt/homebrew/share/info")) @@ -165,8 +166,7 @@ (setq use-short-answers t) (setq inhibit-startup-message t) -(setq visible-bell t) -(jao-when-darwin (setq ring-bell-function (lambda () (message "Ding!")))) +(setq visible-bell (jao-is-linux)) ;;;; server (setenv "EDITOR" "emacsclient") @@ -329,9 +329,9 @@ (use-package tmr :ensure t :init - (jao-when-linux - (setq tmr-sound-file - "/usr/share/sounds/freedesktop/stereo/message.oga"))) + (setq tmr-sound-file + (jao-when-linux "/usr/share/sounds/freedesktop/stereo/message.oga")) + :config (tmr-mode-line-mode 1)) ;;; Crypto ;;;; PGP, EPG, passwords @@ -440,6 +440,9 @@ (defvar jao-theme-term-dark 'modus-vivendi) (defvar jao-theme-term-light 'jao-light-term) +(setq jao-themes-default-face (jao-d-l "Inconsolata LGC" "Hack") + jao-themes-default-size (jao-d-l 10 9)) + (defun jao-themes-setup () (let* ((dark (jao-colors-scheme-dark-p)) (theme (cond ((and dark window-system) jao-theme-dark) @@ -1147,7 +1150,6 @@ ;;;; afio (use-package jao-afio - ;; :if (jao-is-linux) :demand t :config (jao-afio-setup (not window-system)) @@ -1164,11 +1166,13 @@ 'face 'font-lock-warning-face)) (jao-minibuffer-add-variable '(jao-current--frame-id) 100) + (jao-when-linux + (global-set-key (kbd "C-c t") #'jao-afio-goto-chats)) + :bind (("C-c f" . 'jao-afio-goto-main) ("C-c g" . 'jao-afio-goto-mail) ("C-c w" . 'jao-afio-goto-www) ("C-c z" . 'jao-afio-goto-docs) - ("C-c t" . 'jao-afio-goto-chats) ("C-c 0" . 'jao-afio-goto-scratch) ("M-o" . 'jao-afio-toggle))) @@ -1665,6 +1669,7 @@ (jao-when-linux (jao-shell-running-p "river"))) (jao-when-darwin + (defvar jao-sway-enabled nil) (defun jao-wayland-enabled-p () nil) (defun jao-river-enabled-p () nil)) diff --git a/lib/eos/jao-afio.el b/lib/eos/jao-afio.el index 10e9115..4506bd8 100644 --- a/lib/eos/jao-afio.el +++ b/lib/eos/jao-afio.el @@ -122,10 +122,10 @@ ;;;###autoload (defun jao-afio-open-gnus () (interactive) - (delete-other-windows) (jao-org-agenda) (calendar) (find-file (expand-file-name "inbox.org" org-directory)) + (delete-other-windows) (gnus) (jao-gnus--set-summary-line)) diff --git a/lib/eos/jao-r2e.el b/lib/eos/jao-r2e.el new file mode 100644 index 0000000..fa20ddb --- /dev/null +++ b/lib/eos/jao-r2e.el @@ -0,0 +1,206 @@ +;;; jao-r2e.el --- List of rss2email subscriptions -*- lexical-binding: t; -*- + +;; Copyright (C) 2025 Jose Antonio Ortega Ruiz + +;; Author: Jose Antonio Ortega Ruiz <mail@jao.io> +;; Keywords: news + +;; This program 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. + +;; This program 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 this program. If not, see <https://www.gnu.org/licenses/>. + +(require 'jao-url) + +(autoload 'View-quit "view") +(autoload 'eww-view-source "eww") +(autoload 'jao-notmuch-subtags "jao-notmuch") + +(defvar jao-r2e-confirm-toggle nil) + +(defconst jao-r2e--buffer "*r2e*") +(defun jao-r2e--buffer () + (with-current-buffer (get-buffer-create jao-r2e--buffer) + (unless (derived-mode-p 'jao-r2e-mode) + (jao-r2e-mode)) + (current-buffer))) + +(defvar jao-r2e-mode-map + (let ((map (make-keymap))) + (suppress-keymap map) + (define-key map [?q] 'bury-buffer) + (define-key map [?n] 'next-line) + (define-key map [?p] 'previous-line) + (define-key map [?N] 'jao-r2e-next) + (define-key map [?P] 'jao-r2e-prev) + (define-key map [?g] 'jao-r2e-list) + (define-key map [?s] 'jao-r2e-subscribe) + (define-key map [?t] 'jao-r2e-toggle) + (define-key map [?D] 'jao-r2e-delete) + (define-key map [?u] 'jao-r2e-recover) + map)) + +;;;###autoload +(defun jao-r2e-mode () + "A very simple mode to show the output of r2e commands." + (interactive) + (kill-all-local-variables) + (buffer-disable-undo) + (use-local-map jao-r2e-mode-map) + ;; (setq-local font-lock-defaults '(jao-r2e-font-lock-keywords)) + (setq-local truncate-lines t) + (setq-local next-line-add-newlines nil) + (setq major-mode 'jao-r2e-mode) + (setq mode-name "r2e") + (read-only-mode 1)) + +(defun jao-r2e--do (things &optional buffer) + "Execute a r2e command THINGS in the given BUFFER." + (let ((b (or buffer (pop-to-buffer (jao-r2e--buffer))))) + (let ((inhibit-read-only t) + (cmd (format "r2e %s" things))) + (unless buffer + (with-current-buffer b (delete-region (point-min) (point-max)))) + (with-temp-message (format "Running: %s ...." cmd) + (shell-command cmd b)) + (unless buffer (read-only-mode 1))))) + +(defconst jao-r2e--feed-rx + "^\\([0-9]+\\): \\[\\( \\|\\*\\)\\] \\([^ ]+\\) (\\(.+\\) -> \\(.+\\))") + +(defun jao-r2e--feed-at-point () + (beginning-of-line) + (when-let* ((m (looking-at jao-r2e--feed-rx))) + (list (match-string 1) + (match-string 3) + (string= "*" (match-string 2)) + (match-string 4) + (match-string 5)))) + +(defun jao-r2e () + (interactive) + (pop-to-buffer (jao-r2e--buffer)) + (when (looking-at-p "^$") + (jao-r2e-list))) + +(defun jao-r2e-list () + (interactive) + (jao-r2e--do "list")) + +(defun jao-r2e--srx (opp) + (when-let* ((f (jao-r2e--feed-at-point))) + (let ((a (if opp (not (caddr f)) (caddr f)))) + (format "^[0-9]+: \\[%s\\] " (if a "\\*" " "))))) + +(defun jao-r2e-next (opp) + "Next feed with the same (or opposite) status." + (interactive "P") + (when-let* ((rx (jao-r2e--srx opp))) + (next-line) + (when (re-search-forward rx nil t) + (beginning-of-line)))) + +(defun jao-r2e-prev (opp) + "Previous feed with the same (or opposite) status." + (interactive "P") + (when-let* ((rx (jao-r2e--srx opp))) + (when (re-search-backward rx nil t) + (beginning-of-line)))) + +(defun jao-r2e-toggle () + (interactive) + (let ((f (jao-r2e--feed-at-point))) + (unless f (error "No feed at point")) + (let ((p (point)) + (no (car f)) + (name (cadr f)) + (act (if (caddr f) "pause" "unpause"))) + (when (or (not jao-r2e-confirm-toggle) + (yes-or-no-p (format "%s '%s'? " act name))) + (with-temp-buffer + (jao-r2e--do (format "%s %s" act no) (current-buffer))) + (jao-r2e-list) + (goto-char p))))) + +(persist-defvar jao-r2e-deleted-feeds '() + "List of rss2email feeds deleted at some point.") + +(defun jao-r2e-delete () + "Delete feed at point. Use `jao-r2e-recover' to undelete." + (interactive) + (let ((f (jao-r2e--feed-at-point))) + (unless f (error "No feed at point")) + (let ((p (point)) + (no (car f)) + (name (cadr f))) + (when (yes-or-no-p (format "Delete feed '%s'" name)) + (add-to-list 'jao-r2e-deleted-feeds (cdr f)) + (with-temp-buffer + (jao-r2e--do (format "delete %s" no) (current-buffer))) + (jao-r2e-list) + (goto-char p))))) + +(defun jao-r2e-recover () + (interactive) + (when (seq-empty-p jao-r2e-deleted-feeds) + (error "No feeds recoverable at this point.")) + (let ((feed (completing-read "Recover feed: " jao-r2e-deleted-feeds))) + (when-let* ((ps (assoc feed jao-r2e-deleted-feeds)) + (url (caddr ps)) + (mail (car (last ps))) + (cat (when (string-match "feeds\\.\\(.+\\)@localhost" mail) + (match-string 1 mail)))) + (jao-r2e-subscribe (list url feed) cat t) + (setq jao-r2e-deleted-feeds (remove ps jao-r2e-deleted-feeds))))) + +(defun jao-r2e--find-url () + (save-excursion + (when (derived-mode-p 'w3m-mode 'eww-mode) + (if (fboundp 'w3m-view-source) (w3m-view-source) (eww-view-source))) + (goto-char (point-min)) + (when (re-search-forward + "type=\"application/\\(?:atom\\|rss\\)\\+xml\" +" nil t) + (let ((url (save-excursion + (when (re-search-forward + "href=\"\\([^\n\"]+\\)\"" nil t) + (match-string-no-properties 1)))) + (title (when (re-search-forward + "\\(?:title=\"\\([^\n\"]+\\)\" +\\)" nil t) + (match-string-no-properties 1)))) + (cond ((derived-mode-p 'w3m-view-mode) (w3m-view-source)) + ((string-match-p ".*\\*eww-source\\b.*" (buffer-name)) + (View-quit))) + (when url (cons url (or title ""))))))) + +(defun jao-r2e-subscribe (url &optional cat relist) + "Subscribe to a given RSS URL. If URL not given, look for it." + (interactive (list (or (jao-url-around-point) + (jao-r2e--find-url) + (read-string "Feed URL: ")))) + (let* ((url+title (ensure-list url)) + (url (car url+title)) + (title (cdr url+title))) + (unless url (error "No feeds found")) + (let ((url (if (string-match "^feed:" url) (substring url 5) url))) + (when (y-or-n-p (format "Subscribe to <%s>? " url)) + (let* ((name (read-string "Feed name: " title)) + (cats (cons "prog" (jao-notmuch-subtags "feeds"))) + (cat (completing-read "Category: " cats nil t cat)) + (subs (format "r2e add %s '%s' feeds.%s@localhost" + name url cat))) + (with-temp-message "Subscribing..." + (shell-command-to-string subs)) + (with-temp-message "Retrieving feed..." + (shell-command (format "r2e run %s" name))) + (when relist (jao-r2e-list))))))) + +(provide 'jao-r2e) +;;; jao-r2e.el ends here diff --git a/lib/net/jao-eww-session.el b/lib/net/jao-eww-session.el index 4ac5447..da5bc8b 100644 --- a/lib/net/jao-eww-session.el +++ b/lib/net/jao-eww-session.el @@ -1,6 +1,6 @@ ;;; jao-eww-session.el --- Persistent eww sessions -*- lexical-binding: t; -*- -;; Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2012, 2021, 2022 Jose A Ortega Ruiz +;; Copyright (C) 2003-2004, 2006-2009, 2012, 2021-2022, 2025 Jose A Ortega Ruiz ;; Author: Jose A Ortega Ruiz <jao@gnu.org> ;; Version: 0.4 @@ -168,15 +168,14 @@ the session is already displayed in a eww tab, jao-eww-session can: (defun jao-eww-session--to--file (filename &optional skip) (require 'pp) - (when (jao-eww-session-not-empty) - (let ((inhibit-message t) - (session (jao-eww-session--update-current skip))) - (with-temp-buffer - (insert ";;;; File generated by jao-eww-session. DO NOT EDIT!\n") - (pp session (current-buffer)) - (insert "\n" ";;;; End of " - (file-name-nondirectory jao-eww-session-file) "\n") - (write-region (point-min) (point-max) (expand-file-name filename)))))) + (let ((inhibit-message t) + (session (jao-eww-session--update-current skip))) + (with-temp-buffer + (insert ";;;; File generated by jao-eww-session. DO NOT EDIT!\n") + (pp session (current-buffer)) + (insert "\n" ";;;; End of " + (file-name-nondirectory jao-eww-session-file) "\n") + (write-region (point-min) (point-max) (expand-file-name filename))))) (defun jao-eww-session--backup-name (fname) (concat (expand-file-name fname) ".bak")) diff --git a/lib/net/jao-notmuch.el b/lib/net/jao-notmuch.el index aef9757..75ee027 100644 --- a/lib/net/jao-notmuch.el +++ b/lib/net/jao-notmuch.el @@ -1,6 +1,6 @@ ;;; jao-notmuch.el --- Extensions for notmuch -*- lexical-binding: t; -*- -;; Copyright (C) 2021, 2022, 2023, 2024 jao +;; Copyright (C) 2021, 2022, 2023, 2024, 2025 jao ;; Author: jao <mail@jao.io> ;; Keywords: mail @@ -339,6 +339,12 @@ (let ((tags (plist-get (notmuch-tree-get-message-properties) :orig-tags))) (jao-notmuch-tree--tag tags nil))) +(defun jao-notmuch-subtags (tag &rest excl) + (let* ((cmd (concat "notmuch search --output=tags tag:" tag)) + (ts (split-string (shell-command-to-string cmd)))) + (seq-difference ts (append jao-notmuch--shared-tags (cons tag excl))))) + + ;;; fcc (defvar jao-notmuch-mua-reply-not-inherited '("attachment" "sent" "new" "bigml" "jao" "trove")) diff --git a/lib/net/jao-url.el b/lib/net/jao-url.el new file mode 100644 index 0000000..9e58f99 --- /dev/null +++ b/lib/net/jao-url.el @@ -0,0 +1,36 @@ +;;; jao-url.el --- URL handling -*- lexical-binding: t; -*- + +;; Copyright (C) 2025 Jose Antonio Ortega Ruiz + +;; Author: Jose Antonio Ortega Ruiz <mail@jao.io> +;; Keywords: hypermedia + +;; This program 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. + +;; This program 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 this program. If not, see <https://www.gnu.org/licenses/>. + +(require 'shr) +(require 'ffap) +(require 'thingatpt) + +(defun jao-url-around-point (&optional current-url) + (or (and (fboundp 'w3m-anchor) (w3m-anchor)) + (shr-url-at-point nil) + (ffap-url-at-point) + (thing-at-point 'url) + (when current-url + (or (and (fboundp 'w3m-anchor) (w3m-anchor)) + (and (derived-mode-p 'eww-mode) (plist-get eww-data :url)))))) + + +(provide 'jao-url) +;;; jao-url.el ends here diff --git a/lib/prog/jao-clojure.el b/lib/prog/jao-clojure.el new file mode 100644 index 0000000..e044f9e --- /dev/null +++ b/lib/prog/jao-clojure.el @@ -0,0 +1,101 @@ +;;; jao-clojure.el --- Clojure utilities -*- lexical-binding: t; -*- + +;; Copyright (C) 2025 Jose Antonio Ortega Ruiz + +;; Author: Jose Antonio Ortega Ruiz <mail@jao.io> +;; Keywords: languages + +;; This program 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. + +;; This program 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 this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; Helpers for clojure coding + +;;; Code: + +(require 'clojure-mode) +(require 'project) + +;;;; Jumping between implementation and test files +(defun jao-clojure--ext-dir (prefix) + (let* ((ext (file-name-extension buffer-file-name)) + (ext-rx (format "/%s/" ext))) + (if (string-match-p ext-rx buffer-file-name) + (format "%s/%s" prefix ext) + prefix))) + +(defun jao-clojure-find-current-test () + (save-excursion + (and (re-search-backward + "(deftest\\(?:\\W+^:\\w+\\)*\\W+\\b\\(.+\\)\\b" nil t) + (match-string-no-properties 1)))) + +(defvar jao-clojure--src-candidates '("lib" "src" "srv" "app")) + +(defun jao-clojure--test-namespace-p (ns) + (or (string-suffix-p "-test" ns) + (string-match "\\(.+\\)\\.\\(test\\)\\(\\..+\\)" ns))) + +(defun jao-clojure-test-buffer-p () + (jao-clojure--test-namespace-p (clojure-find-ns))) + +(defun jao-clojure--test-for (namespace sep) + (funcall cider-test-infer-test-ns namespace)) + +(defun jao-clojure--infer-test-ns (ns) + (if (jao-clojure--test-namespace-p ns) + ns + (jao-clojure--test-for ns "."))) + +(defun jao-clojure--root () (project-root (project-current))) + +(defun jao-clojure-jump-to-test () + "Jump from implementation to test file." + (interactive) + (let* ((f (format "%s/%s/%s.%s" + (jao-clojure--root) + (jao-clojure--ext-dir "test") + (jao-clojure--test-for (clojure-find-ns) "/") + (file-name-extension buffer-file-name))) + (f (replace-regexp-in-string "-" "_" f))) + (find-file f))) + +(defun jao-clojure--implementation-for (namespace) + (let ((n (replace-regexp-in-string "-test$" "" namespace))) + (replace-regexp-in-string "\\.test\\." "." n))) + +(defun jao-clojure--find-implementation (src) + (let ((f (format "%s/%s/%s.%s" + (jao-clojure--root) + (jao-clojure--ext-dir src) + (jao-clojure--implementation-for (clojure-find-ns)) + (file-name-extension buffer-file-name)))) + (and (file-exists-p f) f))) + +(defun jao-clojure-jump-to-implementation () + "Jump from test file to implementation." + (interactive) + (let ((impl (car (seq-keep #'jao-clojure--find-implementation + jao-clojure--src-candidates)))) + (if impl (find-file impl) (message "No implementation file found")))) + +(defun jao-clojure-other-file () + "Toggle between implementation and test file" + (interactive) + (if (jao-clojure-test-buffer-p) + (jao-clojure-jump-to-implementation) + (jao-clojure-jump-to-test))) + +(provide 'jao-clojure) +;;; jao-clojure.el ends here diff --git a/lib/themes/jao-light-theme.el b/lib/themes/jao-light-theme.el index 30a56af..c9b1882 100644 --- a/lib/themes/jao-light-theme.el +++ b/lib/themes/jao-light-theme.el @@ -18,7 +18,7 @@ (jao-define-custom-theme jao-light (:names (bg-lightest "gray98") - (bg-light "gray95") + (bg-light "#efefef") (light-gray "gray80") @@ -36,9 +36,6 @@ (green "#005555") (lightgreen "darkgreen") (yellow "lightyellow")) - (:face-size (jao-d-l 12 9)) - ;; (:face-family "DejaVu Sans Mono") - (:face-family (jao-d-l "Triplicate T4c" "Hack")) (:bold-weight 'semibold) (:palette (fg "black") (bg "white") @@ -102,6 +99,7 @@ (magit-diff-hunk-heading-highlight (c nil hl) it bf) (message-header-subject (p warning) nbf) (mode-line (c "grey20") :box (:line-width 1 :color "grey80")) + (mode-line-active (c "grey20") :box (:line-width 1 :color "grey80")) (mode-line-inactive (c "grey40" bg-light) :box (:line-width 1 :color "grey80")) (mode-line-buffer-id (~ default) (c nil nil) nit) diff --git a/lib/themes/jao-themes.el b/lib/themes/jao-themes.el index f529842..efb691c 100644 --- a/lib/themes/jao-themes.el +++ b/lib/themes/jao-themes.el @@ -21,8 +21,10 @@ (require 'ansi-color) ;;; palette -(defvar jao-themes-default-face "DejaVu Sans Mono-9") -(defvar jao-themes--face-family "DejaVu Sans Mono") +(defvar jao-themes-default-face nil) +(defvar jao-themes-default-family "Hack") +(defvar jao-themes-default-size 9) +(defvar jao-themes--face-family jao-themes-default-face) (defvar jao-themes--fg "black") (defvar jao-themes--bg "white") (defvar jao-themes--box "grey75") @@ -1228,8 +1230,10 @@ (let ((palette (cdr (assoc :palette args))) (x-faces (cdr (assoc :x-faces args))) (x-colors (cdr (assoc :x-colors args))) - (family (cadr (assoc :face-family args))) - (size (or (cadr (assoc :face-size args)) 9)) + (family (or (cadr (assoc :face-family args)) + jao-themes-default-family)) + (size (or (cadr (assoc :face-size args)) + jao-themes-default-size)) (bw (or (cadr (assoc :bold-weight args)) jao-themes--bold-weight))) `(progn (custom-make-theme-feature ',name) |