diff --git a/cmd-choose-tree.c b/cmd-choose-tree.c index 873b0286..919af491 100644 --- a/cmd-choose-tree.c +++ b/cmd-choose-tree.c @@ -30,8 +30,9 @@ const struct cmd_entry cmd_choose_tree_entry = { .name = "choose-tree", .alias = NULL, - .args = { "f:O:st:w", 0, 1 }, - .usage = "[-sw] [-f filter] [-O sort-order] " CMD_TARGET_PANE_USAGE, + .args = { "F:f:O:st:w", 0, 1 }, + .usage = "[-sw] [-F format] [-f filter] [-O sort-order] " + CMD_TARGET_PANE_USAGE, .target = { 't', CMD_FIND_PANE, 0 }, @@ -43,8 +44,9 @@ const struct cmd_entry cmd_choose_client_entry = { .name = "choose-client", .alias = NULL, - .args = { "f:O:t:", 0, 1 }, - .usage = "[-f filter] [-O sort-order] " CMD_TARGET_PANE_USAGE, + .args = { "F:f:O:t:", 0, 1 }, + .usage = "[-F format] [-f filter] [-O sort-order] " + CMD_TARGET_PANE_USAGE, .target = { 't', CMD_FIND_PANE, 0 }, @@ -56,8 +58,9 @@ const struct cmd_entry cmd_choose_buffer_entry = { .name = "choose-buffer", .alias = NULL, - .args = { "f:O:t:", 0, 1 }, - .usage = "[-f filter] [-O sort-order] " CMD_TARGET_PANE_USAGE, + .args = { "F:f:O:t:", 0, 1 }, + .usage = "[-F format] [-f filter] [-O sort-order] " + CMD_TARGET_PANE_USAGE, .target = { 't', CMD_FIND_PANE, 0 }, diff --git a/format.c b/format.c index ac996f6e..97205481 100644 --- a/format.c +++ b/format.c @@ -1232,6 +1232,10 @@ void format_defaults(struct format_tree *ft, struct client *c, struct session *s, struct winlink *wl, struct window_pane *wp) { + format_add(ft, "session_format", "%d", s != NULL); + format_add(ft, "window_format", "%d", wl != NULL); + format_add(ft, "pane_format", "%d", wp != NULL); + if (s == NULL && c != NULL) s = c->session; if (wl == NULL && s != NULL) @@ -1480,12 +1484,17 @@ format_defaults_pane(struct format_tree *ft, struct window_pane *wp) void format_defaults_paste_buffer(struct format_tree *ft, struct paste_buffer *pb) { - size_t bufsize; - char *s; + struct timeval tv; + size_t size; + char *s; - paste_buffer_data(pb, &bufsize); - format_add(ft, "buffer_size", "%zu", bufsize); + timerclear(&tv); + tv.tv_sec = paste_buffer_created(pb); + paste_buffer_data(pb, &size); + + format_add(ft, "buffer_size", "%zu", size); format_add(ft, "buffer_name", "%s", paste_buffer_name(pb)); + format_add_tv(ft, "buffer_created", &tv); s = paste_make_sample(pb); format_add(ft, "buffer_sample", "%s", s); diff --git a/screen-write.c b/screen-write.c index 88f03a31..15f8d07f 100644 --- a/screen-write.c +++ b/screen-write.c @@ -411,7 +411,7 @@ screen_write_hline(struct screen_write_ctx *ctx, u_int nx, int left, int right) /* Draw a horizontal line on screen. */ void -screen_write_vline(struct screen_write_ctx *ctx, u_int ny, int top, int bottom) +screen_write_vline(struct screen_write_ctx *ctx, u_int ny, int top, int bottom) { struct screen *s = ctx->s; struct grid_cell gc; diff --git a/tmux.1 b/tmux.1 index e7e05b97..367287a2 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1358,6 +1358,7 @@ the end of the visible pane. The default is to capture only the visible contents of the pane. .It Xo .Ic choose-client +.Op Fl F Ar format .Op Fl f Ar filter .Op Fl O Ar sort-order .Op Fl t Ar target-pane @@ -1405,10 +1406,13 @@ or .Ql activity . .Fl f specifies an initial filter. +.Fl F +specifies the format for each item in the list. This command works only if at least one client is attached. .It Xo .Ic choose-tree .Op Fl sw +.Op Fl F Ar format .Op Fl f Ar filter .Op Fl O Ar sort-order .Op Fl t Ar target-pane @@ -1456,6 +1460,8 @@ or .Ql time . .Fl f specifies an initial filter. +.Fl F +specifies the format for each item in the tree. This command works only if at least one client is attached. .It Xo .Ic display-panes @@ -3565,11 +3571,12 @@ The following variables are available, where appropriate: .It Li "alternate_on" Ta "" Ta "If pane is in alternate screen" .It Li "alternate_saved_x" Ta "" Ta "Saved cursor X in alternate screen" .It Li "alternate_saved_y" Ta "" Ta "Saved cursor Y in alternate screen" +.It Li "buffer_created" Ta "" Ta "Time buffer created" .It Li "buffer_name" Ta "" Ta "Name of buffer" .It Li "buffer_sample" Ta "" Ta "Sample of start of buffer" .It Li "buffer_size" Ta "" Ta "Size of the specified buffer in bytes" -.It Li "client_activity" Ta "" Ta "Integer time client last had activity" -.It Li "client_created" Ta "" Ta "Integer time client created" +.It Li "client_activity" Ta "" Ta "Time client last had activity" +.It Li "client_created" Ta "" Ta "Time client created" .It Li "client_control_mode" Ta "" Ta "1 if client is in control mode" .It Li "client_discarded" Ta "" Ta "Bytes discarded when client behind" .It Li "client_height" Ta "" Ta "Height of client" @@ -3622,6 +3629,7 @@ The following variables are available, where appropriate: .It Li "pane_current_path" Ta "" Ta "Current path if available" .It Li "pane_dead" Ta "" Ta "1 if pane is dead" .It Li "pane_dead_status" Ta "" Ta "Exit status of process in dead pane" +.It Li "pane_format" Ta "" Ta "1 if format is for a pane (not assuming the current)" .It Li "pane_height" Ta "" Ta "Height of pane" .It Li "pane_id" Ta "#D" Ta "Unique pane ID" .It Li "pane_in_mode" Ta "" Ta "If pane is in a mode" @@ -3647,9 +3655,10 @@ The following variables are available, where appropriate: .It Li "selection_present" Ta "" Ta "1 if selection started in copy mode" .It Li "session_alerts" Ta "" Ta "List of window indexes with alerts" .It Li "session_attached" Ta "" Ta "Number of clients session is attached to" -.It Li "session_activity" Ta "" Ta "Integer time of session last activity" -.It Li "session_created" Ta "" Ta "Integer time session created" -.It Li "session_last_attached" Ta "" Ta "Integer time session last attached" +.It Li "session_activity" Ta "" Ta "Time of session last activity" +.It Li "session_created" Ta "" Ta "Time session created" +.It Li "session_format" Ta "" Ta "1 if format is for a session (not assuming the current)" +.It Li "session_last_attached" Ta "" Ta "Time session last attached" .It Li "session_group" Ta "" Ta "Name of session group" .It Li "session_grouped" Ta "" Ta "1 if session in a group" .It Li "session_height" Ta "" Ta "Height of session" @@ -3662,12 +3671,12 @@ The following variables are available, where appropriate: .It Li "socket_path" Ta "" Ta "Server socket path" .It Li "start_time" Ta "" Ta "Server start time" .It Li "version" Ta "" Ta "Server version" -.It Li "window_activity" Ta "" Ta "Integer time of window last activity" +.It Li "window_activity" Ta "" Ta "Time of window last activity" .It Li "window_activity_flag" Ta "" Ta "1 if window has activity" .It Li "window_active" Ta "" Ta "1 if window active" .It Li "window_bell_flag" Ta "" Ta "1 if window has bell" -.It Li "window_find_matches" Ta "" Ta "Matched data from the find-window" .It Li "window_flags" Ta "#F" Ta "Window flags" +.It Li "window_format" Ta "" Ta "1 if format is for a window (not assuming the current)" .It Li "window_height" Ta "" Ta "Height of window" .It Li "window_id" Ta "" Ta "Unique window ID" .It Li "window_index" Ta "#I" Ta "Index of window" @@ -4030,6 +4039,7 @@ The buffer commands are as follows: .Bl -tag -width Ds .It Xo .Ic choose-buffer +.Op Fl F Ar format .Op Fl f Ar filter .Op Fl O Ar sort-order .Op Fl t Ar target-pane @@ -4072,6 +4082,8 @@ or .Ql size . .Fl f specifies an initial filter. +.Fl F +specifies the format for each item in the list. This command works only if at least one client is attached. .It Ic clear-history Op Fl t Ar target-pane .D1 (alias: Ic clearhist ) diff --git a/window-buffer.c b/window-buffer.c index cc05ceef..927992d7 100644 --- a/window-buffer.c +++ b/window-buffer.c @@ -35,6 +35,9 @@ static void window_buffer_key(struct window_pane *, #define WINDOW_BUFFER_DEFAULT_COMMAND "paste-buffer -b '%%'" +#define WINDOW_BUFFER_DEFAULT_FORMAT \ + "#{buffer_size} bytes (#{t:buffer_created})" + const struct window_mode window_buffer_mode = { .name = "buffer-mode", @@ -57,7 +60,6 @@ static const char *window_buffer_sort_list[] = { struct window_buffer_itemdata { const char *name; - time_t created; u_int order; size_t size; }; @@ -65,6 +67,7 @@ struct window_buffer_itemdata { struct window_buffer_modedata { struct mode_tree_data *data; char *command; + char *format; struct window_buffer_itemdata **item_list; u_int item_size; @@ -131,7 +134,7 @@ window_buffer_build(void *modedata, u_int sort_type, __unused uint64_t *tag, struct window_buffer_itemdata *item; u_int i; struct paste_buffer *pb; - char *tim, *text, *cp; + char *text, *cp; struct format_tree *ft; for (i = 0; i < data->item_size; i++) @@ -144,7 +147,6 @@ window_buffer_build(void *modedata, u_int sort_type, __unused uint64_t *tag, while ((pb = paste_walk(pb)) != NULL) { item = window_buffer_add_item(data); item->name = xstrdup(paste_buffer_name(pb)); - item->created = paste_buffer_created(pb); paste_buffer_data(pb, &item->size); item->order = paste_buffer_order(pb); } @@ -167,12 +169,13 @@ window_buffer_build(void *modedata, u_int sort_type, __unused uint64_t *tag, for (i = 0; i < data->item_size; i++) { item = data->item_list[i]; + pb = paste_get_name(item->name); + if (pb == NULL) + continue; + ft = format_create(NULL, NULL, FORMAT_NONE, 0); + format_defaults_paste_buffer(ft, pb); + if (filter != NULL) { - pb = paste_get_name(item->name); - if (pb == NULL) - continue; - ft = format_create(NULL, NULL, FORMAT_NONE, 0); - format_defaults_paste_buffer(ft, pb); cp = format_expand(ft, filter); if (!format_true(cp)) { free(cp); @@ -180,16 +183,14 @@ window_buffer_build(void *modedata, u_int sort_type, __unused uint64_t *tag, continue; } free(cp); - format_free(ft); } - tim = ctime(&item->created); - *strchr(tim, '\n') = '\0'; - - xasprintf(&text, "%zu bytes (%s)", item->size, tim); + text = format_expand(ft, data->format); mode_tree_add(data->data, NULL, item, item->order, item->name, text, -1); free(text); + + format_free(ft); } } @@ -268,6 +269,10 @@ window_buffer_init(struct window_pane *wp, __unused struct cmd_find_state *fs, wp->modedata = data = xcalloc(1, sizeof *data); + if (args == NULL || !args_has(args, 'F')) + data->format = xstrdup(WINDOW_BUFFER_DEFAULT_FORMAT); + else + data->format = xstrdup(args_get(args, 'F')); if (args == NULL || args->argc == 0) data->command = xstrdup(WINDOW_BUFFER_DEFAULT_COMMAND); else @@ -298,7 +303,9 @@ window_buffer_free(struct window_pane *wp) window_buffer_free_item(data->item_list[i]); free(data->item_list); + free(data->format); free(data->command); + free(data); } diff --git a/window-client.c b/window-client.c index 2e72a398..214d3b7c 100644 --- a/window-client.c +++ b/window-client.c @@ -36,6 +36,10 @@ static void window_client_key(struct window_pane *, #define WINDOW_CLIENT_DEFAULT_COMMAND "detach-client -t '%%'" +#define WINDOW_CLIENT_DEFAULT_FORMAT \ + "session #{session_name} " \ + "(#{client_width}x#{client_height}, #{t:client_activity})" + const struct window_mode window_client_mode = { .name = "client-mode", @@ -64,6 +68,7 @@ struct window_client_itemdata { struct window_client_modedata { struct mode_tree_data *data; + char *format; char *command; struct window_client_itemdata **item_list; @@ -148,7 +153,7 @@ window_client_build(void *modedata, u_int sort_type, __unused uint64_t *tag, struct window_client_itemdata *item; u_int i; struct client *c; - char *tim, *text, *cp; + char *text, *cp; for (i = 0; i < data->item_size; i++) window_client_free_item(data->item_list[i]); @@ -198,11 +203,7 @@ window_client_build(void *modedata, u_int sort_type, __unused uint64_t *tag, free(cp); } - tim = ctime(&c->activity_time.tv_sec); - *strchr(tim, '\n') = '\0'; - - xasprintf(&text, "session %s (%ux%u, %s)", c->session->name, - c->tty.sx, c->tty.sy, tim); + text = format_single(NULL, data->format, c, NULL, NULL, NULL); mode_tree_add(data->data, NULL, item, (uint64_t)c, c->name, text, -1); free(text); @@ -251,6 +252,10 @@ window_client_init(struct window_pane *wp, __unused struct cmd_find_state *fs, wp->modedata = data = xcalloc(1, sizeof *data); + if (args == NULL || !args_has(args, 'F')) + data->format = xstrdup(WINDOW_CLIENT_DEFAULT_FORMAT); + else + data->format = xstrdup(args_get(args, 'F')); if (args == NULL || args->argc == 0) data->command = xstrdup(WINDOW_CLIENT_DEFAULT_COMMAND); else @@ -281,7 +286,9 @@ window_client_free(struct window_pane *wp) window_client_free_item(data->item_list[i]); free(data->item_list); + free(data->format); free(data->command); + free(data); } diff --git a/window-tree.c b/window-tree.c index a8d7a3fe..7be95307 100644 --- a/window-tree.c +++ b/window-tree.c @@ -33,6 +33,22 @@ static void window_tree_key(struct window_pane *, #define WINDOW_TREE_DEFAULT_COMMAND "switch-client -t '%%'" +#define WINDOW_TREE_DEFAULT_FORMAT \ + "#{?pane_format," \ + "#{pane_current_command} \"#{pane_title}\"" \ + "," \ + "#{?window_format," \ + "#{window_name}#{window_flags} " \ + "(#{window_panes} panes)" \ + "#{?#{==:#{window_panes},1}, \"#{pane_title}\",}" \ + "," \ + "#{session_windows} windows" \ + "#{?session_grouped, (group ,}" \ + "#{session_group}#{?session_grouped,),}" \ + "#{?session_attached, (attached),}" \ + "}" \ + "}" + const struct window_mode window_tree_mode = { .name = "tree-mode", @@ -73,6 +89,7 @@ struct window_tree_modedata { int references; struct mode_tree_data *data; + char *format; char *command; struct window_tree_itemdata **item_list; @@ -215,9 +232,7 @@ window_tree_build_pane(struct session *s, struct winlink *wl, item->winlink = wl->idx; item->pane = wp->id; - text = format_single(NULL, - "#{pane_current_command} \"#{pane_title}\"", - NULL, s, wl, wp); + text = format_single(NULL, data->format, NULL, s, wl, wp); xasprintf(&name, "%u", idx); mode_tree_add(data->data, parent, item, (uint64_t)wp, name, text, -1); @@ -243,10 +258,7 @@ window_tree_build_window(struct session *s, struct winlink *wl, void* modedata, item->winlink = wl->idx; item->pane = -1; - text = format_single(NULL, - "#{window_name}#{window_flags} (#{window_panes} panes)" - "#{?#{==:#{window_panes},1}, \"#{pane_title}\",}", - NULL, s, wl, NULL); + text = format_single(NULL, data->format, NULL, s, wl, NULL); xasprintf(&name, "%u", wl->idx); if (data->type == WINDOW_TREE_SESSION || @@ -319,12 +331,7 @@ window_tree_build_session(struct session *s, void* modedata, item->winlink = -1; item->pane = -1; - text = format_single(NULL, - "#{session_windows} windows" - "#{?session_grouped, (group ,}" - "#{session_group}#{?session_grouped,),}" - "#{?session_attached, (attached),}", - NULL, s, NULL, NULL); + text = format_single(NULL, data->format, NULL, s, NULL, NULL); if (data->type == WINDOW_TREE_SESSION) expanded = 0; @@ -755,6 +762,10 @@ window_tree_init(struct window_pane *wp, struct cmd_find_state *fs, data->wp = wp; data->references = 1; + if (args == NULL || !args_has(args, 'F')) + data->format = xstrdup(WINDOW_TREE_DEFAULT_FORMAT); + else + data->format = xstrdup(args_get(args, 'F')); if (args == NULL || args->argc == 0) data->command = xstrdup(WINDOW_TREE_DEFAULT_COMMAND); else @@ -786,7 +797,9 @@ window_tree_destroy(struct window_tree_modedata *data) window_tree_free_item(data->item_list[i]); free(data->item_list); + free(data->format); free(data->command); + free(data); }