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
