unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
* [PATCH] emacs: tree: support fold/unfold thread
@ 2019-03-21 14:26 Julien Masson
  2019-03-23  8:07 ` Mark Walters
  0 siblings, 1 reply; 3+ messages in thread
From: Julien Masson @ 2019-03-21 14:26 UTC (permalink / raw)
  To: notmuch

This patch allow the user to fold/unfold a thread in the current tree
buffer by pressing "t" key.

By default a string is displayed at the beginning of the overlay to
indicate that this thread is folded.
Pressing again "t" on a folded thread will unfold it.

This feature works accross all the queries which are in Tree View.

Signed-off-by: Julien Masson <massonju.eseo@gmail.com>
---

I started to write this feature only for myself and some people around
me were interested so I thought it might be interesting to share with
you as well :)

Please tell me if you want to change some default value:
-> notmuch-tree-overlay-string
-> notmuch-tree-overlay-fold-face
-> "t" key bind to notmuch-tree-toggle-folding-thread

I personnaly bind <TAB> to notmuch-tree-toggle-folding-thread

 emacs/notmuch-tree.el | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)

diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index c00315e..7227692 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -71,6 +71,11 @@ Note the author string should not contain
   :type '(alist :key-type (string) :value-type (string))
   :group 'notmuch-tree)
 
+(defcustom notmuch-tree-overlay-string " [...]"
+  "String displayed at the beginning of the overlay"
+  :type 'string
+  :group 'notmuch-tree)
+
 ;; Faces for messages that match the query.
 (defface notmuch-tree-match-face
   '((t :inherit default))
@@ -159,6 +164,13 @@ Note the author string should not contain
   :group 'notmuch-tree
   :group 'notmuch-faces)
 
+;; Faces for overlays
+(defface notmuch-tree-overlay-fold-face
+  '((t :inherit 'font-lock-keyword-face))
+  "Default face used to display `notmuch-tree-overlay-string'"
+  :group 'notmuch-tree
+  :group 'notmuch-faces)
+
 (defvar notmuch-tree-previous-subject
   "The subject of the most recent result shown during the async display")
 (make-variable-buffer-local 'notmuch-tree-previous-subject)
@@ -196,6 +208,9 @@ if the user has loaded a different buffer in that window.")
 (make-variable-buffer-local 'notmuch-tree-message-buffer)
 (put 'notmuch-tree-message-buffer 'permanent-local t)
 
+(defvar notmuch-tree-overlays nil
+  "List of overlays used to fold/unfold thread")
+
 (defun notmuch-tree-to-message-pane (func)
   "Execute FUNC in message pane.
 
@@ -294,6 +309,7 @@ FUNC."
     (define-key map " " 'notmuch-tree-scroll-or-next)
     (define-key map (kbd "DEL") 'notmuch-tree-scroll-message-window-back)
     (define-key map "e" 'notmuch-tree-resume-message)
+    (define-key map "t" 'notmuch-tree-toggle-folding-thread)
     map))
 (fset 'notmuch-tree-mode-map notmuch-tree-mode-map)
 
@@ -415,6 +431,60 @@ NOT change the database."
 	(notmuch-draft-resume id)
       (message "No message to resume!"))))
 
+(defun notmuch-tree-find-overlay (buffer start end)
+  "Return the first overlay found in `notmuch-tree-overlays'.
+
+The overlay found is located between START and END position in BUFFER."
+  (seq-find (lambda (ov)
+	      (and (eq (overlay-buffer ov) buffer)
+		   (<= (overlay-start ov) start)
+		   (>= (overlay-end ov) end)))
+	    notmuch-tree-overlays))
+
+(defun notmuch-tree-clean-up-overlays ()
+  "Remove overlays not referenced to any buffer"
+  (setq notmuch-tree-overlays (seq-filter #'overlay-buffer notmuch-tree-overlays)))
+
+(defun notmuch-tree-remove-overlay (overlay)
+  "Delete OVERLAY and remove it from `notmuch-tree-overlays' list"
+  (setq notmuch-tree-overlays (remove overlay notmuch-tree-overlays))
+  (delete-overlay overlay))
+
+(defun notmuch-tree-add-overlay (start end)
+  "Add an overlay from START to END in the current buffer.
+
+If non nil, `notmuch-tree-overlay-string' is added at the end of the line.
+The overlay created is added to `notmuch-tree-overlays' list"
+  (let ((overlay (make-overlay start end)))
+    (add-to-list 'notmuch-tree-overlays overlay)
+    (overlay-put overlay 'invisible t)
+    (when notmuch-tree-overlay-string
+      (overlay-put overlay 'before-string
+		   (propertize notmuch-tree-overlay-string
+			       'face 'notmuch-tree-overlay-fold-face)))))
+
+(defun notmuch-tree-thread-range ()
+  "Return list of Start and End position of the current thread"
+  (let (start end)
+    (save-excursion
+      (while (not (or (notmuch-tree-get-prop :first) (eobp)))
+	(forward-line -1))
+      (setq start (line-end-position))
+      (notmuch-tree-next-thread)
+      (setq end (- (point) 1))
+      (list start end))))
+
+(defun notmuch-tree-toggle-folding-thread ()
+  "Fold / Unfold the current thread"
+  (interactive)
+  (cl-multiple-value-bind (start end)
+      (notmuch-tree-thread-range)
+    (unless (= start end)
+      (let ((overlay (notmuch-tree-find-overlay (current-buffer) start end)))
+	(if overlay
+	    (notmuch-tree-remove-overlay overlay)
+	  (notmuch-tree-add-overlay start end))))))
+
 ;; The next two functions close the message window before calling
 ;; notmuch-search or notmuch-tree but they do so after the user has
 ;; entered the query (in case the user was basing the query on
@@ -966,6 +1036,9 @@ The arguments are:
   ;; Don't track undo information for this buffer
   (set 'buffer-undo-list t)
 
+  ;; clean-up overlays in case where some overlays reference to no buffer
+  (notmuch-tree-clean-up-overlays)
+
   (notmuch-tree-worker query query-context target open-target)
 
   (setq truncate-lines t))
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] emacs: tree: support fold/unfold thread
  2019-03-21 14:26 [PATCH] emacs: tree: support fold/unfold thread Julien Masson
@ 2019-03-23  8:07 ` Mark Walters
  2019-03-25 15:16   ` Masson, Julien
  0 siblings, 1 reply; 3+ messages in thread
From: Mark Walters @ 2019-03-23  8:07 UTC (permalink / raw)
  To: Julien Masson, notmuch


Hello

> This patch allow the user to fold/unfold a thread in the current tree
> buffer by pressing "t" key.

This looks like a really nice feature! I will try and review the code
properly soon, but have some preliminary comments.

> By default a string is displayed at the beginning of the overlay to
> indicate that this thread is folded.

I wonder if it would make sense to make the [....] replace the "tree
symbol" (-> etc)? This would mean that it was always on the screen and the
tree symbol looks a little odd with a collapsed thread.

Secondly, I wonder whether making it collapse just the subthread below
the current message (ie a subtree) would be nice? To me that feels more
generic, but might be more effort than it's worth as the code would need
to deal with nested folds. Then C-u t could do exactly the current
folding (ie the whole thread). But this is just a thought.

Finally a comment on the code

> +The overlay found is located between START and END position in BUFFER."
> +  (seq-find (lambda (ov)

> +(defun notmuch-tree-clean-up-overlays ()
> +  "Remove overlays not referenced to any buffer"
> +  (setq notmuch-tree-overlays (seq-filter #'overlay-buffer notmuch-tree-overlays)))

seq-find and seq-filter are emacs 25+ only I think; at least they don't
seem to be in emacs24 which I think we still support. Perhaps some cl
functions can be used (eg remove-if-not) instead?

Best wishes

Mark

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] emacs: tree: support fold/unfold thread
  2019-03-23  8:07 ` Mark Walters
@ 2019-03-25 15:16   ` Masson, Julien
  0 siblings, 0 replies; 3+ messages in thread
From: Masson, Julien @ 2019-03-25 15:16 UTC (permalink / raw)
  To: Mark Walters, Julien Masson, notmuch

Hello

Thanks for the reviews, I appreciate.

On Sat 23 Mar 2019 at 08:07, Mark Walters <markwalters1009@gmail.com> wrote:

> Hello
>
>> This patch allow the user to fold/unfold a thread in the current tree
>> buffer by pressing "t" key.
>
> This looks like a really nice feature! I will try and review the code
> properly soon, but have some preliminary comments.
>
>> By default a string is displayed at the beginning of the overlay to
>> indicate that this thread is folded.
>
> I wonder if it would make sense to make the [....] replace the "tree
> symbol" (-> etc)? This would mean that it was always on the screen and the
> tree symbol looks a little odd with a collapsed thread.

The range of the overlay is from the end of the line of the subject to
end of the line of the last message.
So on the screen the string "[...]" is placed at the end of the Subject.

If I change the range from the "tree symbol" the subject will be
invisible.

I chose to placed the overlay like this to make sure I still see the
subject of the folded thread.

But if you prefer I can place the overlay from the "tree symbol" position.

>
> Secondly, I wonder whether making it collapse just the subthread below
> the current message (ie a subtree) would be nice? To me that feels more
> generic, but might be more effort than it's worth as the code would need
> to deal with nested folds. Then C-u t could do exactly the current
> folding (ie the whole thread). But this is just a thought.

yes sure I'll send a v2 which handle sub-thread folding.

>
> Finally a comment on the code
>
>> +The overlay found is located between START and END position in BUFFER."
>> +  (seq-find (lambda (ov)
>
>> +(defun notmuch-tree-clean-up-overlays ()
>> +  "Remove overlays not referenced to any buffer"
>> +  (setq notmuch-tree-overlays (seq-filter #'overlay-buffer notmuch-tree-overlays)))
>
> seq-find and seq-filter are emacs 25+ only I think; at least they don't
> seem to be in emacs24 which I think we still support. Perhaps some cl
> functions can be used (eg remove-if-not) instead?

Ah yes sorry, I'll change this in the v2.

>
> Best wishes
>
> Mark

Thanks


Julien Masson

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2019-03-25 15:17 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-21 14:26 [PATCH] emacs: tree: support fold/unfold thread Julien Masson
2019-03-23  8:07 ` Mark Walters
2019-03-25 15:16   ` Masson, Julien

Code repositories for project(s) associated with this public inbox

	https://yhetil.org/notmuch.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).