mirror of
https://github.com/tmux/tmux.git
synced 2026-03-31 16:56:28 +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 \
|
spawn.c \
|
||||||
status.c \
|
status.c \
|
||||||
style.c \
|
style.c \
|
||||||
|
sort.c \
|
||||||
tmux.c \
|
tmux.c \
|
||||||
tty-acs.c \
|
tty-acs.c \
|
||||||
tty-draw.c \
|
tty-draw.c \
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ const struct cmd_entry cmd_list_buffers_entry = {
|
|||||||
.name = "list-buffers",
|
.name = "list-buffers",
|
||||||
.alias = "lsb",
|
.alias = "lsb",
|
||||||
|
|
||||||
.args = { "F:f:", 0, 0, NULL },
|
.args = { "F:f:O:r", 0, 0, NULL },
|
||||||
.usage = "[-F format] [-f filter]",
|
.usage = "[-F format] [-f filter] [-O order]",
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_list_buffers_exec
|
.exec = cmd_list_buffers_exec
|
||||||
@@ -47,20 +47,25 @@ static enum cmd_retval
|
|||||||
cmd_list_buffers_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_list_buffers_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
struct paste_buffer *pb;
|
struct paste_buffer **l;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
const char *template, *filter;
|
const char *template, *filter;
|
||||||
char *line, *expanded;
|
char *line, *expanded;
|
||||||
int flag;
|
int flag;
|
||||||
|
u_int i, n;
|
||||||
|
struct sort_criteria sort_crit;
|
||||||
|
|
||||||
if ((template = args_get(args, 'F')) == NULL)
|
if ((template = args_get(args, 'F')) == NULL)
|
||||||
template = LIST_BUFFERS_TEMPLATE;
|
template = LIST_BUFFERS_TEMPLATE;
|
||||||
filter = args_get(args, 'f');
|
filter = args_get(args, 'f');
|
||||||
|
|
||||||
pb = NULL;
|
sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||||
while ((pb = paste_walk(pb)) != NULL) {
|
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);
|
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) {
|
if (filter != NULL) {
|
||||||
expanded = format_expand(ft, filter);
|
expanded = format_expand(ft, filter);
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ const struct cmd_entry cmd_list_clients_entry = {
|
|||||||
.name = "list-clients",
|
.name = "list-clients",
|
||||||
.alias = "lsc",
|
.alias = "lsc",
|
||||||
|
|
||||||
.args = { "F:f:t:", 0, 0, NULL },
|
.args = { "F:f:O:rt:", 0, 0, NULL },
|
||||||
.usage = "[-F format] [-f filter] " CMD_TARGET_SESSION_USAGE,
|
.usage = "[-F format] [-f filter] [-O order]" CMD_TARGET_SESSION_USAGE,
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_SESSION, 0 },
|
.target = { 't', CMD_FIND_SESSION, 0 },
|
||||||
|
|
||||||
@@ -55,13 +55,14 @@ cmd_list_clients_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
{
|
{
|
||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
struct client *c;
|
struct client **l;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
const char *template, *filter;
|
const char *template, *filter;
|
||||||
u_int idx;
|
u_int i, n;
|
||||||
char *line, *expanded;
|
char *line, *expanded;
|
||||||
int flag;
|
int flag;
|
||||||
|
struct sort_criteria sort_crit;
|
||||||
|
|
||||||
if (args_has(args, 't'))
|
if (args_has(args, 't'))
|
||||||
s = target->s;
|
s = target->s;
|
||||||
@@ -72,14 +73,17 @@ cmd_list_clients_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
template = LIST_CLIENTS_TEMPLATE;
|
template = LIST_CLIENTS_TEMPLATE;
|
||||||
filter = args_get(args, 'f');
|
filter = args_get(args, 'f');
|
||||||
|
|
||||||
idx = 0;
|
sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
sort_crit.reversed = args_has(args, 'r');
|
||||||
if (c->session == NULL || (s != NULL && s != c->session))
|
|
||||||
|
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;
|
continue;
|
||||||
|
|
||||||
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
||||||
format_add(ft, "line", "%u", idx);
|
format_add(ft, "line", "%u", i);
|
||||||
format_defaults(ft, c, NULL, NULL, NULL);
|
format_defaults(ft, l[i], NULL, NULL, NULL);
|
||||||
|
|
||||||
if (filter != NULL) {
|
if (filter != NULL) {
|
||||||
expanded = format_expand(ft, filter);
|
expanded = format_expand(ft, filter);
|
||||||
@@ -94,8 +98,6 @@ cmd_list_clients_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
format_free(ft);
|
format_free(ft);
|
||||||
|
|
||||||
idx++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|||||||
@@ -38,8 +38,9 @@ const struct cmd_entry cmd_list_panes_entry = {
|
|||||||
.name = "list-panes",
|
.name = "list-panes",
|
||||||
.alias = "lsp",
|
.alias = "lsp",
|
||||||
|
|
||||||
.args = { "asF:f:t:", 0, 0, NULL },
|
.args = { "aF:f:O:rst:", 0, 0, NULL },
|
||||||
.usage = "[-as] [-F format] [-f filter] " CMD_TARGET_WINDOW_USAGE,
|
.usage = "[-asr] [-F format] [-f filter] [-O order]"
|
||||||
|
CMD_TARGET_WINDOW_USAGE,
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_WINDOW, 0 },
|
.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 cmdq_item *item, int type)
|
||||||
{
|
{
|
||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
struct window_pane *wp;
|
struct window_pane *wp, **l;
|
||||||
u_int n;
|
u_int i, n;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
const char *template, *filter;
|
const char *template, *filter;
|
||||||
char *line, *expanded;
|
char *line, *expanded;
|
||||||
int flag;
|
int flag;
|
||||||
|
struct sort_criteria sort_crit;
|
||||||
|
|
||||||
template = args_get(args, 'F');
|
template = args_get(args, 'F');
|
||||||
if (template == NULL) {
|
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');
|
filter = args_get(args, 'f');
|
||||||
|
|
||||||
n = 0;
|
sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||||
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
|
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);
|
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
||||||
format_add(ft, "line", "%u", n);
|
format_add(ft, "line", "%u", n);
|
||||||
format_defaults(ft, NULL, s, wl, wp);
|
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);
|
format_free(ft);
|
||||||
n++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ const struct cmd_entry cmd_list_sessions_entry = {
|
|||||||
.name = "list-sessions",
|
.name = "list-sessions",
|
||||||
.alias = "ls",
|
.alias = "ls",
|
||||||
|
|
||||||
.args = { "F:f:", 0, 0, NULL },
|
.args = { "F:f:O:r", 0, 0, NULL },
|
||||||
.usage = "[-F format] [-f filter]",
|
.usage = "[-r] [-F format] [-f filter] [-O order]",
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_list_sessions_exec
|
.exec = cmd_list_sessions_exec
|
||||||
@@ -53,22 +53,26 @@ static enum cmd_retval
|
|||||||
cmd_list_sessions_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_list_sessions_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
struct session *s;
|
struct session **l;
|
||||||
u_int n;
|
u_int n, i;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
const char *template, *filter;
|
const char *template, *filter;
|
||||||
char *line, *expanded;
|
char *line, *expanded;
|
||||||
int flag;
|
int flag;
|
||||||
|
struct sort_criteria sort_crit;
|
||||||
|
|
||||||
if ((template = args_get(args, 'F')) == NULL)
|
if ((template = args_get(args, 'F')) == NULL)
|
||||||
template = LIST_SESSIONS_TEMPLATE;
|
template = LIST_SESSIONS_TEMPLATE;
|
||||||
filter = args_get(args, 'f');
|
filter = args_get(args, 'f');
|
||||||
|
|
||||||
n = 0;
|
sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
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);
|
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
||||||
format_add(ft, "line", "%u", n);
|
format_add(ft, "line", "%u", i);
|
||||||
format_defaults(ft, NULL, s, NULL, NULL);
|
format_defaults(ft, NULL, l[i], NULL, NULL);
|
||||||
|
|
||||||
if (filter != NULL) {
|
if (filter != NULL) {
|
||||||
expanded = format_expand(ft, filter);
|
expanded = format_expand(ft, filter);
|
||||||
@@ -83,7 +87,6 @@ cmd_list_sessions_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
format_free(ft);
|
format_free(ft);
|
||||||
n++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|||||||
@@ -41,16 +41,13 @@
|
|||||||
|
|
||||||
static enum cmd_retval cmd_list_windows_exec(struct cmd *, struct cmdq_item *);
|
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 = {
|
const struct cmd_entry cmd_list_windows_entry = {
|
||||||
.name = "list-windows",
|
.name = "list-windows",
|
||||||
.alias = "lsw",
|
.alias = "lsw",
|
||||||
|
|
||||||
.args = { "F:f:at:", 0, 0, NULL },
|
.args = { "aF:f:O:rt:", 0, 0, NULL },
|
||||||
.usage = "[-a] [-F format] [-f filter] " CMD_TARGET_SESSION_USAGE,
|
.usage = "[-ar] [-F format] [-f filter] [-O order]"
|
||||||
|
CMD_TARGET_SESSION_USAGE,
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_SESSION, 0 },
|
.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 args *args = cmd_get_args(self);
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
|
struct winlink *wl, **l;
|
||||||
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;
|
struct session *s;
|
||||||
|
u_int i, n;
|
||||||
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 format_tree *ft;
|
struct format_tree *ft;
|
||||||
const char *template, *filter;
|
const char *template, *filter;
|
||||||
char *line, *expanded;
|
char *line, *expanded;
|
||||||
int flag;
|
int flag;
|
||||||
|
struct sort_criteria sort_crit;
|
||||||
|
|
||||||
template = args_get(args, 'F');
|
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');
|
filter = args_get(args, 'f');
|
||||||
|
|
||||||
n = 0;
|
sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
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);
|
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
||||||
format_add(ft, "line", "%u", n);
|
format_add(ft, "line", "%u", n);
|
||||||
format_defaults(ft, NULL, s, wl, NULL);
|
format_defaults(ft, NULL, s, wl, NULL);
|
||||||
@@ -125,6 +105,7 @@ cmd_list_windows_session(struct cmd *self, struct session *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
format_free(ft);
|
format_free(ft);
|
||||||
n++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ const struct cmd_entry cmd_switch_client_entry = {
|
|||||||
.name = "switch-client",
|
.name = "switch-client",
|
||||||
.alias = "switchc",
|
.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] "
|
.usage = "[-ElnprZ] [-c target-client] [-t target-session] "
|
||||||
"[-T key-table]",
|
"[-T key-table] [-O order]",
|
||||||
|
|
||||||
/* -t is special */
|
/* -t is special */
|
||||||
|
|
||||||
@@ -60,6 +60,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
const char *tablename;
|
const char *tablename;
|
||||||
struct key_table *table;
|
struct key_table *table;
|
||||||
|
struct sort_criteria sort_crit;
|
||||||
|
|
||||||
if (tflag != NULL &&
|
if (tflag != NULL &&
|
||||||
(tflag[strcspn(tflag, ":.%")] != '\0' || strcmp(tflag, "=") == 0)) {
|
(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);
|
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 (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");
|
cmdq_error(item, "can't find next session");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
} else if (args_has(args, 'p')) {
|
} 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");
|
cmdq_error(item, "can't find previous session");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|||||||
258
format.c
258
format.c
@@ -132,17 +132,7 @@ enum format_type {
|
|||||||
FORMAT_TYPE_PANE
|
FORMAT_TYPE_PANE
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Format loop sort type. */
|
static struct sort_criteria sort_crit;
|
||||||
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;
|
|
||||||
|
|
||||||
struct format_tree {
|
struct format_tree {
|
||||||
enum format_type type;
|
enum format_type type;
|
||||||
@@ -4388,44 +4378,11 @@ format_session_name(struct format_expand_state *es, const char *fmt)
|
|||||||
return (xstrdup("0"));
|
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. */
|
/* Loop over sessions. */
|
||||||
static char *
|
static char *
|
||||||
format_loop_sessions(struct format_expand_state *es, const char *fmt)
|
format_loop_sessions(struct format_expand_state *es, const char *fmt)
|
||||||
{
|
{
|
||||||
|
struct sort_criteria *sc = &sort_crit;
|
||||||
struct format_tree *ft = es->ft;
|
struct format_tree *ft = es->ft;
|
||||||
struct client *c = ft->client;
|
struct client *c = ft->client;
|
||||||
struct cmdq_item *item = ft->item;
|
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;
|
struct format_expand_state next;
|
||||||
char *all, *active, *use, *expanded, *value;
|
char *all, *active, *use, *expanded, *value;
|
||||||
size_t valuelen;
|
size_t valuelen;
|
||||||
struct session *s;
|
struct session *s, **l;
|
||||||
int i, n, last = 0;
|
int i, n, last = 0;
|
||||||
static struct session **l = NULL;
|
|
||||||
static int lsz = 0;
|
|
||||||
|
|
||||||
if (format_choose(es, fmt, &all, &active, 0) != 0) {
|
if (format_choose(es, fmt, &all, &active, 0) != 0) {
|
||||||
all = xstrdup(fmt);
|
all = xstrdup(fmt);
|
||||||
active = NULL;
|
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);
|
value = xcalloc(1, 1);
|
||||||
valuelen = 1;
|
valuelen = 1;
|
||||||
|
|
||||||
|
l = sort_get_sessions(&n, sc);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
s = l[i];
|
s = l[i];
|
||||||
format_log(es, "session loop: $%u", s->id);
|
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"));
|
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. */
|
/* Loop over windows. */
|
||||||
static char *
|
static char *
|
||||||
format_loop_windows(struct format_expand_state *es, const char *fmt)
|
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 format_tree *ft = es->ft;
|
||||||
struct client *c = ft->client;
|
struct client *c = ft->client;
|
||||||
struct cmdq_item *item = ft->item;
|
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;
|
struct format_expand_state next;
|
||||||
char *all, *active, *use, *expanded, *value;
|
char *all, *active, *use, *expanded, *value;
|
||||||
size_t valuelen;
|
size_t valuelen;
|
||||||
struct winlink *wl;
|
struct winlink *wl, **l;
|
||||||
struct window *w;
|
struct window *w;
|
||||||
int i, n, last = 0;
|
int i, n, last = 0;
|
||||||
static struct winlink **l = NULL;
|
|
||||||
static int lsz = 0;
|
|
||||||
|
|
||||||
if (ft->s == NULL) {
|
if (ft->s == NULL) {
|
||||||
format_log(es, "window loop but no session");
|
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;
|
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);
|
value = xcalloc(1, 1);
|
||||||
valuelen = 1;
|
valuelen = 1;
|
||||||
|
|
||||||
|
l = sort_get_winlinks_session(ft->s, &n, sc);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
wl = l[i];
|
wl = l[i];
|
||||||
w = wl->window;
|
w = wl->window;
|
||||||
@@ -4626,27 +4515,11 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
|
|||||||
return (value);
|
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. */
|
/* Loop over panes. */
|
||||||
static char *
|
static char *
|
||||||
format_loop_panes(struct format_expand_state *es, const char *fmt)
|
format_loop_panes(struct format_expand_state *es, const char *fmt)
|
||||||
{
|
{
|
||||||
|
struct sort_criteria *sc = &sort_crit;
|
||||||
struct format_tree *ft = es->ft;
|
struct format_tree *ft = es->ft;
|
||||||
struct client *c = ft->client;
|
struct client *c = ft->client;
|
||||||
struct cmdq_item *item = ft->item;
|
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;
|
struct format_expand_state next;
|
||||||
char *all, *active, *use, *expanded, *value;
|
char *all, *active, *use, *expanded, *value;
|
||||||
size_t valuelen;
|
size_t valuelen;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp, **l;
|
||||||
int i, n, last = 0;
|
int i, n, last = 0;
|
||||||
static struct window_pane **l = NULL;
|
|
||||||
static int lsz = 0;
|
|
||||||
|
|
||||||
if (ft->w == NULL) {
|
if (ft->w == NULL) {
|
||||||
format_log(es, "pane loop but no window");
|
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;
|
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);
|
value = xcalloc(1, 1);
|
||||||
valuelen = 1;
|
valuelen = 1;
|
||||||
|
|
||||||
|
l = sort_get_panes_window(ft->w, &n, sc);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
wp = l[i];
|
wp = l[i];
|
||||||
format_log(es, "pane loop: %%%u", wp->id);
|
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);
|
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. */
|
/* Loop over clients. */
|
||||||
static char *
|
static char *
|
||||||
format_loop_clients(struct format_expand_state *es, const char *fmt)
|
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 format_tree *ft = es->ft;
|
||||||
struct client *c;
|
struct client *c, **l;
|
||||||
struct cmdq_item *item = ft->item;
|
struct cmdq_item *item = ft->item;
|
||||||
struct format_tree *nft;
|
struct format_tree *nft;
|
||||||
struct format_expand_state next;
|
struct format_expand_state next;
|
||||||
char *expanded, *value;
|
char *expanded, *value;
|
||||||
size_t valuelen;
|
size_t valuelen;
|
||||||
int i, n, last = 0;
|
int i, n, last = 0;
|
||||||
static struct client **l = NULL;
|
|
||||||
static int lsz = 0;
|
|
||||||
|
|
||||||
value = xcalloc(1, 1);
|
value = xcalloc(1, 1);
|
||||||
valuelen = 1;
|
valuelen = 1;
|
||||||
|
|
||||||
n = 0;
|
l = sort_get_clients(&n, sc);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
c = l[i];
|
c = l[i];
|
||||||
format_log(es, "client loop: %s", c->name);
|
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,
|
format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||||
char **buf, size_t *len, size_t *off)
|
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 format_tree *ft = es->ft;
|
||||||
struct window_pane *wp = ft->wp;
|
struct window_pane *wp = ft->wp;
|
||||||
const char *errstr, *copy, *cp, *cp2;
|
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;
|
u_int i, count, nsub = 0, nrep;
|
||||||
struct format_expand_state next;
|
struct format_expand_state next;
|
||||||
|
|
||||||
|
/* Set sorting defaults. */
|
||||||
|
sc->order = SORT_ORDER;
|
||||||
|
sc->reversed = 0;
|
||||||
|
|
||||||
/* Make a copy of the key. */
|
/* Make a copy of the key. */
|
||||||
copy = copy0 = xstrndup(key, keylen);
|
copy = copy0 = xstrndup(key, keylen);
|
||||||
|
|
||||||
@@ -5083,18 +4892,18 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
|||||||
case 'S':
|
case 'S':
|
||||||
modifiers |= FORMAT_SESSIONS;
|
modifiers |= FORMAT_SESSIONS;
|
||||||
if (fm->argc < 1) {
|
if (fm->argc < 1) {
|
||||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
sc->order= SORT_INDEX;
|
||||||
sc->reversed = 0;
|
sc->reversed = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (strchr(fm->argv[0], 'i') != NULL)
|
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)
|
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)
|
else if (strchr(fm->argv[0], 't') != NULL)
|
||||||
sc->field = FORMAT_LOOP_BY_TIME;
|
sc->order = SORT_ACTIVITY;
|
||||||
else
|
else
|
||||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
sc->order = SORT_INDEX;
|
||||||
if (strchr(fm->argv[0], 'r') != NULL)
|
if (strchr(fm->argv[0], 'r') != NULL)
|
||||||
sc->reversed = 1;
|
sc->reversed = 1;
|
||||||
else
|
else
|
||||||
@@ -5103,18 +4912,18 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
|||||||
case 'W':
|
case 'W':
|
||||||
modifiers |= FORMAT_WINDOWS;
|
modifiers |= FORMAT_WINDOWS;
|
||||||
if (fm->argc < 1) {
|
if (fm->argc < 1) {
|
||||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
sc->order = SORT_ORDER;
|
||||||
sc->reversed = 0;
|
sc->reversed = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (strchr(fm->argv[0], 'i') != NULL)
|
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)
|
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)
|
else if (strchr(fm->argv[0], 't') != NULL)
|
||||||
sc->field = FORMAT_LOOP_BY_TIME;
|
sc->order = SORT_ACTIVITY;
|
||||||
else
|
else
|
||||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
sc->order = SORT_ORDER;
|
||||||
if (strchr(fm->argv[0], 'r') != NULL)
|
if (strchr(fm->argv[0], 'r') != NULL)
|
||||||
sc->reversed = 1;
|
sc->reversed = 1;
|
||||||
else
|
else
|
||||||
@@ -5122,6 +4931,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
|||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
modifiers |= FORMAT_PANES;
|
modifiers |= FORMAT_PANES;
|
||||||
|
sc->order = SORT_CREATION;
|
||||||
if (fm->argc < 1) {
|
if (fm->argc < 1) {
|
||||||
sc->reversed = 0;
|
sc->reversed = 0;
|
||||||
break;
|
break;
|
||||||
@@ -5134,18 +4944,18 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
|||||||
case 'L':
|
case 'L':
|
||||||
modifiers |= FORMAT_CLIENTS;
|
modifiers |= FORMAT_CLIENTS;
|
||||||
if (fm->argc < 1) {
|
if (fm->argc < 1) {
|
||||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
sc->order = SORT_ORDER;
|
||||||
sc->reversed = 0;
|
sc->reversed = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (strchr(fm->argv[0], 'i') != NULL)
|
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)
|
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)
|
else if (strchr(fm->argv[0], 't') != NULL)
|
||||||
sc->field = FORMAT_LOOP_BY_TIME;
|
sc->order = SORT_ACTIVITY;
|
||||||
else
|
else
|
||||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
sc->order = SORT_ORDER;
|
||||||
if (strchr(fm->argv[0], 'r') != NULL)
|
if (strchr(fm->argv[0], 'r') != NULL)
|
||||||
sc->reversed = 1;
|
sc->reversed = 1;
|
||||||
else
|
else
|
||||||
|
|||||||
35
mode-tree.c
35
mode-tree.c
@@ -48,9 +48,7 @@ struct mode_tree_data {
|
|||||||
void *modedata;
|
void *modedata;
|
||||||
const struct menu_item *menu;
|
const struct menu_item *menu;
|
||||||
|
|
||||||
const char **sort_list;
|
struct sort_criteria sort_crit;
|
||||||
u_int sort_size;
|
|
||||||
struct mode_tree_sort_criteria sort_crit;
|
|
||||||
|
|
||||||
mode_tree_build_cb buildcb;
|
mode_tree_build_cb buildcb;
|
||||||
mode_tree_draw_cb drawcb;
|
mode_tree_draw_cb drawcb;
|
||||||
@@ -59,6 +57,7 @@ struct mode_tree_data {
|
|||||||
mode_tree_height_cb heightcb;
|
mode_tree_height_cb heightcb;
|
||||||
mode_tree_key_cb keycb;
|
mode_tree_key_cb keycb;
|
||||||
mode_tree_swap_cb swapcb;
|
mode_tree_swap_cb swapcb;
|
||||||
|
mode_tree_sort_cb sortcb;
|
||||||
|
|
||||||
struct mode_tree_list children;
|
struct mode_tree_list children;
|
||||||
struct mode_tree_list saved;
|
struct mode_tree_list saved;
|
||||||
@@ -324,7 +323,7 @@ mode_tree_swap(struct mode_tree_data *mtd, int direction)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (mtd->swapcb(mtd->line_list[mtd->current].item->itemdata,
|
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;
|
mtd->current = swap_with;
|
||||||
mode_tree_build(mtd);
|
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_build_cb buildcb, mode_tree_draw_cb drawcb,
|
||||||
mode_tree_search_cb searchcb, mode_tree_menu_cb menucb,
|
mode_tree_search_cb searchcb, mode_tree_menu_cb menucb,
|
||||||
mode_tree_height_cb heightcb, mode_tree_key_cb keycb,
|
mode_tree_height_cb heightcb, mode_tree_key_cb keycb,
|
||||||
mode_tree_swap_cb swapcb, void *modedata, const struct menu_item *menu,
|
mode_tree_swap_cb swapcb, mode_tree_sort_cb sortcb, void *modedata,
|
||||||
const char **sort_list, u_int sort_size, struct screen **s)
|
const struct menu_item *menu, struct screen **s)
|
||||||
{
|
{
|
||||||
struct mode_tree_data *mtd;
|
struct mode_tree_data *mtd;
|
||||||
const char *sort;
|
|
||||||
u_int i;
|
|
||||||
|
|
||||||
mtd = xcalloc(1, sizeof *mtd);
|
mtd = xcalloc(1, sizeof *mtd);
|
||||||
mtd->references = 1;
|
mtd->references = 1;
|
||||||
@@ -468,9 +465,6 @@ mode_tree_start(struct window_pane *wp, struct args *args,
|
|||||||
mtd->modedata = modedata;
|
mtd->modedata = modedata;
|
||||||
mtd->menu = menu;
|
mtd->menu = menu;
|
||||||
|
|
||||||
mtd->sort_list = sort_list;
|
|
||||||
mtd->sort_size = sort_size;
|
|
||||||
|
|
||||||
if (args_has(args, 'N') > 1)
|
if (args_has(args, 'N') > 1)
|
||||||
mtd->preview = MODE_TREE_PREVIEW_BIG;
|
mtd->preview = MODE_TREE_PREVIEW_BIG;
|
||||||
else if (args_has(args, 'N'))
|
else if (args_has(args, 'N'))
|
||||||
@@ -478,13 +472,7 @@ mode_tree_start(struct window_pane *wp, struct args *args,
|
|||||||
else
|
else
|
||||||
mtd->preview = MODE_TREE_PREVIEW_NORMAL;
|
mtd->preview = MODE_TREE_PREVIEW_NORMAL;
|
||||||
|
|
||||||
sort = args_get(args, 'O');
|
mtd->sort_crit.order = sort_order_from_string(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.reversed = args_has(args, 'r');
|
mtd->sort_crit.reversed = args_has(args, 'r');
|
||||||
|
|
||||||
if (args_has(args, 'f'))
|
if (args_has(args, 'f'))
|
||||||
@@ -499,6 +487,7 @@ mode_tree_start(struct window_pane *wp, struct args *args,
|
|||||||
mtd->heightcb = heightcb;
|
mtd->heightcb = heightcb;
|
||||||
mtd->keycb = keycb;
|
mtd->keycb = keycb;
|
||||||
mtd->swapcb = swapcb;
|
mtd->swapcb = swapcb;
|
||||||
|
mtd->sortcb = sortcb;
|
||||||
|
|
||||||
TAILQ_INIT(&mtd->children);
|
TAILQ_INIT(&mtd->children);
|
||||||
|
|
||||||
@@ -566,6 +555,8 @@ mode_tree_build(struct mode_tree_data *mtd)
|
|||||||
TAILQ_CONCAT(&mtd->saved, &mtd->children, entry);
|
TAILQ_CONCAT(&mtd->saved, &mtd->children, entry);
|
||||||
TAILQ_INIT(&mtd->children);
|
TAILQ_INIT(&mtd->children);
|
||||||
|
|
||||||
|
if (mtd->sortcb != NULL)
|
||||||
|
mtd->sortcb(&mtd->sort_crit);
|
||||||
mtd->buildcb(mtd->modedata, &mtd->sort_crit, &tag, mtd->filter);
|
mtd->buildcb(mtd->modedata, &mtd->sort_crit, &tag, mtd->filter);
|
||||||
mtd->no_matches = TAILQ_EMPTY(&mtd->children);
|
mtd->no_matches = TAILQ_EMPTY(&mtd->children);
|
||||||
if (mtd->no_matches)
|
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_cursormove(&ctx, 0, h, 0);
|
||||||
screen_write_box(&ctx, w, sy - h, BOX_LINES_DEFAULT, NULL, NULL);
|
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,
|
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" : "");
|
mtd->sort_crit.reversed ? ", reversed" : "");
|
||||||
} else
|
} else
|
||||||
xasprintf(&text, " %s", mti->name);
|
xasprintf(&text, " %s", mti->name);
|
||||||
@@ -1287,9 +1278,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'O':
|
case 'O':
|
||||||
mtd->sort_crit.field++;
|
sort_next_order(&mtd->sort_crit);
|
||||||
if (mtd->sort_crit.field >= mtd->sort_size)
|
|
||||||
mtd->sort_crit.field = 0;
|
|
||||||
mode_tree_build(mtd);
|
mode_tree_build(mtd);
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
|
|||||||
13
paste.c
13
paste.c
@@ -30,19 +30,6 @@
|
|||||||
* string!
|
* 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_index;
|
||||||
static u_int paste_next_order;
|
static u_int paste_next_order;
|
||||||
static u_int paste_num_automatic;
|
static u_int paste_num_automatic;
|
||||||
|
|||||||
@@ -438,9 +438,9 @@ server_destroy_session(struct session *s)
|
|||||||
else if (detach_on_destroy == 2)
|
else if (detach_on_destroy == 2)
|
||||||
s_new = server_find_session(s, server_newer_detached_session);
|
s_new = server_find_session(s, server_newer_detached_session);
|
||||||
else if (detach_on_destroy == 3)
|
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)
|
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
|
* 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. */
|
/* Find the next usable session. */
|
||||||
struct 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))
|
if (RB_EMPTY(&sessions) || !session_alive(s))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
s2 = RB_NEXT(sessions, &sessions, s);
|
l = sort_get_sessions(&n, sort_crit);
|
||||||
if (s2 == NULL)
|
for (i = 0; i < n; i++) {
|
||||||
s2 = RB_MIN(sessions, &sessions);
|
if (l[i] == s)
|
||||||
if (s2 == s)
|
break;
|
||||||
return (NULL);
|
}
|
||||||
return (s2);
|
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. */
|
/* Find the previous usable session. */
|
||||||
struct 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))
|
if (RB_EMPTY(&sessions) || !session_alive(s))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
s2 = RB_PREV(sessions, &sessions, s);
|
l = sort_get_sessions(&n, sort_crit);
|
||||||
if (s2 == NULL)
|
for (i = 0; i < n; i++) {
|
||||||
s2 = RB_MAX(sessions, &sessions);
|
if (l[i] == s)
|
||||||
if (s2 == s)
|
break;
|
||||||
return (NULL);
|
}
|
||||||
return (s2);
|
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. */
|
/* 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.
|
session.
|
||||||
.Tg lsc
|
.Tg lsc
|
||||||
.It Xo Ic list-clients
|
.It Xo Ic list-clients
|
||||||
|
.Op Fl r
|
||||||
.Op Fl F Ar format
|
.Op Fl F Ar format
|
||||||
.Op Fl f Ar filter
|
.Op Fl f Ar filter
|
||||||
|
.Op Fl O Ar sort-order
|
||||||
.Op Fl t Ar target-session
|
.Op Fl t Ar target-session
|
||||||
.Xc
|
.Xc
|
||||||
.D1 Pq alias: Ic lsc
|
.D1 Pq alias: Ic lsc
|
||||||
@@ -1197,6 +1199,16 @@ Only clients for which the filter is true are shown.
|
|||||||
See the
|
See the
|
||||||
.Sx FORMATS
|
.Sx FORMATS
|
||||||
section.
|
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
|
If
|
||||||
.Ar target-session
|
.Ar target-session
|
||||||
is specified, list only clients connected to that session.
|
is specified, list only clients connected to that session.
|
||||||
@@ -1212,8 +1224,10 @@ or - if omitted - of all commands supported by
|
|||||||
.Nm .
|
.Nm .
|
||||||
.Tg ls
|
.Tg ls
|
||||||
.It Xo Ic list-sessions
|
.It Xo Ic list-sessions
|
||||||
|
.Op Fl r
|
||||||
.Op Fl F Ar format
|
.Op Fl F Ar format
|
||||||
.Op Fl f Ar filter
|
.Op Fl f Ar filter
|
||||||
|
.Op Fl O Ar sort-order
|
||||||
.Xc
|
.Xc
|
||||||
.D1 Pq alias: Ic ls
|
.D1 Pq alias: Ic ls
|
||||||
List all sessions managed by the server.
|
List all sessions managed by the server.
|
||||||
@@ -1225,6 +1239,16 @@ Only sessions for which the filter is true are shown.
|
|||||||
See the
|
See the
|
||||||
.Sx FORMATS
|
.Sx FORMATS
|
||||||
section.
|
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
|
.Tg lockc
|
||||||
.It Ic lock-client Op Fl t Ar target-client
|
.It Ic lock-client Op Fl t Ar target-client
|
||||||
.D1 Pq alias: Ic lockc
|
.D1 Pq alias: Ic lockc
|
||||||
@@ -1621,6 +1645,7 @@ Suspend a client by sending
|
|||||||
.It Xo Ic switch-client
|
.It Xo Ic switch-client
|
||||||
.Op Fl ElnprZ
|
.Op Fl ElnprZ
|
||||||
.Op Fl c Ar target-client
|
.Op Fl c Ar target-client
|
||||||
|
.Op Fl O Ar sort-order
|
||||||
.Op Fl t Ar target-session
|
.Op Fl t Ar target-session
|
||||||
.Op Fl T Ar key-table
|
.Op Fl T Ar key-table
|
||||||
.Xc
|
.Xc
|
||||||
@@ -1647,6 +1672,18 @@ or
|
|||||||
.Fl p
|
.Fl p
|
||||||
is used, the client is moved to the last, next or previous session
|
is used, the client is moved to the last, next or previous session
|
||||||
respectively.
|
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
|
.Fl r
|
||||||
toggles the client
|
toggles the client
|
||||||
.Ic read-only
|
.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 selected client"
|
||||||
.It Li "Z" Ta "Suspend tagged clients"
|
.It Li "Z" Ta "Suspend tagged clients"
|
||||||
.It Li "f" Ta "Enter a format to filter items"
|
.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 "r" Ta "Reverse sort order"
|
||||||
.It Li "v" Ta "Toggle preview"
|
.It Li "v" Ta "Toggle preview"
|
||||||
.It Li "q" Ta "Exit mode"
|
.It Li "q" Ta "Exit mode"
|
||||||
@@ -2683,12 +2720,11 @@ If
|
|||||||
is not given, "detach-client -t \[aq]%%\[aq]" is used.
|
is not given, "detach-client -t \[aq]%%\[aq]" is used.
|
||||||
.Pp
|
.Pp
|
||||||
.Fl O
|
.Fl O
|
||||||
specifies the initial sort field: one of
|
specifies the initial sort order: one of
|
||||||
.Ql name ,
|
.Ql name ,
|
||||||
.Ql size ,
|
.Ql size ,
|
||||||
.Ql creation
|
.Ql creation
|
||||||
(time),
|
(time), or
|
||||||
or
|
|
||||||
.Ql activity
|
.Ql activity
|
||||||
(time).
|
(time).
|
||||||
.Fl r
|
.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 "\&:" Ta "Run a command for each tagged item"
|
||||||
.It Li "f" Ta "Enter a format to filter items"
|
.It Li "f" Ta "Enter a format to filter items"
|
||||||
.It Li "H" Ta "Jump to the starting pane"
|
.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 "r" Ta "Reverse sort order"
|
||||||
.It Li "v" Ta "Toggle preview"
|
.It Li "v" Ta "Toggle preview"
|
||||||
.It Li "q" Ta "Exit mode"
|
.It Li "q" Ta "Exit mode"
|
||||||
@@ -2773,12 +2809,12 @@ If
|
|||||||
is not given, "switch-client -t \[aq]%%\[aq]" is used.
|
is not given, "switch-client -t \[aq]%%\[aq]" is used.
|
||||||
.Pp
|
.Pp
|
||||||
.Fl O
|
.Fl O
|
||||||
specifies the initial sort field: one of
|
specifies the initial sort order: one of
|
||||||
.Ql index ,
|
.Ql index ,
|
||||||
.Ql name ,
|
.Ql name ,
|
||||||
or
|
or
|
||||||
.Ql time
|
.Ql activity
|
||||||
(activity).
|
(time).
|
||||||
.Fl r
|
.Fl r
|
||||||
reverses the sort order.
|
reverses the sort order.
|
||||||
.Fl f
|
.Fl f
|
||||||
@@ -3024,9 +3060,10 @@ If
|
|||||||
is given, the newly linked window is not selected.
|
is given, the newly linked window is not selected.
|
||||||
.Tg lsp
|
.Tg lsp
|
||||||
.It Xo Ic list-panes
|
.It Xo Ic list-panes
|
||||||
.Op Fl as
|
.Op Fl ars
|
||||||
.Op Fl F Ar format
|
.Op Fl F Ar format
|
||||||
.Op Fl f Ar filter
|
.Op Fl f Ar filter
|
||||||
|
.Op Fl O Ar sort-order
|
||||||
.Op Fl t Ar target
|
.Op Fl t Ar target
|
||||||
.Xc
|
.Xc
|
||||||
.D1 Pq alias: Ic lsp
|
.D1 Pq alias: Ic lsp
|
||||||
@@ -3051,11 +3088,21 @@ Only panes for which the filter is true are shown.
|
|||||||
See the
|
See the
|
||||||
.Sx FORMATS
|
.Sx FORMATS
|
||||||
section.
|
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
|
.Tg lsw
|
||||||
.It Xo Ic list-windows
|
.It Xo Ic list-windows
|
||||||
.Op Fl a
|
.Op Fl ar
|
||||||
.Op Fl F Ar format
|
.Op Fl F Ar format
|
||||||
.Op Fl f Ar filter
|
.Op Fl f Ar filter
|
||||||
|
.Op Fl O Ar sort-order
|
||||||
.Op Fl t Ar target-session
|
.Op Fl t Ar target-session
|
||||||
.Xc
|
.Xc
|
||||||
.D1 Pq alias: Ic lsw
|
.D1 Pq alias: Ic lsw
|
||||||
@@ -3072,6 +3119,15 @@ Only windows for which the filter is true are shown.
|
|||||||
See the
|
See the
|
||||||
.Sx FORMATS
|
.Sx FORMATS
|
||||||
section.
|
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
|
.Tg movep
|
||||||
.It Xo Ic move-pane
|
.It Xo Ic move-pane
|
||||||
.Op Fl bdfhv
|
.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 "D" Ta "Delete tagged buffers"
|
||||||
.It Li "e" Ta "Open the buffer in an editor"
|
.It Li "e" Ta "Open the buffer in an editor"
|
||||||
.It Li "f" Ta "Enter a format to filter items"
|
.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 "r" Ta "Reverse sort order"
|
||||||
.It Li "v" Ta "Toggle preview"
|
.It Li "v" Ta "Toggle preview"
|
||||||
.It Li "q" Ta "Exit mode"
|
.It Li "q" Ta "Exit mode"
|
||||||
@@ -7261,10 +7317,10 @@ If
|
|||||||
is not given, "paste-buffer -p -b \[aq]%%\[aq]" is used.
|
is not given, "paste-buffer -p -b \[aq]%%\[aq]" is used.
|
||||||
.Pp
|
.Pp
|
||||||
.Fl O
|
.Fl O
|
||||||
specifies the initial sort field: one of
|
specifies the initial sort order: one of
|
||||||
.Ql time
|
.Ql creation
|
||||||
(creation),
|
(time),
|
||||||
.Ql name
|
.Ql name ,
|
||||||
or
|
or
|
||||||
.Ql size .
|
.Ql size .
|
||||||
.Fl r
|
.Fl r
|
||||||
@@ -7297,8 +7353,10 @@ Delete the buffer named
|
|||||||
or the most recently added automatically named buffer if not specified.
|
or the most recently added automatically named buffer if not specified.
|
||||||
.Tg lsb
|
.Tg lsb
|
||||||
.It Xo Ic list-buffers
|
.It Xo Ic list-buffers
|
||||||
|
.Op Fl r
|
||||||
.Op Fl F Ar format
|
.Op Fl F Ar format
|
||||||
.Op Fl f Ar filter
|
.Op Fl f Ar filter
|
||||||
|
.Op Fl O Ar sort-order
|
||||||
.Xc
|
.Xc
|
||||||
.D1 Pq alias: Ic lsb
|
.D1 Pq alias: Ic lsb
|
||||||
List the global buffers.
|
List the global buffers.
|
||||||
@@ -7310,6 +7368,15 @@ Only buffers for which the filter is true are shown.
|
|||||||
See the
|
See the
|
||||||
.Sx FORMATS
|
.Sx FORMATS
|
||||||
section.
|
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
|
.It Xo Ic load-buffer
|
||||||
.Op Fl w
|
.Op Fl w
|
||||||
.Op Fl b Ar buffer-name
|
.Op Fl b Ar buffer-name
|
||||||
|
|||||||
65
tmux.h
65
tmux.h
@@ -2227,10 +2227,36 @@ struct spawn_context {
|
|||||||
#define SPAWN_ZOOM 0x80
|
#define SPAWN_ZOOM 0x80
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Mode tree sort order. */
|
/* Paste buffer. */
|
||||||
struct mode_tree_sort_criteria {
|
struct paste_buffer {
|
||||||
u_int field;
|
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;
|
int reversed;
|
||||||
|
enum sort_order *order_seq; /* available sort orders */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* tmux.c */
|
/* tmux.c */
|
||||||
@@ -2286,7 +2312,6 @@ void cfg_print_causes(struct cmdq_item *);
|
|||||||
void cfg_show_causes(struct session *);
|
void cfg_show_causes(struct session *);
|
||||||
|
|
||||||
/* paste.c */
|
/* paste.c */
|
||||||
struct paste_buffer;
|
|
||||||
const char *paste_buffer_name(struct paste_buffer *);
|
const char *paste_buffer_name(struct paste_buffer *);
|
||||||
u_int paste_buffer_order(struct paste_buffer *);
|
u_int paste_buffer_order(struct paste_buffer *);
|
||||||
time_t paste_buffer_created(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);
|
void paste_replace(struct paste_buffer *, char *, size_t);
|
||||||
char *paste_make_sample(struct paste_buffer *);
|
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 */
|
/* format.c */
|
||||||
#define FORMAT_STATUS 0x1
|
#define FORMAT_STATUS 0x1
|
||||||
#define FORMAT_FORCE 0x2
|
#define FORMAT_FORCE 0x2
|
||||||
@@ -3347,7 +3390,7 @@ u_int layout_set_next(struct window *);
|
|||||||
u_int layout_set_previous(struct window *);
|
u_int layout_set_previous(struct window *);
|
||||||
|
|
||||||
/* mode-tree.c */
|
/* 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 *);
|
uint64_t *, const char *);
|
||||||
typedef void (*mode_tree_draw_cb)(void *, void *, struct screen_write_ctx *,
|
typedef void (*mode_tree_draw_cb)(void *, void *, struct screen_write_ctx *,
|
||||||
u_int, u_int);
|
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 void (*mode_tree_menu_cb)(void *, struct client *, key_code);
|
||||||
typedef u_int (*mode_tree_height_cb)(void *, u_int);
|
typedef u_int (*mode_tree_height_cb)(void *, u_int);
|
||||||
typedef key_code (*mode_tree_key_cb)(void *, 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);
|
typedef void (*mode_tree_each_cb)(void *, void *, struct client *, key_code);
|
||||||
u_int mode_tree_count_tagged(struct mode_tree_data *);
|
u_int mode_tree_count_tagged(struct mode_tree_data *);
|
||||||
void *mode_tree_get_current(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 *,
|
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_build_cb, mode_tree_draw_cb, mode_tree_search_cb,
|
||||||
mode_tree_menu_cb, mode_tree_height_cb, mode_tree_key_cb,
|
mode_tree_menu_cb, mode_tree_height_cb, mode_tree_key_cb,
|
||||||
mode_tree_swap_cb, void *, const struct menu_item *, const char **,
|
mode_tree_swap_cb, mode_tree_sort_cb, void *,
|
||||||
u_int, struct screen **);
|
const struct menu_item *, struct screen **);
|
||||||
void mode_tree_zoom(struct mode_tree_data *, struct args *);
|
void mode_tree_zoom(struct mode_tree_data *, struct args *);
|
||||||
void mode_tree_build(struct mode_tree_data *);
|
void mode_tree_build(struct mode_tree_data *);
|
||||||
void mode_tree_free(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 *);
|
void session_remove_ref(struct session *, const char *);
|
||||||
char *session_check_name(const char *);
|
char *session_check_name(const char *);
|
||||||
void session_update_activity(struct session *, struct timeval *);
|
void session_update_activity(struct session *, struct timeval *);
|
||||||
struct session *session_next_session(struct session *);
|
struct session *session_next_session(struct session *, struct sort_criteria *);
|
||||||
struct session *session_previous_session(struct session *);
|
struct session *session_previous_session(struct session *,
|
||||||
|
struct sort_criteria *);
|
||||||
struct winlink *session_attach(struct session *, struct window *, int,
|
struct winlink *session_attach(struct session *, struct window *, int,
|
||||||
char **);
|
char **);
|
||||||
int session_detach(struct session *, struct winlink *);
|
int session_detach(struct session *, struct winlink *);
|
||||||
|
|||||||
@@ -76,18 +76,6 @@ const struct window_mode window_buffer_mode = {
|
|||||||
.key = window_buffer_key,
|
.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 {
|
struct window_buffer_itemdata {
|
||||||
const char *name;
|
const char *name;
|
||||||
u_int order;
|
u_int order;
|
||||||
@@ -113,6 +101,13 @@ struct window_buffer_editdata {
|
|||||||
struct paste_buffer *pb;
|
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 *
|
static struct window_buffer_itemdata *
|
||||||
window_buffer_add_item(struct window_buffer_modedata *data)
|
window_buffer_add_item(struct window_buffer_modedata *data)
|
||||||
{
|
{
|
||||||
@@ -131,35 +126,14 @@ window_buffer_free_item(struct window_buffer_itemdata *item)
|
|||||||
free(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
|
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)
|
__unused uint64_t *tag, const char *filter)
|
||||||
{
|
{
|
||||||
struct window_buffer_modedata *data = modedata;
|
struct window_buffer_modedata *data = modedata;
|
||||||
struct window_buffer_itemdata *item;
|
struct window_buffer_itemdata *item;
|
||||||
u_int i;
|
u_int i, n;
|
||||||
struct paste_buffer *pb = NULL;
|
struct paste_buffer *pb, **l;
|
||||||
char *text, *cp;
|
char *text, *cp;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
struct session *s = NULL;
|
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_list = NULL;
|
||||||
data->item_size = 0;
|
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 = window_buffer_add_item(data);
|
||||||
item->name = xstrdup(paste_buffer_name(pb));
|
item->name = xstrdup(paste_buffer_name(l[i]));
|
||||||
paste_buffer_data(pb, &item->size);
|
paste_buffer_data(l[i], &item->size);
|
||||||
item->order = paste_buffer_order(pb);
|
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)) {
|
if (cmd_find_valid_state(&data->fs)) {
|
||||||
s = data->fs.s;
|
s = data->fs.s;
|
||||||
wl = data->fs.wl;
|
wl = data->fs.wl;
|
||||||
@@ -216,7 +187,6 @@ window_buffer_build(void *modedata, struct mode_tree_sort_criteria *sort_crit,
|
|||||||
|
|
||||||
format_free(ft);
|
format_free(ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -351,6 +321,14 @@ window_buffer_get_key(void *modedata, void *itemdata, u_int line)
|
|||||||
return (key);
|
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 *
|
static struct screen *
|
||||||
window_buffer_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
window_buffer_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
||||||
struct args *args)
|
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,
|
data->data = mode_tree_start(wp, args, window_buffer_build,
|
||||||
window_buffer_draw, window_buffer_search, window_buffer_menu, NULL,
|
window_buffer_draw, window_buffer_search, window_buffer_menu, NULL,
|
||||||
window_buffer_get_key, NULL, data, window_buffer_menu_items,
|
window_buffer_get_key, NULL, window_buffer_sort, data,
|
||||||
window_buffer_sort_list, nitems(window_buffer_sort_list), &s);
|
window_buffer_menu_items, &s);
|
||||||
mode_tree_zoom(data->data, args);
|
mode_tree_zoom(data->data, args);
|
||||||
|
|
||||||
mode_tree_build(data->data);
|
mode_tree_build(data->data);
|
||||||
|
|||||||
@@ -71,20 +71,6 @@ const struct window_mode window_client_mode = {
|
|||||||
.key = window_client_key,
|
.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 window_client_itemdata {
|
||||||
struct client *c;
|
struct client *c;
|
||||||
};
|
};
|
||||||
@@ -101,6 +87,14 @@ struct window_client_modedata {
|
|||||||
u_int item_size;
|
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 *
|
static struct window_client_itemdata *
|
||||||
window_client_add_item(struct window_client_modedata *data)
|
window_client_add_item(struct window_client_modedata *data)
|
||||||
{
|
{
|
||||||
@@ -119,54 +113,14 @@ window_client_free_item(struct window_client_itemdata *item)
|
|||||||
free(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
|
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)
|
__unused uint64_t *tag, const char *filter)
|
||||||
{
|
{
|
||||||
struct window_client_modedata *data = modedata;
|
struct window_client_modedata *data = modedata;
|
||||||
struct window_client_itemdata *item;
|
struct window_client_itemdata *item;
|
||||||
u_int i;
|
u_int i, n;
|
||||||
struct client *c;
|
struct client *c, **l;
|
||||||
char *text, *cp;
|
char *text, *cp;
|
||||||
|
|
||||||
for (i = 0; i < data->item_size; i++)
|
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_list = NULL;
|
||||||
data->item_size = 0;
|
data->item_size = 0;
|
||||||
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
l = sort_get_clients(&n, sort_crit);
|
||||||
if (c->session == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
|
for (i = 0; i < n; i++) {
|
||||||
|
if (l[i]->session == NULL ||
|
||||||
|
(l[i]->flags & CLIENT_UNATTACHEDFLAGS))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
item = window_client_add_item(data);
|
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++) {
|
for (i = 0; i < data->item_size; i++) {
|
||||||
item = data->item_list[i];
|
item = data->item_list[i];
|
||||||
c = item->c;
|
c = item->c;
|
||||||
@@ -280,6 +232,14 @@ window_client_get_key(void *modedata, void *itemdata, u_int line)
|
|||||||
return (key);
|
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 *
|
static struct screen *
|
||||||
window_client_init(struct window_mode_entry *wme,
|
window_client_init(struct window_mode_entry *wme,
|
||||||
__unused struct cmd_find_state *fs, struct args *args)
|
__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,
|
data->data = mode_tree_start(wp, args, window_client_build,
|
||||||
window_client_draw, NULL, window_client_menu, NULL,
|
window_client_draw, NULL, window_client_menu, NULL,
|
||||||
window_client_get_key, NULL, data, window_client_menu_items,
|
window_client_get_key, NULL, window_client_sort, data,
|
||||||
window_client_sort_list, nitems(window_client_sort_list), &s);
|
window_client_menu_items, &s);
|
||||||
mode_tree_zoom(data->data, args);
|
mode_tree_zoom(data->data, args);
|
||||||
|
|
||||||
mode_tree_build(data->data);
|
mode_tree_build(data->data);
|
||||||
|
|||||||
@@ -525,7 +525,7 @@ window_customize_build_keys(struct window_customize_modedata *data,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
window_customize_build(void *modedata,
|
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)
|
const char *filter)
|
||||||
{
|
{
|
||||||
struct window_customize_modedata *data = modedata;
|
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,
|
data->data = mode_tree_start(wp, args, window_customize_build,
|
||||||
window_customize_draw, NULL, window_customize_menu,
|
window_customize_draw, NULL, window_customize_menu,
|
||||||
window_customize_height, NULL, NULL, data,
|
window_customize_height, NULL, NULL, NULL, data,
|
||||||
window_customize_menu_items, NULL, 0, &s);
|
window_customize_menu_items, &s);
|
||||||
mode_tree_zoom(data->data, args);
|
mode_tree_zoom(data->data, args);
|
||||||
|
|
||||||
mode_tree_build(data->data);
|
mode_tree_build(data->data);
|
||||||
|
|||||||
187
window-tree.c
187
window-tree.c
@@ -89,18 +89,6 @@ const struct window_mode window_tree_mode = {
|
|||||||
.key = window_tree_key,
|
.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 {
|
enum window_tree_type {
|
||||||
WINDOW_TREE_NONE,
|
WINDOW_TREE_NONE,
|
||||||
WINDOW_TREE_SESSION,
|
WINDOW_TREE_SESSION,
|
||||||
@@ -144,6 +132,13 @@ struct window_tree_modedata {
|
|||||||
u_int each;
|
u_int each;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static enum sort_order window_tree_order_seq[] = {
|
||||||
|
SORT_INDEX,
|
||||||
|
SORT_NAME,
|
||||||
|
SORT_ACTIVITY,
|
||||||
|
SORT_END,
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
window_tree_pull_item(struct window_tree_itemdata *item, struct session **sp,
|
window_tree_pull_item(struct window_tree_itemdata *item, struct session **sp,
|
||||||
struct winlink **wlp, struct window_pane **wp)
|
struct winlink **wlp, struct window_pane **wp)
|
||||||
@@ -196,98 +191,6 @@ window_tree_free_item(struct window_tree_itemdata *item)
|
|||||||
free(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
|
static void
|
||||||
window_tree_build_pane(struct session *s, struct winlink *wl,
|
window_tree_build_pane(struct session *s, struct winlink *wl,
|
||||||
struct window_pane *wp, void *modedata, struct mode_tree_item *parent)
|
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
|
static int
|
||||||
window_tree_build_window(struct session *s, struct winlink *wl,
|
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 mode_tree_item *parent, const char *filter)
|
||||||
{
|
{
|
||||||
struct window_tree_modedata *data = modedata;
|
struct window_tree_modedata *data = modedata;
|
||||||
@@ -381,24 +284,13 @@ window_tree_build_window(struct session *s, struct winlink *wl,
|
|||||||
goto empty;
|
goto empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
l = NULL;
|
l = sort_get_panes_window(wl->window, &n, sort_crit);
|
||||||
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;
|
|
||||||
}
|
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
goto empty;
|
goto empty;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
window_tree_sort = sort_crit;
|
if (window_tree_filter_pane(s, wl, l[i], filter))
|
||||||
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);
|
window_tree_build_pane(s, wl, l[i], modedata, mti);
|
||||||
free(l);
|
}
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
empty:
|
empty:
|
||||||
@@ -410,7 +302,7 @@ empty:
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
window_tree_build_session(struct session *s, void *modedata,
|
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_modedata *data = modedata;
|
||||||
struct window_tree_itemdata *item;
|
struct window_tree_itemdata *item;
|
||||||
@@ -440,15 +332,7 @@ window_tree_build_session(struct session *s, void *modedata,
|
|||||||
expanded);
|
expanded);
|
||||||
free(text);
|
free(text);
|
||||||
|
|
||||||
l = NULL;
|
l = sort_get_winlinks_session(s, &n, sort_crit);
|
||||||
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);
|
|
||||||
|
|
||||||
empty = 0;
|
empty = 0;
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
if (!window_tree_build_window(s, l[i], modedata, sort_crit, mti,
|
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--;
|
data->item_size--;
|
||||||
mode_tree_remove(data->data, mti);
|
mode_tree_remove(data->data, mti);
|
||||||
}
|
}
|
||||||
free(l);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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)
|
uint64_t *tag, const char *filter)
|
||||||
{
|
{
|
||||||
struct window_tree_modedata *data = modedata;
|
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_list = NULL;
|
||||||
data->item_size = 0;
|
data->item_size = 0;
|
||||||
|
|
||||||
l = NULL;
|
l = sort_get_sessions(&n, sort_crit);
|
||||||
n = 0;
|
if (n == 0)
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
return;
|
||||||
|
s = l[n - 1];
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
if (data->squash_groups &&
|
if (data->squash_groups &&
|
||||||
(sg = session_group_contains(s)) != NULL) {
|
(sg = session_group_contains(s)) != NULL) {
|
||||||
if ((sg == current && s != data->fs.s) ||
|
if ((sg == current && s != data->fs.s) ||
|
||||||
(sg != current && s != TAILQ_FIRST(&sg->sessions)))
|
(sg != current && s != TAILQ_FIRST(&sg->sessions)))
|
||||||
continue;
|
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);
|
window_tree_build_session(l[i], modedata, sort_crit, filter);
|
||||||
free(l);
|
}
|
||||||
|
|
||||||
switch (data->type) {
|
switch (data->type) {
|
||||||
case WINDOW_TREE_NONE:
|
case WINDOW_TREE_NONE:
|
||||||
@@ -924,7 +802,8 @@ window_tree_get_key(void *modedata, void *itemdata, u_int line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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 *cur = cur_itemdata;
|
||||||
struct window_tree_itemdata *other = other_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)
|
if (cur_session != other_session)
|
||||||
return (0);
|
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
|
* Swapping indexes would not swap positions in the tree, so prevent
|
||||||
* prevent swapping to avoid confusing the user.
|
* swapping to avoid confusing the user.
|
||||||
*/
|
*/
|
||||||
|
if (sort_would_window_tree_swap(sort_crit, cur_winlink, other_winlink))
|
||||||
return (0);
|
return (0);
|
||||||
}
|
|
||||||
|
|
||||||
other_window = other_winlink->window;
|
other_window = other_winlink->window;
|
||||||
TAILQ_REMOVE(&other_window->winlinks, other_winlink, wentry);
|
TAILQ_REMOVE(&other_window->winlinks, other_winlink, wentry);
|
||||||
@@ -975,6 +852,14 @@ window_tree_swap(void *cur_itemdata, void *other_itemdata)
|
|||||||
return (1);
|
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 *
|
static struct screen *
|
||||||
window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
||||||
struct args *args)
|
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,
|
data->data = mode_tree_start(wp, args, window_tree_build,
|
||||||
window_tree_draw, window_tree_search, window_tree_menu, NULL,
|
window_tree_draw, window_tree_search, window_tree_menu, NULL,
|
||||||
window_tree_get_key, window_tree_swap, data, window_tree_menu_items,
|
window_tree_get_key, window_tree_swap, window_tree_sort, data,
|
||||||
window_tree_sort_list, nitems(window_tree_sort_list), &s);
|
window_tree_menu_items, &s);
|
||||||
mode_tree_zoom(data->data, args);
|
mode_tree_zoom(data->data, args);
|
||||||
|
|
||||||
mode_tree_build(data->data);
|
mode_tree_build(data->data);
|
||||||
|
|||||||
Reference in New Issue
Block a user