mirror of
https://github.com/tmux/tmux.git
synced 2026-02-08 12:37:20 +00:00
Break sorting out into a common file so formats and modes use the same
code. Also add -O for sorting to the list commands. From Dane Jensen in GitHub issue 4813.
This commit is contained in:
1
Makefile
1
Makefile
@@ -114,6 +114,7 @@ SRCS= alerts.c \
|
||||
spawn.c \
|
||||
status.c \
|
||||
style.c \
|
||||
sort.c \
|
||||
tmux.c \
|
||||
tty-acs.c \
|
||||
tty-draw.c \
|
||||
|
||||
@@ -36,8 +36,8 @@ const struct cmd_entry cmd_list_buffers_entry = {
|
||||
.name = "list-buffers",
|
||||
.alias = "lsb",
|
||||
|
||||
.args = { "F:f:", 0, 0, NULL },
|
||||
.usage = "[-F format] [-f filter]",
|
||||
.args = { "F:f:O:r", 0, 0, NULL },
|
||||
.usage = "[-F format] [-f filter] [-O order]",
|
||||
|
||||
.flags = CMD_AFTERHOOK,
|
||||
.exec = cmd_list_buffers_exec
|
||||
@@ -46,21 +46,26 @@ const struct cmd_entry cmd_list_buffers_entry = {
|
||||
static enum cmd_retval
|
||||
cmd_list_buffers_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct args *args = cmd_get_args(self);
|
||||
struct paste_buffer *pb;
|
||||
struct format_tree *ft;
|
||||
const char *template, *filter;
|
||||
char *line, *expanded;
|
||||
int flag;
|
||||
struct args *args = cmd_get_args(self);
|
||||
struct paste_buffer **l;
|
||||
struct format_tree *ft;
|
||||
const char *template, *filter;
|
||||
char *line, *expanded;
|
||||
int flag;
|
||||
u_int i, n;
|
||||
struct sort_criteria sort_crit;
|
||||
|
||||
if ((template = args_get(args, 'F')) == NULL)
|
||||
template = LIST_BUFFERS_TEMPLATE;
|
||||
filter = args_get(args, 'f');
|
||||
|
||||
pb = NULL;
|
||||
while ((pb = paste_walk(pb)) != NULL) {
|
||||
sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||
sort_crit.reversed = args_has(args, 'r');
|
||||
|
||||
l = sort_get_buffers(&n, &sort_crit);
|
||||
for (i = 0; i < n; i++) {
|
||||
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
||||
format_defaults_paste_buffer(ft, pb);
|
||||
format_defaults_paste_buffer(ft, l[i]);
|
||||
|
||||
if (filter != NULL) {
|
||||
expanded = format_expand(ft, filter);
|
||||
|
||||
@@ -41,8 +41,8 @@ const struct cmd_entry cmd_list_clients_entry = {
|
||||
.name = "list-clients",
|
||||
.alias = "lsc",
|
||||
|
||||
.args = { "F:f:t:", 0, 0, NULL },
|
||||
.usage = "[-F format] [-f filter] " CMD_TARGET_SESSION_USAGE,
|
||||
.args = { "F:f:O:rt:", 0, 0, NULL },
|
||||
.usage = "[-F format] [-f filter] [-O order]" CMD_TARGET_SESSION_USAGE,
|
||||
|
||||
.target = { 't', CMD_FIND_SESSION, 0 },
|
||||
|
||||
@@ -53,15 +53,16 @@ const struct cmd_entry cmd_list_clients_entry = {
|
||||
static enum cmd_retval
|
||||
cmd_list_clients_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct args *args = cmd_get_args(self);
|
||||
struct cmd_find_state *target = cmdq_get_target(item);
|
||||
struct client *c;
|
||||
struct session *s;
|
||||
struct format_tree *ft;
|
||||
const char *template, *filter;
|
||||
u_int idx;
|
||||
char *line, *expanded;
|
||||
int flag;
|
||||
struct args *args = cmd_get_args(self);
|
||||
struct cmd_find_state *target = cmdq_get_target(item);
|
||||
struct client **l;
|
||||
struct session *s;
|
||||
struct format_tree *ft;
|
||||
const char *template, *filter;
|
||||
u_int i, n;
|
||||
char *line, *expanded;
|
||||
int flag;
|
||||
struct sort_criteria sort_crit;
|
||||
|
||||
if (args_has(args, 't'))
|
||||
s = target->s;
|
||||
@@ -72,14 +73,17 @@ cmd_list_clients_exec(struct cmd *self, struct cmdq_item *item)
|
||||
template = LIST_CLIENTS_TEMPLATE;
|
||||
filter = args_get(args, 'f');
|
||||
|
||||
idx = 0;
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (c->session == NULL || (s != NULL && s != c->session))
|
||||
sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||
sort_crit.reversed = args_has(args, 'r');
|
||||
|
||||
l = sort_get_clients(&n, &sort_crit);
|
||||
for (i = 0; i < n; i++) {
|
||||
if (l[i]->session == NULL || (s != NULL && s != l[i]->session))
|
||||
continue;
|
||||
|
||||
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
||||
format_add(ft, "line", "%u", idx);
|
||||
format_defaults(ft, c, NULL, NULL, NULL);
|
||||
format_add(ft, "line", "%u", i);
|
||||
format_defaults(ft, l[i], NULL, NULL, NULL);
|
||||
|
||||
if (filter != NULL) {
|
||||
expanded = format_expand(ft, filter);
|
||||
@@ -94,8 +98,6 @@ cmd_list_clients_exec(struct cmd *self, struct cmdq_item *item)
|
||||
}
|
||||
|
||||
format_free(ft);
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
@@ -38,8 +38,9 @@ const struct cmd_entry cmd_list_panes_entry = {
|
||||
.name = "list-panes",
|
||||
.alias = "lsp",
|
||||
|
||||
.args = { "asF:f:t:", 0, 0, NULL },
|
||||
.usage = "[-as] [-F format] [-f filter] " CMD_TARGET_WINDOW_USAGE,
|
||||
.args = { "aF:f:O:rst:", 0, 0, NULL },
|
||||
.usage = "[-asr] [-F format] [-f filter] [-O order]"
|
||||
CMD_TARGET_WINDOW_USAGE,
|
||||
|
||||
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||
|
||||
@@ -89,12 +90,13 @@ cmd_list_panes_window(struct cmd *self, struct session *s, struct winlink *wl,
|
||||
struct cmdq_item *item, int type)
|
||||
{
|
||||
struct args *args = cmd_get_args(self);
|
||||
struct window_pane *wp;
|
||||
u_int n;
|
||||
struct window_pane *wp, **l;
|
||||
u_int i, n;
|
||||
struct format_tree *ft;
|
||||
const char *template, *filter;
|
||||
char *line, *expanded;
|
||||
int flag;
|
||||
struct sort_criteria sort_crit;
|
||||
|
||||
template = args_get(args, 'F');
|
||||
if (template == NULL) {
|
||||
@@ -124,8 +126,12 @@ cmd_list_panes_window(struct cmd *self, struct session *s, struct winlink *wl,
|
||||
}
|
||||
filter = args_get(args, 'f');
|
||||
|
||||
n = 0;
|
||||
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
|
||||
sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||
sort_crit.reversed = args_has(args, 'r');
|
||||
|
||||
l = sort_get_panes_window(wl->window, &n, &sort_crit);
|
||||
for (i = 0; i < n; i++) {
|
||||
wp = l[i];
|
||||
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
||||
format_add(ft, "line", "%u", n);
|
||||
format_defaults(ft, NULL, s, wl, wp);
|
||||
@@ -143,6 +149,5 @@ cmd_list_panes_window(struct cmd *self, struct session *s, struct winlink *wl,
|
||||
}
|
||||
|
||||
format_free(ft);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,8 +42,8 @@ const struct cmd_entry cmd_list_sessions_entry = {
|
||||
.name = "list-sessions",
|
||||
.alias = "ls",
|
||||
|
||||
.args = { "F:f:", 0, 0, NULL },
|
||||
.usage = "[-F format] [-f filter]",
|
||||
.args = { "F:f:O:r", 0, 0, NULL },
|
||||
.usage = "[-r] [-F format] [-f filter] [-O order]",
|
||||
|
||||
.flags = CMD_AFTERHOOK,
|
||||
.exec = cmd_list_sessions_exec
|
||||
@@ -52,23 +52,27 @@ const struct cmd_entry cmd_list_sessions_entry = {
|
||||
static enum cmd_retval
|
||||
cmd_list_sessions_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct args *args = cmd_get_args(self);
|
||||
struct session *s;
|
||||
u_int n;
|
||||
struct format_tree *ft;
|
||||
const char *template, *filter;
|
||||
char *line, *expanded;
|
||||
int flag;
|
||||
struct args *args = cmd_get_args(self);
|
||||
struct session **l;
|
||||
u_int n, i;
|
||||
struct format_tree *ft;
|
||||
const char *template, *filter;
|
||||
char *line, *expanded;
|
||||
int flag;
|
||||
struct sort_criteria sort_crit;
|
||||
|
||||
if ((template = args_get(args, 'F')) == NULL)
|
||||
template = LIST_SESSIONS_TEMPLATE;
|
||||
filter = args_get(args, 'f');
|
||||
|
||||
n = 0;
|
||||
RB_FOREACH(s, sessions, &sessions) {
|
||||
sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||
sort_crit.reversed = args_has(args, 'r');
|
||||
|
||||
l = sort_get_sessions(&n, &sort_crit);
|
||||
for (i = 0; i < n; i++) {
|
||||
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
||||
format_add(ft, "line", "%u", n);
|
||||
format_defaults(ft, NULL, s, NULL, NULL);
|
||||
format_add(ft, "line", "%u", i);
|
||||
format_defaults(ft, NULL, l[i], NULL, NULL);
|
||||
|
||||
if (filter != NULL) {
|
||||
expanded = format_expand(ft, filter);
|
||||
@@ -83,7 +87,6 @@ cmd_list_sessions_exec(struct cmd *self, struct cmdq_item *item)
|
||||
}
|
||||
|
||||
format_free(ft);
|
||||
n++;
|
||||
}
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
@@ -41,16 +41,13 @@
|
||||
|
||||
static enum cmd_retval cmd_list_windows_exec(struct cmd *, struct cmdq_item *);
|
||||
|
||||
static void cmd_list_windows_server(struct cmd *, struct cmdq_item *);
|
||||
static void cmd_list_windows_session(struct cmd *, struct session *,
|
||||
struct cmdq_item *, int);
|
||||
|
||||
const struct cmd_entry cmd_list_windows_entry = {
|
||||
.name = "list-windows",
|
||||
.alias = "lsw",
|
||||
|
||||
.args = { "F:f:at:", 0, 0, NULL },
|
||||
.usage = "[-a] [-F format] [-f filter] " CMD_TARGET_SESSION_USAGE,
|
||||
.args = { "aF:f:O:rt:", 0, 0, NULL },
|
||||
.usage = "[-ar] [-F format] [-f filter] [-O order]"
|
||||
CMD_TARGET_SESSION_USAGE,
|
||||
|
||||
.target = { 't', CMD_FIND_SESSION, 0 },
|
||||
|
||||
@@ -63,51 +60,34 @@ cmd_list_windows_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct args *args = cmd_get_args(self);
|
||||
struct cmd_find_state *target = cmdq_get_target(item);
|
||||
|
||||
if (args_has(args, 'a'))
|
||||
cmd_list_windows_server(self, item);
|
||||
else
|
||||
cmd_list_windows_session(self, target->s, item, 0);
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_list_windows_server(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct session *s;
|
||||
|
||||
RB_FOREACH(s, sessions, &sessions)
|
||||
cmd_list_windows_session(self, s, item, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_list_windows_session(struct cmd *self, struct session *s,
|
||||
struct cmdq_item *item, int type)
|
||||
{
|
||||
struct args *args = cmd_get_args(self);
|
||||
struct winlink *wl;
|
||||
u_int n;
|
||||
struct winlink *wl, **l;
|
||||
struct session *s;
|
||||
u_int i, n;
|
||||
struct format_tree *ft;
|
||||
const char *template, *filter;
|
||||
char *line, *expanded;
|
||||
int flag;
|
||||
struct sort_criteria sort_crit;
|
||||
|
||||
template = args_get(args, 'F');
|
||||
if (template == NULL) {
|
||||
switch (type) {
|
||||
case 0:
|
||||
template = LIST_WINDOWS_TEMPLATE;
|
||||
break;
|
||||
case 1:
|
||||
template = LIST_WINDOWS_WITH_SESSION_TEMPLATE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
filter = args_get(args, 'f');
|
||||
|
||||
n = 0;
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||
sort_crit.reversed = args_has(args, 'r');
|
||||
|
||||
if (args_has(args, 'a')) {
|
||||
l = sort_get_winlinks(&n, &sort_crit);
|
||||
if (template == NULL)
|
||||
template = LIST_WINDOWS_WITH_SESSION_TEMPLATE;
|
||||
} else {
|
||||
l = sort_get_winlinks_session(target->s, &n, &sort_crit);
|
||||
if (template == NULL)
|
||||
template = LIST_WINDOWS_TEMPLATE;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
wl = l[i];
|
||||
s = wl->session;
|
||||
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
||||
format_add(ft, "line", "%u", n);
|
||||
format_defaults(ft, NULL, s, wl, NULL);
|
||||
@@ -125,6 +105,7 @@ cmd_list_windows_session(struct cmd *self, struct session *s,
|
||||
}
|
||||
|
||||
format_free(ft);
|
||||
n++;
|
||||
}
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
@@ -34,9 +34,9 @@ const struct cmd_entry cmd_switch_client_entry = {
|
||||
.name = "switch-client",
|
||||
.alias = "switchc",
|
||||
|
||||
.args = { "lc:EFnpt:rT:Z", 0, 0, NULL },
|
||||
.args = { "c:EFlnO:pt:rT:Z", 0, 0, NULL },
|
||||
.usage = "[-ElnprZ] [-c target-client] [-t target-session] "
|
||||
"[-T key-table]",
|
||||
"[-T key-table] [-O order]",
|
||||
|
||||
/* -t is special */
|
||||
|
||||
@@ -60,6 +60,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct window_pane *wp;
|
||||
const char *tablename;
|
||||
struct key_table *table;
|
||||
struct sort_criteria sort_crit;
|
||||
|
||||
if (tflag != NULL &&
|
||||
(tflag[strcspn(tflag, ":.%")] != '\0' || strcmp(tflag, "=") == 0)) {
|
||||
@@ -95,13 +96,18 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||
sort_crit.reversed = args_has(args, 'r');
|
||||
|
||||
if (args_has(args, 'n')) {
|
||||
if ((s = session_next_session(tc->session)) == NULL) {
|
||||
s = session_next_session(tc->session, &sort_crit);
|
||||
if (s == NULL) {
|
||||
cmdq_error(item, "can't find next session");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
} else if (args_has(args, 'p')) {
|
||||
if ((s = session_previous_session(tc->session)) == NULL) {
|
||||
s = session_previous_session(tc->session, &sort_crit);
|
||||
if (s == NULL) {
|
||||
cmdq_error(item, "can't find previous session");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
258
format.c
258
format.c
@@ -132,17 +132,7 @@ enum format_type {
|
||||
FORMAT_TYPE_PANE
|
||||
};
|
||||
|
||||
/* Format loop sort type. */
|
||||
enum format_loop_sort_type {
|
||||
FORMAT_LOOP_BY_INDEX,
|
||||
FORMAT_LOOP_BY_NAME,
|
||||
FORMAT_LOOP_BY_TIME,
|
||||
};
|
||||
|
||||
static struct format_loop_sort_criteria {
|
||||
enum format_loop_sort_type field;
|
||||
int reversed;
|
||||
} format_loop_sort_criteria;
|
||||
static struct sort_criteria sort_crit;
|
||||
|
||||
struct format_tree {
|
||||
enum format_type type;
|
||||
@@ -4388,44 +4378,11 @@ format_session_name(struct format_expand_state *es, const char *fmt)
|
||||
return (xstrdup("0"));
|
||||
}
|
||||
|
||||
static int
|
||||
format_cmp_session(const void *a0, const void *b0)
|
||||
{
|
||||
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
|
||||
const struct session *const *a = a0;
|
||||
const struct session *const *b = b0;
|
||||
const struct session *sa = *a;
|
||||
const struct session *sb = *b;
|
||||
int result = 0;
|
||||
|
||||
switch (sc->field) {
|
||||
case FORMAT_LOOP_BY_INDEX:
|
||||
result = sa->id - sb->id;
|
||||
break;
|
||||
case FORMAT_LOOP_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 FORMAT_LOOP_BY_NAME:
|
||||
result = strcmp(sa->name, sb->name);
|
||||
break;
|
||||
}
|
||||
|
||||
if (sc->reversed)
|
||||
result = -result;
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* Loop over sessions. */
|
||||
static char *
|
||||
format_loop_sessions(struct format_expand_state *es, const char *fmt)
|
||||
{
|
||||
struct sort_criteria *sc = &sort_crit;
|
||||
struct format_tree *ft = es->ft;
|
||||
struct client *c = ft->client;
|
||||
struct cmdq_item *item = ft->item;
|
||||
@@ -4433,30 +4390,18 @@ format_loop_sessions(struct format_expand_state *es, const char *fmt)
|
||||
struct format_expand_state next;
|
||||
char *all, *active, *use, *expanded, *value;
|
||||
size_t valuelen;
|
||||
struct session *s;
|
||||
struct session *s, **l;
|
||||
int i, n, last = 0;
|
||||
static struct session **l = NULL;
|
||||
static int lsz = 0;
|
||||
|
||||
if (format_choose(es, fmt, &all, &active, 0) != 0) {
|
||||
all = xstrdup(fmt);
|
||||
active = NULL;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
RB_FOREACH(s, sessions, &sessions) {
|
||||
if (lsz <= n) {
|
||||
lsz += 100;
|
||||
l = xreallocarray(l, lsz, sizeof *l);
|
||||
}
|
||||
l[n++] = s;
|
||||
}
|
||||
|
||||
qsort(l, n, sizeof *l, format_cmp_session);
|
||||
|
||||
value = xcalloc(1, 1);
|
||||
valuelen = 1;
|
||||
|
||||
l = sort_get_sessions(&n, sc);
|
||||
for (i = 0; i < n; i++) {
|
||||
s = l[i];
|
||||
format_log(es, "session loop: $%u", s->id);
|
||||
@@ -4509,44 +4454,11 @@ format_window_name(struct format_expand_state *es, const char *fmt)
|
||||
return (xstrdup("0"));
|
||||
}
|
||||
|
||||
static int
|
||||
format_cmp_window(const void *a0, const void *b0)
|
||||
{
|
||||
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
|
||||
const struct winlink *const *a = a0;
|
||||
const struct winlink *const *b = b0;
|
||||
const struct window *wa = (*a)->window;
|
||||
const struct window *wb = (*b)->window;
|
||||
int result = 0;
|
||||
|
||||
switch (sc->field) {
|
||||
case FORMAT_LOOP_BY_INDEX:
|
||||
break;
|
||||
case FORMAT_LOOP_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 FORMAT_LOOP_BY_NAME:
|
||||
result = strcmp(wa->name, wb->name);
|
||||
break;
|
||||
}
|
||||
|
||||
if (sc->reversed)
|
||||
result = -result;
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* Loop over windows. */
|
||||
static char *
|
||||
format_loop_windows(struct format_expand_state *es, const char *fmt)
|
||||
{
|
||||
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
|
||||
struct sort_criteria *sc = &sort_crit;
|
||||
struct format_tree *ft = es->ft;
|
||||
struct client *c = ft->client;
|
||||
struct cmdq_item *item = ft->item;
|
||||
@@ -4554,11 +4466,9 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
|
||||
struct format_expand_state next;
|
||||
char *all, *active, *use, *expanded, *value;
|
||||
size_t valuelen;
|
||||
struct winlink *wl;
|
||||
struct winlink *wl, **l;
|
||||
struct window *w;
|
||||
int i, n, last = 0;
|
||||
static struct winlink **l = NULL;
|
||||
static int lsz = 0;
|
||||
|
||||
if (ft->s == NULL) {
|
||||
format_log(es, "window loop but no session");
|
||||
@@ -4570,31 +4480,10 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
|
||||
active = NULL;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
RB_FOREACH(wl, winlinks, &ft->s->windows) {
|
||||
if (lsz <= n) {
|
||||
lsz += 100;
|
||||
l = xreallocarray(l, lsz, sizeof *l);
|
||||
}
|
||||
l[n++] = wl;
|
||||
}
|
||||
|
||||
if (sc->field != FORMAT_LOOP_BY_INDEX)
|
||||
qsort(l, n, sizeof *l, format_cmp_window);
|
||||
else {
|
||||
/* Use order in the tree as index order. */
|
||||
if (sc->reversed) {
|
||||
for (i = 0; i < n / 2; i++) {
|
||||
wl = l[i];
|
||||
l[i] = l[n - 1 - i];
|
||||
l[n - 1 - i] = wl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
value = xcalloc(1, 1);
|
||||
valuelen = 1;
|
||||
|
||||
l = sort_get_winlinks_session(ft->s, &n, sc);
|
||||
for (i = 0; i < n; i++) {
|
||||
wl = l[i];
|
||||
w = wl->window;
|
||||
@@ -4626,27 +4515,11 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
|
||||
return (value);
|
||||
}
|
||||
|
||||
static int
|
||||
format_cmp_pane(const void *a0, const void *b0)
|
||||
{
|
||||
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
|
||||
const struct window_pane *const *a = a0;
|
||||
const struct window_pane *const *b = b0;
|
||||
const struct window_pane *wpa = *a;
|
||||
const struct window_pane *wpb = *b;
|
||||
int result = 0;
|
||||
|
||||
if (sc->reversed)
|
||||
result = wpb->id - wpa->id;
|
||||
else
|
||||
result = wpa->id - wpb->id;
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* Loop over panes. */
|
||||
static char *
|
||||
format_loop_panes(struct format_expand_state *es, const char *fmt)
|
||||
{
|
||||
struct sort_criteria *sc = &sort_crit;
|
||||
struct format_tree *ft = es->ft;
|
||||
struct client *c = ft->client;
|
||||
struct cmdq_item *item = ft->item;
|
||||
@@ -4654,10 +4527,8 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
|
||||
struct format_expand_state next;
|
||||
char *all, *active, *use, *expanded, *value;
|
||||
size_t valuelen;
|
||||
struct window_pane *wp;
|
||||
struct window_pane *wp, **l;
|
||||
int i, n, last = 0;
|
||||
static struct window_pane **l = NULL;
|
||||
static int lsz = 0;
|
||||
|
||||
if (ft->w == NULL) {
|
||||
format_log(es, "pane loop but no window");
|
||||
@@ -4669,20 +4540,10 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
|
||||
active = NULL;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
TAILQ_FOREACH(wp, &ft->w->panes, entry) {
|
||||
if (lsz <= n) {
|
||||
lsz += 100;
|
||||
l = xreallocarray(l, lsz, sizeof *l);
|
||||
}
|
||||
l[n++] = wp;
|
||||
}
|
||||
|
||||
qsort(l, n, sizeof *l, format_cmp_pane);
|
||||
|
||||
value = xcalloc(1, 1);
|
||||
valuelen = 1;
|
||||
|
||||
l = sort_get_panes_window(ft->w, &n, sc);
|
||||
for (i = 0; i < n; i++) {
|
||||
wp = l[i];
|
||||
format_log(es, "pane loop: %%%u", wp->id);
|
||||
@@ -4713,80 +4574,24 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
|
||||
return (value);
|
||||
}
|
||||
|
||||
static int
|
||||
format_cmp_client(const void *a0, const void *b0)
|
||||
{
|
||||
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
|
||||
const struct client *const *a = a0;
|
||||
const struct client *const *b = b0;
|
||||
const struct client *ca = *a;
|
||||
const struct client *cb = *b;
|
||||
int result = 0;
|
||||
|
||||
switch (sc->field) {
|
||||
case FORMAT_LOOP_BY_INDEX:
|
||||
break;
|
||||
case FORMAT_LOOP_BY_TIME:
|
||||
if (timercmp(&ca->activity_time, &cb->activity_time, >)) {
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
if (timercmp(&ca->activity_time, &cb->activity_time, <)) {
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case FORMAT_LOOP_BY_NAME:
|
||||
result = strcmp(ca->name, cb->name);
|
||||
break;
|
||||
}
|
||||
|
||||
if (sc->reversed)
|
||||
result = -result;
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* Loop over clients. */
|
||||
static char *
|
||||
format_loop_clients(struct format_expand_state *es, const char *fmt)
|
||||
{
|
||||
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
|
||||
struct sort_criteria *sc = &sort_crit;
|
||||
struct format_tree *ft = es->ft;
|
||||
struct client *c;
|
||||
struct client *c, **l;
|
||||
struct cmdq_item *item = ft->item;
|
||||
struct format_tree *nft;
|
||||
struct format_expand_state next;
|
||||
char *expanded, *value;
|
||||
size_t valuelen;
|
||||
int i, n, last = 0;
|
||||
static struct client **l = NULL;
|
||||
static int lsz = 0;
|
||||
|
||||
value = xcalloc(1, 1);
|
||||
valuelen = 1;
|
||||
|
||||
n = 0;
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (lsz <= n) {
|
||||
lsz += 100;
|
||||
l = xreallocarray(l, lsz, sizeof *l);
|
||||
}
|
||||
l[n++] = c;
|
||||
}
|
||||
|
||||
if (sc->field != FORMAT_LOOP_BY_INDEX)
|
||||
qsort(l, n, sizeof *l, format_cmp_client);
|
||||
else {
|
||||
/* Use order in the list as index order. */
|
||||
if (sc->reversed) {
|
||||
for (i = 0; i < n / 2; i++) {
|
||||
c = l[i];
|
||||
l[i] = l[n - 1 - i];
|
||||
l[n - 1 - i] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
l = sort_get_clients(&n, sc);
|
||||
for (i = 0; i < n; i++) {
|
||||
c = l[i];
|
||||
format_log(es, "client loop: %s", c->name);
|
||||
@@ -4956,7 +4761,7 @@ static int
|
||||
format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
char **buf, size_t *len, size_t *off)
|
||||
{
|
||||
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
|
||||
struct sort_criteria *sc = &sort_crit;
|
||||
struct format_tree *ft = es->ft;
|
||||
struct window_pane *wp = ft->wp;
|
||||
const char *errstr, *copy, *cp, *cp2;
|
||||
@@ -4973,6 +4778,10 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
u_int i, count, nsub = 0, nrep;
|
||||
struct format_expand_state next;
|
||||
|
||||
/* Set sorting defaults. */
|
||||
sc->order = SORT_ORDER;
|
||||
sc->reversed = 0;
|
||||
|
||||
/* Make a copy of the key. */
|
||||
copy = copy0 = xstrndup(key, keylen);
|
||||
|
||||
@@ -5083,18 +4892,18 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
case 'S':
|
||||
modifiers |= FORMAT_SESSIONS;
|
||||
if (fm->argc < 1) {
|
||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
||||
sc->order= SORT_INDEX;
|
||||
sc->reversed = 0;
|
||||
break;
|
||||
}
|
||||
if (strchr(fm->argv[0], 'i') != NULL)
|
||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
||||
sc->order = SORT_INDEX;
|
||||
else if (strchr(fm->argv[0], 'n') != NULL)
|
||||
sc->field = FORMAT_LOOP_BY_NAME;
|
||||
sc->order = SORT_NAME;
|
||||
else if (strchr(fm->argv[0], 't') != NULL)
|
||||
sc->field = FORMAT_LOOP_BY_TIME;
|
||||
sc->order = SORT_ACTIVITY;
|
||||
else
|
||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
||||
sc->order = SORT_INDEX;
|
||||
if (strchr(fm->argv[0], 'r') != NULL)
|
||||
sc->reversed = 1;
|
||||
else
|
||||
@@ -5103,18 +4912,18 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
case 'W':
|
||||
modifiers |= FORMAT_WINDOWS;
|
||||
if (fm->argc < 1) {
|
||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
||||
sc->order = SORT_ORDER;
|
||||
sc->reversed = 0;
|
||||
break;
|
||||
}
|
||||
if (strchr(fm->argv[0], 'i') != NULL)
|
||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
||||
sc->order = SORT_ORDER;
|
||||
else if (strchr(fm->argv[0], 'n') != NULL)
|
||||
sc->field = FORMAT_LOOP_BY_NAME;
|
||||
sc->order = SORT_NAME;
|
||||
else if (strchr(fm->argv[0], 't') != NULL)
|
||||
sc->field = FORMAT_LOOP_BY_TIME;
|
||||
sc->order = SORT_ACTIVITY;
|
||||
else
|
||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
||||
sc->order = SORT_ORDER;
|
||||
if (strchr(fm->argv[0], 'r') != NULL)
|
||||
sc->reversed = 1;
|
||||
else
|
||||
@@ -5122,6 +4931,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
break;
|
||||
case 'P':
|
||||
modifiers |= FORMAT_PANES;
|
||||
sc->order = SORT_CREATION;
|
||||
if (fm->argc < 1) {
|
||||
sc->reversed = 0;
|
||||
break;
|
||||
@@ -5134,18 +4944,18 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
case 'L':
|
||||
modifiers |= FORMAT_CLIENTS;
|
||||
if (fm->argc < 1) {
|
||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
||||
sc->order = SORT_ORDER;
|
||||
sc->reversed = 0;
|
||||
break;
|
||||
}
|
||||
if (strchr(fm->argv[0], 'i') != NULL)
|
||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
||||
sc->order = SORT_ORDER;
|
||||
else if (strchr(fm->argv[0], 'n') != NULL)
|
||||
sc->field = FORMAT_LOOP_BY_NAME;
|
||||
sc->order = SORT_NAME;
|
||||
else if (strchr(fm->argv[0], 't') != NULL)
|
||||
sc->field = FORMAT_LOOP_BY_TIME;
|
||||
sc->order = SORT_ACTIVITY;
|
||||
else
|
||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
||||
sc->order = SORT_ORDER;
|
||||
if (strchr(fm->argv[0], 'r') != NULL)
|
||||
sc->reversed = 1;
|
||||
else
|
||||
|
||||
37
mode-tree.c
37
mode-tree.c
@@ -48,9 +48,7 @@ struct mode_tree_data {
|
||||
void *modedata;
|
||||
const struct menu_item *menu;
|
||||
|
||||
const char **sort_list;
|
||||
u_int sort_size;
|
||||
struct mode_tree_sort_criteria sort_crit;
|
||||
struct sort_criteria sort_crit;
|
||||
|
||||
mode_tree_build_cb buildcb;
|
||||
mode_tree_draw_cb drawcb;
|
||||
@@ -59,6 +57,7 @@ struct mode_tree_data {
|
||||
mode_tree_height_cb heightcb;
|
||||
mode_tree_key_cb keycb;
|
||||
mode_tree_swap_cb swapcb;
|
||||
mode_tree_sort_cb sortcb;
|
||||
|
||||
struct mode_tree_list children;
|
||||
struct mode_tree_list saved;
|
||||
@@ -324,7 +323,7 @@ mode_tree_swap(struct mode_tree_data *mtd, int direction)
|
||||
return;
|
||||
|
||||
if (mtd->swapcb(mtd->line_list[mtd->current].item->itemdata,
|
||||
mtd->line_list[swap_with].item->itemdata)) {
|
||||
mtd->line_list[swap_with].item->itemdata, &mtd->sort_crit)) {
|
||||
mtd->current = swap_with;
|
||||
mode_tree_build(mtd);
|
||||
}
|
||||
@@ -382,7 +381,7 @@ mode_tree_expand(struct mode_tree_data *mtd, uint64_t tag)
|
||||
u_int found;
|
||||
|
||||
if (!mode_tree_get_tag(mtd, tag, &found))
|
||||
return;
|
||||
return;
|
||||
if (!mtd->line_list[found].item->expanded) {
|
||||
mtd->line_list[found].item->expanded = 1;
|
||||
mode_tree_build(mtd);
|
||||
@@ -454,12 +453,10 @@ mode_tree_start(struct window_pane *wp, struct args *args,
|
||||
mode_tree_build_cb buildcb, mode_tree_draw_cb drawcb,
|
||||
mode_tree_search_cb searchcb, mode_tree_menu_cb menucb,
|
||||
mode_tree_height_cb heightcb, mode_tree_key_cb keycb,
|
||||
mode_tree_swap_cb swapcb, void *modedata, const struct menu_item *menu,
|
||||
const char **sort_list, u_int sort_size, struct screen **s)
|
||||
mode_tree_swap_cb swapcb, mode_tree_sort_cb sortcb, void *modedata,
|
||||
const struct menu_item *menu, struct screen **s)
|
||||
{
|
||||
struct mode_tree_data *mtd;
|
||||
const char *sort;
|
||||
u_int i;
|
||||
|
||||
mtd = xcalloc(1, sizeof *mtd);
|
||||
mtd->references = 1;
|
||||
@@ -468,9 +465,6 @@ mode_tree_start(struct window_pane *wp, struct args *args,
|
||||
mtd->modedata = modedata;
|
||||
mtd->menu = menu;
|
||||
|
||||
mtd->sort_list = sort_list;
|
||||
mtd->sort_size = sort_size;
|
||||
|
||||
if (args_has(args, 'N') > 1)
|
||||
mtd->preview = MODE_TREE_PREVIEW_BIG;
|
||||
else if (args_has(args, 'N'))
|
||||
@@ -478,13 +472,7 @@ mode_tree_start(struct window_pane *wp, struct args *args,
|
||||
else
|
||||
mtd->preview = MODE_TREE_PREVIEW_NORMAL;
|
||||
|
||||
sort = args_get(args, 'O');
|
||||
if (sort != NULL) {
|
||||
for (i = 0; i < sort_size; i++) {
|
||||
if (strcasecmp(sort, sort_list[i]) == 0)
|
||||
mtd->sort_crit.field = i;
|
||||
}
|
||||
}
|
||||
mtd->sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||
mtd->sort_crit.reversed = args_has(args, 'r');
|
||||
|
||||
if (args_has(args, 'f'))
|
||||
@@ -499,6 +487,7 @@ mode_tree_start(struct window_pane *wp, struct args *args,
|
||||
mtd->heightcb = heightcb;
|
||||
mtd->keycb = keycb;
|
||||
mtd->swapcb = swapcb;
|
||||
mtd->sortcb = sortcb;
|
||||
|
||||
TAILQ_INIT(&mtd->children);
|
||||
|
||||
@@ -566,6 +555,8 @@ mode_tree_build(struct mode_tree_data *mtd)
|
||||
TAILQ_CONCAT(&mtd->saved, &mtd->children, entry);
|
||||
TAILQ_INIT(&mtd->children);
|
||||
|
||||
if (mtd->sortcb != NULL)
|
||||
mtd->sortcb(&mtd->sort_crit);
|
||||
mtd->buildcb(mtd->modedata, &mtd->sort_crit, &tag, mtd->filter);
|
||||
mtd->no_matches = TAILQ_EMPTY(&mtd->children);
|
||||
if (mtd->no_matches)
|
||||
@@ -851,9 +842,9 @@ mode_tree_draw(struct mode_tree_data *mtd)
|
||||
screen_write_cursormove(&ctx, 0, h, 0);
|
||||
screen_write_box(&ctx, w, sy - h, BOX_LINES_DEFAULT, NULL, NULL);
|
||||
|
||||
if (mtd->sort_list != NULL) {
|
||||
if (mtd->sort_crit.order_seq != NULL) {
|
||||
xasprintf(&text, " %s (sort: %s%s)", mti->name,
|
||||
mtd->sort_list[mtd->sort_crit.field],
|
||||
sort_order_to_string(mtd->sort_crit.order),
|
||||
mtd->sort_crit.reversed ? ", reversed" : "");
|
||||
} else
|
||||
xasprintf(&text, " %s", mti->name);
|
||||
@@ -1287,9 +1278,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
||||
}
|
||||
break;
|
||||
case 'O':
|
||||
mtd->sort_crit.field++;
|
||||
if (mtd->sort_crit.field >= mtd->sort_size)
|
||||
mtd->sort_crit.field = 0;
|
||||
sort_next_order(&mtd->sort_crit);
|
||||
mode_tree_build(mtd);
|
||||
break;
|
||||
case 'r':
|
||||
|
||||
13
paste.c
13
paste.c
@@ -30,19 +30,6 @@
|
||||
* string!
|
||||
*/
|
||||
|
||||
struct paste_buffer {
|
||||
char *data;
|
||||
size_t size;
|
||||
|
||||
char *name;
|
||||
time_t created;
|
||||
int automatic;
|
||||
u_int order;
|
||||
|
||||
RB_ENTRY(paste_buffer) name_entry;
|
||||
RB_ENTRY(paste_buffer) time_entry;
|
||||
};
|
||||
|
||||
static u_int paste_next_index;
|
||||
static u_int paste_next_order;
|
||||
static u_int paste_num_automatic;
|
||||
|
||||
@@ -438,9 +438,9 @@ server_destroy_session(struct session *s)
|
||||
else if (detach_on_destroy == 2)
|
||||
s_new = server_find_session(s, server_newer_detached_session);
|
||||
else if (detach_on_destroy == 3)
|
||||
s_new = session_previous_session(s);
|
||||
s_new = session_previous_session(s, NULL);
|
||||
else if (detach_on_destroy == 4)
|
||||
s_new = session_next_session(s);
|
||||
s_new = session_next_session(s, NULL);
|
||||
|
||||
/*
|
||||
* If no suitable new session was found above, then look for any
|
||||
|
||||
44
session.c
44
session.c
@@ -295,36 +295,48 @@ session_update_activity(struct session *s, struct timeval *from)
|
||||
|
||||
/* Find the next usable session. */
|
||||
struct session *
|
||||
session_next_session(struct session *s)
|
||||
session_next_session(struct session *s, struct sort_criteria *sort_crit)
|
||||
{
|
||||
struct session *s2;
|
||||
struct session **l;
|
||||
u_int n, i;
|
||||
|
||||
if (RB_EMPTY(&sessions) || !session_alive(s))
|
||||
return (NULL);
|
||||
|
||||
s2 = RB_NEXT(sessions, &sessions, s);
|
||||
if (s2 == NULL)
|
||||
s2 = RB_MIN(sessions, &sessions);
|
||||
if (s2 == s)
|
||||
return (NULL);
|
||||
return (s2);
|
||||
l = sort_get_sessions(&n, sort_crit);
|
||||
for (i = 0; i < n; i++) {
|
||||
if (l[i] == s)
|
||||
break;
|
||||
}
|
||||
if (i == n)
|
||||
fatalx("session %s not found in sorted list", s->name);
|
||||
i++;
|
||||
if (i == n)
|
||||
i = 0;
|
||||
return (l[i]);
|
||||
}
|
||||
|
||||
/* Find the previous usable session. */
|
||||
struct session *
|
||||
session_previous_session(struct session *s)
|
||||
session_previous_session(struct session *s, struct sort_criteria *sort_crit)
|
||||
{
|
||||
struct session *s2;
|
||||
struct session **l;
|
||||
u_int n, i;
|
||||
|
||||
if (RB_EMPTY(&sessions) || !session_alive(s))
|
||||
return (NULL);
|
||||
|
||||
s2 = RB_PREV(sessions, &sessions, s);
|
||||
if (s2 == NULL)
|
||||
s2 = RB_MAX(sessions, &sessions);
|
||||
if (s2 == s)
|
||||
return (NULL);
|
||||
return (s2);
|
||||
l = sort_get_sessions(&n, sort_crit);
|
||||
for (i = 0; i < n; i++) {
|
||||
if (l[i] == s)
|
||||
break;
|
||||
}
|
||||
if (i == n)
|
||||
fatalx("session %s not found in sorted list", s->name);
|
||||
if (i == 0)
|
||||
i = n;
|
||||
i--;
|
||||
return (l[i]);
|
||||
}
|
||||
|
||||
/* Attach a window to a session. */
|
||||
|
||||
536
sort.c
Normal file
536
sort.c
Normal file
@@ -0,0 +1,536 @@
|
||||
/* $OpenBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2026 Dane Jensen <dhcjensen@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
static struct sort_criteria *sort_criteria;
|
||||
|
||||
static void
|
||||
sort_qsort(void *l, u_int len, u_int size, int (*cmp)(const void *, const void *),
|
||||
struct sort_criteria *sort_crit)
|
||||
{
|
||||
u_int i;
|
||||
void *tmp, **ll;
|
||||
|
||||
if (sort_crit->order == SORT_END)
|
||||
return;
|
||||
|
||||
if (sort_crit->order == SORT_ORDER) {
|
||||
if (sort_crit->reversed) {
|
||||
ll = l;
|
||||
for (i = 0; i < len / 2; i++) {
|
||||
tmp = ll[i];
|
||||
ll[i] = ll[len - 1 - i];
|
||||
ll[len - 1 - i] = tmp;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sort_criteria = sort_crit;
|
||||
qsort(l, len, size, cmp);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
sort_buffer_cmp(const void *a0, const void *b0)
|
||||
{
|
||||
struct sort_criteria *sort_crit = sort_criteria;
|
||||
const struct paste_buffer *const *a = a0;
|
||||
const struct paste_buffer *const *b = b0;
|
||||
const struct paste_buffer *pa = *a;
|
||||
const struct paste_buffer *pb = *b;
|
||||
int result = 0;
|
||||
|
||||
switch (sort_crit->order) {
|
||||
case SORT_NAME:
|
||||
result = strcmp(pa->name, pb->name);
|
||||
break;
|
||||
case SORT_CREATION:
|
||||
result = pa->order - pb->order;
|
||||
break;
|
||||
case SORT_SIZE:
|
||||
result = pa->size - pb->size;
|
||||
break;
|
||||
case SORT_ACTIVITY:
|
||||
case SORT_INDEX:
|
||||
case SORT_ORDER:
|
||||
case SORT_END:
|
||||
break;
|
||||
}
|
||||
|
||||
if (result == 0)
|
||||
result = strcmp(pa->name, pb->name);
|
||||
|
||||
if (sort_crit->reversed)
|
||||
result = -result;
|
||||
return (result);
|
||||
}
|
||||
|
||||
static int
|
||||
sort_client_cmp(const void *a0, const void *b0)
|
||||
{
|
||||
struct sort_criteria *sort_crit = sort_criteria;
|
||||
const struct client *const *a = a0;
|
||||
const struct client *const *b = b0;
|
||||
const struct client *ca = *a;
|
||||
const struct client *cb = *b;
|
||||
int result = 0;
|
||||
|
||||
switch (sort_crit->order) {
|
||||
case SORT_NAME:
|
||||
result = strcmp(ca->name, cb->name);
|
||||
break;
|
||||
case SORT_SIZE:
|
||||
result = ca->tty.sx - cb->tty.sx;
|
||||
if (result == 0)
|
||||
result = ca->tty.sy - cb->tty.sy;
|
||||
break;
|
||||
case SORT_CREATION:
|
||||
if (timercmp(&ca->creation_time, &cb->creation_time, >))
|
||||
result = 1;
|
||||
else if (timercmp(&ca->creation_time, &cb->creation_time, <))
|
||||
result = -1;
|
||||
break;
|
||||
case SORT_ACTIVITY:
|
||||
if (timercmp(&ca->activity_time, &cb->activity_time, >))
|
||||
result = -1;
|
||||
else if (timercmp(&ca->activity_time, &cb->activity_time, <))
|
||||
result = 1;
|
||||
break;
|
||||
case SORT_INDEX:
|
||||
case SORT_ORDER:
|
||||
case SORT_END:
|
||||
break;
|
||||
}
|
||||
|
||||
if (result == 0)
|
||||
result = strcmp(ca->name, cb->name);
|
||||
|
||||
if (sort_crit->reversed)
|
||||
result = -result;
|
||||
return (result);
|
||||
}
|
||||
|
||||
static int
|
||||
sort_session_cmp(const void *a0, const void *b0)
|
||||
{
|
||||
struct sort_criteria *sort_crit = sort_criteria;
|
||||
const struct session *const *a = a0;
|
||||
const struct session *const *b = b0;
|
||||
const struct session *sa = *a;
|
||||
const struct session *sb = *b;
|
||||
int result = 0;
|
||||
|
||||
switch (sort_crit->order) {
|
||||
case SORT_INDEX:
|
||||
result = sa->id - sb->id;
|
||||
break;
|
||||
case SORT_CREATION:
|
||||
if (timercmp(&sa->creation_time, &sb->creation_time, >)) {
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
if (timercmp(&sa->creation_time, &sb->creation_time, <)) {
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SORT_ACTIVITY:
|
||||
if (timercmp(&sa->activity_time, &sb->activity_time, >)) {
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
if (timercmp(&sa->activity_time, &sb->activity_time, <)) {
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SORT_NAME:
|
||||
result = strcmp(sa->name, sb->name);
|
||||
break;
|
||||
case SORT_ORDER:
|
||||
case SORT_SIZE:
|
||||
case SORT_END:
|
||||
break;
|
||||
}
|
||||
|
||||
if (result == 0)
|
||||
result = strcmp(sa->name, sb->name);
|
||||
|
||||
if (sort_crit->reversed)
|
||||
result = -result;
|
||||
return (result);
|
||||
}
|
||||
|
||||
static int
|
||||
sort_pane_cmp(const void *a0, const void *b0)
|
||||
{
|
||||
struct sort_criteria *sort_crit = sort_criteria;
|
||||
struct window_pane *a = *(struct window_pane **)a0;
|
||||
struct window_pane *b = *(struct window_pane **)b0;
|
||||
int result = 0;
|
||||
u_int ai, bi;
|
||||
|
||||
switch (sort_crit->order) {
|
||||
case SORT_ACTIVITY:
|
||||
result = a->active_point - b->active_point;
|
||||
break;
|
||||
case SORT_CREATION:
|
||||
result = a->id - b->id;
|
||||
break;
|
||||
case SORT_INDEX:
|
||||
case SORT_NAME:
|
||||
case SORT_ORDER:
|
||||
case SORT_SIZE:
|
||||
case SORT_END:
|
||||
break;
|
||||
}
|
||||
if (result == 0) {
|
||||
/*
|
||||
* Panes don't have names, so use number order for any other
|
||||
* sort field.
|
||||
*/
|
||||
window_pane_index(a, &ai);
|
||||
window_pane_index(b, &bi);
|
||||
result = ai - bi;
|
||||
}
|
||||
|
||||
if (sort_crit->reversed)
|
||||
result = -result;
|
||||
return (result);
|
||||
}
|
||||
|
||||
static int
|
||||
sort_winlink_cmp(const void *a0, const void *b0)
|
||||
{
|
||||
struct sort_criteria *sort_crit = sort_criteria;
|
||||
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 = 0;
|
||||
|
||||
switch (sort_crit->order) {
|
||||
case SORT_INDEX:
|
||||
result = wla->idx - wlb->idx;
|
||||
break;
|
||||
case SORT_ACTIVITY:
|
||||
if (timercmp(&wa->activity_time, &wb->activity_time, >)) {
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
if (timercmp(&wa->activity_time, &wb->activity_time, <)) {
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SORT_NAME:
|
||||
result = strcmp(wa->name, wb->name);
|
||||
break;
|
||||
case SORT_CREATION:
|
||||
case SORT_ORDER:
|
||||
case SORT_SIZE:
|
||||
case SORT_END:
|
||||
break;
|
||||
}
|
||||
|
||||
if (result == 0)
|
||||
result = strcmp(wa->name, wb->name);
|
||||
|
||||
if (sort_crit->reversed)
|
||||
result = -result;
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
sort_next_order(struct sort_criteria *sort_crit)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
if (sort_crit->order_seq == NULL)
|
||||
return;
|
||||
for (i = 0; sort_crit->order_seq[i] != SORT_END; i++) {
|
||||
if (sort_crit->order == sort_crit->order_seq[i])
|
||||
break;
|
||||
}
|
||||
|
||||
if (sort_crit->order_seq[i] == SORT_END)
|
||||
i = 0;
|
||||
else {
|
||||
i++;
|
||||
if (sort_crit->order_seq[i] == SORT_END)
|
||||
i = 0;
|
||||
}
|
||||
sort_crit->order = sort_crit->order_seq[i];
|
||||
}
|
||||
|
||||
enum sort_order
|
||||
sort_order_from_string(const char* order)
|
||||
{
|
||||
if (order != NULL) {
|
||||
if (strcasecmp(order, "activity") == 0)
|
||||
return (SORT_ACTIVITY);
|
||||
if (strcasecmp(order, "creation") == 0)
|
||||
return (SORT_CREATION);
|
||||
if (strcasecmp(order, "index") == 0)
|
||||
return (SORT_INDEX);
|
||||
if (strcasecmp(order, "name") == 0)
|
||||
return (SORT_NAME);
|
||||
if (strcasecmp(order, "order") == 0)
|
||||
return (SORT_ORDER);
|
||||
if (strcasecmp(order, "size") == 0)
|
||||
return (SORT_SIZE);
|
||||
}
|
||||
return (SORT_END);
|
||||
}
|
||||
|
||||
const char *
|
||||
sort_order_to_string(enum sort_order order)
|
||||
{
|
||||
if (order == SORT_ACTIVITY)
|
||||
return "activity";
|
||||
if (order == SORT_CREATION)
|
||||
return "creation";
|
||||
if (order == SORT_INDEX)
|
||||
return "index";
|
||||
if (order == SORT_NAME)
|
||||
return "name";
|
||||
if (order == SORT_ORDER)
|
||||
return "order";
|
||||
if (order == SORT_SIZE)
|
||||
return "size";
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
sort_would_window_tree_swap(struct sort_criteria *sort_crit,
|
||||
struct winlink *wla, struct winlink *wlb)
|
||||
{
|
||||
if (sort_crit->order == SORT_INDEX)
|
||||
return (0);
|
||||
sort_criteria = sort_crit;
|
||||
return (sort_winlink_cmp(&wla, &wlb) != 0);
|
||||
}
|
||||
|
||||
struct paste_buffer **
|
||||
sort_get_buffers(u_int *n, struct sort_criteria *sort_crit)
|
||||
{
|
||||
struct paste_buffer *pb = NULL;
|
||||
u_int i;
|
||||
static struct paste_buffer **l = NULL;
|
||||
static u_int lsz = 0;
|
||||
|
||||
i = 0;
|
||||
while ((pb = paste_walk(pb)) != NULL) {
|
||||
if (lsz <= i) {
|
||||
lsz += 100;
|
||||
l = xreallocarray(l, lsz, sizeof *l);
|
||||
}
|
||||
l[i++] = pb;
|
||||
}
|
||||
|
||||
sort_qsort(l, i, sizeof *l, sort_buffer_cmp, sort_crit);
|
||||
*n = i;
|
||||
|
||||
return (l);
|
||||
}
|
||||
|
||||
struct client **
|
||||
sort_get_clients(u_int *n, struct sort_criteria *sort_crit)
|
||||
{
|
||||
struct client *c;
|
||||
u_int i;
|
||||
static struct client **l = NULL;
|
||||
static u_int lsz = 0;
|
||||
|
||||
i = 0;
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (lsz <= i) {
|
||||
lsz += 100;
|
||||
l = xreallocarray(l, lsz, sizeof *l);
|
||||
}
|
||||
l[i++] = c;
|
||||
}
|
||||
|
||||
sort_qsort(l, i, sizeof *l, sort_client_cmp, sort_crit);
|
||||
*n = i;
|
||||
|
||||
return (l);
|
||||
}
|
||||
|
||||
struct session **
|
||||
sort_get_sessions(u_int *n, struct sort_criteria *sort_crit)
|
||||
{
|
||||
struct session *s;
|
||||
u_int i;
|
||||
static struct session **l = NULL;
|
||||
static u_int lsz = 0;
|
||||
|
||||
i = 0;
|
||||
RB_FOREACH(s, sessions, &sessions) {
|
||||
if (lsz <= i) {
|
||||
lsz += 100;
|
||||
l = xreallocarray(l, lsz, sizeof *l);
|
||||
}
|
||||
l[i++] = s;
|
||||
}
|
||||
|
||||
sort_qsort(l, i, sizeof *l, sort_session_cmp, sort_crit);
|
||||
*n = i;
|
||||
|
||||
return (l);
|
||||
}
|
||||
|
||||
struct window_pane **
|
||||
sort_get_panes(u_int *n, struct sort_criteria *sort_crit)
|
||||
{
|
||||
struct session *s;
|
||||
struct winlink *wl;
|
||||
struct window *w;
|
||||
struct window_pane *wp;
|
||||
u_int i;
|
||||
static struct window_pane **l = NULL;
|
||||
static u_int lsz = 0;
|
||||
|
||||
i = 0;
|
||||
RB_FOREACH(s, sessions, &sessions) {
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
w = wl->window;
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if (lsz <= i) {
|
||||
lsz += 100;
|
||||
l = xreallocarray(l, lsz, sizeof *l);
|
||||
}
|
||||
l[i++] = wp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort_qsort(l, i, sizeof *l, sort_pane_cmp, sort_crit);
|
||||
*n = i;
|
||||
|
||||
return (l);
|
||||
}
|
||||
|
||||
struct window_pane **
|
||||
sort_get_panes_session(struct session *s, u_int *n,
|
||||
struct sort_criteria *sort_crit)
|
||||
{
|
||||
struct winlink *wl = NULL;
|
||||
struct window *w = NULL;
|
||||
struct window_pane *wp = NULL;
|
||||
u_int i;
|
||||
static struct window_pane **l = NULL;
|
||||
static u_int lsz = 0;
|
||||
|
||||
i = 0;
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if (lsz <= i) {
|
||||
lsz += 100;
|
||||
l = xreallocarray(l, lsz, sizeof *l);
|
||||
}
|
||||
l[i++] = wp;
|
||||
}
|
||||
}
|
||||
|
||||
sort_qsort(l, i, sizeof *l, sort_pane_cmp, sort_crit);
|
||||
*n = i;
|
||||
|
||||
return (l);
|
||||
}
|
||||
|
||||
struct window_pane **
|
||||
sort_get_panes_window(struct window *w, u_int *n,
|
||||
struct sort_criteria *sort_crit)
|
||||
{
|
||||
struct window_pane *wp;
|
||||
u_int i;
|
||||
static struct window_pane **l = NULL;
|
||||
static u_int lsz = 0;
|
||||
|
||||
i = 0;
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if (lsz <= i) {
|
||||
lsz += 100;
|
||||
l = xreallocarray(l, lsz, sizeof *l);
|
||||
}
|
||||
l[i++] = wp;
|
||||
}
|
||||
|
||||
sort_qsort(l, i, sizeof *l, sort_pane_cmp, sort_crit);
|
||||
*n = i;
|
||||
|
||||
return (l);
|
||||
}
|
||||
|
||||
struct winlink **
|
||||
sort_get_winlinks(u_int *n, struct sort_criteria *sort_crit)
|
||||
{
|
||||
struct session *s;
|
||||
struct winlink *wl;
|
||||
u_int i;
|
||||
static struct winlink **l = NULL;
|
||||
static u_int lsz = 0;
|
||||
|
||||
i = 0;
|
||||
RB_FOREACH(s, sessions, &sessions) {
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
if (lsz <= i) {
|
||||
lsz += 100;
|
||||
l = xreallocarray(l, lsz, sizeof *l);
|
||||
}
|
||||
l[i++] = wl;
|
||||
}
|
||||
}
|
||||
|
||||
sort_qsort(l, i, sizeof *l, sort_winlink_cmp, sort_crit);
|
||||
*n = i;
|
||||
|
||||
return (l);
|
||||
}
|
||||
|
||||
struct winlink **
|
||||
sort_get_winlinks_session(struct session *s, u_int *n,
|
||||
struct sort_criteria *sort_crit)
|
||||
{
|
||||
struct winlink *wl;
|
||||
u_int i;
|
||||
static struct winlink **l = NULL;
|
||||
static u_int lsz = 0;
|
||||
|
||||
i = 0;
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
if (lsz <= i) {
|
||||
lsz += 100;
|
||||
l = xreallocarray(l, lsz, sizeof *l);
|
||||
}
|
||||
l[i++] = wl;
|
||||
}
|
||||
|
||||
sort_qsort(l, i, sizeof *l, sort_winlink_cmp, sort_crit);
|
||||
*n = i;
|
||||
|
||||
return (l);
|
||||
}
|
||||
97
tmux.1
97
tmux.1
@@ -1183,8 +1183,10 @@ flag clears alerts (bell, activity, or silence) in all windows linked to the
|
||||
session.
|
||||
.Tg lsc
|
||||
.It Xo Ic list-clients
|
||||
.Op Fl r
|
||||
.Op Fl F Ar format
|
||||
.Op Fl f Ar filter
|
||||
.Op Fl O Ar sort-order
|
||||
.Op Fl t Ar target-session
|
||||
.Xc
|
||||
.D1 Pq alias: Ic lsc
|
||||
@@ -1197,6 +1199,16 @@ Only clients for which the filter is true are shown.
|
||||
See the
|
||||
.Sx FORMATS
|
||||
section.
|
||||
.Fl O
|
||||
specifies the sort order: one of
|
||||
.Ql name ,
|
||||
.Ql size ,
|
||||
.Ql creation
|
||||
(time), or
|
||||
.Ql activity
|
||||
(time).
|
||||
.Fl r
|
||||
reverses the sort order.
|
||||
If
|
||||
.Ar target-session
|
||||
is specified, list only clients connected to that session.
|
||||
@@ -1212,8 +1224,10 @@ or - if omitted - of all commands supported by
|
||||
.Nm .
|
||||
.Tg ls
|
||||
.It Xo Ic list-sessions
|
||||
.Op Fl r
|
||||
.Op Fl F Ar format
|
||||
.Op Fl f Ar filter
|
||||
.Op Fl O Ar sort-order
|
||||
.Xc
|
||||
.D1 Pq alias: Ic ls
|
||||
List all sessions managed by the server.
|
||||
@@ -1225,6 +1239,16 @@ Only sessions for which the filter is true are shown.
|
||||
See the
|
||||
.Sx FORMATS
|
||||
section.
|
||||
.Fl O
|
||||
specifies the sort order: one of
|
||||
.Ql index ,
|
||||
.Ql name ,
|
||||
.Ql creation
|
||||
(time), or
|
||||
.Ql activity
|
||||
(time).
|
||||
.Fl r
|
||||
reverses the sort order.
|
||||
.Tg lockc
|
||||
.It Ic lock-client Op Fl t Ar target-client
|
||||
.D1 Pq alias: Ic lockc
|
||||
@@ -1621,6 +1645,7 @@ Suspend a client by sending
|
||||
.It Xo Ic switch-client
|
||||
.Op Fl ElnprZ
|
||||
.Op Fl c Ar target-client
|
||||
.Op Fl O Ar sort-order
|
||||
.Op Fl t Ar target-session
|
||||
.Op Fl T Ar key-table
|
||||
.Xc
|
||||
@@ -1647,6 +1672,18 @@ or
|
||||
.Fl p
|
||||
is used, the client is moved to the last, next or previous session
|
||||
respectively.
|
||||
.Fl O
|
||||
may be used with
|
||||
.Fl n
|
||||
and
|
||||
.Fl p
|
||||
to specify the field to sort on: one of
|
||||
.Ql name ,
|
||||
.Ql size ,
|
||||
.Ql creation
|
||||
(time), or
|
||||
.Ql activity
|
||||
(time).
|
||||
.Fl r
|
||||
toggles the client
|
||||
.Ic read-only
|
||||
@@ -2667,7 +2704,7 @@ 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 field"
|
||||
.It Li "O" Ta "Change sort order"
|
||||
.It Li "r" Ta "Reverse sort order"
|
||||
.It Li "v" Ta "Toggle preview"
|
||||
.It Li "q" Ta "Exit mode"
|
||||
@@ -2683,12 +2720,11 @@ If
|
||||
is not given, "detach-client -t \[aq]%%\[aq]" is used.
|
||||
.Pp
|
||||
.Fl O
|
||||
specifies the initial sort field: one of
|
||||
specifies the initial sort order: one of
|
||||
.Ql name ,
|
||||
.Ql size ,
|
||||
.Ql creation
|
||||
(time),
|
||||
or
|
||||
(time), or
|
||||
.Ql activity
|
||||
(time).
|
||||
.Fl r
|
||||
@@ -2755,7 +2791,7 @@ The following keys may be used in tree mode:
|
||||
.It Li "\&:" Ta "Run a command for each tagged item"
|
||||
.It Li "f" Ta "Enter a format to filter items"
|
||||
.It Li "H" Ta "Jump to the starting pane"
|
||||
.It Li "O" Ta "Change sort field"
|
||||
.It Li "O" Ta "Change sort order"
|
||||
.It Li "r" Ta "Reverse sort order"
|
||||
.It Li "v" Ta "Toggle preview"
|
||||
.It Li "q" Ta "Exit mode"
|
||||
@@ -2773,12 +2809,12 @@ If
|
||||
is not given, "switch-client -t \[aq]%%\[aq]" is used.
|
||||
.Pp
|
||||
.Fl O
|
||||
specifies the initial sort field: one of
|
||||
specifies the initial sort order: one of
|
||||
.Ql index ,
|
||||
.Ql name ,
|
||||
or
|
||||
.Ql time
|
||||
(activity).
|
||||
.Ql activity
|
||||
(time).
|
||||
.Fl r
|
||||
reverses the sort order.
|
||||
.Fl f
|
||||
@@ -3024,9 +3060,10 @@ If
|
||||
is given, the newly linked window is not selected.
|
||||
.Tg lsp
|
||||
.It Xo Ic list-panes
|
||||
.Op Fl as
|
||||
.Op Fl ars
|
||||
.Op Fl F Ar format
|
||||
.Op Fl f Ar filter
|
||||
.Op Fl O Ar sort-order
|
||||
.Op Fl t Ar target
|
||||
.Xc
|
||||
.D1 Pq alias: Ic lsp
|
||||
@@ -3051,11 +3088,21 @@ Only panes for which the filter is true are shown.
|
||||
See the
|
||||
.Sx FORMATS
|
||||
section.
|
||||
.Fl O
|
||||
specifies the sort order: one of
|
||||
.Ql name ,
|
||||
.Ql creation
|
||||
(time), or
|
||||
.Ql activity
|
||||
(time).
|
||||
.Fl r
|
||||
reverses the sort order.
|
||||
.Tg lsw
|
||||
.It Xo Ic list-windows
|
||||
.Op Fl a
|
||||
.Op Fl ar
|
||||
.Op Fl F Ar format
|
||||
.Op Fl f Ar filter
|
||||
.Op Fl O Ar sort-order
|
||||
.Op Fl t Ar target-session
|
||||
.Xc
|
||||
.D1 Pq alias: Ic lsw
|
||||
@@ -3072,6 +3119,15 @@ Only windows for which the filter is true are shown.
|
||||
See the
|
||||
.Sx FORMATS
|
||||
section.
|
||||
.Fl O
|
||||
specifies the sort order: one of
|
||||
.Ql index ,
|
||||
.Ql name ,
|
||||
or
|
||||
.Ql activity
|
||||
(time).
|
||||
.Fl r
|
||||
reverses the sort order.
|
||||
.Tg movep
|
||||
.It Xo Ic move-pane
|
||||
.Op Fl bdfhv
|
||||
@@ -7245,7 +7301,7 @@ The following keys may be used in buffer mode:
|
||||
.It Li "D" Ta "Delete tagged buffers"
|
||||
.It Li "e" Ta "Open the buffer in an editor"
|
||||
.It Li "f" Ta "Enter a format to filter items"
|
||||
.It Li "O" Ta "Change sort field"
|
||||
.It Li "O" Ta "Change sort order"
|
||||
.It Li "r" Ta "Reverse sort order"
|
||||
.It Li "v" Ta "Toggle preview"
|
||||
.It Li "q" Ta "Exit mode"
|
||||
@@ -7261,10 +7317,10 @@ If
|
||||
is not given, "paste-buffer -p -b \[aq]%%\[aq]" is used.
|
||||
.Pp
|
||||
.Fl O
|
||||
specifies the initial sort field: one of
|
||||
.Ql time
|
||||
(creation),
|
||||
.Ql name
|
||||
specifies the initial sort order: one of
|
||||
.Ql creation
|
||||
(time),
|
||||
.Ql name ,
|
||||
or
|
||||
.Ql size .
|
||||
.Fl r
|
||||
@@ -7297,8 +7353,10 @@ Delete the buffer named
|
||||
or the most recently added automatically named buffer if not specified.
|
||||
.Tg lsb
|
||||
.It Xo Ic list-buffers
|
||||
.Op Fl r
|
||||
.Op Fl F Ar format
|
||||
.Op Fl f Ar filter
|
||||
.Op Fl O Ar sort-order
|
||||
.Xc
|
||||
.D1 Pq alias: Ic lsb
|
||||
List the global buffers.
|
||||
@@ -7310,6 +7368,15 @@ Only buffers for which the filter is true are shown.
|
||||
See the
|
||||
.Sx FORMATS
|
||||
section.
|
||||
.Fl O
|
||||
specifies the sort order: one of
|
||||
.Ql name ,
|
||||
.Ql size ,
|
||||
or
|
||||
.Ql creation
|
||||
(time).
|
||||
.Fl r
|
||||
reverses the sort order.
|
||||
.It Xo Ic load-buffer
|
||||
.Op Fl w
|
||||
.Op Fl b Ar buffer-name
|
||||
|
||||
67
tmux.h
67
tmux.h
@@ -2227,10 +2227,36 @@ struct spawn_context {
|
||||
#define SPAWN_ZOOM 0x80
|
||||
};
|
||||
|
||||
/* Mode tree sort order. */
|
||||
struct mode_tree_sort_criteria {
|
||||
u_int field;
|
||||
int reversed;
|
||||
/* Paste buffer. */
|
||||
struct paste_buffer {
|
||||
char *data;
|
||||
size_t size;
|
||||
|
||||
char *name;
|
||||
time_t created;
|
||||
int automatic;
|
||||
u_int order;
|
||||
|
||||
RB_ENTRY(paste_buffer) name_entry;
|
||||
RB_ENTRY(paste_buffer) time_entry;
|
||||
};
|
||||
|
||||
/* Sort orders. */
|
||||
enum sort_order {
|
||||
SORT_ACTIVITY,
|
||||
SORT_CREATION,
|
||||
SORT_INDEX,
|
||||
SORT_NAME,
|
||||
SORT_ORDER,
|
||||
SORT_SIZE,
|
||||
SORT_END,
|
||||
};
|
||||
|
||||
/* Sort criteria. */
|
||||
struct sort_criteria {
|
||||
enum sort_order order;
|
||||
int reversed;
|
||||
enum sort_order *order_seq; /* available sort orders */
|
||||
};
|
||||
|
||||
/* tmux.c */
|
||||
@@ -2286,7 +2312,6 @@ void cfg_print_causes(struct cmdq_item *);
|
||||
void cfg_show_causes(struct session *);
|
||||
|
||||
/* paste.c */
|
||||
struct paste_buffer;
|
||||
const char *paste_buffer_name(struct paste_buffer *);
|
||||
u_int paste_buffer_order(struct paste_buffer *);
|
||||
time_t paste_buffer_created(struct paste_buffer *);
|
||||
@@ -2302,6 +2327,24 @@ int paste_set(char *, size_t, const char *, char **);
|
||||
void paste_replace(struct paste_buffer *, char *, size_t);
|
||||
char *paste_make_sample(struct paste_buffer *);
|
||||
|
||||
/* sort.c */
|
||||
void sort_next_order(struct sort_criteria *);
|
||||
enum sort_order sort_order_from_string(const char *);
|
||||
const char *sort_order_to_string(enum sort_order);
|
||||
int sort_would_window_tree_swap(struct sort_criteria *,
|
||||
struct winlink *, struct winlink *);
|
||||
struct paste_buffer **sort_get_buffers(u_int *, struct sort_criteria *);
|
||||
struct client **sort_get_clients(u_int *, struct sort_criteria *);
|
||||
struct session **sort_get_sessions(u_int *, struct sort_criteria *);
|
||||
struct window_pane **sort_get_panes(u_int *, struct sort_criteria *);
|
||||
struct window_pane **sort_get_panes_session(struct session *, u_int *,
|
||||
struct sort_criteria *);
|
||||
struct window_pane **sort_get_panes_window(struct window *, u_int *,
|
||||
struct sort_criteria *);
|
||||
struct winlink **sort_get_winlinks(u_int *, struct sort_criteria *);
|
||||
struct winlink **sort_get_winlinks_session(struct session *, u_int *,
|
||||
struct sort_criteria *);
|
||||
|
||||
/* format.c */
|
||||
#define FORMAT_STATUS 0x1
|
||||
#define FORMAT_FORCE 0x2
|
||||
@@ -3347,7 +3390,7 @@ u_int layout_set_next(struct window *);
|
||||
u_int layout_set_previous(struct window *);
|
||||
|
||||
/* mode-tree.c */
|
||||
typedef void (*mode_tree_build_cb)(void *, struct mode_tree_sort_criteria *,
|
||||
typedef void (*mode_tree_build_cb)(void *, struct sort_criteria *,
|
||||
uint64_t *, const char *);
|
||||
typedef void (*mode_tree_draw_cb)(void *, void *, struct screen_write_ctx *,
|
||||
u_int, u_int);
|
||||
@@ -3355,7 +3398,8 @@ typedef int (*mode_tree_search_cb)(void *, void *, const char *, int);
|
||||
typedef void (*mode_tree_menu_cb)(void *, struct client *, key_code);
|
||||
typedef u_int (*mode_tree_height_cb)(void *, u_int);
|
||||
typedef key_code (*mode_tree_key_cb)(void *, void *, u_int);
|
||||
typedef int (*mode_tree_swap_cb)(void *, void *);
|
||||
typedef int (*mode_tree_swap_cb)(void *, void *, struct sort_criteria *);
|
||||
typedef void (*mode_tree_sort_cb)(struct sort_criteria *);
|
||||
typedef void (*mode_tree_each_cb)(void *, void *, struct client *, key_code);
|
||||
u_int mode_tree_count_tagged(struct mode_tree_data *);
|
||||
void *mode_tree_get_current(struct mode_tree_data *);
|
||||
@@ -3371,8 +3415,8 @@ int mode_tree_down(struct mode_tree_data *, int);
|
||||
struct mode_tree_data *mode_tree_start(struct window_pane *, struct args *,
|
||||
mode_tree_build_cb, mode_tree_draw_cb, mode_tree_search_cb,
|
||||
mode_tree_menu_cb, mode_tree_height_cb, mode_tree_key_cb,
|
||||
mode_tree_swap_cb, void *, const struct menu_item *, const char **,
|
||||
u_int, struct screen **);
|
||||
mode_tree_swap_cb, mode_tree_sort_cb, void *,
|
||||
const struct menu_item *, struct screen **);
|
||||
void mode_tree_zoom(struct mode_tree_data *, struct args *);
|
||||
void mode_tree_build(struct mode_tree_data *);
|
||||
void mode_tree_free(struct mode_tree_data *);
|
||||
@@ -3482,8 +3526,9 @@ void session_add_ref(struct session *, const char *);
|
||||
void session_remove_ref(struct session *, const char *);
|
||||
char *session_check_name(const char *);
|
||||
void session_update_activity(struct session *, struct timeval *);
|
||||
struct session *session_next_session(struct session *);
|
||||
struct session *session_previous_session(struct session *);
|
||||
struct session *session_next_session(struct session *, struct sort_criteria *);
|
||||
struct session *session_previous_session(struct session *,
|
||||
struct sort_criteria *);
|
||||
struct winlink *session_attach(struct session *, struct window *, int,
|
||||
char **);
|
||||
int session_detach(struct session *, struct winlink *);
|
||||
|
||||
@@ -76,18 +76,6 @@ const struct window_mode window_buffer_mode = {
|
||||
.key = window_buffer_key,
|
||||
};
|
||||
|
||||
enum window_buffer_sort_type {
|
||||
WINDOW_BUFFER_BY_TIME,
|
||||
WINDOW_BUFFER_BY_NAME,
|
||||
WINDOW_BUFFER_BY_SIZE,
|
||||
};
|
||||
static const char *window_buffer_sort_list[] = {
|
||||
"time",
|
||||
"name",
|
||||
"size"
|
||||
};
|
||||
static struct mode_tree_sort_criteria *window_buffer_sort;
|
||||
|
||||
struct window_buffer_itemdata {
|
||||
const char *name;
|
||||
u_int order;
|
||||
@@ -113,6 +101,13 @@ struct window_buffer_editdata {
|
||||
struct paste_buffer *pb;
|
||||
};
|
||||
|
||||
static enum sort_order window_buffer_order_seq[] = {
|
||||
SORT_CREATION,
|
||||
SORT_NAME,
|
||||
SORT_SIZE,
|
||||
SORT_END,
|
||||
};
|
||||
|
||||
static struct window_buffer_itemdata *
|
||||
window_buffer_add_item(struct window_buffer_modedata *data)
|
||||
{
|
||||
@@ -131,35 +126,14 @@ window_buffer_free_item(struct window_buffer_itemdata *item)
|
||||
free(item);
|
||||
}
|
||||
|
||||
static int
|
||||
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;
|
||||
int result = 0;
|
||||
|
||||
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;
|
||||
|
||||
/* Use WINDOW_BUFFER_BY_NAME as default order and tie breaker. */
|
||||
if (result == 0)
|
||||
result = strcmp((*a)->name, (*b)->name);
|
||||
|
||||
if (window_buffer_sort->reversed)
|
||||
result = -result;
|
||||
return (result);
|
||||
}
|
||||
|
||||
static void
|
||||
window_buffer_build(void *modedata, struct mode_tree_sort_criteria *sort_crit,
|
||||
window_buffer_build(void *modedata, struct sort_criteria *sort_crit,
|
||||
__unused uint64_t *tag, const char *filter)
|
||||
{
|
||||
struct window_buffer_modedata *data = modedata;
|
||||
struct window_buffer_itemdata *item;
|
||||
u_int i;
|
||||
struct paste_buffer *pb = NULL;
|
||||
u_int i, n;
|
||||
struct paste_buffer *pb, **l;
|
||||
char *text, *cp;
|
||||
struct format_tree *ft;
|
||||
struct session *s = NULL;
|
||||
@@ -172,17 +146,14 @@ window_buffer_build(void *modedata, struct mode_tree_sort_criteria *sort_crit,
|
||||
data->item_list = NULL;
|
||||
data->item_size = 0;
|
||||
|
||||
while ((pb = paste_walk(pb)) != NULL) {
|
||||
l = sort_get_buffers(&n, sort_crit);
|
||||
for (i = 0; i < n; i++) {
|
||||
item = window_buffer_add_item(data);
|
||||
item->name = xstrdup(paste_buffer_name(pb));
|
||||
paste_buffer_data(pb, &item->size);
|
||||
item->order = paste_buffer_order(pb);
|
||||
item->name = xstrdup(paste_buffer_name(l[i]));
|
||||
paste_buffer_data(l[i], &item->size);
|
||||
item->order = paste_buffer_order(l[i]);
|
||||
}
|
||||
|
||||
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;
|
||||
wl = data->fs.wl;
|
||||
@@ -216,7 +187,6 @@ window_buffer_build(void *modedata, struct mode_tree_sort_criteria *sort_crit,
|
||||
|
||||
format_free(ft);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -351,6 +321,14 @@ window_buffer_get_key(void *modedata, void *itemdata, u_int line)
|
||||
return (key);
|
||||
}
|
||||
|
||||
static void
|
||||
window_buffer_sort(struct sort_criteria *sort_crit)
|
||||
{
|
||||
sort_crit->order_seq = window_buffer_order_seq;
|
||||
if (sort_crit->order == SORT_END)
|
||||
sort_crit->order = sort_crit->order_seq[0];
|
||||
}
|
||||
|
||||
static struct screen *
|
||||
window_buffer_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
||||
struct args *args)
|
||||
@@ -378,8 +356,8 @@ window_buffer_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
||||
|
||||
data->data = mode_tree_start(wp, args, window_buffer_build,
|
||||
window_buffer_draw, window_buffer_search, window_buffer_menu, NULL,
|
||||
window_buffer_get_key, NULL, data, window_buffer_menu_items,
|
||||
window_buffer_sort_list, nitems(window_buffer_sort_list), &s);
|
||||
window_buffer_get_key, NULL, window_buffer_sort, data,
|
||||
window_buffer_menu_items, &s);
|
||||
mode_tree_zoom(data->data, args);
|
||||
|
||||
mode_tree_build(data->data);
|
||||
|
||||
@@ -71,20 +71,6 @@ const struct window_mode window_client_mode = {
|
||||
.key = window_client_key,
|
||||
};
|
||||
|
||||
enum window_client_sort_type {
|
||||
WINDOW_CLIENT_BY_NAME,
|
||||
WINDOW_CLIENT_BY_SIZE,
|
||||
WINDOW_CLIENT_BY_CREATION_TIME,
|
||||
WINDOW_CLIENT_BY_ACTIVITY_TIME,
|
||||
};
|
||||
static const char *window_client_sort_list[] = {
|
||||
"name",
|
||||
"size",
|
||||
"creation",
|
||||
"activity"
|
||||
};
|
||||
static struct mode_tree_sort_criteria *window_client_sort;
|
||||
|
||||
struct window_client_itemdata {
|
||||
struct client *c;
|
||||
};
|
||||
@@ -101,6 +87,14 @@ struct window_client_modedata {
|
||||
u_int item_size;
|
||||
};
|
||||
|
||||
static enum sort_order window_client_order_seq[] = {
|
||||
SORT_NAME,
|
||||
SORT_SIZE,
|
||||
SORT_CREATION,
|
||||
SORT_ACTIVITY,
|
||||
SORT_END,
|
||||
};
|
||||
|
||||
static struct window_client_itemdata *
|
||||
window_client_add_item(struct window_client_modedata *data)
|
||||
{
|
||||
@@ -119,54 +113,14 @@ window_client_free_item(struct window_client_itemdata *item)
|
||||
free(item);
|
||||
}
|
||||
|
||||
static int
|
||||
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 *itema = *a;
|
||||
const struct window_client_itemdata *itemb = *b;
|
||||
struct client *ca = itema->c;
|
||||
struct client *cb = itemb->c;
|
||||
int result = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Use WINDOW_CLIENT_BY_NAME as default order and tie breaker. */
|
||||
if (result == 0)
|
||||
result = strcmp(ca->name, cb->name);
|
||||
|
||||
if (window_client_sort->reversed)
|
||||
result = -result;
|
||||
return (result);
|
||||
}
|
||||
|
||||
static void
|
||||
window_client_build(void *modedata, struct mode_tree_sort_criteria *sort_crit,
|
||||
window_client_build(void *modedata, struct sort_criteria *sort_crit,
|
||||
__unused uint64_t *tag, const char *filter)
|
||||
{
|
||||
struct window_client_modedata *data = modedata;
|
||||
struct window_client_itemdata *item;
|
||||
u_int i;
|
||||
struct client *c;
|
||||
u_int i, n;
|
||||
struct client *c, **l;
|
||||
char *text, *cp;
|
||||
|
||||
for (i = 0; i < data->item_size; i++)
|
||||
@@ -175,20 +129,18 @@ window_client_build(void *modedata, struct mode_tree_sort_criteria *sort_crit,
|
||||
data->item_list = NULL;
|
||||
data->item_size = 0;
|
||||
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (c->session == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
|
||||
l = sort_get_clients(&n, sort_crit);
|
||||
for (i = 0; i < n; i++) {
|
||||
if (l[i]->session == NULL ||
|
||||
(l[i]->flags & CLIENT_UNATTACHEDFLAGS))
|
||||
continue;
|
||||
|
||||
item = window_client_add_item(data);
|
||||
item->c = c;
|
||||
item->c = l[i];
|
||||
|
||||
c->references++;
|
||||
l[i]->references++;
|
||||
}
|
||||
|
||||
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];
|
||||
c = item->c;
|
||||
@@ -280,6 +232,14 @@ window_client_get_key(void *modedata, void *itemdata, u_int line)
|
||||
return (key);
|
||||
}
|
||||
|
||||
static void
|
||||
window_client_sort(struct sort_criteria *sort_crit)
|
||||
{
|
||||
sort_crit->order_seq = window_client_order_seq;
|
||||
if (sort_crit->order == SORT_END)
|
||||
sort_crit->order = sort_crit->order_seq[0];
|
||||
}
|
||||
|
||||
static struct screen *
|
||||
window_client_init(struct window_mode_entry *wme,
|
||||
__unused struct cmd_find_state *fs, struct args *args)
|
||||
@@ -306,8 +266,8 @@ window_client_init(struct window_mode_entry *wme,
|
||||
|
||||
data->data = mode_tree_start(wp, args, window_client_build,
|
||||
window_client_draw, NULL, window_client_menu, NULL,
|
||||
window_client_get_key, NULL, data, window_client_menu_items,
|
||||
window_client_sort_list, nitems(window_client_sort_list), &s);
|
||||
window_client_get_key, NULL, window_client_sort, data,
|
||||
window_client_menu_items, &s);
|
||||
mode_tree_zoom(data->data, args);
|
||||
|
||||
mode_tree_build(data->data);
|
||||
|
||||
@@ -525,7 +525,7 @@ window_customize_build_keys(struct window_customize_modedata *data,
|
||||
|
||||
static void
|
||||
window_customize_build(void *modedata,
|
||||
__unused struct mode_tree_sort_criteria *sort_crit, __unused uint64_t *tag,
|
||||
__unused struct sort_criteria *sort_crit, __unused uint64_t *tag,
|
||||
const char *filter)
|
||||
{
|
||||
struct window_customize_modedata *data = modedata;
|
||||
@@ -891,8 +891,8 @@ window_customize_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
||||
|
||||
data->data = mode_tree_start(wp, args, window_customize_build,
|
||||
window_customize_draw, NULL, window_customize_menu,
|
||||
window_customize_height, NULL, NULL, data,
|
||||
window_customize_menu_items, NULL, 0, &s);
|
||||
window_customize_height, NULL, NULL, NULL, data,
|
||||
window_customize_menu_items, &s);
|
||||
mode_tree_zoom(data->data, args);
|
||||
|
||||
mode_tree_build(data->data);
|
||||
|
||||
193
window-tree.c
193
window-tree.c
@@ -89,18 +89,6 @@ const struct window_mode window_tree_mode = {
|
||||
.key = window_tree_key,
|
||||
};
|
||||
|
||||
enum window_tree_sort_type {
|
||||
WINDOW_TREE_BY_INDEX,
|
||||
WINDOW_TREE_BY_NAME,
|
||||
WINDOW_TREE_BY_TIME,
|
||||
};
|
||||
static const char *window_tree_sort_list[] = {
|
||||
"index",
|
||||
"name",
|
||||
"time"
|
||||
};
|
||||
static struct mode_tree_sort_criteria *window_tree_sort;
|
||||
|
||||
enum window_tree_type {
|
||||
WINDOW_TREE_NONE,
|
||||
WINDOW_TREE_SESSION,
|
||||
@@ -144,6 +132,13 @@ struct window_tree_modedata {
|
||||
u_int each;
|
||||
};
|
||||
|
||||
static enum sort_order window_tree_order_seq[] = {
|
||||
SORT_INDEX,
|
||||
SORT_NAME,
|
||||
SORT_ACTIVITY,
|
||||
SORT_END,
|
||||
};
|
||||
|
||||
static void
|
||||
window_tree_pull_item(struct window_tree_itemdata *item, struct session **sp,
|
||||
struct winlink **wlp, struct window_pane **wp)
|
||||
@@ -196,98 +191,6 @@ window_tree_free_item(struct window_tree_itemdata *item)
|
||||
free(item);
|
||||
}
|
||||
|
||||
static int
|
||||
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 *sa = *a;
|
||||
const struct session *sb = *b;
|
||||
int result = 0;
|
||||
|
||||
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_window(const void *a0, const void *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 = 0;
|
||||
|
||||
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_pane(const void *a0, const void *b0)
|
||||
{
|
||||
struct window_pane **a = (struct window_pane **)a0;
|
||||
struct window_pane **b = (struct window_pane **)b0;
|
||||
int result;
|
||||
u_int ai, bi;
|
||||
|
||||
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.
|
||||
*/
|
||||
window_pane_index(*a, &ai);
|
||||
window_pane_index(*b, &bi);
|
||||
result = ai - bi;
|
||||
}
|
||||
if (window_tree_sort->reversed)
|
||||
result = -result;
|
||||
return (result);
|
||||
}
|
||||
|
||||
static void
|
||||
window_tree_build_pane(struct session *s, struct winlink *wl,
|
||||
struct window_pane *wp, void *modedata, struct mode_tree_item *parent)
|
||||
@@ -339,7 +242,7 @@ window_tree_filter_pane(struct session *s, struct winlink *wl,
|
||||
|
||||
static int
|
||||
window_tree_build_window(struct session *s, struct winlink *wl,
|
||||
void *modedata, struct mode_tree_sort_criteria *sort_crit,
|
||||
void *modedata, struct sort_criteria *sort_crit,
|
||||
struct mode_tree_item *parent, const char *filter)
|
||||
{
|
||||
struct window_tree_modedata *data = modedata;
|
||||
@@ -381,24 +284,13 @@ window_tree_build_window(struct session *s, struct winlink *wl,
|
||||
goto empty;
|
||||
}
|
||||
|
||||
l = NULL;
|
||||
n = 0;
|
||||
|
||||
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
|
||||
if (!window_tree_filter_pane(s, wl, wp, filter))
|
||||
continue;
|
||||
l = xreallocarray(l, n + 1, sizeof *l);
|
||||
l[n++] = wp;
|
||||
}
|
||||
l = sort_get_panes_window(wl->window, &n, sort_crit);
|
||||
if (n == 0)
|
||||
goto empty;
|
||||
|
||||
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);
|
||||
free(l);
|
||||
for (i = 0; i < n; i++) {
|
||||
if (window_tree_filter_pane(s, wl, l[i], filter))
|
||||
window_tree_build_pane(s, wl, l[i], modedata, mti);
|
||||
}
|
||||
return (1);
|
||||
|
||||
empty:
|
||||
@@ -410,7 +302,7 @@ empty:
|
||||
|
||||
static void
|
||||
window_tree_build_session(struct session *s, void *modedata,
|
||||
struct mode_tree_sort_criteria *sort_crit, const char *filter)
|
||||
struct sort_criteria *sort_crit, const char *filter)
|
||||
{
|
||||
struct window_tree_modedata *data = modedata;
|
||||
struct window_tree_itemdata *item;
|
||||
@@ -440,15 +332,7 @@ window_tree_build_session(struct session *s, void *modedata,
|
||||
expanded);
|
||||
free(text);
|
||||
|
||||
l = NULL;
|
||||
n = 0;
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
l = xreallocarray(l, n + 1, sizeof *l);
|
||||
l[n++] = wl;
|
||||
}
|
||||
window_tree_sort = sort_crit;
|
||||
qsort(l, n, sizeof *l, window_tree_cmp_window);
|
||||
|
||||
l = sort_get_winlinks_session(s, &n, sort_crit);
|
||||
empty = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
if (!window_tree_build_window(s, l[i], modedata, sort_crit, mti,
|
||||
@@ -460,11 +344,10 @@ window_tree_build_session(struct session *s, void *modedata,
|
||||
data->item_size--;
|
||||
mode_tree_remove(data->data, mti);
|
||||
}
|
||||
free(l);
|
||||
}
|
||||
|
||||
static void
|
||||
window_tree_build(void *modedata, struct mode_tree_sort_criteria *sort_crit,
|
||||
window_tree_build(void *modedata, struct sort_criteria *sort_crit,
|
||||
uint64_t *tag, const char *filter)
|
||||
{
|
||||
struct window_tree_modedata *data = modedata;
|
||||
@@ -480,24 +363,19 @@ window_tree_build(void *modedata, struct mode_tree_sort_criteria *sort_crit,
|
||||
data->item_list = NULL;
|
||||
data->item_size = 0;
|
||||
|
||||
l = NULL;
|
||||
n = 0;
|
||||
RB_FOREACH(s, sessions, &sessions) {
|
||||
l = sort_get_sessions(&n, sort_crit);
|
||||
if (n == 0)
|
||||
return;
|
||||
s = l[n - 1];
|
||||
for (i = 0; i < n; i++) {
|
||||
if (data->squash_groups &&
|
||||
(sg = session_group_contains(s)) != NULL) {
|
||||
if ((sg == current && s != data->fs.s) ||
|
||||
(sg != current && s != TAILQ_FIRST(&sg->sessions)))
|
||||
continue;
|
||||
}
|
||||
l = xreallocarray(l, n + 1, sizeof *l);
|
||||
l[n++] = s;
|
||||
}
|
||||
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_crit, filter);
|
||||
free(l);
|
||||
}
|
||||
|
||||
switch (data->type) {
|
||||
case WINDOW_TREE_NONE:
|
||||
@@ -924,7 +802,8 @@ window_tree_get_key(void *modedata, void *itemdata, u_int line)
|
||||
}
|
||||
|
||||
static int
|
||||
window_tree_swap(void *cur_itemdata, void *other_itemdata)
|
||||
window_tree_swap(void *cur_itemdata, void *other_itemdata,
|
||||
struct sort_criteria *sort_crit)
|
||||
{
|
||||
struct window_tree_itemdata *cur = cur_itemdata;
|
||||
struct window_tree_itemdata *other = other_itemdata;
|
||||
@@ -945,14 +824,12 @@ window_tree_swap(void *cur_itemdata, void *other_itemdata)
|
||||
if (cur_session != other_session)
|
||||
return (0);
|
||||
|
||||
if (window_tree_sort->field != WINDOW_TREE_BY_INDEX &&
|
||||
window_tree_cmp_window(&cur_winlink, &other_winlink) != 0) {
|
||||
/*
|
||||
* Swapping indexes would not swap positions in the tree, so
|
||||
* prevent swapping to avoid confusing the user.
|
||||
*/
|
||||
/*
|
||||
* Swapping indexes would not swap positions in the tree, so prevent
|
||||
* swapping to avoid confusing the user.
|
||||
*/
|
||||
if (sort_would_window_tree_swap(sort_crit, cur_winlink, other_winlink))
|
||||
return (0);
|
||||
}
|
||||
|
||||
other_window = other_winlink->window;
|
||||
TAILQ_REMOVE(&other_window->winlinks, other_winlink, wentry);
|
||||
@@ -975,6 +852,14 @@ window_tree_swap(void *cur_itemdata, void *other_itemdata)
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
window_tree_sort(struct sort_criteria *sort_crit)
|
||||
{
|
||||
sort_crit->order_seq = window_tree_order_seq;
|
||||
if (sort_crit->order == SORT_END)
|
||||
sort_crit->order = sort_crit->order_seq[0];
|
||||
}
|
||||
|
||||
static struct screen *
|
||||
window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
||||
struct args *args)
|
||||
@@ -1013,8 +898,8 @@ window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
||||
|
||||
data->data = mode_tree_start(wp, args, window_tree_build,
|
||||
window_tree_draw, window_tree_search, window_tree_menu, NULL,
|
||||
window_tree_get_key, window_tree_swap, data, window_tree_menu_items,
|
||||
window_tree_sort_list, nitems(window_tree_sort_list), &s);
|
||||
window_tree_get_key, window_tree_swap, window_tree_sort, data,
|
||||
window_tree_menu_items, &s);
|
||||
mode_tree_zoom(data->data, args);
|
||||
|
||||
mode_tree_build(data->data);
|
||||
|
||||
Reference in New Issue
Block a user