Mu4e: cooperative lock control

This commit is contained in:
TEC 2020-10-13 17:21:52 +08:00
parent fdc8effd0a
commit c59a1ff498
No known key found for this signature in database
GPG key ID: 779591AFDB81F06C
3 changed files with 107 additions and 1 deletions

View file

@ -116,6 +116,8 @@ sudo apt-get install maildir-utils mu4e # mu and mu4e respectivly
+ Tidied mu4e headers view, with flags from =all-the-icons= + Tidied mu4e headers view, with flags from =all-the-icons=
+ Consistent colouring of reply depths (across compose and gnus modes) + Consistent colouring of reply depths (across compose and gnus modes)
+ Prettified =mu4e:main= view + Prettified =mu4e:main= view
+ Cooperative locking of the =mu= process. Another Emacs instance may request
access, or grab the lock when it's available.
+ =org-msg= integration + =org-msg= integration
- can be toggled per-message by applying the - can be toggled per-message by applying the
universal argument (=SPC u=) to the compose/reply/forward action. universal argument (=SPC u=) to the compose/reply/forward action.

View file

@ -268,6 +268,7 @@ clicked."
(list :style (format "transform: scale(%.3f)" (list :style (format "transform: scale(%.3f)"
(/ 1.0 (plist-get org-format-latex-options :scale)))))) (/ 1.0 (plist-get org-format-latex-options :scale))))))
;;;###autoload
(defun +org-html-latex-fragment-scaled (latex-fragment _contents info) (defun +org-html-latex-fragment-scaled (latex-fragment _contents info)
"Transcode a LATEX-FRAGMENT object from Org to HTML. "Transcode a LATEX-FRAGMENT object from Org to HTML.
CONTENTS is nil. INFO is a plist holding contextual information. CONTENTS is nil. INFO is a plist holding contextual information.
@ -299,6 +300,7 @@ account for the value of :scale in `org-format-latex-options'."
(org-html--format-image source attributes info))))) (org-html--format-image source attributes info)))))
(t latex-frag)))) (t latex-frag))))
;;;###autoload
(defun +org-html-latex-environment-scaled (latex-environment _contents info) (defun +org-html-latex-environment-scaled (latex-environment _contents info)
"Transcode a LATEX-ENVIRONMENT element from Org to HTML. "Transcode a LATEX-ENVIRONMENT element from Org to HTML.
CONTENTS is nil. INFO is a plist holding contextual information. CONTENTS is nil. INFO is a plist holding contextual information.
@ -343,3 +345,95 @@ scales the image to account for the value of :scale in `org-format-latex-options
(org-html--format-image source attributes info) (org-html--format-image source attributes info)
info caption label))))) info caption label)))))
(t (org-html--wrap-latex-environment latex-frag info caption label))))) (t (org-html--wrap-latex-environment latex-frag info caption label)))))
;;
;; Cooperative locking
(defvar +mu4e-lock-file "/tmp/mu4e_lock"
"Location of the lock file which stores the PID of the process currenty running mu4e")
(defvar +mu4e-lock-request-file "/tmp/mu4e_lock_request"
"Location of the lock file for which creating indicated that another process wants the lock to be released")
(defvar +mu4e-lock-greedy nil
"Whether to 'grab' the `+mu4e-lock-file' if nobody else has it, i.e. start Mu4e")
(defvar +mu4e-lock-relaxed nil
"Whether if someone else wants the lock (signaled via `+mu4e-lock-request-file'), we should stop Mu4e and let go of it")
;;;###autoload
(defun +mu4e-lock-pid-info ()
"Get info on the PID refered to in `+mu4e-lock-file' in the form (pid . process-attributes)
If the file or process do not exist, the lock file is deleted an nil returned."
(when (file-exists-p +mu4e-lock-file)
(let* ((pid (string-to-number (f-read-text +mu4e-lock-file 'utf-8)))
(process (process-attributes pid)))
(if process (cons pid process)
(delete-file +mu4e-lock-file) nil))))
;;;###autoload
(defun +mu4e-lock-avalible (&optional strict)
"If the `+mu4e-lock-file' is avalible (unset or owned by this emacs) return t.
If STRICT only accept an unset lock file."
(not (when-let* ((lock-info (+mu4e-lock-pid-info))
(pid (car lock-info)))
(when (or strict (/= (emacs-pid) pid)) t))))
;;;###autoload
(defun +mu4e-lock-file-delete-maybe ()
"Check `+mu4e-lock-file', and delete it if this process is responsible for it."
(when (+mu4e-lock-avalible)
(delete-file +mu4e-lock-file)
(file-notify-rm-watch +mu4e-lock--request-watcher)))
;;;###autoload
(defun +mu4e-lock-start (orig-fun &optional callback)
"Check `+mu4e-lock-file', and if another process is responsible for it, abort starting.
Else, write to this process' PID to the lock file"
(unless (+mu4e-lock-avalible)
(shell-command (format "touch %s" +mu4e-lock-request-file))
(message "Lock file exists, requesting that it be given up")
(sleep-for 0.1)
(delete-file +mu4e-lock-request-file))
(if (not (+mu4e-lock-avalible))
(user-error "Unfortunately another Emacs is already doing stuff with Mu4e, and you can only have one at a time")
(f-write-text (number-to-string (emacs-pid)) 'utf-8 +mu4e-lock-file)
(delete-file +mu4e-lock-request-file)
(funcall orig-fun callback)
(setq +mu4e-lock--request-watcher
(file-notify-add-watch +mu4e-lock-request-file
'(change)
#'+mu4e-lock-request))))
(defvar +mu4e-lock--file-watcher nil)
(defvar +mu4e-lock--file-just-deleted nil)
(defvar +mu4e-lock--request-watcher nil)
;;;###autoload
(defun +mu4e-lock-add-watcher ()
(setq +mu4e-lock--file-just-deleted nil)
(file-notify-rm-watch +mu4e-lock--file-watcher)
(setq +mu4e-lock--file-watcher
(file-notify-add-watch +mu4e-lock-file
'(change)
#'++mu4e-lock-file-updated)))
;;;###autoload
(defun +mu4e-lock-request (event)
"Handle another process requesting the Mu4e lock."
(when (equal (nth 1 event) 'created)
(when +mu4e-lock-relaxed
(mu4e~stop)
(file-notify-rm-watch +mu4e-lock--file-watcher)
(message "Someone else wants to use Mu4e, releasing lock")
(delete-file +mu4e-lock-file)
(run-at-time 0.2 nil #'+mu4e-lock-add-watcher))
(delete-file +mu4e-lock-request-file)))
;;;###autoload
(defun ++mu4e-lock-file-updated (event)
(if +mu4e-lock--file-just-deleted
(+mu4e-lock-add-watcher)
(when (equal (nth 1 event) 'deleted)
(setq +mu4e-lock--file-just-deleted t)
(when (and +mu4e-lock-greedy (+mu4e-lock-avalible t))
(message "Noticed Mu4e lock was avalible, grabbed it")
(run-at-time 0.2 nil #'mu4e~start)))))

View file

@ -193,7 +193,17 @@
(advice-add #'mu4e~main-action-str :override #'+mu4e~main-action-str-prettier) (advice-add #'mu4e~main-action-str :override #'+mu4e~main-action-str-prettier)
(when (featurep! :editor evil) (when (featurep! :editor evil)
;; As +mu4e~main-action-str-prettier replaces [k]ey with key q]uit should become quit ;; As +mu4e~main-action-str-prettier replaces [k]ey with key q]uit should become quit
(setq evil-collection-mu4e-end-region-misc "quit"))) (setq evil-collection-mu4e-end-region-misc "quit"))
;; process lock control
(when IS-WINDOWS
(setq ;; REVIEW untested
+mu4e-lock-file (expand-file-name "%userprofile%\\AppData\\Local\\Temp\\mu4e_lock")
+mu4e-lock-request-file (expand-file-name "%userprofile%\\AppData\\Local\\Temp\\mu4e_lock_request")))
(add-hook 'kill-emacs-hook #'+mu4e-lock-file-delete-maybe)
(advice-add 'mu4e~start :around #'+mu4e-lock-start)
(advice-add 'mu4e-quit :after #'+mu4e-lock-file-delete-maybe))
(use-package! org-msg (use-package! org-msg
:after mu4e :after mu4e