* initial implementation of the header/view split viewmode (WIP)

This commit is contained in:
djcb
2012-04-08 12:43:37 +03:00
parent 1b451b754a
commit bf36858c9d
3 changed files with 89 additions and 36 deletions

View File

@ -27,9 +27,10 @@
;; headers like 'To:' or 'Subject:') ;; headers like 'To:' or 'Subject:')
;; Code: ;; Code:
(eval-when-compile (require 'cl)) (eval-when-compile (require 'cl))
(require 'hl-line)
(require 'mu4e-proc) (require 'mu4e-proc)
;;;; internal variables/constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; internal variables/constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -129,7 +130,7 @@ from the database. This function will hide the removed message from
the current list of headers." the current list of headers."
(when (buffer-live-p mu4e-hdrs-buffer) (when (buffer-live-p mu4e-hdrs-buffer)
(with-current-buffer mu4e-hdrs-buffer (with-current-buffer mu4e-hdrs-buffer
(mu4e-hdrs-remove-header docid)))) (mu4e-hdrs-remove-header docid))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -351,15 +352,20 @@ after the end of the search results."
(make-local-variable 'mu4e-hdrs-proc) (make-local-variable 'mu4e-hdrs-proc)
(make-local-variable 'mu4e-marks-map) (make-local-variable 'mu4e-marks-map)
(make-local-variable 'mu4e-thread-info-map) (make-local-variable 'mu4e-thread-info-map)
(make-local-variable 'global-mode-string)
(make-local-variable 'global-mode-string)
(make-local-variable 'hl-line-face)
(setq (setq
mu4e-marks-map (make-hash-table :size 16 :rehash-size 2) mu4e-marks-map (make-hash-table :size 16 :rehash-size 2)
mu4e-thread-info-map (make-hash-table :size 512 :rehash-size 2) mu4e-thread-info-map (make-hash-table :size 512 :rehash-size 2)
truncate-lines t truncate-lines t
buffer-undo-list t ;; don't record undo information buffer-undo-list t ;; don't record undo information
overwrite-mode 'overwrite-mode-binary) overwrite-mode 'overwrite-mode-binary
hl-line-face 'mu4e-header-highlight-face)
(hl-line-mode 1)
(setq header-line-format (setq header-line-format
(cons (cons
(make-string (make-string
@ -415,11 +421,11 @@ of the beginning of the line."
(when (null to-mark) (when (null to-mark)
(if (null newpoint) (if (null newpoint)
(goto-char oldpoint) ;; not found; restore old pos (goto-char oldpoint) ;; not found; restore old pos
(progn (progn
(beginning-of-line) ;; found, move to beginning of line (beginning-of-line) ;; found, move to beginning of line
(setq newpoint (point))))) (setq newpoint (point)))))
newpoint)) ;; return the point, or nil if not found newpoint)) ;; return the point, or nil if not found
@ -431,7 +437,7 @@ docid DOCID, or nil if it cannot be found."
(setq pos (mu4e--goto-docid docid))) (setq pos (mu4e--goto-docid docid)))
pos)) pos))
;;;; markers mark headers for ;;;; markers mark headers for
(defun mu4e--mark-header (docid mark) (defun mu4e--mark-header (docid mark)
"(Visually) mark the header for DOCID with character MARK." "(Visually) mark the header for DOCID with character MARK."
(with-current-buffer mu4e-hdrs-buffer (with-current-buffer mu4e-hdrs-buffer
@ -550,7 +556,7 @@ The following marks are available, and the corresponding props:
;; mu4e-goto-docid docid t will take us just after the docid cookie ;; mu4e-goto-docid docid t will take us just after the docid cookie
;; and then we skip the mu4e-hdrs-fringe ;; and then we skip the mu4e-hdrs-fringe
(start (+ (length mu4e-hdrs-fringe) (start (+ (length mu4e-hdrs-fringe)
(mu4e--goto-docid docid t))) (mu4e--goto-docid docid t)))
(overlay (make-overlay start (+ start (length targetstr))))) (overlay (make-overlay start (+ start (length targetstr)))))
(overlay-put overlay 'display targetstr))))))) (overlay-put overlay 'display targetstr)))))))
@ -707,29 +713,51 @@ do a new search."
(defun mu4e-view-message () (defun mu4e-view-message ()
"View the message at point." "View the message at point."
(interactive) (interactive)
(mu4e-hdrs-view)) (let ((viewwin (when (buffer-live-p mu4e-view-buffer)
(get-buffer-window mu4e-view-buffer))))
(unless (window-live-p viewwin)
;; no view window yet; create one, based on the split settings etc.
(setq viewwin
(cond ;; is there are live window for the message view?
;; split horizontally
((eq mu4e-split-mode 'horizontal)
(split-window nil mu4e-headers-visible-lines 'below))
;; split vertically
((eq mu4e-split-mode 'vertical)
(split-window nil mu4e-headers-visible-columns 'right))
;; no splitting; just use the currently selected one
(t
(selected-window)))))
;; okay, now we have viewwin
(select-window viewwin)
(mu4e-hdrs-view)))
(defun mu4e--hdrs-move (lines)
"Move point LINES lines forward (if LINES is positive) or
backward (if LINES is negative). If this succeeds, return the new
docid. Otherwise, return nil."
(with-current-buffer mu4e-hdrs-buffer
(hl-line-unhighlight)
(let ((succeeded (= 0 (forward-line lines)))
(docid (mu4e--docid-at-point)))
;; trick to move point, even if this function is called when this window
;; is not visible
(set-window-point (get-buffer-window mu4e-hdrs-buffer) (point))
(hl-line-highlight)
;; return the docid only if the move succeeded
(when succeeded docid))))
(defun mu4e-next-header () (defun mu4e-next-header ()
"Move point to the next message header. If this succeeds, return "Move point to the next message header. If this succeeds, return
the new docid. Otherwise, return nil." the new docid. Otherwise, return nil."
(interactive) (interactive)
(with-current-buffer mu4e-hdrs-buffer (mu4e--hdrs-move 1))
(when (= 0 (forward-line 1))
(or (mu4e--docid-at-point) (mu4e-next-header)) ;; skip non-headers
;; trick to move point, even if this function is called when this window
;; is not visible
(set-window-point (get-buffer-window mu4e-hdrs-buffer) (point)))))
(defun mu4e-prev-header () (defun mu4e-prev-header ()
"Move point to the previous message header. If this succeeds, "Move point to the previous message header. If this succeeds,
return the new docid. Otherwise, return nil." return the new docid. Otherwise, return nil."
(interactive) (interactive)
(with-current-buffer mu4e-hdrs-buffer (mu4e--hdrs-move -1))
(when (= 0 (forward-line -1))
(or (mu4e--docid-at-point) (mu4e-prev-header)) ;; skip non-headers
;; trick to move point, even if this function is called when this window
;; is not visible
(set-window-point (get-buffer-window mu4e-hdrs-buffer) (point)))))
(defun mu4e-jump-to-maildir () (defun mu4e-jump-to-maildir ()

View File

@ -35,8 +35,7 @@
(defconst mu4e-view-buffer-name "*mu4e-view*" (defconst mu4e-view-buffer-name "*mu4e-view*"
"*internal* Name for the message view buffer") "*internal* Name for the message view buffer")
(defconst mu4e-raw-view-buffer-name "*mu4e-raw-view*" (defvar mu4e-view-buffer nil "*internal* The view buffer.")
"*internal* Name for the raw message view buffer")
;; some buffer-local variables ;; some buffer-local variables
(defvar mu4e-hdrs-buffer nil (defvar mu4e-hdrs-buffer nil
@ -50,7 +49,6 @@
wanting to show specific messages - for example, `mu4e-org'." wanting to show specific messages - for example, `mu4e-org'."
(mu4e-proc-view-msg msgid)) (mu4e-proc-view-msg msgid))
(defun mu4e-view (msg hdrsbuf &optional update) (defun mu4e-view (msg hdrsbuf &optional update)
"Display the message MSG in a new buffer, and keep in sync with HDRSBUF. "Display the message MSG in a new buffer, and keep in sync with HDRSBUF.
'In sync' here means that moving to the next/previous message in 'In sync' here means that moving to the next/previous message in
@ -64,6 +62,7 @@ marking if it still had that."
(let ((buf (get-buffer-create mu4e-view-buffer-name)) (let ((buf (get-buffer-create mu4e-view-buffer-name))
(inhibit-read-only t)) (inhibit-read-only t))
(with-current-buffer buf (with-current-buffer buf
(setq mu4e-view-buffer buf)
(erase-buffer) (erase-buffer)
(insert (insert
(mapconcat (mapconcat
@ -456,8 +455,10 @@ number them so they can be opened using `mu4e-view-go-to-url'."
;; raw mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; raw mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; some buffer-local variables ;; some buffer-local variables
(defvar mu4e-view-buffer nil (defconst mu4e-raw-view-buffer-name "*mu4e-raw-view*"
"*internal* View buffer connected to this raw view.") "*internal* Name for the raw message view buffer")
(defvar mu4e-raw-view-buffer nil "*internal* The raw view buffer.")
(defvar mu4e-raw-view-mode-map nil (defvar mu4e-raw-view-mode-map nil
"Keymap for \"*mu4e-raw-view*\" buffers.") "Keymap for \"*mu4e-raw-view*\" buffers.")
@ -501,7 +502,7 @@ number them so they can be opened using `mu4e-view-go-to-url'."
(insert-file file) (insert-file file)
;; initialize view-mode ;; initialize view-mode
(mu4e-raw-view-mode) (mu4e-raw-view-mode)
(setq mu4e-view-buffer view-buffer) (setq mu4e-raw-view-buffer view-buffer)
(switch-to-buffer buf) (switch-to-buffer buf)
(goto-char (point-min))))) (goto-char (point-min)))))
@ -517,7 +518,7 @@ number them so they can be opened using `mu4e-view-go-to-url'."
(erase-buffer) (erase-buffer)
(process-file-shell-command cmd file buf) (process-file-shell-command cmd file buf)
(mu4e-raw-view-mode) (mu4e-raw-view-mode)
(setq mu4e-view-buffer view-buffer) (setq mu4e-raw-view-buffer view-buffer)
(switch-to-buffer buf) (switch-to-buffer buf)
(goto-char (point-min))))) (goto-char (point-min)))))
@ -525,9 +526,7 @@ number them so they can be opened using `mu4e-view-go-to-url'."
(defun mu4e-raw-view-quit-buffer () (defun mu4e-raw-view-quit-buffer ()
"Quit the raw view and return to the message." "Quit the raw view and return to the message."
(interactive) (interactive)
(if (buffer-live-p mu4e-view-buffer) (kill-buffer))
(switch-to-buffer mu4e-view-buffer)
(kill-buffer)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; functions for org-contacts ;; functions for org-contacts
@ -610,10 +609,10 @@ citations."
(defun mu4e-view-quit-buffer () (defun mu4e-view-quit-buffer ()
"Quit the message view and return to the headers." "Quit the message view and return to the headers."
(interactive) (interactive)
(if (buffer-live-p mu4e-hdrs-buffer) (kill-buffer-and-window)
(switch-to-buffer mu4e-hdrs-buffer) (when (buffer-live-p mu4e-hdrs-buffer)
(kill-buffer))) (switch-to-buffer mu4e-hdrs-buffer)))
(defun mu4e-view-next-header () (defun mu4e-view-next-header ()
"View the next header." "View the next header."
(interactive) (interactive)

View File

@ -116,6 +116,12 @@ form (QUERY DESCRIPTION KEY), where QUERY is a string with a mu
query, DESCRIPTION is a short description of the query (this will query, DESCRIPTION is a short description of the query (this will
show up in the UI), and KEY is a shortcut key for the query.") show up in the UI), and KEY is a shortcut key for the query.")
(defvar mu4e-split-mode nil
"How to show messages / headers; as symbol which is either:
nil: don't split (show either headers or messages, not both)
horizontal: split horizontally (headers on top)
vertical: split vertically (headers on the left).
Also see `mu4e-headers-visible-lines'.")
;; Sending ;; Sending
(defgroup mu4e-sending nil (defgroup mu4e-sending nil
@ -208,6 +214,20 @@ designated shortcut character for the maildir.")
:type 'symbol :type 'symbol
:group 'mu4e-headers) :group 'mu4e-headers)
(defcustom mu4e-headers-visible-lines 8
"Number of header lines to display for the header view when using
the horizontal split-view."
:type 'integer
:group 'mu4e-headers)
(defcustom mu4e-headers-visible-columns 30
"Number of columns to display for the header view when using the
vertical split-view."
:type 'integer
:group 'mu4e-headers)
;; the message view ;; the message view
(defgroup mu4e-view nil (defgroup mu4e-view nil
"Settings for the message view." "Settings for the message view."
@ -312,6 +332,7 @@ sent folder."
:group 'mu4e :group 'mu4e
:group 'faces) :group 'faces)
(defface mu4e-unread-face (defface mu4e-unread-face
'((t :inherit font-lock-keyword-face :bold t)) '((t :inherit font-lock-keyword-face :bold t))
"Face for an unread message header." "Face for an unread message header."
@ -351,6 +372,11 @@ flag set)."
view." view."
:group 'mu4e-faces) :group 'mu4e-faces)
(defface mu4e-header-highlight-face
'((t :inherit default :weight bold :underline t))
"Face for the header at point."
:group 'mu4e-faces)
(defface mu4e-view-header-value-face (defface mu4e-view-header-value-face
'((t :inherit font-lock-doc-face)) '((t :inherit font-lock-doc-face))
"Face for a header value (such as \"Re: Hello!\") in the message "Face for a header value (such as \"Re: Hello!\") in the message