From bf36858c9d49425d10efbb9affcbce2533da53fd Mon Sep 17 00:00:00 2001 From: djcb Date: Sun, 8 Apr 2012 12:43:37 +0300 Subject: [PATCH] * initial implementation of the header/view split viewmode (WIP) --- emacs/mu4e-hdrs.el | 72 ++++++++++++++++++++++++++++++++-------------- emacs/mu4e-view.el | 27 +++++++++-------- emacs/mu4e.el | 26 +++++++++++++++++ 3 files changed, 89 insertions(+), 36 deletions(-) diff --git a/emacs/mu4e-hdrs.el b/emacs/mu4e-hdrs.el index 564d6fdf..addaa9b6 100644 --- a/emacs/mu4e-hdrs.el +++ b/emacs/mu4e-hdrs.el @@ -27,9 +27,10 @@ ;; headers like 'To:' or 'Subject:') ;; Code: - + (eval-when-compile (require 'cl)) +(require 'hl-line) (require 'mu4e-proc) ;;;; internal variables/constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -129,7 +130,7 @@ from the database. This function will hide the removed message from the current list of headers." (when (buffer-live-p 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-marks-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 mu4e-marks-map (make-hash-table :size 16 :rehash-size 2) mu4e-thread-info-map (make-hash-table :size 512 :rehash-size 2) truncate-lines t 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 (cons (make-string @@ -415,11 +421,11 @@ of the beginning of the line." (when (null to-mark) (if (null newpoint) (goto-char oldpoint) ;; not found; restore old pos - (progn + (progn (beginning-of-line) ;; found, move to beginning of line (setq newpoint (point))))) 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))) pos)) -;;;; markers mark headers for +;;;; markers mark headers for (defun mu4e--mark-header (docid mark) "(Visually) mark the header for DOCID with character MARK." (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 ;; and then we skip the 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-put overlay 'display targetstr))))))) @@ -707,29 +713,51 @@ do a new search." (defun mu4e-view-message () "View the message at point." (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 () "Move point to the next message header. If this succeeds, return the new docid. Otherwise, return nil." (interactive) - (with-current-buffer mu4e-hdrs-buffer - (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))))) - + (mu4e--hdrs-move 1)) + (defun mu4e-prev-header () "Move point to the previous message header. If this succeeds, return the new docid. Otherwise, return nil." (interactive) - (with-current-buffer mu4e-hdrs-buffer - (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))))) + (mu4e--hdrs-move -1)) (defun mu4e-jump-to-maildir () diff --git a/emacs/mu4e-view.el b/emacs/mu4e-view.el index c1327a86..3981fddd 100644 --- a/emacs/mu4e-view.el +++ b/emacs/mu4e-view.el @@ -35,8 +35,7 @@ (defconst mu4e-view-buffer-name "*mu4e-view*" "*internal* Name for the message view buffer") -(defconst mu4e-raw-view-buffer-name "*mu4e-raw-view*" - "*internal* Name for the raw message view buffer") +(defvar mu4e-view-buffer nil "*internal* The view buffer.") ;; some buffer-local variables (defvar mu4e-hdrs-buffer nil @@ -50,7 +49,6 @@ wanting to show specific messages - for example, `mu4e-org'." (mu4e-proc-view-msg msgid)) - (defun mu4e-view (msg hdrsbuf &optional update) "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 @@ -64,6 +62,7 @@ marking if it still had that." (let ((buf (get-buffer-create mu4e-view-buffer-name)) (inhibit-read-only t)) (with-current-buffer buf + (setq mu4e-view-buffer buf) (erase-buffer) (insert (mapconcat @@ -456,8 +455,10 @@ number them so they can be opened using `mu4e-view-go-to-url'." ;; raw mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; some buffer-local variables -(defvar mu4e-view-buffer nil - "*internal* View buffer connected to this raw view.") +(defconst mu4e-raw-view-buffer-name "*mu4e-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 "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) ;; initialize view-mode (mu4e-raw-view-mode) - (setq mu4e-view-buffer view-buffer) + (setq mu4e-raw-view-buffer view-buffer) (switch-to-buffer buf) (goto-char (point-min))))) @@ -517,7 +518,7 @@ number them so they can be opened using `mu4e-view-go-to-url'." (erase-buffer) (process-file-shell-command cmd file buf) (mu4e-raw-view-mode) - (setq mu4e-view-buffer view-buffer) + (setq mu4e-raw-view-buffer view-buffer) (switch-to-buffer buf) (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 () "Quit the raw view and return to the message." (interactive) - (if (buffer-live-p mu4e-view-buffer) - (switch-to-buffer mu4e-view-buffer) - (kill-buffer))) + (kill-buffer)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; functions for org-contacts @@ -610,10 +609,10 @@ citations." (defun mu4e-view-quit-buffer () "Quit the message view and return to the headers." (interactive) - (if (buffer-live-p mu4e-hdrs-buffer) - (switch-to-buffer mu4e-hdrs-buffer) - (kill-buffer))) - + (kill-buffer-and-window) + (when (buffer-live-p mu4e-hdrs-buffer) + (switch-to-buffer mu4e-hdrs-buffer))) + (defun mu4e-view-next-header () "View the next header." (interactive) diff --git a/emacs/mu4e.el b/emacs/mu4e.el index fd8a79a9..52f41a84 100644 --- a/emacs/mu4e.el +++ b/emacs/mu4e.el @@ -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 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 (defgroup mu4e-sending nil @@ -208,6 +214,20 @@ designated shortcut character for the maildir.") :type 'symbol :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 (defgroup mu4e-view nil "Settings for the message view." @@ -312,6 +332,7 @@ sent folder." :group 'mu4e :group 'faces) + (defface mu4e-unread-face '((t :inherit font-lock-keyword-face :bold t)) "Face for an unread message header." @@ -351,6 +372,11 @@ flag set)." view." :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 '((t :inherit font-lock-doc-face)) "Face for a header value (such as \"Re: Hello!\") in the message