From 37583f0a69d22668bdd47e0b30b61d8dac74bdf6 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 16 Aug 2019 11:49:12 +0000 Subject: Add a flag to reverse sort in the various choose modes, from Benjamin Poirier in GitHub issue 1875. --- window-tree.c | 168 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 88 insertions(+), 80 deletions(-) (limited to 'window-tree.c') diff --git a/window-tree.c b/window-tree.c index b9fc4a6a..a0127c2f 100644 --- a/window-tree.c +++ b/window-tree.c @@ -89,6 +89,7 @@ static const char *window_tree_sort_list[] = { "name", "time" }; +static struct mode_tree_sort_criteria *window_tree_sort; enum window_tree_type { WINDOW_TREE_NONE, @@ -184,62 +185,92 @@ window_tree_free_item(struct window_tree_itemdata *item) } static int -window_tree_cmp_session_name(const void *a0, const void *b0) +window_tree_cmp_session(const void *a0, const void *b0) { - const struct session *const *a = a0; - const struct session *const *b = b0; + const struct session *const *a = a0; + const struct session *const *b = b0; + const struct session *sa = *a; + const struct session *sb = *b; + int result; - return (strcmp((*a)->name, (*b)->name)); -} - -static int -window_tree_cmp_session_time(const void *a0, const void *b0) -{ - const struct session *const *a = a0; - const struct session *const *b = b0; + switch (window_tree_sort->field) { + case WINDOW_TREE_BY_INDEX: + result = sa->id - sb->id; + break; + case WINDOW_TREE_BY_TIME: + if (timercmp(&sa->activity_time, &sb->activity_time, >)) { + result = -1; + break; + } + if (timercmp(&sa->activity_time, &sb->activity_time, <)) { + result = 1; + break; + } + /* FALLTHROUGH */ + case WINDOW_TREE_BY_NAME: + result = strcmp(sa->name, sb->name); + break; + } - if (timercmp(&(*a)->activity_time, &(*b)->activity_time, >)) - return (-1); - if (timercmp(&(*a)->activity_time, &(*b)->activity_time, <)) - return (1); - return (strcmp((*a)->name, (*b)->name)); + if (window_tree_sort->reversed) + result = -result; + return (result); } static int -window_tree_cmp_window_name(const void *a0, const void *b0) +window_tree_cmp_window(const void *a0, const void *b0) { - const struct winlink *const *a = a0; - const struct winlink *const *b = b0; - - return (strcmp((*a)->window->name, (*b)->window->name)); -} + const struct winlink *const *a = a0; + const struct winlink *const *b = b0; + const struct winlink *wla = *a; + const struct winlink *wlb = *b; + struct window *wa = wla->window; + struct window *wb = wlb->window; + int result; + + switch (window_tree_sort->field) { + case WINDOW_TREE_BY_INDEX: + result = wla->idx - wlb->idx; + break; + case WINDOW_TREE_BY_TIME: + if (timercmp(&wa->activity_time, &wb->activity_time, >)) { + result = -1; + break; + } + if (timercmp(&wa->activity_time, &wb->activity_time, <)) { + result = 1; + break; + } + /* FALLTHROUGH */ + case WINDOW_TREE_BY_NAME: + result = strcmp(wa->name, wb->name); + break; + } -static int -window_tree_cmp_window_time(const void *a0, const void *b0) -{ - const struct winlink *const *a = a0; - const struct winlink *const *b = b0; - - if (timercmp(&(*a)->window->activity_time, - &(*b)->window->activity_time, >)) - return (-1); - if (timercmp(&(*a)->window->activity_time, - &(*b)->window->activity_time, <)) - return (1); - return (strcmp((*a)->window->name, (*b)->window->name)); + if (window_tree_sort->reversed) + result = -result; + return (result); } static int -window_tree_cmp_pane_time(const void *a0, const void *b0) +window_tree_cmp_pane(const void *a0, const void *b0) { - const struct window_pane *const *a = a0; - const struct window_pane *const *b = b0; + const struct window_pane *const *a = a0; + const struct window_pane *const *b = b0; + int result; - if ((*a)->active_point < (*b)->active_point) - return (-1); - if ((*a)->active_point > (*b)->active_point) - return (1); - return (0); + if (window_tree_sort->field == WINDOW_TREE_BY_TIME) + result = (*a)->active_point - (*b)->active_point; + else { + /* + * Panes don't have names, so use number order for any other + * sort field. + */ + result = (*a)->id - (*b)->id; + } + if (window_tree_sort->reversed) + result *= -1; + return (result); } static void @@ -285,8 +316,9 @@ window_tree_filter_pane(struct session *s, struct winlink *wl, } static int -window_tree_build_window(struct session *s, struct winlink *wl, void* modedata, - u_int sort_type, struct mode_tree_item *parent, const char *filter) +window_tree_build_window(struct session *s, struct winlink *wl, + void* modedata, struct mode_tree_sort_criteria *sort_crit, + struct mode_tree_item *parent, const char *filter) { struct window_tree_modedata *data = modedata; struct window_tree_itemdata *item; @@ -335,16 +367,8 @@ window_tree_build_window(struct session *s, struct winlink *wl, void* modedata, if (n == 0) goto empty; - switch (sort_type) { - case WINDOW_TREE_BY_INDEX: - break; - case WINDOW_TREE_BY_NAME: - /* Panes don't have names, so leave in number order. */ - break; - case WINDOW_TREE_BY_TIME: - qsort(l, n, sizeof *l, window_tree_cmp_pane_time); - break; - } + window_tree_sort = sort_crit; + qsort(l, n, sizeof *l, window_tree_cmp_pane); for (i = 0; i < n; i++) window_tree_build_pane(s, wl, l[i], modedata, mti); @@ -360,7 +384,7 @@ empty: static void window_tree_build_session(struct session *s, void* modedata, - u_int sort_type, const char *filter) + struct mode_tree_sort_criteria *sort_crit, const char *filter) { struct window_tree_modedata *data = modedata; struct window_tree_itemdata *item; @@ -392,20 +416,12 @@ window_tree_build_session(struct session *s, void* modedata, l = xreallocarray(l, n + 1, sizeof *l); l[n++] = wl; } - switch (sort_type) { - case WINDOW_TREE_BY_INDEX: - break; - case WINDOW_TREE_BY_NAME: - qsort(l, n, sizeof *l, window_tree_cmp_window_name); - break; - case WINDOW_TREE_BY_TIME: - qsort(l, n, sizeof *l, window_tree_cmp_window_time); - break; - } + window_tree_sort = sort_crit; + qsort(l, n, sizeof *l, window_tree_cmp_window); empty = 0; for (i = 0; i < n; i++) { - if (!window_tree_build_window(s, l[i], modedata, sort_type, mti, + if (!window_tree_build_window(s, l[i], modedata, sort_crit, mti, filter)) empty++; } @@ -418,8 +434,8 @@ window_tree_build_session(struct session *s, void* modedata, } static void -window_tree_build(void *modedata, u_int sort_type, uint64_t *tag, - const char *filter) +window_tree_build(void *modedata, struct mode_tree_sort_criteria *sort_crit, + uint64_t *tag, const char *filter) { struct window_tree_modedata *data = modedata; struct session *s, **l; @@ -446,19 +462,11 @@ window_tree_build(void *modedata, u_int sort_type, uint64_t *tag, l = xreallocarray(l, n + 1, sizeof *l); l[n++] = s; } - switch (sort_type) { - case WINDOW_TREE_BY_INDEX: - break; - case WINDOW_TREE_BY_NAME: - qsort(l, n, sizeof *l, window_tree_cmp_session_name); - break; - case WINDOW_TREE_BY_TIME: - qsort(l, n, sizeof *l, window_tree_cmp_session_time); - break; - } + window_tree_sort = sort_crit; + qsort(l, n, sizeof *l, window_tree_cmp_session); for (i = 0; i < n; i++) - window_tree_build_session(l[i], modedata, sort_type, filter); + window_tree_build_session(l[i], modedata, sort_crit, filter); free(l); switch (data->type) { -- cgit v1.2.3