[PATCH] Add explicit open/close thread functions.

"Kevin J. McCarthy" <[email protected]>
Newsgroups gmane.mail.mutt.devel
Message-ID <[email protected]>
The current functions <collapse-thread> and <collapse-all> are in fact
toggles.  This makes it tricky to control how a macro behaves, for
instance.

Add functions <open-thread>, <close-thread>, <open-all-threads>,
<close-all-threads> to explicitly open or close threads.

Renaming the existing toggle functions is not practical due to how
long they have been in use.  I could add new <toggle-thread>
<toggle-all-threads> functions but that would require new OPS to work
properly with keybindings.  I don't think it's worth the extra
trouble.
---
The diff looks more complicated than it is due to indentation changes.
See:
https://gitlab.com/muttmua/mutt/-/commit/39cf6a25f89b391cbfe35de805ef6095cc31e93a
for a diff without whitespace changes.

 OPS         | 20 ++++++++++++++++
 curs_main.c | 66 +++++++++++++++++++++++++++++++++--------------------
 functions.h |  4 ++++
 3 files changed, 65 insertions(+), 25 deletions(-)

diff --git a/OPS b/OPS
index b4cd2512..aee20ac1 100644
--- a/OPS
+++ b/OPS
@@ -1194,6 +1194,26 @@ OP_MAIN_COLLAPSE_THREAD N_("collapse/uncollapse current thread")
  */
 OP_MAIN_COLLAPSE_ALL N_("collapse/uncollapse all threads")
 
+/* L10N: Help screen description for OP_MAIN_OPEN_THREAD
+   index menu: <open-thread>
+ */
+OP_MAIN_OPEN_THREAD N_("uncollapse current thread")
+
+/* L10N: Help screen description for OP_MAIN_OPEN_ALL_THREADS
+   index menu: <open-all-threads>
+ */
+OP_MAIN_OPEN_ALL_THREADS N_("uncollapse all threads")
+
+/* L10N: Help screen description for OP_MAIN_CLOSE_THREAD
+   index menu: <close-thread>
+ */
+OP_MAIN_CLOSE_THREAD N_("collapse current thread")
+
+/* L10N: Help screen description for OP_MAIN_CLOSE_ALL_THREADS
+   index menu: <close-all-threads>
+ */
+OP_MAIN_CLOSE_ALL_THREADS N_("collapse all threads")
+
 /* L10N: Help screen description for OP_DESCEND_DIRECTORY
    browser menu: <descend-directory>
  */
diff --git a/curs_main.c b/curs_main.c
index 9fbc6750..843efec9 100644
--- a/curs_main.c
+++ b/curs_main.c
@@ -2060,6 +2060,8 @@ int mutt_index_menu (void)
         break;
 
       case OP_MAIN_COLLAPSE_THREAD:
+      case OP_MAIN_CLOSE_THREAD:
+      case OP_MAIN_OPEN_THREAD:
         CHECK_MSGCOUNT;
         CHECK_VISIBLE;
 
@@ -2069,7 +2071,8 @@ int mutt_index_menu (void)
           break;
         }
 
-        if (CURHDR->collapsed)
+        if ((op == OP_MAIN_COLLAPSE_THREAD || op == OP_MAIN_OPEN_THREAD) &&
+            CURHDR->collapsed)
         {
           /* Note this returns the *old* virtual index of the root message.
            *
@@ -2081,29 +2084,32 @@ int mutt_index_menu (void)
           if (option (OPTUNCOLLAPSEJUMP))
             menu->current = mutt_thread_next_unread (Context, CURHDR);
         }
-        else if (option (OPTCOLLAPSEUNREAD) || !UNREAD (CURHDR))
+        else if (op == OP_MAIN_COLLAPSE_THREAD || op == OP_MAIN_CLOSE_THREAD)
         {
-          HEADER *base;
-          int final;
-          /* This also returns the *old* virtual index of the root, but now
-           * we have to find the new position of the root, which isn't
-           * the same for sort=reverse-threads. */
-          final = mutt_collapse_thread (Context, CURHDR);
-          base = Context->hdrs[Context->v2r[final]];
-          mutt_set_virtual (Context);
-          for (j = 0; j < Context->vcount; j++)
+          if (option (OPTCOLLAPSEUNREAD) || !UNREAD (CURHDR))
           {
-            if (Context->hdrs[Context->v2r[j]]->index == base->index)
+            HEADER *base;
+            int final;
+            /* This also returns the *old* virtual index of the root, but now
+             * we have to find the new position of the root, which isn't
+             * the same for sort=reverse-threads. */
+            final = mutt_collapse_thread (Context, CURHDR);
+            base = Context->hdrs[Context->v2r[final]];
+            mutt_set_virtual (Context);
+            for (j = 0; j < Context->vcount; j++)
             {
-              menu->current = j;
-              break;
+              if (Context->hdrs[Context->v2r[j]]->index == base->index)
+              {
+                menu->current = j;
+                break;
+              }
             }
           }
-        }
-        else
-        {
-          mutt_error _("Thread contains unread messages.");
-          break;
+          else
+          {
+            mutt_error _("Thread contains unread messages.");
+            break;
+          }
         }
 
         menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
@@ -2111,6 +2117,8 @@ int mutt_index_menu (void)
         break;
 
       case OP_MAIN_COLLAPSE_ALL:
+      case OP_MAIN_OPEN_ALL_THREADS:
+      case OP_MAIN_CLOSE_ALL_THREADS:
         CHECK_MSGCOUNT;
         CHECK_VISIBLE;
 
@@ -2125,17 +2133,25 @@ int mutt_index_menu (void)
           THREAD *thread, *top;
           int final;
 
-          if (CURHDR->collapsed)
-            final = mutt_uncollapse_thread (Context, CURHDR);
-          else if (option (OPTCOLLAPSEUNREAD) || !UNREAD (CURHDR))
-            final = mutt_collapse_thread (Context, CURHDR);
+          if (op == OP_MAIN_COLLAPSE_ALL)
+            Context->collapsed = !Context->collapsed;
+          else if (op == OP_MAIN_OPEN_ALL_THREADS)
+            Context->collapsed = 0;
           else
-            final = CURHDR->virtual;
+            Context->collapsed = 1;
+
+          final = CURHDR->virtual;
+          if (CURHDR->collapsed != Context->collapsed)
+          {
+            if (CURHDR->collapsed)
+              final = mutt_uncollapse_thread (Context, CURHDR);
+            else if (option (OPTCOLLAPSEUNREAD) || !UNREAD (CURHDR))
+              final = mutt_collapse_thread (Context, CURHDR);
+          }
 
           base = Context->hdrs[Context->v2r[final]];
 
           top = Context->tree;
-          Context->collapsed = !Context->collapsed;
           while ((thread = top) != NULL)
           {
             while (!thread->message)
diff --git a/functions.h b/functions.h
index 5c640afc..81705ddd 100644
--- a/functions.h
+++ b/functions.h
@@ -145,6 +145,8 @@ const struct menu_func_op_t OpMain[] = { /* map: index */
   { "change-folder-readonly",    OP_MAIN_CHANGE_FOLDER_READONLY },
   { "check-traditional-pgp",     OP_CHECK_TRADITIONAL },
   { "clear-flag",                OP_MAIN_CLEAR_FLAG },
+  { "close-thread",              OP_MAIN_CLOSE_THREAD },
+  { "close-all-threads",         OP_MAIN_CLOSE_ALL_THREADS },
   { "collapse-all",              OP_MAIN_COLLAPSE_ALL },
   { "collapse-thread",           OP_MAIN_COLLAPSE_THREAD },
   { "compose-to-sender",         OP_COMPOSE_TO_SENDER },
@@ -191,6 +193,8 @@ const struct menu_func_op_t OpMain[] = { /* map: index */
   { "next-undeleted",            OP_MAIN_NEXT_UNDELETED },
   { "next-unread",               OP_MAIN_NEXT_UNREAD },
   { "next-unread-mailbox",       OP_MAIN_NEXT_UNREAD_MAILBOX },
+  { "open-thread",               OP_MAIN_OPEN_THREAD },
+  { "open-all-threads",          OP_MAIN_OPEN_ALL_THREADS },
   { "parent-message",            OP_MAIN_PARENT_MESSAGE },
   { "pipe-message",              OP_PIPE },
   { "previous-new",              OP_MAIN_PREV_NEW },
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.