* emacs/: more WIP
This commit is contained in:
@ -42,7 +42,6 @@ notation) e.g. for mail headers")
|
|||||||
(defvar mu-date-format-long "%c" "date format (in strftime(2)
|
(defvar mu-date-format-long "%c" "date format (in strftime(2)
|
||||||
notation) for the mail view and in replied/forwarded message quotations")
|
notation) for the mail view and in replied/forwarded message quotations")
|
||||||
|
|
||||||
|
|
||||||
(defvar mu-folder-draft "/home/djcb/Maildir/")
|
(defvar mu-folder-draft "/home/djcb/Maildir/")
|
||||||
|
|
||||||
(defface mu-date-face '((t (:foreground "#8c5353"))) "")
|
(defface mu-date-face '((t (:foreground "#8c5353"))) "")
|
||||||
@ -64,6 +63,13 @@ notation) for the mail view and in replied/forwarded message quotations")
|
|||||||
|
|
||||||
(defvar mu-own-address "djcb" "regexp matching my own address")
|
(defvar mu-own-address "djcb" "regexp matching my own address")
|
||||||
|
|
||||||
|
|
||||||
|
;;; internal stuff
|
||||||
|
(defvar mu-parent-buf nil "the parent buffer for a
|
||||||
|
buffer (buffer-local), i.e., the buffer we'll return to when this
|
||||||
|
buffer is killed")
|
||||||
|
|
||||||
|
|
||||||
(defun mu-binary-version ()
|
(defun mu-binary-version ()
|
||||||
"get the version of the mu binary"
|
"get the version of the mu binary"
|
||||||
(let ((cmd (concat mu-binary
|
(let ((cmd (concat mu-binary
|
||||||
@ -157,8 +163,8 @@ Lisp data as a plist. Returns nil in case of error"
|
|||||||
(let* ((cmd (concat mu-binary " view --format=sexp " path))
|
(let* ((cmd (concat mu-binary " view --format=sexp " path))
|
||||||
(str (shell-command-to-string cmd))
|
(str (shell-command-to-string cmd))
|
||||||
(msglst (read-from-string str)))
|
(msglst (read-from-string str)))
|
||||||
(if (msglst)
|
(if msglst
|
||||||
(car msglist)
|
(car msglst)
|
||||||
(progn (message "Failed to parse message") nil)))))
|
(progn (message "Failed to parse message") nil)))))
|
||||||
|
|
||||||
|
|
||||||
@ -167,17 +173,105 @@ Lisp data as a plist. Returns nil in case of error"
|
|||||||
;; TODO
|
;; TODO
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
;; todo: check for unhandled marks
|
|
||||||
(defun mu-quit-buffer ()
|
(defun mu-quit-buffer ()
|
||||||
"kill this find or view buffer"
|
"kill this buffer, and switch to it's parentbuf if it is alive"
|
||||||
(interactive)
|
(interactive)
|
||||||
(if (or (equalp major-mode 'mu-find-mode)
|
(let ((parentbuf (mu-parent-buf)))
|
||||||
(equalp major-mode 'mu-view-mode))
|
(kill-buffer)
|
||||||
(kill-buffer)))
|
(when (buffer-live-p parentbuf)
|
||||||
|
(switch-to-buffer parentbuf))))
|
||||||
|
|
||||||
|
(defun mu-get-marked ()
|
||||||
|
"get all marked messages as a list; each element is a cell;
|
||||||
|
with 'action', 'source' , 'target'). ie one of three:
|
||||||
|
('delete <path>)
|
||||||
|
('trash <path> <target>)
|
||||||
|
('move <path> <target>)"
|
||||||
|
(let ((lst))
|
||||||
|
(with-current-buffer mu-find-buffer-name
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (point-min))
|
||||||
|
(while (re-search-forward "^." nil t)
|
||||||
|
(let* ((char0 (match-string 0))
|
||||||
|
(action (get-text-property 0 'action char0))
|
||||||
|
(path (get-text-property 0 'path char0))
|
||||||
|
(target (get-text-property 0 'target char0)))
|
||||||
|
(cond
|
||||||
|
((eq action 'trash)
|
||||||
|
(setq lst (cons (list 'trash path target) lst)))
|
||||||
|
((eq action 'delete)
|
||||||
|
(setq lst (cons (list 'delete path) lst)))
|
||||||
|
((eq action 'move)
|
||||||
|
(setq lst (cons (list 'move path target) lst))))))))
|
||||||
|
lst))
|
||||||
|
|
||||||
|
(defun mu-execute ()
|
||||||
|
"execute marked actions on messages"
|
||||||
|
(interactive)
|
||||||
|
(let* ((markedcount (mu-count-marked))
|
||||||
|
(movenum (nth 0 markedcount)) (trashnum (nth 1 markedcount))
|
||||||
|
(deletenum (nth 2 markedcount)))
|
||||||
|
(if (= 0 (apply '+ markedcount))
|
||||||
|
(message "No messages are marked")
|
||||||
|
(if (and (< 0 movenum)
|
||||||
|
(y-or-n-p (format "Do you want to move %d message(s)?" movenum)))
|
||||||
|
(message "Moving message(s)"))
|
||||||
|
(if (and (< 0 trashnum)
|
||||||
|
(y-or-n-p (format "Do you want to move %d message(s) to trash?" trashnum)))
|
||||||
|
(message "Trashing message(s)"))
|
||||||
|
(if (and (< 0 deletenum)
|
||||||
|
(yes-or-no-p (format "Do you want to permanently delete %d message(s)?"
|
||||||
|
deletenum)))
|
||||||
|
(message "Deleting message(s)"))
|
||||||
|
(mu-find-refresh))))
|
||||||
|
|
||||||
|
|
||||||
|
(defun mu-foreach-marked (func)
|
||||||
|
"call FUNC for each marked message; the argument to FUNC is a list, either:
|
||||||
|
with 'action', 'source' , 'target'). ie one of three:
|
||||||
|
('delete <path>)
|
||||||
|
('trash <path> <target>)
|
||||||
|
('move <path> <target>)"
|
||||||
|
(with-current-buffer mu-find-buffer-name
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (point-min))
|
||||||
|
(while (re-search-forward "^." nil t)
|
||||||
|
(move-beginning-of-line 1)
|
||||||
|
(let* ((char0 (match-string 0))
|
||||||
|
(action (get-text-property 0 'action char0))
|
||||||
|
(path (get-text-property 0 'path char0))
|
||||||
|
(target (get-text-property 0 'target char0)))
|
||||||
|
(cond
|
||||||
|
((eq action 'trash) (funcall func (list 'trash path target)))
|
||||||
|
((eq action 'delete) (funcall func (list 'delete path)))
|
||||||
|
((eq action 'move) (funcall func (list 'move path target)))))
|
||||||
|
(move-end-of-line 1)))))
|
||||||
|
|
||||||
|
(defun mu-count-marked ()
|
||||||
|
"return a vector with three items (marked-move marked-trash
|
||||||
|
marked-delete) which are the number of messages marked for each
|
||||||
|
of those"
|
||||||
|
(let ((result (make-vector 3 0)))
|
||||||
|
(mu-foreach-marked
|
||||||
|
(lambda (cell)
|
||||||
|
(case (car cell)
|
||||||
|
('move (aset result 0 (+ 1 (aref result 0))))
|
||||||
|
('trash (aset result 1 (+ 1 (aref result 1))))
|
||||||
|
('delete (aset result 2 (+ 1 (aref result 2)))))))
|
||||||
|
(append result nil))) ;; convert to list
|
||||||
|
|
||||||
|
(defun mu-unmark-all ()
|
||||||
|
"unmark all messages"
|
||||||
|
(interactive)
|
||||||
|
(let ((marked 0))
|
||||||
|
(mu-foreach-marked (lambda(cell) (setq marked (+ 1 marked))))
|
||||||
|
(if (= 0 marked)
|
||||||
|
(message "No messages are marked")
|
||||||
|
(when (y-or-n-p (format "Unmark %d message(s)?" marked))
|
||||||
|
(mu-foreach-marked
|
||||||
|
(lambda(cell)
|
||||||
|
(let ((inhibit-read-only t))
|
||||||
|
(delete-char 1)
|
||||||
|
(insert-and-inherit " "))))))))
|
||||||
|
|
||||||
(provide 'mu-common)
|
(provide 'mu-common)
|
||||||
|
|||||||
@ -315,11 +315,11 @@ the mu find output")
|
|||||||
(delete-char 1)
|
(delete-char 1)
|
||||||
(case what
|
(case what
|
||||||
('trash (insert-and-inherit
|
('trash (insert-and-inherit
|
||||||
(mu-str (propertize "d" 'action what))))
|
(mu-str (propertize "d" 'action what 'target "/foo/bar"))))
|
||||||
('delete (insert-and-inherit
|
('delete (insert-and-inherit
|
||||||
(mu-str (propertize "D" 'action what))))
|
(mu-str (propertize "D" 'action what 'target "/foo/bar"))))
|
||||||
('move (insert-and-inherit
|
('move (insert-and-inherit
|
||||||
(mu-str (propertize "m" 'action what))))
|
(mu-str (propertize "m" 'action what 'target "/foo/bar"))))
|
||||||
('none (insert-and-inherit " ")))
|
('none (insert-and-inherit " ")))
|
||||||
(forward-line))))))
|
(forward-line))))))
|
||||||
|
|
||||||
|
|||||||
@ -46,7 +46,7 @@
|
|||||||
(format "On %s, %s wrote:\n"
|
(format "On %s, %s wrote:\n"
|
||||||
(format-time-string mu-date-format-long (plist-get msg :date))
|
(format-time-string mu-date-format-long (plist-get msg :date))
|
||||||
(cdr (car (plist-get msg :from)))))
|
(cdr (car (plist-get msg :from)))))
|
||||||
|
|
||||||
(defun mu-message-cite (msg)
|
(defun mu-message-cite (msg)
|
||||||
"cite an existing message"
|
"cite an existing message"
|
||||||
(let ((body
|
(let ((body
|
||||||
@ -120,14 +120,10 @@ create a forwarded message. After creation, switch to the message editor"
|
|||||||
"create a reply to the message at point; After creation, switch
|
"create a reply to the message at point; After creation, switch
|
||||||
to the message editor"
|
to the message editor"
|
||||||
(let ((path (mu-get-path)))
|
(let ((path (mu-get-path)))
|
||||||
(when path
|
(when path
|
||||||
(let ())
|
(mu-ask-key "Reply to [s]ender only or to [a]ll?")
|
||||||
|
(mu-message-reply-or-forward path))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(mu-ask-key "Reply to [s]ender only or to [a]ll?")
|
|
||||||
(mu-message-reply-or-forward path))
|
|
||||||
|
|
||||||
(defun mu-message-forward (path)
|
(defun mu-message-forward (path)
|
||||||
"create a forward-message to the message at PATH; After
|
"create a forward-message to the message at PATH; After
|
||||||
creation, switch to the message editor"
|
creation, switch to the message editor"
|
||||||
|
|||||||
@ -114,7 +114,7 @@ function returns the resulting name"
|
|||||||
|
|
||||||
(defvar mu-view-mode-map
|
(defvar mu-view-mode-map
|
||||||
(let ((map (make-sparse-keymap)))
|
(let ((map (make-sparse-keymap)))
|
||||||
(define-key map "q" 'mu-view-quit-buffer)
|
(define-key map "q" 'mu-quit-buffer)
|
||||||
(define-key map "s" 'mu-find)
|
(define-key map "s" 'mu-find)
|
||||||
(define-key map "f" 'mu-forward)
|
(define-key map "f" 'mu-forward)
|
||||||
(define-key map "r" 'mu-reply)
|
(define-key map "r" 'mu-reply)
|
||||||
@ -144,10 +144,4 @@ function returns the resulting name"
|
|||||||
(when (mu-find-prev)
|
(when (mu-find-prev)
|
||||||
(mu-view (mu-get-path)))))
|
(mu-view (mu-get-path)))))
|
||||||
|
|
||||||
(defun mu-view-quit-buffer ()
|
|
||||||
"quit this buffer and return to the find buffer"
|
|
||||||
(interactive)
|
|
||||||
(mu-quit-buffer)
|
|
||||||
(switch-to-buffer mu-find-buffer-name))
|
|
||||||
|
|
||||||
(provide 'mu-view)
|
(provide 'mu-view)
|
||||||
|
|||||||
11
emacs/mu.el
11
emacs/mu.el
@ -38,19 +38,22 @@
|
|||||||
(define-key mu-find-mode-map "o" 'mu-find-change-sort)
|
(define-key mu-find-mode-map "o" 'mu-find-change-sort)
|
||||||
(define-key mu-find-mode-map "g" 'mu-find-refresh)
|
(define-key mu-find-mode-map "g" 'mu-find-refresh)
|
||||||
(define-key mu-find-mode-map "m" 'mu-find-mark-for-move)
|
(define-key mu-find-mode-map "m" 'mu-find-mark-for-move)
|
||||||
(define-key mu-find-mode-map "d" 'mu-find-mark-for-thrash)
|
(define-key mu-find-mode-map "d" 'mu-find-mark-for-trash)
|
||||||
(define-key mu-find-mode-map "D" 'mu-find-mark-for-deletion)
|
(define-key mu-find-mode-map "D" 'mu-find-mark-for-deletion)
|
||||||
(define-key mu-find-mode-map "u" 'mu-find-unmark)
|
(define-key mu-find-mode-map "u" 'mu-find-unmark)
|
||||||
|
(define-key mu-find-mode-map "U" 'mu-unmark-all)
|
||||||
(define-key mu-find-mode-map "r" 'mu-reply)
|
(define-key mu-find-mode-map "r" 'mu-reply)
|
||||||
(define-key mu-view-mode-map "f" 'mu-forward)
|
(define-key mu-find-mode-map "f" 'mu-forward)
|
||||||
|
(define-key mu-find-mode-map "x" 'mu-execute)
|
||||||
|
|
||||||
(define-key mu-view-mode-map "q" 'mu-view-quit-buffer)
|
|
||||||
|
(define-key mu-view-mode-map "q" 'mu-quit-buffer)
|
||||||
(define-key mu-view-mode-map "f" 'mu-view-find)
|
(define-key mu-view-mode-map "f" 'mu-view-find)
|
||||||
(define-key mu-view-mode-map "n" 'mu-view-next)
|
(define-key mu-view-mode-map "n" 'mu-view-next)
|
||||||
(define-key mu-view-mode-map "p" 'mu-view-prev)
|
(define-key mu-view-mode-map "p" 'mu-view-prev)
|
||||||
(define-key mu-view-mode-map "r" 'mu-reply)
|
(define-key mu-view-mode-map "r" 'mu-reply)
|
||||||
(define-key mu-view-mode-map "f" 'mu-forward)
|
(define-key mu-view-mode-map "f" 'mu-forward)
|
||||||
|
(define-key mu-view-mode-map "x" 'mu-execute)
|
||||||
|
|
||||||
(provide 'mu)
|
(provide 'mu)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user