From 0f8eb65fb807a125dd601cd6b3ee746e6c7b6020 Mon Sep 17 00:00:00 2001 From: jao Date: Sun, 6 Sep 2026 15:36:38 +0100 Subject: a slew of little fixes courtesy of the byte compiler --- attic/elisp/jao-multisession.el | 341 +++++++++++++++++++++++++++++++++++++ attic/elisp/jao-vterm-repl.el | 130 ++++++++++++++ custom/jao-custom-gnus.el | 13 ++ custom/jao-custom-pdf.el | 40 ++++- init.el | 80 +++------ lib/doc/jao-doc-view.el | 11 +- lib/doc/jao-mac.el | 67 +++++--- lib/doc/jao-org-focus.el | 2 +- lib/doc/jao-org-links.el | 5 +- lib/doc/jao-org-notes.el | 4 +- lib/doc/jao-pdf.el | 47 +---- lib/doc/jao-words.el | 2 +- lib/eos/jao-afio.el | 5 +- lib/eos/jao-buffers.el | 57 +++++++ lib/eos/jao-dirmon.el | 8 +- lib/eos/jao-eshell-here.el | 7 +- lib/eos/jao-multisession.el | 341 ------------------------------------- lib/eos/jao-notify.el | 2 +- lib/eos/jao-r2e.el | 233 ------------------------- lib/eos/jao-shell.el | 4 +- lib/eos/jao-sleep.el | 4 +- lib/eos/jao-tracking.el | 4 +- lib/eos/jao-wayland.el | 1 + lib/jao-recoll.el | 76 --------- lib/media/jao-lyrics.el | 11 +- lib/media/jao-mpc.el | 5 +- lib/media/jao-mpris.el | 12 +- lib/media/jao-random-album.el | 5 +- lib/net/jao-eww-session.el | 2 +- lib/net/jao-notmuch-gnus.el | 15 -- lib/net/jao-notmuch.el | 2 +- lib/net/jao-proton-utils.el | 34 ++-- lib/net/jao-r2e.el | 231 +++++++++++++++++++++++++ lib/net/randomsig.el | 82 ++++----- lib/prog/jao-clojure.el | 7 +- lib/prog/jao-rust.el | 7 + lib/prog/jao-sloc.el | 2 +- lib/prog/jao-vterm-repl.el | 130 -------------- lib/skels/jao-skel-cpp.el | 10 +- lib/themes/jao-dark-theme.el | 136 --------------- lib/themes/jao-light-term-theme.el | 121 ------------- lib/themes/jao-light-theme.el | 135 --------------- lib/themes/jao-themes.el | 1 + themes/jao-dark-theme.el | 136 +++++++++++++++ themes/jao-light-term-theme.el | 121 +++++++++++++ themes/jao-light-theme.el | 135 +++++++++++++++ 46 files changed, 1408 insertions(+), 1416 deletions(-) create mode 100644 attic/elisp/jao-multisession.el create mode 100644 attic/elisp/jao-vterm-repl.el create mode 100644 lib/eos/jao-buffers.el delete mode 100644 lib/eos/jao-multisession.el delete mode 100644 lib/eos/jao-r2e.el delete mode 100644 lib/jao-recoll.el create mode 100644 lib/net/jao-r2e.el delete mode 100644 lib/prog/jao-vterm-repl.el delete mode 100644 lib/themes/jao-dark-theme.el delete mode 100644 lib/themes/jao-light-term-theme.el delete mode 100644 lib/themes/jao-light-theme.el create mode 100644 themes/jao-dark-theme.el create mode 100644 themes/jao-light-term-theme.el create mode 100644 themes/jao-light-theme.el diff --git a/attic/elisp/jao-multisession.el b/attic/elisp/jao-multisession.el new file mode 100644 index 0000000..7c06183 --- /dev/null +++ b/attic/elisp/jao-multisession.el @@ -0,0 +1,341 @@ +;;; multisession.el --- Multisession storage for variables -*- lexical-binding: t; -*- + +;; Copyright (C) 2021-2026 Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. + +;; GNU Emacs 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. + +;; GNU Emacs 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 GNU Emacs. If not, see . + +;;; Commentary: + +;; This library provides multisession variables for Emacs Lisp, to +;; make them persist between sessions. +;; +;; Use `define-multisession-variable' to define a multisession +;; variable, and `multisession-value' to read its value. Use +;; `list-multisession-values' to list multisession variables. +;; +;; Users might want to customize `multisession-storage' and +;; `multisession-directory'. +;; +;; See Info node `(elisp) Multisession Variables' for more +;; information. + +;;; Code: + +(require 'cl-lib) +(require 'eieio) +(require 'tabulated-list) + +(defcustom multisession-storage 'files + "Storage method for multisession variables. +Valid methods are `sqlite' and `files'." + :type '(choice (const :tag "SQLite" sqlite) + (const :tag "Files" files)) + :version "29.1" + :group 'files) + +(defcustom multisession-directory (expand-file-name "multisession/" + user-emacs-directory) + "Directory to store multisession variables." + :type 'file + :version "29.1" + :group 'files) + +;;;###autoload +(defmacro define-multisession-variable (name initial-value &optional doc + &rest args) + "Make NAME into a multisession variable initialized from INITIAL-VALUE. +DOC should be a doc string, and ARGS are keywords as applicable to +`make-multisession'." + (declare (indent defun)) + (unless (plist-get args :package) + (setq args (nconc (list :package + (replace-regexp-in-string "-.*" "" + (symbol-name name))) + args))) + `(defvar ,name + (make-multisession :key ,(symbol-name name) + :initial-value ,initial-value + ,@args) + ,@(list doc))) + +(defconst multisession--unbound (make-symbol "unbound")) + +(cl-defstruct (multisession + (:constructor nil) + (:constructor multisession--create) + (:conc-name multisession--)) + "A persistent variable that will live across Emacs invocations." + key + (initial-value nil) + package + (storage multisession-storage) + (synchronized nil) + (cached-value multisession--unbound) + (cached-sequence 0)) + +(cl-defun make-multisession (&key key initial-value package synchronized + storage) + "Create a multisession object." + (unless package + (error "No package for the multisession object")) + (unless key + (error "No key for the multisession object")) + (unless (stringp package) + (error "The package has to be a string")) + (unless (stringp key) + (error "The key has to be a string")) + (multisession--create + :key key + :synchronized synchronized + :initial-value initial-value + :package package + :storage (or storage multisession-storage))) + +(defun multisession-value (object) + "Return the value of the multisession OBJECT." + (if (null user-init-file) + ;; If we don't have storage, then just return the value from the + ;; object. + (if (eq (multisession--cached-value object) multisession--unbound) + (multisession--initial-value object) + (multisession--cached-value object)) + ;; We have storage, so we update from storage. + (multisession-backend-value (multisession--storage object) object))) + +(defun multisession--set-value (object value) + "Set the stored value of OBJECT to VALUE." + (if (null user-init-file) + ;; We have no backend, so just store the value. + (setf (multisession--cached-value object) value) + ;; We have a backend. + (multisession--backend-set-value (multisession--storage object) + object value))) + +(defun multisession-delete (object) + "Delete OBJECT from the backend storage." + (multisession--backend-delete (multisession--storage object) object)) + +(gv-define-simple-setter multisession-value multisession--set-value) + +;; Files Backend + +(defun multisession--encode-file-name (name) + (url-hexify-string name)) + +(defun multisession--read-file-value (file object) + (catch 'done + (let ((i 0) + last-error) + (while (< i 10) + (condition-case err + (throw 'done + (with-temp-buffer + (let* ((time (file-attribute-modification-time + (file-attributes file))) + (coding-system-for-read 'utf-8-emacs-unix)) + (insert-file-contents file) + (let ((stored (read (current-buffer)))) + (setf (multisession--cached-value object) stored + (multisession--cached-sequence object) time) + stored)))) + ;; Windows uses OS-level file locking that may preclude + ;; reading the file in some circumstances. In addition, + ;; rename-file is not an atomic operation on MS-Windows, + ;; when the target file already exists, so there could be a + ;; small race window when the file to read doesn't yet + ;; exist. So when these problems happen, wait a bit and retry. + ((permission-denied file-missing) + (setq i (1+ i) + last-error err) + (sleep-for (+ 0.1 (/ (float (random 10)) 10)))))) + (signal (car last-error) (cdr last-error))))) + +(defun multisession--object-file-name (object) + (expand-file-name + (concat "files/" + (multisession--encode-file-name (multisession--package object)) + "/" + (multisession--encode-file-name (multisession--key object)) + ".value") + multisession-directory)) + +(cl-defmethod multisession-backend-value ((_type (eql 'files)) object) + (let ((file (multisession--object-file-name object))) + (cond + ;; We have no value yet; see whether it's stored. + ((eq (multisession--cached-value object) multisession--unbound) + (if (file-exists-p file) + (multisession--read-file-value file object) + ;; Nope; return the initial value. + (multisession--initial-value object))) + ;; We have a value, but we want to update in case some other + ;; Emacs instance has updated. + ((multisession--synchronized object) + (if (and (file-exists-p file) + (time-less-p (multisession--cached-sequence object) + (file-attribute-modification-time + (file-attributes file)))) + (multisession--read-file-value file object) + ;; Nothing, return the cached value. + (multisession--cached-value object))) + ;; Just return the cached value. + (t + (multisession--cached-value object))))) + +(cl-defmethod multisession--backend-set-value ((_type (eql 'files)) + object value) + (let ((file (multisession--object-file-name object)) + (time (current-time))) + ;; Ensure that the directory exists. + (let ((dir (file-name-directory file))) + (unless (file-exists-p dir) + (make-directory dir t))) + (with-temp-buffer + (let ((print-length nil) + (print-circle t) + (print-level nil)) + (prin1 value (current-buffer))) + (goto-char (point-min)) + (condition-case nil + (read (current-buffer)) + (error (error "Unable to store unreadable value: %s" (buffer-string)))) + ;; Write to a temp file in the same directory and rename to the + ;; file for somewhat better atomicity. + (let ((coding-system-for-write 'utf-8-emacs-unix) + (create-lockfiles nil) + (temp (make-temp-name file)) + (write-region-inhibit-fsync nil)) + (write-region (point-min) (point-max) temp nil 'silent) + (set-file-times temp time) + (rename-file temp file t))) + (setf (multisession--cached-sequence object) time + (multisession--cached-value object) value))) + +(cl-defmethod multisession--backend-values ((_type (eql 'files))) + (mapcar (lambda (file) + (let ((bits (file-name-split file))) + (list (url-unhex-string (car (last bits 2))) + (url-unhex-string + (file-name-sans-extension (car (last bits)))) + (with-temp-buffer + (let ((coding-system-for-read 'utf-8-emacs-unix)) + (insert-file-contents file) + (read (current-buffer))))))) + (directory-files-recursively + (expand-file-name "files" multisession-directory) + "\\.value\\'"))) + +(cl-defmethod multisession--backend-delete ((_type (eql 'files)) object) + (let ((file (multisession--object-file-name object))) + (when (file-exists-p file) + (delete-file file)))) + +;; Mode for editing. + +(defvar-keymap multisession-edit-mode-map + :parent tabulated-list-mode-map + "d" #'multisession-delete-value + "e" #'multisession-edit-value) + +(define-derived-mode multisession-edit-mode special-mode "Multisession" + "This mode lists all elements in the \"multisession\" database." + :interactive nil + (buffer-disable-undo) + (setq-local buffer-read-only t + truncate-lines t) + (setq tabulated-list-format + [("Package" 10) + ("Key" 30) + ("Value" 30)]) + (setq-local revert-buffer-function #'multisession-edit-mode--revert)) + +;;;###autoload +(defun list-multisession-values (&optional choose-storage) + "List all values in the \"multisession\" database. +If CHOOSE-STORAGE (interactively, the prefix), query for the +storage method to list." + (interactive "P") + (let ((storage + (if choose-storage + (intern (completing-read "Storage method: " '(sqlite files) nil t)) + multisession-storage))) + (pop-to-buffer (get-buffer-create (format "*Multisession %s*" storage))) + (multisession-edit-mode) + (setq-local multisession-storage storage) + (multisession-edit-mode--revert) + (goto-char (point-min)))) + +(defun multisession-edit-mode--revert (&rest _) + (let ((inhibit-read-only t) + (id (get-text-property (point) 'tabulated-list-id))) + (erase-buffer) + (tabulated-list-init-header) + (setq tabulated-list-entries + (mapcar (lambda (elem) + (list + (cons (car elem) (cadr elem)) + (vector (car elem) (cadr elem) + (string-replace "\n" "\\n" + (format "%s" (caddr elem)))))) + (multisession--backend-values multisession-storage))) + (tabulated-list-print t) + (goto-char (point-min)) + (when id + (when-let* ((match + (text-property-search-forward 'tabulated-list-id id t))) + (goto-char (prop-match-beginning match)))))) + +(defun multisession-delete-value (id) + "Delete the value at point." + (interactive (list (get-text-property (point) 'tabulated-list-id)) + multisession-edit-mode) + (unless id + (error "No value on the current line")) + (unless (yes-or-no-p "Really delete this item? ") + (user-error "Not deleting")) + (multisession--backend-delete multisession-storage + (make-multisession :package (car id) + :key (cdr id))) + (let ((inhibit-read-only t)) + (beginning-of-line) + (delete-region (point) (progn (forward-line 1) (point))))) + +(defun multisession-edit-value (id) + "Edit the value at point." + (interactive (list (get-text-property (point) 'tabulated-list-id)) + multisession-edit-mode) + (unless id + (error "No value on the current line")) + (let* ((object (or + ;; If the multisession variable already exists, use + ;; it (so that we update it). + (if-let* ((sym (intern-soft (cdr id)))) + (and (boundp sym) (symbol-value sym)) + nil) + ;; Create a new object. + (make-multisession + :package (car id) + :key (cdr id) + :storage multisession-storage))) + (value (multisession-value object))) + (setf (multisession-value object) + (car (read-from-string + (read-string "New value: " (prin1-to-string value)))))) + (multisession-edit-mode--revert)) + +(provide 'jao-multisession) + +;;; multisession.el ends here diff --git a/attic/elisp/jao-vterm-repl.el b/attic/elisp/jao-vterm-repl.el new file mode 100644 index 0000000..699ff39 --- /dev/null +++ b/attic/elisp/jao-vterm-repl.el @@ -0,0 +1,130 @@ +;;; jao-vterm-repl.el --- vterm-based repls -*- lexical-binding: t; -*- + +;; Copyright (C) 2020, 2021 jao + +;; Author: jao +;; Keywords: terminals + +;; 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 . + +;;; Commentary: + +;; Helpers to launch reply things such as erlang shells inside a vterm. +;; For instance, to declare an erl repl for rebar projects, one would call: +;; +;; (jao-vterm-repl-register "rebar.config" "rebar3 shell" "^[0-9]+> ") + +;;; Code: + +(require 'jao-compilation) + +(declare-function 'vterm-copy-mode "vterm") +(declare-function 'vterm-send-string "vterm") +(declare-function 'vterm-send-return "vterm") + +(defun jao-vterm-repl--buffer-name (&optional dir) + (format "*vterm -- repl - %s*" (or dir (jao-compilation-root)))) + +(defvar jao-vterm-repl-repls nil) +(defvar jao-vterm-repl-prompts nil) +(defvar-local jao-vterm-repl--name nil) +(defvar-local jao-vterm-repl--last-buffer nil) +(defvar-local jao-vterm-repl--prompt-rx "^[0-9]+> ") + +(setq vterm-buffer-name-string nil) + +(defun jao-vterm-repl--exec (cmd &optional name) + (vterm name) + (when name + (vterm-send-string "unset PROMPT_COMMAND\n\n")) + (vterm-send-string cmd) + (vterm-send-return) + (when name (rename-buffer name t))) + +;;;###autoload +(defun jao-vterm-repl-previous-prompt () + (interactive) + (when (derived-mode-p 'vterm-mode) + (vterm-copy-mode 1) + (forward-line 0) + (when (re-search-backward jao-vterm-repl--prompt-rx nil t) + (goto-char (match-end 0))))) + +;;;###autoload +(defun jao-vterm-repl-next-prompt () + (interactive) + (when (derived-mode-p 'vterm-mode) + (vterm-copy-mode 1) + (or (re-search-forward jao-vterm-repl--prompt-rx nil t) + (vterm-copy-mode -1)) + (unless (save-excursion + (re-search-forward jao-vterm-repl--prompt-rx nil t)) + (vterm-copy-mode -1)))) + +;;;###autoload +(define-minor-mode jao-vterm-repl-mode "repl-aware vterm" nil nil + '(("\C-c\C-p" . jao-vterm-repl-previous-prompt) + ("\C-c\C-n" . jao-vterm-repl-next-prompt) + ("\C-c\C-z" . jao-vterm-repl-pop-to-src))) + +;;;###autoload +(defun jao-vterm-repl () + (let* ((dir (jao-compilation-root)) + (vname (jao-vterm-repl--buffer-name dir)) + (root-name (jao-compilation-root-file)) + (buffer (seq-find `(lambda (b) + (string= + (buffer-local-value 'jao-vterm-repl--name + b) + ,vname)) + (buffer-list)))) + (or buffer + (let ((default-directory dir) + (prompt (cdr (assoc root-name jao-vterm-repl-prompts))) + (cmd (or (cdr (assoc root-name jao-vterm-repl-repls)) + (read-string "REPL command: "))) + (bname (format "* vrepl - %s/%s *" + (file-name-base (string-remove-suffix "/" dir)) + root-name))) + (jao-vterm-repl--exec cmd bname) + (jao-vterm-repl-mode) + (setq-local jao-vterm-repl--name vname) + (when prompt (setq-local jao-vterm-repl--prompt-rx prompt)) + (current-buffer))))) + +;;;###autoload +(defun jao-vterm-repl-register (build-file repl-cmd prompt-rx) + (jao-compilation-add-dominating build-file) + (add-to-list 'jao-vterm-repl-repls (cons build-file repl-cmd)) + (add-to-list 'jao-vterm-repl-prompts (cons build-file prompt-rx))) + +;;;###autoload +(defun jao-vterm-repl-pop-to-repl () + (interactive) + (let ((bn (current-buffer))) + (pop-to-buffer (jao-vterm-repl)) + (setq-local jao-vterm-repl--last-buffer bn))) + +;;;###autoload +(defun jao-vterm-repl-pop-to-src () + (interactive) + (when (buffer-live-p jao-vterm-repl--last-buffer) + (pop-to-buffer jao-vterm-repl--last-buffer))) + +;;;###autoload +(defun jao-vterm-repl-send (cmd) + (with-current-buffer (jao-vterm-repl) (vterm-send-string cmd))) + +(provide 'jao-vterm-repl) +;;; jao-vterm-repl.el ends here diff --git a/custom/jao-custom-gnus.el b/custom/jao-custom-gnus.el index dad3de1..7e7172b 100644 --- a/custom/jao-custom-gnus.el +++ b/custom/jao-custom-gnus.el @@ -825,3 +825,16 @@ (jao-when-darwin (define-key gnus-group-mode-map "O" 'jao-mac-open-nnw)) + +(with-eval-after-load "consult-notmuch" + (defun jao-notmuch-gnus--open-candidate (candidate) + "Open a notmuch-search completion candidate email in Gnus." + (message "candidate: %S" candidate) + (jao-notmuch-gnus-goto-message (consult-notmuch--candidate-id candidate))) + + (defun jao-gnus-consult-notmuch () + "Run a consult-notmuch query that opens candidates in Gnus." + (interactive) + (jao-notmuch-gnus--open-candidate (consult-notmuch--search))) + + (consult-customize jao-gnus-consult-notmuch :preview-key 'any)) diff --git a/custom/jao-custom-pdf.el b/custom/jao-custom-pdf.el index 50612bf..e82873f 100644 --- a/custom/jao-custom-pdf.el +++ b/custom/jao-custom-pdf.el @@ -1,6 +1,42 @@ ;; -*- lexical-binding: t -*- ;;;; open pdfs +(defun jao-find-or-open (file &optional page height) + (cond ((and jao-pdf-open-in-emacs window-system) + (let* ((buffs (buffer-list)) + (b (catch 'done + (while buffs + (when (string-equal (buffer-file-name (car buffs)) file) + (throw 'done (car buffs))) + (setq buffs (cdr buffs)))))) + (jao-afio-goto-docs) + (if b (pop-to-buffer b) (find-file file)) + (when page (jao-doc-view-goto-page page height)))) + (jao-river-enabled (jao-river-open-with-zathura file page)) + (jao-sway-enabled (jao-sway-open-with-zathura file page)) + ((eq system-type 'darwin) (jao-mac-open-in-skim file page)) + (t (jao-zathura-open file page)))) + +(defun jao-open-with-zathura () + (interactive) + (jao-when-linux + (when-let* ((f buffer-file-name)) + (let ((p (jao-doc-view-current-page))) + (cond (jao-river-enabled (jao-river-open-with-zathura f p)) + (jao-sway-enabled (jao-sway-open-with-zathura f p)) + (t (jao-zathura-open f p))))))) + +(defun jao-zathura-open (file page) + (jao-when-linux + (let ((id (jao-x11-search-window (jao-pdf-zathura-title-rx file)))) + (if (string-blank-p id) + (progn + (when jao-xmonad-enabled (jao-x11-goto-ws 2)) + (jao-shell-exec (jao-pdf-zathura-open-cmd file page))) + (let* ((page (if page (format " && xdotool type %dg" page) "")) + (cmd (format "xdotool windowactivate %s%s" id page))) + (jao-shell-exec cmd t)))))) + (use-package saveplace-pdf-view :ensure t :demand t @@ -8,9 +44,11 @@ (use-package jao-pdf :demand t + :after jao-custom-org :config (setq jao-open-doc-fun 'jao-find-or-open) - (setq jao-org-open-pdf-fun jao-open-doc-fun)) + (setq jao-org-open-pdf-fun jao-open-doc-fun) + (setq jao-pdf-org-dir jao-org-dir)) ;;;; doc-view (use-package doc-view diff --git a/init.el b/init.el index 6fc295a..2cebc20 100644 --- a/init.el +++ b/init.el @@ -91,9 +91,6 @@ (add-to-list 'load-path (expand-file-name "custom" jao-emacs-dir)) (add-to-list 'load-path "/usr/local/share/emacs/site-lisp/") -(setopt user-lisp-directory (expand-file-name "lib" jao-emacs-dir)) -(prepare-user-lisp) - (defvar jao-info-dir (expand-file-name "info" jao-doc-dir)) (require 'info) (add-to-list 'Info-directory-list jao-info-dir) @@ -426,15 +423,9 @@ (defun jao-colors-scheme () (if (jao-colors-scheme-dark-p) 'dark 'light)) -(customize-set-variable 'frame-background-mode (jao-colors-scheme)) - -(setq custom-theme-directory - (expand-file-name "lib/themes" jao-emacs-dir)) +(setopt frame-background-mode (jao-colors-scheme)) -(defvar jao-theme-dark 'jao-dark) -(defvar jao-theme-light 'jao-light) -(defvar jao-theme-term-dark 'modus-vivendi) -(defvar jao-theme-term-light 'jao-light-term) +(setopt custom-theme-directory (expand-file-name "themes" jao-emacs-dir)) (use-package jao-themes :demand t @@ -447,14 +438,14 @@ (defun jao-themes-setup () (let* ((dark (jao-colors-scheme-dark-p)) - (theme (cond ((and dark window-system) jao-theme-dark) - (dark jao-theme-term-dark) - (window-system jao-theme-light) - (t jao-theme-term-light)))) + (theme (cond ((and dark window-system) 'jao-dark) + (dark 'modus-vivendi) + (window-system 'jao-light) + (t 'jao-light-term)))) (load-theme theme t) (modify-all-frames-parameters `((font . ,jao-themes-default-face))))) -(jao-themes-setup) +(add-hook 'after-init-hook #'jao-themes-setup) ;;; Help system ;;;; which-key @@ -599,7 +590,8 @@ ;;;; jao-notify (use-package jao-notify :demand t - :init (setq jao-notify-use-messages (jao-d-l 'mac t))) + :init (setq jao-notify-use-messages (jao-d-l 'mac t) + jao-notify-audio-icon (jao-data-file "music-player-icon.png"))) ;;;; tracking (use-package tracking @@ -956,31 +948,7 @@ (require 'autorevert) (global-auto-revert-mode 1) -;;;; attached buffers -(defun jao-display-buffer-below-selected (buffer alist) - (delete-other-windows-vertically) - (display-buffer-below-selected buffer alist)) - -(defun jao-display-below-eldoc (buffer alist) - (let ((w (selected-window))) - (pop-to-buffer "*eldoc*" nil t) - (jao-display-buffer-below-selected buffer alist) - (select-window w t))) - -(defun jao-attached-buffer-entry (name-rx height) - `(,name-rx (display-buffer-reuse-window - jao-display-buffer-below-selected) - (window-height . ,(or height 25)))) - -(defmacro jao-with-attached-buffer (name-rx height &rest body) - (declare (indent defun)) - `(let ((display-buffer-alist '(,(jao-attached-buffer-entry name-rx height)))) - ,@body)) - -(defun jao-define-attached-buffer (name-rx &optional height) - (add-to-list 'display-buffer-alist - (jao-attached-buffer-entry name-rx height))) - +;;; attached buffers (use-package xref :config (jao-define-attached-buffer "^\\*xref\\*")) @@ -1285,18 +1253,20 @@ (add-hook 'text-mode-hook 'turn-on-auto-fill) ;;;; dictionaries -(use-package dictionary - :init (setq dictionary-use-single-buffer t - dictionary-server "localhost") - :commands (dictionary-search - dictionary-match-words - dictionary-lookup-definition - dictionary - dictionary-mouse-popup-matching-words - dictionary-popup-matching-words - dictionary-tooltip-mode - global-dictionary-tooltip-mode) - :bind (("C-c d" . dictionary-search))) +(jao-d-l + (global-set-key (kbd "C-c d") 'jao-mac-dict) + (use-package dictionary + :init (setq dictionary-use-single-buffer t + dictionary-server "localhost") + :commands (dictionary-search + dictionary-match-words + dictionary-lookup-definition + dictionary + dictionary-mouse-popup-matching-words + dictionary-popup-matching-words + dictionary-tooltip-mode + global-dictionary-tooltip-mode) + :bind (("C-c d" . dictionary-search)))) (use-package ispell :custom ((ispell-personal-dictionary @@ -1467,7 +1437,7 @@ (interactive "P") ,@prelude (let ((jao-use-vterm (if term (not jao-use-vterm) jao-use-vterm))) - (if-let ((b (jao-term--find ,cmd))) + (if-let* ((b (jao-term--find ,cmd))) (pop-to-buffer b) (jao-exec-in-term ,cmd ,(format "*%s*" name)))))) diff --git a/lib/doc/jao-doc-view.el b/lib/doc/jao-doc-view.el index 223984a..bb89f03 100644 --- a/lib/doc/jao-doc-view.el +++ b/lib/doc/jao-doc-view.el @@ -18,9 +18,15 @@ ;; Author: Jose Antonio Ortega Ruiz ;; Start date: Fri Feb 15, 2013 01:21 +(require 'browse-url) +(require 'thingatpt) (require 'doc-view) (require 'jao-pdf) +(declare-function pdf-view-image-size "pdf-view") +(declare-function pdf-view-goto-page "pdf-view") +(declare-function pdf-view-current-page "pdf-view") + ;;; Utilities (defmacro jao-doc-view--funcall (a b &rest args) @@ -39,8 +45,7 @@ ;;; imenu (defun jao-doc-view-enable-imenu (file-name goto-page) - (let ((ifun (lambda () (doc-view-imenu-index file-name goto-page))) - (doc-view-imenu-enabled t)) + (let ((ifun (lambda () (doc-view-imenu-index file-name goto-page)))) (doc-view-imenu-setup) (setq-local imenu-create-index-function ifun))) @@ -48,7 +53,7 @@ (defvar-local jao-doc-view--trail-back ()) (defvar-local jao-doc-view--trail-fwd ()) -(defun jao-doc-view--trail-push (dest-page) +(defun jao-doc-view--trail-push () (when-let* ((page (jao-doc-view-current-page))) (unless (eq (car jao-doc-view--trail-back) page) (push page jao-doc-view--trail-back)))) diff --git a/lib/doc/jao-mac.el b/lib/doc/jao-mac.el index 269e853..916a84d 100644 --- a/lib/doc/jao-mac.el +++ b/lib/doc/jao-mac.el @@ -18,6 +18,7 @@ ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . +(require 'thingatpt) (require 'jao-shell) ;;; applescript @@ -51,7 +52,9 @@ "Invoke open after formatting thing with args, using `format'" (jao-shell-exec (format "open %s" (apply #'format thing args)))) -(defun jao-mac-open-in-skim (&optional file page height) +(declare-function 'doc-view-current-page "doc-view") + +(defun jao-mac-open-in-skim (&optional file page _height) (interactive) (let* ((file (if file (expand-file-name file) (buffer-file-name))) (page (or page (and (derived-mode-p 'doc-view-mode) @@ -60,7 +63,7 @@ ;; https://alvinalexander.com/macos/applescript-how-to-open-pdf-file-in-preview-go-to-page/ ;; This will work as long as Preview is the default app for the file at hand. -(defun jao-mac-open-in-preview (&optional file page height) +(defun jao-mac-open-in-preview (&optional file page _height) (interactive) (let ((file (if file (expand-file-name file) (buffer-file-name))) (page (or page (and (derived-mode-p 'doc-view-doc) @@ -88,6 +91,21 @@ (when (string-match ".*=\"\\([0-9]+\\)\" ." s) (string-to-number (match-string 1 s)))) ) +;;; dict + +(defvar jao-mac-dict-history nil) + +(defun jao-mac-dict (&optional word) + (interactive (list (thing-at-point 'word))) + (jao-mac-open "dict://%S" + (read-string (format "Look up (%s): " word) + nil + 'jao-mac-dict-history + (substring-no-properties word) + t))) + +;;(setq completion-auto-help nil) + ;;; Skim (defvar jao-skim--current-file-script (jao-mac-applescript-prepare @@ -204,29 +222,28 @@ ;;; DevonThink -(defun jao-devon-tell (&rest script-lines) - (apply #'jao-mac-tell-app "id DNtp" script-lines )) - -(defun jao-devon-find-url (file) - (jao-devon-tell - "repeat with db in databases" - (format "set res to lookup records with path %S in db" - (file-truename file)) - "if res /= {} then return the reference URL of (item 1 of res)" - "end repeat" - "return \"\"")) - -(defun jao-devon-show-search (s) - (jao-devon-tell (format "show search %S" s) "activate")) - -(defun jao-devon-open (file &optional page height) - (let ((url (jao-devon-find-url file))) - (if (string-empty-p (or url "")) - (let ((jao-pdf-open-in-emacs t)) - (jao-find-or-open file page height)) - (let* ((p (if page (format "?page=%s" (- page 1)) "")) - (u (format "%s%s" url p))) - (jao-mac-open "%s%s" url p))))) +;; (defun jao-devon-tell (&rest script-lines) +;; (apply #'jao-mac-tell-app "id DNtp" script-lines )) + +;; (defun jao-devon-find-url (file) +;; (jao-devon-tell +;; "repeat with db in databases" +;; (format "set res to lookup records with path %S in db" +;; (file-truename file)) +;; "if res /= {} then return the reference URL of (item 1 of res)" +;; "end repeat" +;; "return \"\"")) + +;; (defun jao-devon-show-search (s) +;; (jao-devon-tell (format "show search %S" s) "activate")) + +;; (defun jao-devon-open (file &optional page height) +;; (let ((url (jao-devon-find-url file))) +;; (if (string-empty-p (or url "")) +;; (let ((jao-pdf-open-in-emacs t)) +;; (jao-find-or-open file page height)) +;; (let ((p (if page (format "?page=%s" (- page 1)) ""))) +;; (jao-mac-open "%s%s" url p))))) (provide 'jao-mac) ;;; jao-mac.el ends here diff --git a/lib/doc/jao-org-focus.el b/lib/doc/jao-org-focus.el index 2c0805d..a8d72be 100644 --- a/lib/doc/jao-org-focus.el +++ b/lib/doc/jao-org-focus.el @@ -77,7 +77,7 @@ When invoked on an indirect buffer, pops back to its base." (setq jao-org-focus--parent parent jao-org-focus--section title) (org-narrow-to-subtree) - (show-subtree) + (outline-show-subtree) (count-words (point-min) (point-max)))))) (defun jao-org-focus-redisplay () diff --git a/lib/doc/jao-org-links.el b/lib/doc/jao-org-links.el index 8ccd06a..b38deb0 100644 --- a/lib/doc/jao-org-links.el +++ b/lib/doc/jao-org-links.el @@ -1,9 +1,12 @@ ;; -*- lexical-binding: t; -*- +(require 'org) +(require 'browse-url) (require 'jao-org-notes) (require 'jao-doc-view) (require 'jao-doc-session) (require 'jao-pdf) +(require 'jao-afio) (defvar jao-org--sink-dir "./") (defvar jao-org-open-pdf-fun #'jao-org--default-open) @@ -46,7 +49,7 @@ (defun jao-org-links--complete-doc (&optional arg) (let ((default-directory jao-org--sink-dir)) (let ((f (replace-regexp-in-string "^file:" "doc:" - (org-file-complete-link arg)))) + (org-link-complete-file arg)))) (if (jao-pdf-is-pdf-file f) (let ((page (read-from-minibuffer "Page: " ""))) (if (> (string-to-number page) 0) diff --git a/lib/doc/jao-org-notes.el b/lib/doc/jao-org-notes.el index 78ff76c..929ab66 100644 --- a/lib/doc/jao-org-notes.el +++ b/lib/doc/jao-org-notes.el @@ -76,7 +76,7 @@ (and (string-match-p "^[^:]+ + :" m) "tags") "titles")) -(defun jao-org-notes--consult-rg (prompt &optional cat no-req cmd initial) +(defun jao-org-notes--consult-rg (prompt &optional cat no-req initial) (let ((default-directory (expand-file-name (or cat "") jao-org-notes-dir))) (consult--read (consult--async-pipeline @@ -102,7 +102,7 @@ (defun jao-org-notes--insert-title (&optional title) (let* ((cat (jao-org-notes--cat)) - (note (jao-org-notes--consult-rg "Title: " cat t nil title)) + (note (jao-org-notes--consult-rg "Title: " cat t title)) (title (file-name-base note)) (title (replace-regexp-in-string "^#" "" title))) (when (not (string-empty-p title)) diff --git a/lib/doc/jao-pdf.el b/lib/doc/jao-pdf.el index 5d27048..0a1734f 100644 --- a/lib/doc/jao-pdf.el +++ b/lib/doc/jao-pdf.el @@ -1,6 +1,6 @@ ;;; jao-pdf.el --- utilities for pdf files -*- lexical-binding: t; -*- -;; Copyright (C) 2022, 2025 jao +;; Copyright (C) 2022, 2025, 2026 jao ;; Author: jao ;; Keywords: docs @@ -27,10 +27,13 @@ ;; - Interoperability with zathura. (require 'jao-doc-session) +(require 'jao-afio) +(require 'browse-url) ;;; PDF info (declare-function 'pdf-info-outline "pdf-info") +(defvar jao-pdf-org-dir nil) (defvar-local jao-pdf--outline nil) @@ -56,7 +59,7 @@ (setq-local jao-pdf--outline (doc-view--pdf-outline file-name))) (let ((page (or page (and (derived-mode-p 'doc-view-mode) (doc-view-current-page)) - (and (derived-mode-p 'pdf-view) (pdf-view-current-page)))) + (and (fboundp 'pdf-view-current-page) (pdf-view-current-page)))) (outline jao-pdf--outline) (cur-page 0) (cur-title (jao-pdf-title (or file-name buffer-file-name "title")))) @@ -91,21 +94,11 @@ (fn (file-name-nondirectory file)) (lnk (format "doc:%s::%s" fn page)) (desc (format "%s (p. %s)" (jao-pdf-section-title page file) no))) - (org-make-link-string lnk desc))) + (org-link-make-string lnk desc))) (defun jao-pdf-zathura-org-link (title) (jao-pdf--zathura-link (jao-pdf-zathura-file-info title))) -(defun jao-zathura-open (file page) - (let ((id (jao-x11-search-window (jao-pdf-zathura-title-rx file)))) - (if (string-blank-p id) - (progn - (when jao-xmonad-enabled (jao-x11-goto-ws 2)) - (jao-shell-exec (jao-pdf-zathura-open-cmd file page))) - (let* ((page (if page (format " && xdotool type %dg" page) "")) - (cmd (format "xdotool windowactivate %s%s" id page))) - (jao-shell-exec cmd t))))) - ;;; Mac (when (eq system-type 'darwin) @@ -115,7 +108,7 @@ (file (file-name-nondirectory (car fp))) (page (cadr fp)) (lnk (format "doc:%s::%s" file page))) - (org-make-link-string lnk title))) + (org-link-make-string lnk title))) (defun jao-pdf-insert-skim-org-link () (interactive) @@ -127,27 +120,11 @@ ;;; Open doc functions (defvar jao-pdf-open-in-emacs t) -(defun jao-find-or-open (file &optional page height) - (cond ((and jao-pdf-open-in-emacs window-system) - (let* ((buffs (buffer-list)) - (b (catch 'done - (while buffs - (when (string-equal (buffer-file-name (car buffs)) file) - (throw 'done (car buffs))) - (setq buffs (cdr buffs)))))) - (jao-afio-goto-docs) - (if b (pop-to-buffer b) (find-file file)) - (when page (jao-doc-view-goto-page page height)))) - (jao-river-enabled (jao-river-open-with-zathura file page)) - (jao-sway-enabled (jao-sway-open-with-zathura file page)) - ((eq system-type 'darwin) (jao-mac-open-in-skim file page)) - (t (jao-zathura-open file page)))) - (defun jao-open-doc (&optional file page height) (interactive) (when-let* ((file (or file (read-file-name "Document: " - (concat jao-org-dir "/doc/"))))) + (concat jao-pdf-org-dir "/doc/"))))) (funcall jao-open-doc-fun file page height))) (defun jao-select-pdf () @@ -155,14 +132,6 @@ (jao-buffer-same-mode '(pdf-view-mode doc-view-mode org-mode) #'jao-afio-goto-docs)) -(defun jao-open-with-zathura () - (interactive) - (when-let* ((f buffer-file-name)) - (let ((p (jao-doc-view-current-page))) - (cond (jao-river-enabled (jao-river-open-with-zathura f p)) - (jao-sway-enabled (jao-sway-open-with-zathura f p)) - (t (jao-zathura-open f p)))))) - ;;; doc:// links for browse-url (defun jao-open-doc-url (url &rest _) diff --git a/lib/doc/jao-words.el b/lib/doc/jao-words.el index 32baab8..328fecf 100644 --- a/lib/doc/jao-words.el +++ b/lib/doc/jao-words.el @@ -67,7 +67,7 @@ (org-mode) (indent-region (point-min) (point-max)) (goto-char 5) - (next-line 2) + (forward-line 2) (org-table-next-field) (org-table-sort-lines nil ?N))) (pop-to-buffer "*word-statistics*")) diff --git a/lib/eos/jao-afio.el b/lib/eos/jao-afio.el index 525cf60..9e402a2 100644 --- a/lib/eos/jao-afio.el +++ b/lib/eos/jao-afio.el @@ -73,7 +73,7 @@ (assoc 'def jao-afio-frame-parameters))))) (modify-frame-parameters nil params))))) -(defun jao-afio--init (&optional f) +(defun jao-afio--init (&optional _f) (interactive) (jao-afio--current-config ?c) (if jao-afio-use-frames @@ -168,7 +168,8 @@ (find-file (expand-file-name "inbox.org" org-directory)) (delete-other-windows) (gnus) - (jao-gnus--set-summary-line)) + ;; (jao-gnus--set-summary-line) + ) (defun jao-afio--mail-sidebar () (other-window 1) diff --git a/lib/eos/jao-buffers.el b/lib/eos/jao-buffers.el new file mode 100644 index 0000000..5a41486 --- /dev/null +++ b/lib/eos/jao-buffers.el @@ -0,0 +1,57 @@ +;;; jao-buffers.el --- utilities to deal with buffers and windows -*- lexical-binding: t; -*- + +;; Copyright (C) 2026 Jose Antonio Ortega Ruiz + +;; Author: Jose Antonio Ortega Ruiz +;; Keywords: files + +;; 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 . + +;;; Commentary: + +;; + +;;; Code: + +;;;; attached buffers +(defun jao-display-buffer-below-selected (buffer alist) + (delete-other-windows-vertically) + (display-buffer-below-selected buffer alist)) + +(defun jao-display-below-eldoc (buffer alist) + (let ((w (selected-window))) + (pop-to-buffer "*eldoc*" nil t) + (jao-display-buffer-below-selected buffer alist) + (select-window w t))) + +(defun jao-attached-buffer-entry (name-rx height) + `(,name-rx (display-buffer-reuse-window + jao-display-buffer-below-selected) + (window-height . ,(or height 25)))) + +;;;###autoload +(defmacro jao-with-attached-buffer (name-rx height &rest body) + (declare (indent defun)) + `(let ((display-buffer-alist '(,(jao-attached-buffer-entry name-rx height)))) + ,@body)) + +;;;###autoload +(defun jao-define-attached-buffer (name-rx &optional height) + (add-to-list 'display-buffer-alist + (jao-attached-buffer-entry name-rx height))) + + + +(provide 'jao-buffers) +;;; jao-buffers.el ends here diff --git a/lib/eos/jao-dirmon.el b/lib/eos/jao-dirmon.el index 6a897d3..261433d 100644 --- a/lib/eos/jao-dirmon.el +++ b/lib/eos/jao-dirmon.el @@ -1,6 +1,6 @@ ;;; jao-dirmon.el --- little utility to monitor disk usage -*- lexical-binding: t; -*- -;; Copyright (C) 2022, 2024, 2025 jao +;; Copyright (C) 2022, 2024, 2025, 2026 jao ;; Author: jao ;; Keywords: tools @@ -50,7 +50,7 @@ (defun jao-dirmon--show-deltas (old current deltas) (with-current-buffer (get-buffer-create jao-dirmon-buffer) - (view-mode-disable) + (view-mode -1) (delete-region (point-min) (point-max)) (insert "High deltas since " (car old) "\n\n") (dolist (d (seq-sort-by #'cdr #'> deltas)) @@ -60,8 +60,8 @@ (dolist (c (seq-take-while (lambda (x) (> (cdr x) threshold)) (seq-sort-by #'cdr #'> current))) (insert (format "- %s: %s Mb\n" (car c) (cdr c))))) - (beginning-of-buffer) - (view-mode-enable) + (goto-char (point-min)) + (view-mode 1) (pop-to-buffer (current-buffer) nil t) (when (y-or-n-p "Save current state?") (setf (multisession-value jao-dirmon-last) diff --git a/lib/eos/jao-eshell-here.el b/lib/eos/jao-eshell-here.el index 870e639..8733cb9 100644 --- a/lib/eos/jao-eshell-here.el +++ b/lib/eos/jao-eshell-here.el @@ -1,6 +1,6 @@ ;;; jao-eshell-here.el --- Easy opening of eshell buffers -*- lexical-binding: t; -*- -;; Copyright (C) 2021, 2023 jao +;; Copyright (C) 2021, 2023, 2026 jao ;; Author: jao ;; Keywords: eshell @@ -25,6 +25,11 @@ ;;; Code: (require 'eshell) +(require 'esh-mode) +(require 'em-dirs) +(require 'jao-buffers) +(require 'project) + (defvar jao-eshell-here-display-buffer-alist '(("^\\*eshell" diff --git a/lib/eos/jao-multisession.el b/lib/eos/jao-multisession.el deleted file mode 100644 index 5583fb6..0000000 --- a/lib/eos/jao-multisession.el +++ /dev/null @@ -1,341 +0,0 @@ -;;; multisession.el --- Multisession storage for variables -*- lexical-binding: t; -*- - -;; Copyright (C) 2021-2026 Free Software Foundation, Inc. - -;; This file is part of GNU Emacs. - -;; GNU Emacs 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. - -;; GNU Emacs 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 GNU Emacs. If not, see . - -;;; Commentary: - -;; This library provides multisession variables for Emacs Lisp, to -;; make them persist between sessions. -;; -;; Use `define-multisession-variable' to define a multisession -;; variable, and `multisession-value' to read its value. Use -;; `list-multisession-values' to list multisession variables. -;; -;; Users might want to customize `multisession-storage' and -;; `multisession-directory'. -;; -;; See Info node `(elisp) Multisession Variables' for more -;; information. - -;;; Code: - -(require 'cl-lib) -(require 'eieio) -(require 'tabulated-list) - -(defcustom multisession-storage 'files - "Storage method for multisession variables. -Valid methods are `sqlite' and `files'." - :type '(choice (const :tag "SQLite" sqlite) - (const :tag "Files" files)) - :version "29.1" - :group 'files) - -(defcustom multisession-directory (expand-file-name "multisession/" - user-emacs-directory) - "Directory to store multisession variables." - :type 'file - :version "29.1" - :group 'files) - -;;;###autoload -(defmacro define-multisession-variable (name initial-value &optional doc - &rest args) - "Make NAME into a multisession variable initialized from INITIAL-VALUE. -DOC should be a doc string, and ARGS are keywords as applicable to -`make-multisession'." - (declare (indent defun)) - (unless (plist-get args :package) - (setq args (nconc (list :package - (replace-regexp-in-string "-.*" "" - (symbol-name name))) - args))) - `(defvar ,name - (make-multisession :key ,(symbol-name name) - :initial-value ,initial-value - ,@args) - ,@(list doc))) - -(defconst multisession--unbound (make-symbol "unbound")) - -(cl-defstruct (multisession - (:constructor nil) - (:constructor multisession--create) - (:conc-name multisession--)) - "A persistent variable that will live across Emacs invocations." - key - (initial-value nil) - package - (storage multisession-storage) - (synchronized nil) - (cached-value multisession--unbound) - (cached-sequence 0)) - -(cl-defun make-multisession (&key key initial-value package synchronized - storage) - "Create a multisession object." - (unless package - (error "No package for the multisession object")) - (unless key - (error "No key for the multisession object")) - (unless (stringp package) - (error "The package has to be a string")) - (unless (stringp key) - (error "The key has to be a string")) - (multisession--create - :key key - :synchronized synchronized - :initial-value initial-value - :package package - :storage (or storage multisession-storage))) - -(defun multisession-value (object) - "Return the value of the multisession OBJECT." - (if (null user-init-file) - ;; If we don't have storage, then just return the value from the - ;; object. - (if (eq (multisession--cached-value object) multisession--unbound) - (multisession--initial-value object) - (multisession--cached-value object)) - ;; We have storage, so we update from storage. - (multisession-backend-value (multisession--storage object) object))) - -(defun multisession--set-value (object value) - "Set the stored value of OBJECT to VALUE." - (if (null user-init-file) - ;; We have no backend, so just store the value. - (setf (multisession--cached-value object) value) - ;; We have a backend. - (multisession--backend-set-value (multisession--storage object) - object value))) - -(defun multisession-delete (object) - "Delete OBJECT from the backend storage." - (multisession--backend-delete (multisession--storage object) object)) - -(gv-define-simple-setter multisession-value multisession--set-value) - -;; Files Backend - -(defun multisession--encode-file-name (name) - (url-hexify-string name)) - -(defun multisession--read-file-value (file object) - (catch 'done - (let ((i 0) - last-error) - (while (< i 10) - (condition-case err - (throw 'done - (with-temp-buffer - (let* ((time (file-attribute-modification-time - (file-attributes file))) - (coding-system-for-read 'utf-8-emacs-unix)) - (insert-file-contents file) - (let ((stored (read (current-buffer)))) - (setf (multisession--cached-value object) stored - (multisession--cached-sequence object) time) - stored)))) - ;; Windows uses OS-level file locking that may preclude - ;; reading the file in some circumstances. In addition, - ;; rename-file is not an atomic operation on MS-Windows, - ;; when the target file already exists, so there could be a - ;; small race window when the file to read doesn't yet - ;; exist. So when these problems happen, wait a bit and retry. - ((permission-denied file-missing) - (setq i (1+ i) - last-error err) - (sleep-for (+ 0.1 (/ (float (random 10)) 10)))))) - (signal (car last-error) (cdr last-error))))) - -(defun multisession--object-file-name (object) - (expand-file-name - (concat "files/" - (multisession--encode-file-name (multisession--package object)) - "/" - (multisession--encode-file-name (multisession--key object)) - ".value") - multisession-directory)) - -(cl-defmethod multisession-backend-value ((_type (eql 'files)) object) - (let ((file (multisession--object-file-name object))) - (cond - ;; We have no value yet; see whether it's stored. - ((eq (multisession--cached-value object) multisession--unbound) - (if (file-exists-p file) - (multisession--read-file-value file object) - ;; Nope; return the initial value. - (multisession--initial-value object))) - ;; We have a value, but we want to update in case some other - ;; Emacs instance has updated. - ((multisession--synchronized object) - (if (and (file-exists-p file) - (time-less-p (multisession--cached-sequence object) - (file-attribute-modification-time - (file-attributes file)))) - (multisession--read-file-value file object) - ;; Nothing, return the cached value. - (multisession--cached-value object))) - ;; Just return the cached value. - (t - (multisession--cached-value object))))) - -(cl-defmethod multisession--backend-set-value ((_type (eql 'files)) - object value) - (let ((file (multisession--object-file-name object)) - (time (current-time))) - ;; Ensure that the directory exists. - (let ((dir (file-name-directory file))) - (unless (file-exists-p dir) - (make-directory dir t))) - (with-temp-buffer - (let ((print-length nil) - (print-circle t) - (print-level nil)) - (prin1 value (current-buffer))) - (goto-char (point-min)) - (condition-case nil - (read (current-buffer)) - (error (error "Unable to store unreadable value: %s" (buffer-string)))) - ;; Write to a temp file in the same directory and rename to the - ;; file for somewhat better atomicity. - (let ((coding-system-for-write 'utf-8-emacs-unix) - (create-lockfiles nil) - (temp (make-temp-name file)) - (write-region-inhibit-fsync nil)) - (write-region (point-min) (point-max) temp nil 'silent) - (set-file-times temp time) - (rename-file temp file t))) - (setf (multisession--cached-sequence object) time - (multisession--cached-value object) value))) - -(cl-defmethod multisession--backend-values ((_type (eql 'files))) - (mapcar (lambda (file) - (let ((bits (file-name-split file))) - (list (url-unhex-string (car (last bits 2))) - (url-unhex-string - (file-name-sans-extension (car (last bits)))) - (with-temp-buffer - (let ((coding-system-for-read 'utf-8-emacs-unix)) - (insert-file-contents file) - (read (current-buffer))))))) - (directory-files-recursively - (expand-file-name "files" multisession-directory) - "\\.value\\'"))) - -(cl-defmethod multisession--backend-delete ((_type (eql 'files)) object) - (let ((file (multisession--object-file-name object))) - (when (file-exists-p file) - (delete-file file)))) - -;; Mode for editing. - -(defvar-keymap multisession-edit-mode-map - :parent tabulated-list-mode-map - "d" #'multisession-delete-value - "e" #'multisession-edit-value) - -(define-derived-mode multisession-edit-mode special-mode "Multisession" - "This mode lists all elements in the \"multisession\" database." - :interactive nil - (buffer-disable-undo) - (setq-local buffer-read-only t - truncate-lines t) - (setq tabulated-list-format - [("Package" 10) - ("Key" 30) - ("Value" 30)]) - (setq-local revert-buffer-function #'multisession-edit-mode--revert)) - -;;;###autoload -(defun list-multisession-values (&optional choose-storage) - "List all values in the \"multisession\" database. -If CHOOSE-STORAGE (interactively, the prefix), query for the -storage method to list." - (interactive "P") - (let ((storage - (if choose-storage - (intern (completing-read "Storage method: " '(sqlite files) nil t)) - multisession-storage))) - (pop-to-buffer (get-buffer-create (format "*Multisession %s*" storage))) - (multisession-edit-mode) - (setq-local multisession-storage storage) - (multisession-edit-mode--revert) - (goto-char (point-min)))) - -(defun multisession-edit-mode--revert (&rest _) - (let ((inhibit-read-only t) - (id (get-text-property (point) 'tabulated-list-id))) - (erase-buffer) - (tabulated-list-init-header) - (setq tabulated-list-entries - (mapcar (lambda (elem) - (list - (cons (car elem) (cadr elem)) - (vector (car elem) (cadr elem) - (string-replace "\n" "\\n" - (format "%s" (caddr elem)))))) - (multisession--backend-values multisession-storage))) - (tabulated-list-print t) - (goto-char (point-min)) - (when id - (when-let* ((match - (text-property-search-forward 'tabulated-list-id id t))) - (goto-char (prop-match-beginning match)))))) - -(defun multisession-delete-value (id) - "Delete the value at point." - (interactive (list (get-text-property (point) 'tabulated-list-id)) - multisession-edit-mode) - (unless id - (error "No value on the current line")) - (unless (yes-or-no-p "Really delete this item? ") - (user-error "Not deleting")) - (multisession--backend-delete multisession-storage - (make-multisession :package (car id) - :key (cdr id))) - (let ((inhibit-read-only t)) - (beginning-of-line) - (delete-region (point) (progn (forward-line 1) (point))))) - -(defun multisession-edit-value (id) - "Edit the value at point." - (interactive (list (get-text-property (point) 'tabulated-list-id)) - multisession-edit-mode) - (unless id - (error "No value on the current line")) - (let* ((object (or - ;; If the multisession variable already exists, use - ;; it (so that we update it). - (if-let (sym (intern-soft (cdr id))) - (and (boundp sym) (symbol-value sym)) - nil) - ;; Create a new object. - (make-multisession - :package (car id) - :key (cdr id) - :storage multisession-storage))) - (value (multisession-value object))) - (setf (multisession-value object) - (car (read-from-string - (read-string "New value: " (prin1-to-string value)))))) - (multisession-edit-mode--revert)) - -(provide 'jao-multisession) - -;;; multisession.el ends here diff --git a/lib/eos/jao-notify.el b/lib/eos/jao-notify.el index 941be36..c1efb58 100644 --- a/lib/eos/jao-notify.el +++ b/lib/eos/jao-notify.el @@ -14,7 +14,7 @@ (defvar jao-notify-use-messages nil) (defvar jao-notify-timeout 5000) -(defvar jao-notify-audio-icon (jao-data-file "music-player-icon.png")) +(defvar jao-notify-audio-icon nil) (declare-function notifications-notify "notifications") (declare-function alert "alert") diff --git a/lib/eos/jao-r2e.el b/lib/eos/jao-r2e.el deleted file mode 100644 index 81bbed6..0000000 --- a/lib/eos/jao-r2e.el +++ /dev/null @@ -1,233 +0,0 @@ -;;; jao-r2e.el --- List of rss2email subscriptions -*- lexical-binding: t; -*- - -;; Copyright (C) 2025, 2026 Jose Antonio Ortega Ruiz - -;; Author: Jose Antonio Ortega Ruiz -;; 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 . - -(require 'multisession) -(require 'jao-url) - -(autoload 'View-quit "view") -(autoload 'eww-view-source "eww") -(autoload 'jao-notmuch-subtags "jao-notmuch") - -(defvar jao-r2e-command "r2e") -(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) - (define-key map [?y] 'jao-r2e-kill-url) - (define-key map [?x] 'jao-r2e-list-subscribed) - 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 "%s %s" jao-r2e-command 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-list-subscribed (arg) - "Show only subscribed (unsubscribed with arg) feeds." - (interactive "P") - (jao-r2e-list) - (let ((inhibit-read-only t)) - (flush-lines (if arg ".*\\[\\*\\].*" ".*\\[ \\].*")))) - -(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-kill-url () - "Copy as kill the URL of the feed at point." - (interactive) - (let ((url (cadddr (jao-r2e--feed-at-point)))) - (if (not url) - (error "No feed at point") - (kill-new url) - (message "%s" url)))) - -(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))))) - -(define-multisession-variable jao-r2e-deleted-feeds '() - "List of rss2email feeds deleted at some point.") - -(defun jao-r2e--deleted () (multisession-value jao-r2e-deleted-feeds)) - -(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)) - (entry (cdr f))) - (when (yes-or-no-p (format "Delete feed '%s'" (car entry))) - (setf (multisession-value jao-r2e-deleted-feeds) - (cons entry (remove entry (jao-r2e--deleted)))) - (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)) - (error "No feeds recoverable at this point.")) - (let* ((entries (jao-r2e--deleted)) - (feed (completing-read "Recover feed: " entries))) - (when-let* ((ps (assoc feed entries)) - (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) - (setf (multisession-value jao-r2e-deleted-feeds) (remove ps entries))))) - -(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)) - (sfmt (format "%%s add %s '%s' mail+feeds_%s@jao.io" name url cat)) - (subs )) - (with-temp-message "Subscribing..." - (shell-command-to-string (format sfmt "r2e")) - (when (not (string= jao-r2e-command "r2e")) - (shell-command-to-string (format sfmt jao-r2e-command)))) - (when (y-or-n-p "Retrieve feeds now? ") - (with-temp-message "Retrieving feed..." - (shell-command (format "%s run %s" jao-r2e-command name)))) - (when relist (jao-r2e-list))))))) - -(provide 'jao-r2e) -;;; jao-r2e.el ends here diff --git a/lib/eos/jao-shell.el b/lib/eos/jao-shell.el index 86bf46b..e13e07f 100644 --- a/lib/eos/jao-shell.el +++ b/lib/eos/jao-shell.el @@ -1,6 +1,6 @@ ;;; jao-shell.el --- shell utils -*- lexical-binding: t; -*- -;; Copyright (C) 2022 jao +;; Copyright (C) 2022, 2026 jao ;; Author: jao ;; Keywords: shell @@ -59,7 +59,7 @@ (defun jao-shell-output (cmd handler) (with-temp-buffer (call-process-shell-command cmd nil (current-buffer)) - (beginning-of-buffer) + (goto-char (point-min)) (funcall handler))) (defun jao-shell-running-p (pr) (eq 0 (jao-shell-exec* t "pidof" pr))) diff --git a/lib/eos/jao-sleep.el b/lib/eos/jao-sleep.el index b047373..3b46031 100644 --- a/lib/eos/jao-sleep.el +++ b/lib/eos/jao-sleep.el @@ -1,6 +1,6 @@ ;;; jao-sleep.el --- Actions upon sleep/awake -*- lexical-binding: t; -*- -;; Copyright (C) 2020 jao +;; Copyright (C) 2020, 2026 jao ;; Author: jao ;; Keywords: hardware @@ -25,7 +25,7 @@ (defvar jao-sleep-sleep-functions nil) (defvar jao-sleep-awake-functions nil) -(defvar jao-sleep--dbus-registration-object nil) +(defvar jao-sleep--dbus-sleep-registration-object nil) (defun jao-sleep--dbus-sleep-handler (sleep-start) (condition-case nil diff --git a/lib/eos/jao-tracking.el b/lib/eos/jao-tracking.el index 280e9fb..6ee04bd 100644 --- a/lib/eos/jao-tracking.el +++ b/lib/eos/jao-tracking.el @@ -87,11 +87,11 @@ (defvar jao-tracking--pipe (let ((name "/tmp/emacs.status")) (unless (file-exists-p name) - (shell-command (format "mkfifo %s" name name))) + (shell-command (format "mkfifo %s" name))) name)) (defun jao-tracking-set-log (v) - (when (member window-system '(x)) + (when (fboundp 'x-change-window-property) (x-change-window-property "_EMACS_LOG" v nil nil nil nil 0)) (if jao-wayland-enabled (let ((inhibit-message t)) diff --git a/lib/eos/jao-wayland.el b/lib/eos/jao-wayland.el index 9458ccb..e743eb0 100644 --- a/lib/eos/jao-wayland.el +++ b/lib/eos/jao-wayland.el @@ -18,6 +18,7 @@ ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . +(require 'browse-url) (require 'jao-shell) (require 'jao-pdf) (require 'jao-tracking) diff --git a/lib/jao-recoll.el b/lib/jao-recoll.el deleted file mode 100644 index 364dfb5..0000000 --- a/lib/jao-recoll.el +++ /dev/null @@ -1,76 +0,0 @@ -;;; jao-recoll.el --- Utilities to use recoll -*- lexical-binding: t; -*- - -;; Copyright (C) 2025 Jose Antonio Ortega Ruiz - -;; Author: Jose Antonio Ortega Ruiz -;; Keywords: mail, text - -;; 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 . - -;;; Commentary: - -;; Notably, a half-backed backend for Gnus - -;;; Code: - -(require 'gnus-search) - -(defclass gnus-search-recoll (gnus-search-indexed) - ((separator :type string :initform ".") - (program :initform "recoll") - (raw-queries-p :initform t))) - -(cl-defmethod gnus-search-indexed-extract ((_engine gnus-search-recoll)) - (prog1 (and (looking-at "^file://\\(.+\\)$") (list (match-string 1) 100)) - (forward-line 1))) - -(cl-defmethod gnus-search-transform-expression ((_engine gnus-search-recoll) - expr) - expr) - -(cl-defmethod gnus-search-indexed-search-command ((engine gnus-search-recoll) - (qstring string) - query - &optional groups) - (let* ((subdir (slot-value engine 'remove-prefix)) - (sep (slot-value engine 'separator)) - (gdirs (mapcar (lambda (g) - (let ((g (gnus-group-short-name g))) - (replace-regexp-in-string "\\." sep g))) - (or groups - (and (not (string= "" subdir)) (list subdir))))) - (dirsq (and gdirs - (concat "(" - (mapconcat (lambda (d) (format "dir:%s" d)) - gdirs " OR ") - ")"))) - (qstring (if (string-prefix-p "id:" qstring) - (replace-regexp-in-string "<\\|>" "\"" qstring) - qstring)) - (qstring (if (cdr (assoc 'thread query)) - (concat qstring " OR " - (replace-regexp-in-string "id:\"" "ref:\"" - qstring)) - qstring)) - (qstring (replace-regexp-in-string " or " " OR " qstring)) - (qstring (replace-regexp-in-string " and " " AND " qstring)) - (q (format "mime:message %s (%s)" dirsq qstring))) - ;; (message "query is: %s -- %S" q query) - `("-b" "-t" "-q" ,q))) - -(defun jao-recoll-gnus-search-engine (dir) - `(nnml "" (gnus-search-engine gnus-search-recoll (remove-prefix ,dir)))) - -(provide 'jao-recoll) -;;; jao-recoll.el ends here diff --git a/lib/media/jao-lyrics.el b/lib/media/jao-lyrics.el index f7b47ca..c00a913 100644 --- a/lib/media/jao-lyrics.el +++ b/lib/media/jao-lyrics.el @@ -99,8 +99,13 @@ "^\\(CreditsWritten by:\\|External linksNominate\\)" nil t) (beginning-of-line) (kill-region (point) (point-max))) - (replace-string " " "" nil (point-min) (point-max)) - (replace-string "\\'" "'" nil (point-min) (point-max)) + (goto-char (point-min)) + (save-excursion + (while (search-forward " " nil t) + (replace-match ""))) + (save-excursion + (while (search-forward "\\'" nil t) + (replace-match "'"))) (save-buffer))) (defun jao-lyrics--download (artist title &optional noartist) @@ -115,7 +120,7 @@ (jao-lyrics--clean-download fn) (prog1 (jao-lyrics--get-cached artist title) (message nil)))) -(defvar jao-lyrics-info-function) +(defvar jao-lyrics-info-function nil) (defvar-local jao-lyrics--info-function nil) ;;;###autoload diff --git a/lib/media/jao-mpc.el b/lib/media/jao-mpc.el index 43046b4..cb47f17 100644 --- a/lib/media/jao-mpc.el +++ b/lib/media/jao-mpc.el @@ -31,6 +31,7 @@ (require 'jao-lyrics) (require 'jao-random-album) (require 'jao-notify) +(require 'jao-minibuffer) (defconst jao-mpc--albums "*MPC Albums*") (defconst jao-mpc--playlist "*MPC Playlist*") @@ -259,12 +260,12 @@ (message "%s" (jao-mpc--current-str port t))) ;;;###autoload -(defun jao-mpc-echo-current-times (&optional port) +(defun jao-mpc-echo-current-times (&optional _port) (interactive) (message "Playing time: %s" (jao-mpc--current-timestr t))) ;;;###autoload -(defun jao-mpc-notify (&optional port) +(defun jao-mpc-notify (&optional _port) (interactive) (when-let* ((current (jao-mpc--current))) (let* ((artist (or (alist-get 'artist current) "Anonymous")) diff --git a/lib/media/jao-mpris.el b/lib/media/jao-mpris.el index 7331cf3..c120ae3 100644 --- a/lib/media/jao-mpris.el +++ b/lib/media/jao-mpris.el @@ -51,10 +51,9 @@ (interactive "p") (jao-mpris-seek (- secs))) -(defun jao-mpris-vol (n) +(defun jao-mpris-vol (vol) (interactive "p") - (let ((secs (if (zerop n) 10 n))) - (jao-mpris--playerctl "volume" (format "%d" n)))) + (jao-mpris--playerctl "volume" (format "%d" (if (zerop vol) 10 vol)))) (defun jao-mpris-vol-down (n) (interactive "p") @@ -146,9 +145,10 @@ (interactive "P") (when refresh (jao-mpris--track)) (when jao-mpris--current - (jao-notify (format "%s%s" (if-let (s (jao-mpris--get 'status)) - (format "%s: " s) - "") + (jao-notify (format "%s%s" + (if-let* ((s (jao-mpris--get 'status))) + (format "%s: " s) + "") (jao-mpris--format))))) (defun jao-mpris-minibuffer-order (order) diff --git a/lib/media/jao-random-album.el b/lib/media/jao-random-album.el index 07d04e8..540f6a6 100644 --- a/lib/media/jao-random-album.el +++ b/lib/media/jao-random-album.el @@ -28,9 +28,10 @@ (defun jao-random-album--buffer-lines () (let ((lines nil)) - (dotimes (n (1- (line-number-at-pos (point-max))) lines) + (dotimes (n (1- (line-number-at-pos (point-max)))) (when (> n jao-random-album-skip-lines) - (push (1+ n) lines))))) + (push (1+ n) lines))) + lines)) (defun jao-random-lines () (or (multisession-value jao-random-lines) diff --git a/lib/net/jao-eww-session.el b/lib/net/jao-eww-session.el index adbe98f..76da717 100644 --- a/lib/net/jao-eww-session.el +++ b/lib/net/jao-eww-session.el @@ -68,7 +68,7 @@ (car (or s (jao-eww-session--current)))) (defun jao-eww-session-titles (&optional s) - (let ((s (or s jao-eww-current-session))) + (let ((s (or s (jao-eww-session--current)))) (mapcar 'cdr (cadr s)))) (defun jao-eww-session--update () diff --git a/lib/net/jao-notmuch-gnus.el b/lib/net/jao-notmuch-gnus.el index 9a17841..9b408c2 100644 --- a/lib/net/jao-notmuch-gnus.el +++ b/lib/net/jao-notmuch-gnus.el @@ -237,21 +237,6 @@ Example: (org-link-set-parameters "gnus" :store #'ignore) (org-link-set-parameters "notmuch" :store #'ignore) -;;; consult-notmuch - -(with-eval-after-load "consult-notmuch" - (defun jao-notmuch-gnus--open-candidate (candidate) - "Open a notmuch-search completion candidate email in Gnus." - (message "candidate: %S" candidate) - (jao-notmuch-gnus-goto-message (consult-notmuch--candidate-id candidate))) - - (defun jao-gnus-consult-notmuch () - "Run a consult-notmuch query that opens candidates in Gnus." - (interactive) - (jao-notmuch-gnus--open-candidate (consult-notmuch--search))) - - (consult-customize jao-gnus-consult-notmuch :preview-key 'any)) - ;;; tags and flags (defun jao-notmuch-gnus-flag-current (&rest _) diff --git a/lib/net/jao-notmuch.el b/lib/net/jao-notmuch.el index 625c8e6..40db88d 100644 --- a/lib/net/jao-notmuch.el +++ b/lib/net/jao-notmuch.el @@ -34,7 +34,7 @@ ;;; targetting the displayed message from the tree view (defvar-local jao-notmuch--tree-buffer nil) -(declare eww--url-at-point "eww") +(declare-function eww--url-at-point "eww") (defun jao-notmuch-goto-message-buffer (&optional and-click no-record) (interactive "P") diff --git a/lib/net/jao-proton-utils.el b/lib/net/jao-proton-utils.el index 0a08f5d..a8f13eb 100644 --- a/lib/net/jao-proton-utils.el +++ b/lib/net/jao-proton-utils.el @@ -1,4 +1,4 @@ -;; jao-proton-utils.el -- simple interaction with Proton mail and vpn +;; jao-proton-utils.el -- simple interaction with Proton mail and vpn -*- lexical-binding: t; -*- ;; Copyright (c) 2018, 2019, 2020, 2023, 2026 Jose Antonio Ortega Ruiz @@ -54,6 +54,22 @@ (defvar jao-proton-vpn-font-lock-keywords '("\\[.+\\]")) +(defvar proton-vpn-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 [?g] 'proton-vpn-status) + (define-key map [?r] 'proton-vpn-reconnect) + (define-key map [?d] (lambda () + (interactive) + (when (y-or-n-p "Disconnect?") + (proton-vpn-disconnect)))) + (define-key map [?c] 'proton-vpn-connect) + map)) + + ;;;###autoload (defun proton-vpn-mode () "A very simple mode to show the output of ProtonVPN commands" @@ -121,21 +137,5 @@ (interactive) (jao-proton-vpn--do "d")) -(setq proton-vpn-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 [?g] 'proton-vpn-status) - (define-key map [?r] 'proton-vpn-reconnect) - (define-key map [?d] (lambda () - (interactive) - (when (y-or-n-p "Disconnect?") - (proton-vpn-disconnect)))) - (define-key map [?c] 'proton-vpn-connect) - map)) - - (provide 'jao-proton-utils) ;;; jao-proton.el ends here diff --git a/lib/net/jao-r2e.el b/lib/net/jao-r2e.el new file mode 100644 index 0000000..f28b66b --- /dev/null +++ b/lib/net/jao-r2e.el @@ -0,0 +1,231 @@ +;;; jao-r2e.el --- List of rss2email subscriptions -*- lexical-binding: t; -*- + +;; Copyright (C) 2025, 2026 Jose Antonio Ortega Ruiz + +;; Author: Jose Antonio Ortega Ruiz +;; 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 . + +(require 'multisession) +(require 'jao-url) + +(autoload 'View-quit "view") +(autoload 'eww-view-source "eww") +(autoload 'jao-notmuch-subtags "jao-notmuch") + +(defvar jao-r2e-command "r2e") +(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) + (define-key map [?y] 'jao-r2e-kill-url) + (define-key map [?x] 'jao-r2e-list-subscribed) + 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 "%s %s" jao-r2e-command 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-list-subscribed (arg) + "Show only subscribed (unsubscribed with arg) feeds." + (interactive "P") + (jao-r2e-list) + (let ((inhibit-read-only t)) + (flush-lines (if arg ".*\\[\\*\\].*" ".*\\[ \\].*")))) + +(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))) + (forward-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-kill-url () + "Copy as kill the URL of the feed at point." + (interactive) + (let ((url (cadddr (jao-r2e--feed-at-point)))) + (if (not url) + (error "No feed at point") + (kill-new url) + (message "%s" url)))) + +(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))))) + +(define-multisession-variable jao-r2e-deleted-feeds '() + "List of rss2email feeds deleted at some point.") + +(defun jao-r2e--deleted () (multisession-value jao-r2e-deleted-feeds)) + +(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)) + (entry (cdr f))) + (when (yes-or-no-p (format "Delete feed '%s'" (car entry))) + (setf (multisession-value jao-r2e-deleted-feeds) + (cons entry (remove entry (jao-r2e--deleted)))) + (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)) + (error "No feeds recoverable at this point.")) + (let* ((entries (jao-r2e--deleted)) + (feed (completing-read "Recover feed: " entries))) + (when-let* ((ps (assoc feed entries)) + (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) + (setf (multisession-value jao-r2e-deleted-feeds) (remove ps entries))))) + +(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)))) + (when (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)) + (sfmt (format "%%s add %s '%s' mail+feeds_%s@jao.io" name url cat))) + (with-temp-message "Subscribing..." + (shell-command-to-string (format sfmt "r2e")) + (when (not (string= jao-r2e-command "r2e")) + (shell-command-to-string (format sfmt jao-r2e-command)))) + (when (y-or-n-p "Retrieve feeds now? ") + (with-temp-message "Retrieving feed..." + (shell-command (format "%s run %s" jao-r2e-command name)))) + (when relist (jao-r2e-list))))))) + +(provide 'jao-r2e) +;;; jao-r2e.el ends here diff --git a/lib/net/randomsig.el b/lib/net/randomsig.el index 9029f13..e3c735b 100644 --- a/lib/net/randomsig.el +++ b/lib/net/randomsig.el @@ -308,7 +308,7 @@ You probably want to have a newline at the end of it." ;; get a list with file names of signature files (let ((sigfiles (randomsig-files-to-list files))) ;; Insert all files into the newly created buffer - (mapcar + (mapc (lambda (fname) (let ((pos (point-max))) @@ -348,10 +348,10 @@ You probably want to have a newline at the end of it." (defun randomsig-goto-signature () -;; This function is stolen fom message-goto signature. -;; Go to beginnig of the signature, and return t. -;; If there is no signature in current buffer, go to end of buffer, -;; and return nil. + ;; This function is stolen fom message-goto signature. + ;; Go to beginnig of the signature, and return t. + ;; If there is no signature in current buffer, go to end of buffer, + ;; and return nil. (goto-char (point-min)) (if (re-search-forward "^-- $" nil t) (progn @@ -383,30 +383,25 @@ Else a signature out of `randomsig-files' will be choosen." (randomsig-read-signatures-to-buffer randomsig-buffer-name files) (goto-char (point-min)) - (let '(count 0) 'selected - - ;; Count number of signatures - (while (search-forward-regexp randomsig-delimiter-pattern nil t) - (setq count (1+ count))) - - ;; Select random signature out out these - (setq selected (1+ (random count))) - (goto-char (point-min)) - (if (search-forward-regexp randomsig-delimiter-pattern nil t selected) - (forward-char)) - - ;; Cut signature and return it - (let '(here (point)) 'signature-string - - (if (not (search-forward-regexp randomsig-delimiter-pattern - nil t)) - (goto-char (point-max)) - (beginning-of-line)) - (setq signature-string - (concat randomsig-static-string - (buffer-substring here (point)))) - (kill-buffer randomsig-buffer-name) - signature-string)))) + (let ((count 0) (selected nil)) + ;; Count number of signatures + (while (search-forward-regexp randomsig-delimiter-pattern nil t) + (setq count (1+ count))) + ;; Select random signature out out these + (setq selected (1+ (random count))) + (goto-char (point-min)) + (if (search-forward-regexp randomsig-delimiter-pattern nil t selected) + (forward-char)) + ;; Cut signature and return it + (let ((here (point)) + (signature-string nil)) + (if (not (search-forward-regexp randomsig-delimiter-pattern nil t)) + (goto-char (point-max)) + (beginning-of-line)) + (setq signature-string + (concat randomsig-static-string (buffer-substring here (point)))) + (kill-buffer randomsig-buffer-name) + signature-string)))) (defun randomsig-replace-sig (arg) @@ -415,34 +410,31 @@ When called with prefix, read the filename of the signature-file that should be used" (interactive "P") (save-excursion - (randomsig-replace-signature (randomsig-signature (if arg (randomsig-prompt "read from signature-lib: ") randomsig-files))))) - - (defun randomsig-message-read-sig (arg) "Get the signature of current message and copy it to a file. If mark is active, get the marked region instead. When called with prefix, let the user edit the signature before saving" (interactive "P") (save-excursion - (let '(signature-string + (let ((signature-string (if (randomsig-mark-active-p) (buffer-substring (point) (mark)) (progn (if (randomsig-goto-signature) - (let `(here (point)) + (let ((here (point))) (goto-char (point-max)) (while (char-equal (char-before) 10) (backward-char)) (buffer-substring here (point))) - nil)))) + nil))))) (when signature-string (if arg (progn @@ -451,7 +443,6 @@ When called with prefix, let the user edit the signature before saving" (randomsig-edit signature-string)) (randomsig-write-signature signature-string)))))) - (defun randomsig-write-signature (signature-string) (set-buffer (find-file-noselect (expand-file-name @@ -465,14 +456,13 @@ When called with prefix, let the user edit the signature before saving" (save-buffer)) -(defun gnus/randomsig-summary-read-sig (arg) - "Get the signature of current message and copy it to a file" - (interactive "P") - (progn ;save-excursion - ;; FIXME: Doesn't return to summary buffer (save-excursion should do this) - (gnus-summary-select-article-buffer) - (randomsig-message-read-sig arg))) - +;; (defun gnus/randomsig-summary-read-sig (arg) +;; "Get the signature of current message and copy it to a file" +;; (interactive "P") +;; (progn ;save-excursion +;; ;; FIXME: Doesn't return to summary buffer (save-excursion should do this) +;; (gnus-summary-select-article-buffer) +;; (randomsig-message-read-sig arg))) (defun randomsig-search-sigfiles (&optional file) "Scan `randomsig-dir' and its subdirectories for regular files. @@ -489,7 +479,7 @@ If FILE is given, only FILE and its subdirectory will be searched." ;; unwanted... nil - (let '(path (expand-file-name file randomsig-dir)) + (let ((path (expand-file-name file randomsig-dir))) (if (file-directory-p path) (mapcan (lambda (f) (randomsig-search-sigfiles (if (string= file "") @@ -571,7 +561,7 @@ You most likely do not want to call `randomsig-edit-mode' directly. \\{randomsig-edit-mode-map}" (define-key randomsig-edit-mode-map - (kbd "C-c C-c") 'randomsig-edit-done)) + (kbd "C-c C-c") 'randomsig-edit-done)) ;;; Commands for randomsig-select-mode diff --git a/lib/prog/jao-clojure.el b/lib/prog/jao-clojure.el index 8faa6b1..7de62ba 100644 --- a/lib/prog/jao-clojure.el +++ b/lib/prog/jao-clojure.el @@ -1,6 +1,6 @@ ;;; jao-clojure.el --- Clojure utilities -*- lexical-binding: t; -*- -;; Copyright (C) 2025 Jose Antonio Ortega Ruiz +;; Copyright (C) 2025, 2026 Jose Antonio Ortega Ruiz ;; Author: Jose Antonio Ortega Ruiz ;; Keywords: languages @@ -28,6 +28,7 @@ (require 'project) (require 'cider-test) (require 'jao-skel) +(require 'jao-compilation) ;;;; Jumping between implementation and test files (defun jao-clojure--ext-dir (prefix) @@ -107,7 +108,7 @@ (jao-clojure-jump-to-implementation) (jao-clojure-jump-to-test))) -(defun jao-clojure--setup-compilation (&optional ns) +(defun jao-clojure--setup-compilation (&optional _ns) ;; (set (make-local-variable 'compile-command) (jao-clojure--test-str ns)) ) @@ -131,7 +132,7 @@ "[clojure.test.check.generators :as gen]\n " "[clojure.test.check.properties :as prop :include-macros true]\n")) -(defun jao-clojure--cljs-test-reqs (prefix-cmp last-cmp test-check) +(defun jao-clojure--cljs-test-reqs (prefix-cmp last-cmp _test-check) (concat " (:require [cljs.test :as t :refer-macros [is deftest async]]" "\n [" prefix-cmp "." last-cmp " :as " last-cmp "])")) diff --git a/lib/prog/jao-rust.el b/lib/prog/jao-rust.el index b2549ab..53b0058 100644 --- a/lib/prog/jao-rust.el +++ b/lib/prog/jao-rust.el @@ -20,6 +20,13 @@ ;;; Code: +(declare-function rustic-cargo-bin "rustic") +(declare-function rustic-run-cargo-command "rustic") +(defvar rustic-cargo-test-runner) +(defvar rustic-cargo-use-last-stored-arguments) +(defvar rustic-default-test-arguments) +(defvar rustic-test-arguments) + (defun jao-rust--root () (locate-dominating-file default-directory "Cargo.toml")) diff --git a/lib/prog/jao-sloc.el b/lib/prog/jao-sloc.el index 1f0e9ab..a325871 100644 --- a/lib/prog/jao-sloc.el +++ b/lib/prog/jao-sloc.el @@ -1,4 +1,4 @@ -;; sloc.el -- LOC utilities +;; sloc.el -- LOC utilities -*- lexical-binding: t; -*- ;;;###autoload (defun count-sloc-region (beg end kind) diff --git a/lib/prog/jao-vterm-repl.el b/lib/prog/jao-vterm-repl.el deleted file mode 100644 index 699ff39..0000000 --- a/lib/prog/jao-vterm-repl.el +++ /dev/null @@ -1,130 +0,0 @@ -;;; jao-vterm-repl.el --- vterm-based repls -*- lexical-binding: t; -*- - -;; Copyright (C) 2020, 2021 jao - -;; Author: jao -;; Keywords: terminals - -;; 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 . - -;;; Commentary: - -;; Helpers to launch reply things such as erlang shells inside a vterm. -;; For instance, to declare an erl repl for rebar projects, one would call: -;; -;; (jao-vterm-repl-register "rebar.config" "rebar3 shell" "^[0-9]+> ") - -;;; Code: - -(require 'jao-compilation) - -(declare-function 'vterm-copy-mode "vterm") -(declare-function 'vterm-send-string "vterm") -(declare-function 'vterm-send-return "vterm") - -(defun jao-vterm-repl--buffer-name (&optional dir) - (format "*vterm -- repl - %s*" (or dir (jao-compilation-root)))) - -(defvar jao-vterm-repl-repls nil) -(defvar jao-vterm-repl-prompts nil) -(defvar-local jao-vterm-repl--name nil) -(defvar-local jao-vterm-repl--last-buffer nil) -(defvar-local jao-vterm-repl--prompt-rx "^[0-9]+> ") - -(setq vterm-buffer-name-string nil) - -(defun jao-vterm-repl--exec (cmd &optional name) - (vterm name) - (when name - (vterm-send-string "unset PROMPT_COMMAND\n\n")) - (vterm-send-string cmd) - (vterm-send-return) - (when name (rename-buffer name t))) - -;;;###autoload -(defun jao-vterm-repl-previous-prompt () - (interactive) - (when (derived-mode-p 'vterm-mode) - (vterm-copy-mode 1) - (forward-line 0) - (when (re-search-backward jao-vterm-repl--prompt-rx nil t) - (goto-char (match-end 0))))) - -;;;###autoload -(defun jao-vterm-repl-next-prompt () - (interactive) - (when (derived-mode-p 'vterm-mode) - (vterm-copy-mode 1) - (or (re-search-forward jao-vterm-repl--prompt-rx nil t) - (vterm-copy-mode -1)) - (unless (save-excursion - (re-search-forward jao-vterm-repl--prompt-rx nil t)) - (vterm-copy-mode -1)))) - -;;;###autoload -(define-minor-mode jao-vterm-repl-mode "repl-aware vterm" nil nil - '(("\C-c\C-p" . jao-vterm-repl-previous-prompt) - ("\C-c\C-n" . jao-vterm-repl-next-prompt) - ("\C-c\C-z" . jao-vterm-repl-pop-to-src))) - -;;;###autoload -(defun jao-vterm-repl () - (let* ((dir (jao-compilation-root)) - (vname (jao-vterm-repl--buffer-name dir)) - (root-name (jao-compilation-root-file)) - (buffer (seq-find `(lambda (b) - (string= - (buffer-local-value 'jao-vterm-repl--name - b) - ,vname)) - (buffer-list)))) - (or buffer - (let ((default-directory dir) - (prompt (cdr (assoc root-name jao-vterm-repl-prompts))) - (cmd (or (cdr (assoc root-name jao-vterm-repl-repls)) - (read-string "REPL command: "))) - (bname (format "* vrepl - %s/%s *" - (file-name-base (string-remove-suffix "/" dir)) - root-name))) - (jao-vterm-repl--exec cmd bname) - (jao-vterm-repl-mode) - (setq-local jao-vterm-repl--name vname) - (when prompt (setq-local jao-vterm-repl--prompt-rx prompt)) - (current-buffer))))) - -;;;###autoload -(defun jao-vterm-repl-register (build-file repl-cmd prompt-rx) - (jao-compilation-add-dominating build-file) - (add-to-list 'jao-vterm-repl-repls (cons build-file repl-cmd)) - (add-to-list 'jao-vterm-repl-prompts (cons build-file prompt-rx))) - -;;;###autoload -(defun jao-vterm-repl-pop-to-repl () - (interactive) - (let ((bn (current-buffer))) - (pop-to-buffer (jao-vterm-repl)) - (setq-local jao-vterm-repl--last-buffer bn))) - -;;;###autoload -(defun jao-vterm-repl-pop-to-src () - (interactive) - (when (buffer-live-p jao-vterm-repl--last-buffer) - (pop-to-buffer jao-vterm-repl--last-buffer))) - -;;;###autoload -(defun jao-vterm-repl-send (cmd) - (with-current-buffer (jao-vterm-repl) (vterm-send-string cmd))) - -(provide 'jao-vterm-repl) -;;; jao-vterm-repl.el ends here diff --git a/lib/skels/jao-skel-cpp.el b/lib/skels/jao-skel-cpp.el index 0ddb61e..1180495 100644 --- a/lib/skels/jao-skel-cpp.el +++ b/lib/skels/jao-skel-cpp.el @@ -1,6 +1,6 @@ ;;; jao-skel-cpp.el -*- lexical-binding: t; -*- -;; Copyright (C) 2004, 2005, 2008, 2009, 2022 Jose Antonio Ortega Ruiz +;; Copyright (C) 2004, 2005, 2008, 2009, 2022, 2026 Jose Antonio Ortega Ruiz ;; Author: Jose A Ortega Ruiz ;; Keywords: tools @@ -50,7 +50,7 @@ ;;; Auxiliar functions (defun jao-skel-cpp--find-other (ext) (file-name-nondirectory - (or (ff-other-file-name) + (or (ff-get-other-file) (concat (file-name-sans-extension (buffer-name)) "." ext)))) (defun jao-skel-cpp-make-guard-name (ns) @@ -68,7 +68,7 @@ (defsubst jao-skel-cpp--ns2str (ns) (mapconcat 'identity ns "::")) (defun jao-skel-cpp--get-ns-list (&optional acc) - (do* ((result acc (cons next result)) + (cl-do* ((result acc (cons next result)) (next (jao-skel-cpp--read-ns (jao-skel-cpp--ns2str acc)) (jao-skel-cpp--read-ns (jao-skel-cpp--ns2str (reverse result))))) ((string= next "") (reverse result)))) @@ -98,11 +98,11 @@ (while (re-search-forward "namespace\\s-\\w+\\s-{\\|}+\\s-//\\s-namespace" nil t) (push (thing-at-point 'line) lines) - (next-line))) + (forward-line))) lines)) (defun jao-skel-cpp--copy-namespace () - (let* ((name (ff-other-file-name)) + (let* ((name (ff-get-file-name)) (buff (and name (find-file-noselect name))) (nlines)) (when buff diff --git a/lib/themes/jao-dark-theme.el b/lib/themes/jao-dark-theme.el deleted file mode 100644 index 9e07f1a..0000000 --- a/lib/themes/jao-dark-theme.el +++ /dev/null @@ -1,136 +0,0 @@ -;;; jao-dark-theme.el --- a dark theme with blue-green accent -*- lexical-binding: t; -*- - -;; Author: jao -;; Keywords: themes - -;; 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 . - -(defvar jao-theme-dark-bold - (if (> emacs-major-version 28) 'medium 'semibold)) - -(jao-define-custom-theme jao-dark - (:names (bg "#282b33" nil nil) - (bg-alt "#1f2024" nil nil) - (fg "#c6c6c6") - (fg-0.5 "#a6a6a6") - (fg-1 "#868686") - (fg-2 "#666666") - (blue "#819cd6") - (blueish "#6e7899") - (dark-blue "#616c96") - (green "#5b94ab") - (yellow "antiquewhite3") - (dark-yellow "antiquewhite4") - (orange "#a6c1e0") - (orange2 "#dd8844") - (red "#e1c1ee" "#ff6655" "red") - (comments "azure4" "lightblue4") - (constants "honeydew4") - (dimm-line-fg "#3f3f3f") - (dimm-line "#7f7f7f") - (error "#e1c1ee") - (functions "#7ebebd") - (functions2 "#44b9b1") - (keywords "cadetblue3") - (keywords2 "#51afef") - (modeline-bg "#22242b") - (modeline-bg-inactive "#24262d") - ;;(region "#41454b") - (region "#31353b") - (strings "honeydew3") - (success "#5b94ab") - (warning "#cfcf9c") - (warning2 "#ECBE7B")) - (:face-family "Fira Code") - (:face-size 9) - (:bold-weight jao-theme-dark-bold) - (:palette (fg "#c6c6c6") - (bg "#1f2024") - (box "grey25") - (button (p f12) bx nul) - (hilite (c nil region) ex) - (link (ul dark-blue)) ;; (ul dimm-line) - (visited-link (ul dark-blue)) - (tab-sel (c 252 232) nbf) - (tab-unsel (c 245 232)) - (comment (c comments)) - (keyword (c keywords)) - (function (c functions)) - (type (c constants)) - (variable-name (c nil)) - (constant (c constants)) - (string (c strings) it) - (error (c warning2)) - (warning (c warning)) - (success (c green)) - (dimm (c dimm-line)) - (gnus-mail (c nil)) - (gnus-news (c nil)) - (outline-1 (c strings) nbf) - (outline-2 (c functions) nbf) - (outline-3 (c blue) nbf) - (outline-4 (c functions2) nbf) - (outline-5 (c nil)) - (f00 (c "lightskyblue3")) - (f01 (c "lightskyblue4")) - (f02 (c "lightblue3")) - (f10 (c "lightblue4")) - (f11 (c "lightblue2")) - (f12 (c "azure3"))) - (:x-faces (clojure-keyword-face (c "powder blue")) - (corfu-background (c "white" "grey20")) - (corfu-bar (c nil "grey20")) ;; moving part of the bar - (corfu-border (~ corfu-background)) ;; background of the bar - (corfu-current (c "white" "grey50") nbf nit nul) - (corfu-echo (~ default)) - (cursor (c warning2 warning2)) - (diff-hl-change (c green)) - (diff-hl-delete (c orange2) bf) - (diff-hl-insert (c dark-blue)) - (fill-column-indicator (c "black") :inherit nil) - (font-lock-doc-face (~ font-lock-comment-face) it) - (fringe (p dimm)) - (gnus-button (c "lightyellow3")) - (gnus-cite-1 (c fg-0.5)) - (gnus-cite-2 (c fg-1)) - (gnus-cite-3 (c fg-2)) - (gnus-cite-4 (c fg-2)) - ;; (gnus-group-mail-3 (c yellow)) - ;; (gnus-group-mail-3-empty (c fg-0.5)) - ;; (gnus-group-news-3 (~ gnus-group-mail-3)) - ;; (gnus-group-news-3-empty (~ gnus-group-mail-3-empty)) - ;; (gnus-group-mail-low (p f10)) - ;; (gnus-group-mail-low-empty (~ gnus-group-mail-3-empty)) - (gnus-summary-cancelled (c "dark slate gray" nil) st) - (gnus-summary-selected (p warning) nul nbf) - (header-line (p hilite)) - (magit-diff-context-highlight (p hilite) ex) - (mode-line (c "grey60" modeline-bg) - :box (:line-width 1 :color "#282b33")) - (mode-line-inactive (c "grey35" modeline-bg-inactive) - :box (:line-width 1 :color "#282b33")) - (mode-line-buffer-id (c yellow)) - (org-hide (c 0 nil)) - (org-code (c yellow)) - (scroll-bar (c bg)) - (show-paren-match (c "darkseagreen1" "#5f5f5f")) - (shr-link (c blue) (ul dark-blue)) - (vertical-border (c "black") :inherit nil) - (vertico-group-separator (p dimm) :strike-through "#6f6f6f"))) - -;; (enable-theme 'jao-dark) -;; (jao-mode-line-adjust-faces) - - -(provide 'jao-dark-theme) diff --git a/lib/themes/jao-light-term-theme.el b/lib/themes/jao-light-term-theme.el deleted file mode 100644 index ccd6a3f..0000000 --- a/lib/themes/jao-light-term-theme.el +++ /dev/null @@ -1,121 +0,0 @@ -;;; jao-light-term-theme.el --- a light theme -*- lexical-binding: t; -*- - -;; Author: jao -;; Keywords: themes - -;; 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 . - -(jao-define-custom-theme jao-light-term - (:names (bg-lightest "gray98") - (bg-light "gray95") - - (light-gray "gray80") - - (black "black") - (dark-gray "gray30") - (fg-light "gray40") - - ;; (hl "#f2f2f2") - (hl "ivory2") - (dimm "lemonchiffon4") - - (warning "orange4") - (red "burlywood4") - (blue "#023770") - (green "#005555") - (lightgreen "darkgreen") - (yellow "lightyellow")) - (:face-size 9) - (:face-family "DejaVu Sans Mono") - (:bold-weight 'bold) - (:palette (fg "#000000") - (bg "#ffffff") - (box "gray80") - (hilite (c nil hl)) - (link (c green) nbf nul) - (visited-link (c green)) - (tab-sel (~ mode-line)) - (tab-unsel (~ mode-line-inactive)) - (comment (c fg-light) it) - (keyword (c blue) bf) - (type (c blue) nbf) - (function (c green)) - (variable-name (c black)) - (constant (c dark-gray)) - (string (c blue) nit) - (warning (c warning)) - (error (c red) bf) - (dimm (c dimm)) - (gnus-mail (c "black")) - (gnus-news (c "black")) - (outline (c "black") bf) - (outline-1 (c green) nbf nul ex) - (outline-2 (c blue) nbf) - (outline-3 (c lightgreen) nbf) - (outline-4 (c blue) nul nbf) - (outline-5 (c blue) nul nbf) - (f00 (c green)) - (f01 (c blue)) - (f02 (c dark-gray)) - (f10 (p f00)) - (f11 (p f01)) - (f12 (p f02))) - (:x-faces (button (c blue bg-lightest)) - (compilation-info (c "#223142" nil) nbf) - (completions-group-separator (c nil ni) (st "grey80")) - (corfu-default (~ default) (c "black" "grey95")) - (corfu-bar (c nil "grey80")) ;; moving part of the bar - (corfu-border (~ corfu-background)) ;; background of the bar - (corfu-current (c "black" "grey95") nbf nit (ul "grey70")) - (cursor (c "sienna3" "sienna3")) - (diff-hl-margin-change (c "lightcyan2" nil)) - (diff-hl-margin-insert (c "honeydew2" nil)) - (diff-hl-margin-delete (c "wheat1" nil)) - (eww-form-text (p hilite)) - (fill-column-indicator (c "grey80")) - (fringe (c "grey70" nil)) - (gnus-button (c blue)) - (gnus-cite-1 (c "darkslategray" nil)) - (gnus-cite-2 (c "slate gray" nil)) - (gnus-cite-3 (c "slate gray" nil)) - (gnus-cite-4 (c "slate gray" nil)) - (gnus-header-name (c fg-light)) - (gnus-summary-selected (c green) nbf) - (gnus-summary-cancelled (c "sienna3" nil) st) - (header-line (c dark-gray bg-lightest) - :box (:line-width 1 :color "grey90")) - (magit-diff-context-highlight (c nil hl) ex) - (magit-diff-hunk-heading-highlight (c nil hl) it bf) - (mode-line (c "grey20" "gray90") nbf) - (mode-line-inactive (c "grey40" "gray95")) - (mode-line-buffer-id (~ default) (c dark-blue-2 nil) nit) - (mode-line-emphasis (c green nil)) - (mode-line-highlight (c green nil)) - (org-link (p link) (ul "grey80")) - (scroll-bar (c "grey90" nil)) - (show-paren-match (c nil "grey85")) - (shr-text (c nil nil)) - (shr-link (~ link) (ul light-gray)) - (shr-code (c blue nil)) - (success (c green)) - (vertical-border (c "grey70" nil)) - (vertico-current (c nil yellow) nul ext) - (widget-button (c blue nil) nit nul) - (widget-field (c nil bg-light) nit nul) - (whitespace-tag (p hilite)))) - -;; (enable-theme 'jao-light-term) -;; (jao-mode-line-adjust-faces) - -(provide 'jao-light-term-theme) diff --git a/lib/themes/jao-light-theme.el b/lib/themes/jao-light-theme.el deleted file mode 100644 index 7f75c68..0000000 --- a/lib/themes/jao-light-theme.el +++ /dev/null @@ -1,135 +0,0 @@ -;;; jao-light-theme.el --- a light theme -*- lexical-binding: t; -*- - -;; Author: jao -;; Keywords: themes - -;; 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 . - -(jao-define-custom-theme jao-light - (:names (bg-lightest "gray98") - (bg-light "#efefef") - - (light-gray "gray80") - - (black "black") - (dark-gray "gray30") - (fg-light "gray40") - - (hl "#f2f2f2") - (dimm "lemonchiffon4") - - (warning "orange4") - (red "burlywood4") - (blue "#023770") - (pale-blue "honeydew3") - (green "#005555") - (lightgreen "darkgreen") - (yellow "lightyellow")) - (:bold-weight 'semibold) - (:palette (fg "black") - (bg "white") - (box "gray80") - (hilite (c nil hl)) - (button (c fg-light bg-lightest) (ul light-gray)) - (link (c green) nbf (ul light-gray)) - (visited-link (ul light-gray) nbf) - (tab-sel (~ mode-line)) - (tab-unsel (~ mode-line-inactive)) - (comment (c fg-light) it) - (keyword (c blue) bf) - (type (c blue) nbf) - (function (c green)) - (variable-name (c black)) - (constant (c dark-gray)) - (string (c blue) nit) - (warning (c warning)) - (error (c red) bf) - (dimm (c dimm)) - (gnus-mail (c "black")) - (gnus-news (c "black")) - (outline (c "black") bf) - (outline-1 (c green) bf) - (outline-2 (c green) nbf) - (outline-3 (c blue) nul nbf) - (outline-4 (c blue) nul nbf) - (outline-5 (c blue) nul nbf) - (f00 (c green)) - (f01 (c blue)) - (f02 (c dark-gray)) - (f10 (p f00)) - (f11 (p f01)) - (f12 (p f02))) - (:x-faces (compilation-info (c "#223142" nil) nbf) - (completions-group-separator (c nil ni) (st "grey80")) - (corfu-default (~ default) (c "black" "grey95")) - (corfu-bar (c nil "grey80")) ;; moving part of the bar - (corfu-border (~ corfu-background)) ;; background of the bar - (corfu-current (c "black" "grey95") nbf nit (ul "grey70")) - (cursor (c "sienna3" "sienna3")) - (diff-hl-change (c "white" "honeydew2")) - (diff-hl-insert (c "white" "lemonchiffon2")) - (diff-hl-delete (c "white" "wheat1")) - (diff-hl-margin-change (c pale-blue)) - (diff-hl-margin-insert (c pale-blue)) - (diff-hl-margin-delete (c "wheat1")) - (fill-column-indicator (c "grey80")) - (fringe (c "grey70" nil)) - (gnus-button (c blue)) - (gnus-cite-1 (c "darkslategray" nil)) - (gnus-cite-2 (c "slate gray" nil)) - (gnus-cite-3 (c "slate gray" nil)) - (gnus-cite-4 (c "slate gray" nil)) - (gnus-face-4 (p f11) :family "Triplicate C4c") - (gnus-header-name (c fg-light)) - (gnus-summary-selected (c green) nbf) - (gnus-summary-cancelled (c "sienna3" nil) st) - (header-line (c dark-gray bg-lightest) - :box (:line-width 1 :color "grey90")) - (magit-diff-context-highlight (c nil yellow) ex) - (magit-diff-hunk-heading-highlight (c nil hl) it bf) - (message-header-subject (p warning) nbf) - (mode-line - (c "seashell3" nil) - :box (:line-width 1 :color "#dfdfdf" :style flat-button)) - (mode-line-active - (c "#3f3f3f" "gray96") - :box (:line-width 1 :color "#dfdfdf" :style flat-button)) - (mode-line-inactive - (c "#afafaf" nil) - :box (:line-width 1 :color "#efefdf" :style flat-button)) - (mode-line-buffer-id (~ default) (c nil nil) nit) - (mode-line-emphasis (c green nil)) - (mode-line-highlight (c green nil)) - (org-agenda-calendar-event (p f02)) - (org-agenda-structure (c nil "#efefef") ex) - (org-agenda-date (~ default)) - (org-agenda-date-today (~ org-agenda-structure) ex) - (org-link (p link) (ul "grey80")) - (org-time-grid (c "grey60" nil)) - (tab-bar (~ header-line) :family "Source Code Pro") - (scroll-bar (c "grey80" nil)) - (show-paren-match (c nil "grey85")) - (shr-text (c nil nil)) - (shr-link (~ link) (ul light-gray)) - (shr-code (c blue nil)) - (success (c green)) - (vertical-border (c "#dfdfdf" nil)) - (vterm-color-yellow (c "darkgoldenrod4" yellow)) - (window-divider (c "grey99" nil)) - (widget-button (~ default) nit (ul "grey80")))) - -;; (enable-theme 'jao-light) -;; (jao-mode-line-adjust-faces) - -(provide 'jao-light-theme) diff --git a/lib/themes/jao-themes.el b/lib/themes/jao-themes.el index d21baf5..dc3eee5 100644 --- a/lib/themes/jao-themes.el +++ b/lib/themes/jao-themes.el @@ -1231,6 +1231,7 @@ (cons kind f-alist) (assq-delete-all kind window-system-default-frame-alist))))) +;;;###autoload (defmacro jao-define-custom-theme (name &rest args) (let ((palette (cdr (assoc :palette args))) (x-faces (cdr (assoc :x-faces args))) diff --git a/themes/jao-dark-theme.el b/themes/jao-dark-theme.el new file mode 100644 index 0000000..9e07f1a --- /dev/null +++ b/themes/jao-dark-theme.el @@ -0,0 +1,136 @@ +;;; jao-dark-theme.el --- a dark theme with blue-green accent -*- lexical-binding: t; -*- + +;; Author: jao +;; Keywords: themes + +;; 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 . + +(defvar jao-theme-dark-bold + (if (> emacs-major-version 28) 'medium 'semibold)) + +(jao-define-custom-theme jao-dark + (:names (bg "#282b33" nil nil) + (bg-alt "#1f2024" nil nil) + (fg "#c6c6c6") + (fg-0.5 "#a6a6a6") + (fg-1 "#868686") + (fg-2 "#666666") + (blue "#819cd6") + (blueish "#6e7899") + (dark-blue "#616c96") + (green "#5b94ab") + (yellow "antiquewhite3") + (dark-yellow "antiquewhite4") + (orange "#a6c1e0") + (orange2 "#dd8844") + (red "#e1c1ee" "#ff6655" "red") + (comments "azure4" "lightblue4") + (constants "honeydew4") + (dimm-line-fg "#3f3f3f") + (dimm-line "#7f7f7f") + (error "#e1c1ee") + (functions "#7ebebd") + (functions2 "#44b9b1") + (keywords "cadetblue3") + (keywords2 "#51afef") + (modeline-bg "#22242b") + (modeline-bg-inactive "#24262d") + ;;(region "#41454b") + (region "#31353b") + (strings "honeydew3") + (success "#5b94ab") + (warning "#cfcf9c") + (warning2 "#ECBE7B")) + (:face-family "Fira Code") + (:face-size 9) + (:bold-weight jao-theme-dark-bold) + (:palette (fg "#c6c6c6") + (bg "#1f2024") + (box "grey25") + (button (p f12) bx nul) + (hilite (c nil region) ex) + (link (ul dark-blue)) ;; (ul dimm-line) + (visited-link (ul dark-blue)) + (tab-sel (c 252 232) nbf) + (tab-unsel (c 245 232)) + (comment (c comments)) + (keyword (c keywords)) + (function (c functions)) + (type (c constants)) + (variable-name (c nil)) + (constant (c constants)) + (string (c strings) it) + (error (c warning2)) + (warning (c warning)) + (success (c green)) + (dimm (c dimm-line)) + (gnus-mail (c nil)) + (gnus-news (c nil)) + (outline-1 (c strings) nbf) + (outline-2 (c functions) nbf) + (outline-3 (c blue) nbf) + (outline-4 (c functions2) nbf) + (outline-5 (c nil)) + (f00 (c "lightskyblue3")) + (f01 (c "lightskyblue4")) + (f02 (c "lightblue3")) + (f10 (c "lightblue4")) + (f11 (c "lightblue2")) + (f12 (c "azure3"))) + (:x-faces (clojure-keyword-face (c "powder blue")) + (corfu-background (c "white" "grey20")) + (corfu-bar (c nil "grey20")) ;; moving part of the bar + (corfu-border (~ corfu-background)) ;; background of the bar + (corfu-current (c "white" "grey50") nbf nit nul) + (corfu-echo (~ default)) + (cursor (c warning2 warning2)) + (diff-hl-change (c green)) + (diff-hl-delete (c orange2) bf) + (diff-hl-insert (c dark-blue)) + (fill-column-indicator (c "black") :inherit nil) + (font-lock-doc-face (~ font-lock-comment-face) it) + (fringe (p dimm)) + (gnus-button (c "lightyellow3")) + (gnus-cite-1 (c fg-0.5)) + (gnus-cite-2 (c fg-1)) + (gnus-cite-3 (c fg-2)) + (gnus-cite-4 (c fg-2)) + ;; (gnus-group-mail-3 (c yellow)) + ;; (gnus-group-mail-3-empty (c fg-0.5)) + ;; (gnus-group-news-3 (~ gnus-group-mail-3)) + ;; (gnus-group-news-3-empty (~ gnus-group-mail-3-empty)) + ;; (gnus-group-mail-low (p f10)) + ;; (gnus-group-mail-low-empty (~ gnus-group-mail-3-empty)) + (gnus-summary-cancelled (c "dark slate gray" nil) st) + (gnus-summary-selected (p warning) nul nbf) + (header-line (p hilite)) + (magit-diff-context-highlight (p hilite) ex) + (mode-line (c "grey60" modeline-bg) + :box (:line-width 1 :color "#282b33")) + (mode-line-inactive (c "grey35" modeline-bg-inactive) + :box (:line-width 1 :color "#282b33")) + (mode-line-buffer-id (c yellow)) + (org-hide (c 0 nil)) + (org-code (c yellow)) + (scroll-bar (c bg)) + (show-paren-match (c "darkseagreen1" "#5f5f5f")) + (shr-link (c blue) (ul dark-blue)) + (vertical-border (c "black") :inherit nil) + (vertico-group-separator (p dimm) :strike-through "#6f6f6f"))) + +;; (enable-theme 'jao-dark) +;; (jao-mode-line-adjust-faces) + + +(provide 'jao-dark-theme) diff --git a/themes/jao-light-term-theme.el b/themes/jao-light-term-theme.el new file mode 100644 index 0000000..ccd6a3f --- /dev/null +++ b/themes/jao-light-term-theme.el @@ -0,0 +1,121 @@ +;;; jao-light-term-theme.el --- a light theme -*- lexical-binding: t; -*- + +;; Author: jao +;; Keywords: themes + +;; 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 . + +(jao-define-custom-theme jao-light-term + (:names (bg-lightest "gray98") + (bg-light "gray95") + + (light-gray "gray80") + + (black "black") + (dark-gray "gray30") + (fg-light "gray40") + + ;; (hl "#f2f2f2") + (hl "ivory2") + (dimm "lemonchiffon4") + + (warning "orange4") + (red "burlywood4") + (blue "#023770") + (green "#005555") + (lightgreen "darkgreen") + (yellow "lightyellow")) + (:face-size 9) + (:face-family "DejaVu Sans Mono") + (:bold-weight 'bold) + (:palette (fg "#000000") + (bg "#ffffff") + (box "gray80") + (hilite (c nil hl)) + (link (c green) nbf nul) + (visited-link (c green)) + (tab-sel (~ mode-line)) + (tab-unsel (~ mode-line-inactive)) + (comment (c fg-light) it) + (keyword (c blue) bf) + (type (c blue) nbf) + (function (c green)) + (variable-name (c black)) + (constant (c dark-gray)) + (string (c blue) nit) + (warning (c warning)) + (error (c red) bf) + (dimm (c dimm)) + (gnus-mail (c "black")) + (gnus-news (c "black")) + (outline (c "black") bf) + (outline-1 (c green) nbf nul ex) + (outline-2 (c blue) nbf) + (outline-3 (c lightgreen) nbf) + (outline-4 (c blue) nul nbf) + (outline-5 (c blue) nul nbf) + (f00 (c green)) + (f01 (c blue)) + (f02 (c dark-gray)) + (f10 (p f00)) + (f11 (p f01)) + (f12 (p f02))) + (:x-faces (button (c blue bg-lightest)) + (compilation-info (c "#223142" nil) nbf) + (completions-group-separator (c nil ni) (st "grey80")) + (corfu-default (~ default) (c "black" "grey95")) + (corfu-bar (c nil "grey80")) ;; moving part of the bar + (corfu-border (~ corfu-background)) ;; background of the bar + (corfu-current (c "black" "grey95") nbf nit (ul "grey70")) + (cursor (c "sienna3" "sienna3")) + (diff-hl-margin-change (c "lightcyan2" nil)) + (diff-hl-margin-insert (c "honeydew2" nil)) + (diff-hl-margin-delete (c "wheat1" nil)) + (eww-form-text (p hilite)) + (fill-column-indicator (c "grey80")) + (fringe (c "grey70" nil)) + (gnus-button (c blue)) + (gnus-cite-1 (c "darkslategray" nil)) + (gnus-cite-2 (c "slate gray" nil)) + (gnus-cite-3 (c "slate gray" nil)) + (gnus-cite-4 (c "slate gray" nil)) + (gnus-header-name (c fg-light)) + (gnus-summary-selected (c green) nbf) + (gnus-summary-cancelled (c "sienna3" nil) st) + (header-line (c dark-gray bg-lightest) + :box (:line-width 1 :color "grey90")) + (magit-diff-context-highlight (c nil hl) ex) + (magit-diff-hunk-heading-highlight (c nil hl) it bf) + (mode-line (c "grey20" "gray90") nbf) + (mode-line-inactive (c "grey40" "gray95")) + (mode-line-buffer-id (~ default) (c dark-blue-2 nil) nit) + (mode-line-emphasis (c green nil)) + (mode-line-highlight (c green nil)) + (org-link (p link) (ul "grey80")) + (scroll-bar (c "grey90" nil)) + (show-paren-match (c nil "grey85")) + (shr-text (c nil nil)) + (shr-link (~ link) (ul light-gray)) + (shr-code (c blue nil)) + (success (c green)) + (vertical-border (c "grey70" nil)) + (vertico-current (c nil yellow) nul ext) + (widget-button (c blue nil) nit nul) + (widget-field (c nil bg-light) nit nul) + (whitespace-tag (p hilite)))) + +;; (enable-theme 'jao-light-term) +;; (jao-mode-line-adjust-faces) + +(provide 'jao-light-term-theme) diff --git a/themes/jao-light-theme.el b/themes/jao-light-theme.el new file mode 100644 index 0000000..7f75c68 --- /dev/null +++ b/themes/jao-light-theme.el @@ -0,0 +1,135 @@ +;;; jao-light-theme.el --- a light theme -*- lexical-binding: t; -*- + +;; Author: jao +;; Keywords: themes + +;; 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 . + +(jao-define-custom-theme jao-light + (:names (bg-lightest "gray98") + (bg-light "#efefef") + + (light-gray "gray80") + + (black "black") + (dark-gray "gray30") + (fg-light "gray40") + + (hl "#f2f2f2") + (dimm "lemonchiffon4") + + (warning "orange4") + (red "burlywood4") + (blue "#023770") + (pale-blue "honeydew3") + (green "#005555") + (lightgreen "darkgreen") + (yellow "lightyellow")) + (:bold-weight 'semibold) + (:palette (fg "black") + (bg "white") + (box "gray80") + (hilite (c nil hl)) + (button (c fg-light bg-lightest) (ul light-gray)) + (link (c green) nbf (ul light-gray)) + (visited-link (ul light-gray) nbf) + (tab-sel (~ mode-line)) + (tab-unsel (~ mode-line-inactive)) + (comment (c fg-light) it) + (keyword (c blue) bf) + (type (c blue) nbf) + (function (c green)) + (variable-name (c black)) + (constant (c dark-gray)) + (string (c blue) nit) + (warning (c warning)) + (error (c red) bf) + (dimm (c dimm)) + (gnus-mail (c "black")) + (gnus-news (c "black")) + (outline (c "black") bf) + (outline-1 (c green) bf) + (outline-2 (c green) nbf) + (outline-3 (c blue) nul nbf) + (outline-4 (c blue) nul nbf) + (outline-5 (c blue) nul nbf) + (f00 (c green)) + (f01 (c blue)) + (f02 (c dark-gray)) + (f10 (p f00)) + (f11 (p f01)) + (f12 (p f02))) + (:x-faces (compilation-info (c "#223142" nil) nbf) + (completions-group-separator (c nil ni) (st "grey80")) + (corfu-default (~ default) (c "black" "grey95")) + (corfu-bar (c nil "grey80")) ;; moving part of the bar + (corfu-border (~ corfu-background)) ;; background of the bar + (corfu-current (c "black" "grey95") nbf nit (ul "grey70")) + (cursor (c "sienna3" "sienna3")) + (diff-hl-change (c "white" "honeydew2")) + (diff-hl-insert (c "white" "lemonchiffon2")) + (diff-hl-delete (c "white" "wheat1")) + (diff-hl-margin-change (c pale-blue)) + (diff-hl-margin-insert (c pale-blue)) + (diff-hl-margin-delete (c "wheat1")) + (fill-column-indicator (c "grey80")) + (fringe (c "grey70" nil)) + (gnus-button (c blue)) + (gnus-cite-1 (c "darkslategray" nil)) + (gnus-cite-2 (c "slate gray" nil)) + (gnus-cite-3 (c "slate gray" nil)) + (gnus-cite-4 (c "slate gray" nil)) + (gnus-face-4 (p f11) :family "Triplicate C4c") + (gnus-header-name (c fg-light)) + (gnus-summary-selected (c green) nbf) + (gnus-summary-cancelled (c "sienna3" nil) st) + (header-line (c dark-gray bg-lightest) + :box (:line-width 1 :color "grey90")) + (magit-diff-context-highlight (c nil yellow) ex) + (magit-diff-hunk-heading-highlight (c nil hl) it bf) + (message-header-subject (p warning) nbf) + (mode-line + (c "seashell3" nil) + :box (:line-width 1 :color "#dfdfdf" :style flat-button)) + (mode-line-active + (c "#3f3f3f" "gray96") + :box (:line-width 1 :color "#dfdfdf" :style flat-button)) + (mode-line-inactive + (c "#afafaf" nil) + :box (:line-width 1 :color "#efefdf" :style flat-button)) + (mode-line-buffer-id (~ default) (c nil nil) nit) + (mode-line-emphasis (c green nil)) + (mode-line-highlight (c green nil)) + (org-agenda-calendar-event (p f02)) + (org-agenda-structure (c nil "#efefef") ex) + (org-agenda-date (~ default)) + (org-agenda-date-today (~ org-agenda-structure) ex) + (org-link (p link) (ul "grey80")) + (org-time-grid (c "grey60" nil)) + (tab-bar (~ header-line) :family "Source Code Pro") + (scroll-bar (c "grey80" nil)) + (show-paren-match (c nil "grey85")) + (shr-text (c nil nil)) + (shr-link (~ link) (ul light-gray)) + (shr-code (c blue nil)) + (success (c green)) + (vertical-border (c "#dfdfdf" nil)) + (vterm-color-yellow (c "darkgoldenrod4" yellow)) + (window-divider (c "grey99" nil)) + (widget-button (~ default) nit (ul "grey80")))) + +;; (enable-theme 'jao-light) +;; (jao-mode-line-adjust-faces) + +(provide 'jao-light-theme) -- cgit v1.2.3