mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:26:05 +00:00 
			
		
		
		
	Add a flag to reverse sort in the various choose modes, from Benjamin
Poirier in GitHub issue 1875.
This commit is contained in:
		@@ -30,8 +30,8 @@ const struct cmd_entry cmd_choose_tree_entry = {
 | 
			
		||||
	.name = "choose-tree",
 | 
			
		||||
	.alias = NULL,
 | 
			
		||||
 | 
			
		||||
	.args = { "F:Gf:NO:st:wZ", 0, 1 },
 | 
			
		||||
	.usage = "[-GNsw] [-F format] [-f filter] [-O sort-order] "
 | 
			
		||||
	.args = { "F:Gf:NO:rst:wZ", 0, 1 },
 | 
			
		||||
	.usage = "[-GNrswZ] [-F format] [-f filter] [-O sort-order] "
 | 
			
		||||
	         CMD_TARGET_PANE_USAGE " [template]",
 | 
			
		||||
 | 
			
		||||
	.target = { 't', CMD_FIND_PANE, 0 },
 | 
			
		||||
@@ -44,8 +44,8 @@ const struct cmd_entry cmd_choose_client_entry = {
 | 
			
		||||
	.name = "choose-client",
 | 
			
		||||
	.alias = NULL,
 | 
			
		||||
 | 
			
		||||
	.args = { "F:f:NO:t:Z", 0, 1 },
 | 
			
		||||
	.usage = "[-N] [-F format] [-f filter] [-O sort-order] "
 | 
			
		||||
	.args = { "F:f:NO:rt:Z", 0, 1 },
 | 
			
		||||
	.usage = "[-NrZ] [-F format] [-f filter] [-O sort-order] "
 | 
			
		||||
	         CMD_TARGET_PANE_USAGE " [template]",
 | 
			
		||||
 | 
			
		||||
	.target = { 't', CMD_FIND_PANE, 0 },
 | 
			
		||||
@@ -58,8 +58,8 @@ const struct cmd_entry cmd_choose_buffer_entry = {
 | 
			
		||||
	.name = "choose-buffer",
 | 
			
		||||
	.alias = NULL,
 | 
			
		||||
 | 
			
		||||
	.args = { "F:f:NO:t:Z", 0, 1 },
 | 
			
		||||
	.usage = "[-N] [-F format] [-f filter] [-O sort-order] "
 | 
			
		||||
	.args = { "F:f:NO:rt:Z", 0, 1 },
 | 
			
		||||
	.usage = "[-NrZ] [-F format] [-f filter] [-O sort-order] "
 | 
			
		||||
	         CMD_TARGET_PANE_USAGE " [template]",
 | 
			
		||||
 | 
			
		||||
	.target = { 't', CMD_FIND_PANE, 0 },
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										25
									
								
								mode-tree.c
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								mode-tree.c
									
									
									
									
									
								
							@@ -39,7 +39,7 @@ struct mode_tree_data {
 | 
			
		||||
 | 
			
		||||
	const char		**sort_list;
 | 
			
		||||
	u_int			  sort_size;
 | 
			
		||||
	u_int			  sort_type;
 | 
			
		||||
	struct mode_tree_sort_criteria sort_crit;
 | 
			
		||||
 | 
			
		||||
	mode_tree_build_cb        buildcb;
 | 
			
		||||
	mode_tree_draw_cb         drawcb;
 | 
			
		||||
@@ -334,7 +334,6 @@ mode_tree_start(struct window_pane *wp, struct args *args,
 | 
			
		||||
 | 
			
		||||
	mtd->sort_list = sort_list;
 | 
			
		||||
	mtd->sort_size = sort_size;
 | 
			
		||||
	mtd->sort_type = 0;
 | 
			
		||||
 | 
			
		||||
	mtd->preview = !args_has(args, 'N');
 | 
			
		||||
 | 
			
		||||
@@ -342,9 +341,10 @@ mode_tree_start(struct window_pane *wp, struct args *args,
 | 
			
		||||
	if (sort != NULL) {
 | 
			
		||||
		for (i = 0; i < sort_size; i++) {
 | 
			
		||||
			if (strcasecmp(sort, sort_list[i]) == 0)
 | 
			
		||||
				mtd->sort_type = i;
 | 
			
		||||
				mtd->sort_crit.field = i;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	mtd->sort_crit.reversed = args_has(args, 'r');
 | 
			
		||||
 | 
			
		||||
	if (args_has(args, 'f'))
 | 
			
		||||
		mtd->filter = xstrdup(args_get(args, 'f'));
 | 
			
		||||
@@ -392,10 +392,10 @@ mode_tree_build(struct mode_tree_data *mtd)
 | 
			
		||||
	TAILQ_CONCAT(&mtd->saved, &mtd->children, entry);
 | 
			
		||||
	TAILQ_INIT(&mtd->children);
 | 
			
		||||
 | 
			
		||||
	mtd->buildcb(mtd->modedata, mtd->sort_type, &tag, mtd->filter);
 | 
			
		||||
	mtd->buildcb(mtd->modedata, &mtd->sort_crit, &tag, mtd->filter);
 | 
			
		||||
	mtd->no_matches = TAILQ_EMPTY(&mtd->children);
 | 
			
		||||
	if (mtd->no_matches)
 | 
			
		||||
		mtd->buildcb(mtd->modedata, mtd->sort_type, &tag, NULL);
 | 
			
		||||
		mtd->buildcb(mtd->modedata, &mtd->sort_crit, &tag, NULL);
 | 
			
		||||
 | 
			
		||||
	mode_tree_free_items(&mtd->saved);
 | 
			
		||||
	TAILQ_INIT(&mtd->saved);
 | 
			
		||||
@@ -634,8 +634,9 @@ mode_tree_draw(struct mode_tree_data *mtd)
 | 
			
		||||
	screen_write_cursormove(&ctx, 0, h, 0);
 | 
			
		||||
	screen_write_box(&ctx, w, sy - h);
 | 
			
		||||
 | 
			
		||||
	xasprintf(&text, " %s (sort: %s)", mti->name,
 | 
			
		||||
	    mtd->sort_list[mtd->sort_type]);
 | 
			
		||||
	xasprintf(&text, " %s (sort: %s%s)", mti->name,
 | 
			
		||||
	    mtd->sort_list[mtd->sort_crit.field],
 | 
			
		||||
	    mtd->sort_crit.reversed ? ", reversed" : "");
 | 
			
		||||
	if (w - 2 >= strlen(text)) {
 | 
			
		||||
		screen_write_cursormove(&ctx, 1, h, 0);
 | 
			
		||||
		screen_write_puts(&ctx, &gc0, "%s", text);
 | 
			
		||||
@@ -993,9 +994,13 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case 'O':
 | 
			
		||||
		mtd->sort_type++;
 | 
			
		||||
		if (mtd->sort_type == mtd->sort_size)
 | 
			
		||||
			mtd->sort_type = 0;
 | 
			
		||||
		mtd->sort_crit.field++;
 | 
			
		||||
		if (mtd->sort_crit.field == mtd->sort_size)
 | 
			
		||||
			mtd->sort_crit.field = 0;
 | 
			
		||||
		mode_tree_build(mtd);
 | 
			
		||||
		break;
 | 
			
		||||
	case 'r':
 | 
			
		||||
		mtd->sort_crit.reversed = !mtd->sort_crit.reversed;
 | 
			
		||||
		mode_tree_build(mtd);
 | 
			
		||||
		break;
 | 
			
		||||
	case KEYC_LEFT:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										27
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								tmux.1
									
									
									
									
									
								
							@@ -1692,7 +1692,7 @@ the end of the visible pane.
 | 
			
		||||
The default is to capture only the visible contents of the pane.
 | 
			
		||||
.It Xo
 | 
			
		||||
.Ic choose-client
 | 
			
		||||
.Op Fl NZ
 | 
			
		||||
.Op Fl NrZ
 | 
			
		||||
.Op Fl F Ar format
 | 
			
		||||
.Op Fl f Ar filter
 | 
			
		||||
.Op Fl O Ar sort-order
 | 
			
		||||
@@ -1721,7 +1721,8 @@ The following keys may be used in client mode:
 | 
			
		||||
.It Li "z" Ta "Suspend selected client"
 | 
			
		||||
.It Li "Z" Ta "Suspend tagged clients"
 | 
			
		||||
.It Li "f" Ta "Enter a format to filter items"
 | 
			
		||||
.It Li "O" Ta "Change sort order"
 | 
			
		||||
.It Li "O" Ta "Change sort field"
 | 
			
		||||
.It Li "r" Ta "Reverse sort order"
 | 
			
		||||
.It Li "v" Ta "Toggle preview"
 | 
			
		||||
.It Li "q" Ta "Exit mode"
 | 
			
		||||
.El
 | 
			
		||||
@@ -1736,12 +1737,14 @@ If
 | 
			
		||||
is not given, "detach-client -t '%%'" is used.
 | 
			
		||||
.Pp
 | 
			
		||||
.Fl O
 | 
			
		||||
specifies the initial sort order: one of
 | 
			
		||||
specifies the initial sort field: one of
 | 
			
		||||
.Ql name ,
 | 
			
		||||
.Ql size ,
 | 
			
		||||
.Ql creation ,
 | 
			
		||||
or
 | 
			
		||||
.Ql activity .
 | 
			
		||||
.Fl r
 | 
			
		||||
reverses the sort order.
 | 
			
		||||
.Fl f
 | 
			
		||||
specifies an initial filter: the filter is a format - if it evaluates to zero,
 | 
			
		||||
the item in the list is not shown, otherwise it is shown.
 | 
			
		||||
@@ -1753,7 +1756,7 @@ starts without the preview.
 | 
			
		||||
This command works only if at least one client is attached.
 | 
			
		||||
.It Xo
 | 
			
		||||
.Ic choose-tree
 | 
			
		||||
.Op Fl GNswZ
 | 
			
		||||
.Op Fl GNrswZ
 | 
			
		||||
.Op Fl F Ar format
 | 
			
		||||
.Op Fl f Ar filter
 | 
			
		||||
.Op Fl O Ar sort-order
 | 
			
		||||
@@ -1785,7 +1788,8 @@ The following keys may be used in tree mode:
 | 
			
		||||
.It Li "C-t" Ta "Tag all items"
 | 
			
		||||
.It Li "\&:" Ta "Run a command for each tagged item"
 | 
			
		||||
.It Li "f" Ta "Enter a format to filter items"
 | 
			
		||||
.It Li "O" Ta "Change sort order"
 | 
			
		||||
.It Li "O" Ta "Change sort field"
 | 
			
		||||
.It Li "r" Ta "Reverse sort order"
 | 
			
		||||
.It Li "v" Ta "Toggle preview"
 | 
			
		||||
.It Li "q" Ta "Exit mode"
 | 
			
		||||
.El
 | 
			
		||||
@@ -1800,11 +1804,13 @@ If
 | 
			
		||||
is not given, "switch-client -t '%%'" is used.
 | 
			
		||||
.Pp
 | 
			
		||||
.Fl O
 | 
			
		||||
specifies the initial sort order: one of
 | 
			
		||||
specifies the initial sort field: one of
 | 
			
		||||
.Ql index ,
 | 
			
		||||
.Ql name ,
 | 
			
		||||
or
 | 
			
		||||
.Ql time .
 | 
			
		||||
.Fl r
 | 
			
		||||
reverses the sort order.
 | 
			
		||||
.Fl f
 | 
			
		||||
specifies an initial filter: the filter is a format - if it evaluates to zero,
 | 
			
		||||
the item in the list is not shown, otherwise it is shown.
 | 
			
		||||
@@ -4860,7 +4866,7 @@ The buffer commands are as follows:
 | 
			
		||||
.Bl -tag -width Ds
 | 
			
		||||
.It Xo
 | 
			
		||||
.Ic choose-buffer
 | 
			
		||||
.Op Fl NZ
 | 
			
		||||
.Op Fl NZr
 | 
			
		||||
.Op Fl F Ar format
 | 
			
		||||
.Op Fl f Ar filter
 | 
			
		||||
.Op Fl O Ar sort-order
 | 
			
		||||
@@ -4887,7 +4893,8 @@ The following keys may be used in buffer mode:
 | 
			
		||||
.It Li "d" Ta "Delete selected buffer"
 | 
			
		||||
.It Li "D" Ta "Delete tagged buffers"
 | 
			
		||||
.It Li "f" Ta "Enter a format to filter items"
 | 
			
		||||
.It Li "O" Ta "Change sort order"
 | 
			
		||||
.It Li "O" Ta "Change sort field"
 | 
			
		||||
.It Li "r" Ta "Reverse sort order"
 | 
			
		||||
.It Li "v" Ta "Toggle preview"
 | 
			
		||||
.It Li "q" Ta "Exit mode"
 | 
			
		||||
.El
 | 
			
		||||
@@ -4902,11 +4909,13 @@ If
 | 
			
		||||
is not given, "paste-buffer -b '%%'" is used.
 | 
			
		||||
.Pp
 | 
			
		||||
.Fl O
 | 
			
		||||
specifies the initial sort order: one of
 | 
			
		||||
specifies the initial sort field: one of
 | 
			
		||||
.Ql time ,
 | 
			
		||||
.Ql name
 | 
			
		||||
or
 | 
			
		||||
.Ql size .
 | 
			
		||||
.Fl r
 | 
			
		||||
reverses the sort order.
 | 
			
		||||
.Fl f
 | 
			
		||||
specifies an initial filter: the filter is a format - if it evaluates to zero,
 | 
			
		||||
the item in the list is not shown, otherwise it is shown.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1682,6 +1682,12 @@ struct spawn_context {
 | 
			
		||||
#define SPAWN_EMPTY 0x40
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Mode tree sort order. */
 | 
			
		||||
struct mode_tree_sort_criteria {
 | 
			
		||||
	u_int	field;
 | 
			
		||||
	int	reversed;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* tmux.c */
 | 
			
		||||
extern struct options	*global_options;
 | 
			
		||||
extern struct options	*global_s_options;
 | 
			
		||||
@@ -2473,7 +2479,8 @@ u_int		 layout_set_next(struct window *);
 | 
			
		||||
u_int		 layout_set_previous(struct window *);
 | 
			
		||||
 | 
			
		||||
/* mode-tree.c */
 | 
			
		||||
typedef void (*mode_tree_build_cb)(void *, u_int, uint64_t *, const char *);
 | 
			
		||||
typedef void (*mode_tree_build_cb)(void *, struct mode_tree_sort_criteria *,
 | 
			
		||||
				   uint64_t *, const char *);
 | 
			
		||||
typedef void (*mode_tree_draw_cb)(void *, void *, struct screen_write_ctx *,
 | 
			
		||||
	     u_int, u_int);
 | 
			
		||||
typedef int (*mode_tree_search_cb)(void *, void *, const char *);
 | 
			
		||||
 
 | 
			
		||||
@@ -75,6 +75,7 @@ static const char *window_buffer_sort_list[] = {
 | 
			
		||||
	"name",
 | 
			
		||||
	"size"
 | 
			
		||||
};
 | 
			
		||||
static struct mode_tree_sort_criteria *window_buffer_sort;
 | 
			
		||||
 | 
			
		||||
struct window_buffer_itemdata {
 | 
			
		||||
	const char	*name;
 | 
			
		||||
@@ -113,43 +114,29 @@ window_buffer_free_item(struct window_buffer_itemdata *item)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
window_buffer_cmp_name(const void *a0, const void *b0)
 | 
			
		||||
window_buffer_cmp(const void *a0, const void *b0)
 | 
			
		||||
{
 | 
			
		||||
	const struct window_buffer_itemdata *const *a = a0;
 | 
			
		||||
	const struct window_buffer_itemdata *const *b = b0;
 | 
			
		||||
	const struct window_buffer_itemdata *const	*a = a0;
 | 
			
		||||
	const struct window_buffer_itemdata *const	*b = b0;
 | 
			
		||||
	int						 result = 0;
 | 
			
		||||
 | 
			
		||||
	return (strcmp((*a)->name, (*b)->name));
 | 
			
		||||
}
 | 
			
		||||
	if (window_buffer_sort->field == WINDOW_BUFFER_BY_TIME)
 | 
			
		||||
		result = (*b)->order - (*a)->order;
 | 
			
		||||
	else if (window_buffer_sort->field == WINDOW_BUFFER_BY_SIZE)
 | 
			
		||||
		result = (*b)->size - (*a)->size;
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
window_buffer_cmp_time(const void *a0, const void *b0)
 | 
			
		||||
{
 | 
			
		||||
	const struct window_buffer_itemdata *const *a = a0;
 | 
			
		||||
	const struct window_buffer_itemdata *const *b = b0;
 | 
			
		||||
	/* Use WINDOW_BUFFER_BY_NAME as default order and tie breaker. */
 | 
			
		||||
	if (result == 0)
 | 
			
		||||
		result = strcmp((*a)->name, (*b)->name);
 | 
			
		||||
 | 
			
		||||
	if ((*a)->order > (*b)->order)
 | 
			
		||||
		return (-1);
 | 
			
		||||
	if ((*a)->order < (*b)->order)
 | 
			
		||||
		return (1);
 | 
			
		||||
	return (strcmp((*a)->name, (*b)->name));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
window_buffer_cmp_size(const void *a0, const void *b0)
 | 
			
		||||
{
 | 
			
		||||
	const struct window_buffer_itemdata *const *a = a0;
 | 
			
		||||
	const struct window_buffer_itemdata *const *b = b0;
 | 
			
		||||
 | 
			
		||||
	if ((*a)->size > (*b)->size)
 | 
			
		||||
		return (-1);
 | 
			
		||||
	if ((*a)->size < (*b)->size)
 | 
			
		||||
		return (1);
 | 
			
		||||
	return (strcmp((*a)->name, (*b)->name));
 | 
			
		||||
	if (window_buffer_sort->reversed)
 | 
			
		||||
		result = -result;
 | 
			
		||||
	return (result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
window_buffer_build(void *modedata, u_int sort_type, __unused uint64_t *tag,
 | 
			
		||||
    const char *filter)
 | 
			
		||||
window_buffer_build(void *modedata, struct mode_tree_sort_criteria *sort_crit,
 | 
			
		||||
    __unused uint64_t *tag, const char *filter)
 | 
			
		||||
{
 | 
			
		||||
	struct window_buffer_modedata	*data = modedata;
 | 
			
		||||
	struct window_buffer_itemdata	*item;
 | 
			
		||||
@@ -175,20 +162,9 @@ window_buffer_build(void *modedata, u_int sort_type, __unused uint64_t *tag,
 | 
			
		||||
		item->order = paste_buffer_order(pb);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (sort_type) {
 | 
			
		||||
	case WINDOW_BUFFER_BY_NAME:
 | 
			
		||||
		qsort(data->item_list, data->item_size, sizeof *data->item_list,
 | 
			
		||||
		    window_buffer_cmp_name);
 | 
			
		||||
		break;
 | 
			
		||||
	case WINDOW_BUFFER_BY_TIME:
 | 
			
		||||
		qsort(data->item_list, data->item_size, sizeof *data->item_list,
 | 
			
		||||
		    window_buffer_cmp_time);
 | 
			
		||||
		break;
 | 
			
		||||
	case WINDOW_BUFFER_BY_SIZE:
 | 
			
		||||
		qsort(data->item_list, data->item_size, sizeof *data->item_list,
 | 
			
		||||
		    window_buffer_cmp_size);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	window_buffer_sort = sort_crit;
 | 
			
		||||
	qsort(data->item_list, data->item_size, sizeof *data->item_list,
 | 
			
		||||
	    window_buffer_cmp);
 | 
			
		||||
 | 
			
		||||
	if (cmd_find_valid_state(&data->fs)) {
 | 
			
		||||
		s = data->fs.s;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										104
									
								
								window-client.c
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								window-client.c
									
									
									
									
									
								
							@@ -75,6 +75,7 @@ static const char *window_client_sort_list[] = {
 | 
			
		||||
	"creation",
 | 
			
		||||
	"activity"
 | 
			
		||||
};
 | 
			
		||||
static struct mode_tree_sort_criteria *window_client_sort;
 | 
			
		||||
 | 
			
		||||
struct window_client_itemdata {
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
@@ -110,60 +111,48 @@ window_client_free_item(struct window_client_itemdata *item)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
window_client_cmp_name(const void *a0, const void *b0)
 | 
			
		||||
window_client_cmp(const void *a0, const void *b0)
 | 
			
		||||
{
 | 
			
		||||
	const struct window_client_itemdata *const *a = a0;
 | 
			
		||||
	const struct window_client_itemdata *const *b = b0;
 | 
			
		||||
	const struct window_client_itemdata *const	*a = a0;
 | 
			
		||||
	const struct window_client_itemdata *const	*b = b0;
 | 
			
		||||
	const struct window_client_itemdata		*itema = *a;
 | 
			
		||||
	const struct window_client_itemdata		*itemb = *b;
 | 
			
		||||
	struct client					*ca = itema->c;
 | 
			
		||||
	struct client					*cb = itemb->c;
 | 
			
		||||
	int						 result = 0;
 | 
			
		||||
 | 
			
		||||
	return (strcmp((*a)->c->name, (*b)->c->name));
 | 
			
		||||
}
 | 
			
		||||
	switch (window_client_sort->field) {
 | 
			
		||||
	case WINDOW_CLIENT_BY_SIZE:
 | 
			
		||||
		result = ca->tty.sx - cb->tty.sx;
 | 
			
		||||
		if (result == 0)
 | 
			
		||||
			result = ca->tty.sy - cb->tty.sy;
 | 
			
		||||
		break;
 | 
			
		||||
	case WINDOW_CLIENT_BY_CREATION_TIME:
 | 
			
		||||
		if (timercmp(&ca->creation_time, &cb->creation_time, >))
 | 
			
		||||
			result = -1;
 | 
			
		||||
		else if (timercmp(&ca->creation_time, &cb->creation_time, <))
 | 
			
		||||
			result = 1;
 | 
			
		||||
		break;
 | 
			
		||||
	case WINDOW_CLIENT_BY_ACTIVITY_TIME:
 | 
			
		||||
		if (timercmp(&ca->activity_time, &cb->activity_time, >))
 | 
			
		||||
			result = -1;
 | 
			
		||||
		else if (timercmp(&ca->activity_time, &cb->activity_time, <))
 | 
			
		||||
			result = 1;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
window_client_cmp_size(const void *a0, const void *b0)
 | 
			
		||||
{
 | 
			
		||||
	const struct window_client_itemdata *const *a = a0;
 | 
			
		||||
	const struct window_client_itemdata *const *b = b0;
 | 
			
		||||
	/* Use WINDOW_CLIENT_BY_NAME as default order and tie breaker. */
 | 
			
		||||
	if (result == 0)
 | 
			
		||||
		result = strcmp(ca->name, cb->name);
 | 
			
		||||
 | 
			
		||||
	if ((*a)->c->tty.sx < (*b)->c->tty.sx)
 | 
			
		||||
		return (-1);
 | 
			
		||||
	if ((*a)->c->tty.sx > (*b)->c->tty.sx)
 | 
			
		||||
		return (1);
 | 
			
		||||
	if ((*a)->c->tty.sy < (*b)->c->tty.sy)
 | 
			
		||||
		return (-1);
 | 
			
		||||
	if ((*a)->c->tty.sy > (*b)->c->tty.sy)
 | 
			
		||||
		return (1);
 | 
			
		||||
	return (strcmp((*a)->c->name, (*b)->c->name));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
window_client_cmp_creation_time(const void *a0, const void *b0)
 | 
			
		||||
{
 | 
			
		||||
	const struct window_client_itemdata *const *a = a0;
 | 
			
		||||
	const struct window_client_itemdata *const *b = b0;
 | 
			
		||||
 | 
			
		||||
	if (timercmp(&(*a)->c->creation_time, &(*b)->c->creation_time, >))
 | 
			
		||||
		return (-1);
 | 
			
		||||
	if (timercmp(&(*a)->c->creation_time, &(*b)->c->creation_time, <))
 | 
			
		||||
		return (1);
 | 
			
		||||
	return (strcmp((*a)->c->name, (*b)->c->name));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
window_client_cmp_activity_time(const void *a0, const void *b0)
 | 
			
		||||
{
 | 
			
		||||
	const struct window_client_itemdata *const *a = a0;
 | 
			
		||||
	const struct window_client_itemdata *const *b = b0;
 | 
			
		||||
 | 
			
		||||
	if (timercmp(&(*a)->c->activity_time, &(*b)->c->activity_time, >))
 | 
			
		||||
		return (-1);
 | 
			
		||||
	if (timercmp(&(*a)->c->activity_time, &(*b)->c->activity_time, <))
 | 
			
		||||
		return (1);
 | 
			
		||||
	return (strcmp((*a)->c->name, (*b)->c->name));
 | 
			
		||||
	if (window_client_sort->reversed)
 | 
			
		||||
		result = -result;
 | 
			
		||||
	return (result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
window_client_build(void *modedata, u_int sort_type, __unused uint64_t *tag,
 | 
			
		||||
    const char *filter)
 | 
			
		||||
window_client_build(void *modedata, struct mode_tree_sort_criteria *sort_crit,
 | 
			
		||||
    __unused uint64_t *tag, const char *filter)
 | 
			
		||||
{
 | 
			
		||||
	struct window_client_modedata	*data = modedata;
 | 
			
		||||
	struct window_client_itemdata	*item;
 | 
			
		||||
@@ -187,24 +176,9 @@ window_client_build(void *modedata, u_int sort_type, __unused uint64_t *tag,
 | 
			
		||||
		c->references++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (sort_type) {
 | 
			
		||||
	case WINDOW_CLIENT_BY_NAME:
 | 
			
		||||
		qsort(data->item_list, data->item_size, sizeof *data->item_list,
 | 
			
		||||
		    window_client_cmp_name);
 | 
			
		||||
		break;
 | 
			
		||||
	case WINDOW_CLIENT_BY_SIZE:
 | 
			
		||||
		qsort(data->item_list, data->item_size, sizeof *data->item_list,
 | 
			
		||||
		    window_client_cmp_size);
 | 
			
		||||
		break;
 | 
			
		||||
	case WINDOW_CLIENT_BY_CREATION_TIME:
 | 
			
		||||
		qsort(data->item_list, data->item_size, sizeof *data->item_list,
 | 
			
		||||
		    window_client_cmp_creation_time);
 | 
			
		||||
		break;
 | 
			
		||||
	case WINDOW_CLIENT_BY_ACTIVITY_TIME:
 | 
			
		||||
		qsort(data->item_list, data->item_size, sizeof *data->item_list,
 | 
			
		||||
		    window_client_cmp_activity_time);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	window_client_sort = sort_crit;
 | 
			
		||||
	qsort(data->item_list, data->item_size, sizeof *data->item_list,
 | 
			
		||||
	    window_client_cmp);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < data->item_size; i++) {
 | 
			
		||||
		item = data->item_list[i];
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										170
									
								
								window-tree.c
									
									
									
									
									
								
							
							
						
						
									
										170
									
								
								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));
 | 
			
		||||
	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 (window_tree_sort->reversed)
 | 
			
		||||
		result = -result;
 | 
			
		||||
	return (result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
window_tree_cmp_session_time(const void *a0, const void *b0)
 | 
			
		||||
window_tree_cmp_window(const void *a0, const void *b0)
 | 
			
		||||
{
 | 
			
		||||
	const struct session *const *a = a0;
 | 
			
		||||
	const struct session *const *b = b0;
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
	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));
 | 
			
		||||
	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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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_pane(const void *a0, const void *b0)
 | 
			
		||||
{
 | 
			
		||||
	const struct winlink *const *a = a0;
 | 
			
		||||
	const struct winlink *const *b = b0;
 | 
			
		||||
	const struct window_pane *const	*a = a0;
 | 
			
		||||
	const struct window_pane *const	*b = b0;
 | 
			
		||||
	int				 result;
 | 
			
		||||
 | 
			
		||||
	return (strcmp((*a)->window->name, (*b)->window->name));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
window_tree_cmp_pane_time(const void *a0, const void *b0)
 | 
			
		||||
{
 | 
			
		||||
	const struct window_pane *const *a = a0;
 | 
			
		||||
	const struct window_pane *const *b = b0;
 | 
			
		||||
 | 
			
		||||
	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) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user