From c6975b3bb46c35f8b41d934fd622033aa79a828c Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 10 Apr 2018 10:48:44 +0000 Subject: Add x and X to choose-tree (with a confirmation prompt) to kill an item. Suggested by Matt Zagrabelny. --- cmd-kill-pane.c | 12 +----- server-fn.c | 16 ++++++++ tmux.1 | 2 + tmux.h | 1 + window-tree.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 140 insertions(+), 15 deletions(-) diff --git a/cmd-kill-pane.c b/cmd-kill-pane.c index a8a423d0..01b1f518 100644 --- a/cmd-kill-pane.c +++ b/cmd-kill-pane.c @@ -47,9 +47,8 @@ cmd_kill_pane_exec(struct cmd *self, struct cmdq_item *item) struct winlink *wl = item->target.wl; struct window_pane *loopwp, *tmpwp, *wp = item->target.wp; - server_unzoom_window(wl->window); - if (args_has(self->args, 'a')) { + server_unzoom_window(wl->window); TAILQ_FOREACH_SAFE(loopwp, &wl->window->panes, entry, tmpwp) { if (loopwp == wp) continue; @@ -60,13 +59,6 @@ cmd_kill_pane_exec(struct cmd *self, struct cmdq_item *item) return (CMD_RETURN_NORMAL); } - if (window_count_panes(wl->window) == 1) { - server_kill_window(wl->window); - recalculate_sizes(); - } else { - layout_close_pane(wp); - window_remove_pane(wl->window, wp); - server_redraw_window(wl->window); - } + server_kill_pane(wp); return (CMD_RETURN_NORMAL); } diff --git a/server-fn.c b/server-fn.c index ef96bf58..b4defdd4 100644 --- a/server-fn.c +++ b/server-fn.c @@ -177,6 +177,22 @@ server_lock_client(struct client *c) proc_send(c->peer, MSG_LOCK, -1, cmd, strlen(cmd) + 1); } +void +server_kill_pane(struct window_pane *wp) +{ + struct window *w = wp->window; + + if (window_count_panes(w) == 1) { + server_kill_window(w); + recalculate_sizes(); + } else { + server_unzoom_window(w); + layout_close_pane(wp); + window_remove_pane(w, wp); + server_redraw_window(w); + } +} + void server_kill_window(struct window *w) { diff --git a/tmux.1 b/tmux.1 index 3db23786..31faa1f6 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1459,6 +1459,8 @@ The following keys may be used in tree mode: .It Li "Enter" Ta "Choose selected item" .It Li "Up" Ta "Select previous item" .It Li "Down" Ta "Select next item" +.It Li "x" Ta "Kill selected item" +.It Li "X" Ta "Kill tagged items" .It Li "<" Ta "Scroll list of previews left" .It Li ">" Ta "Scroll list of previews right" .It Li "C-s" Ta "Search by name" diff --git a/tmux.h b/tmux.h index aa3ba3d1..9c901bd5 100644 --- a/tmux.h +++ b/tmux.h @@ -1920,6 +1920,7 @@ void server_status_window(struct window *); void server_lock(void); void server_lock_session(struct session *); void server_lock_client(struct client *); +void server_kill_pane(struct window_pane *); void server_kill_window(struct window *); int server_link_window(struct session *, struct winlink *, struct session *, int, int, int, char **); diff --git a/window-tree.c b/window-tree.c index 926eaec1..52ab195e 100644 --- a/window-tree.c +++ b/window-tree.c @@ -18,6 +18,7 @@ #include +#include #include #include @@ -860,8 +861,6 @@ window_tree_destroy(struct window_tree_modedata *data) if (--data->references != 0) return; - mode_tree_free(data->data); - for (i = 0; i < data->item_size; i++) window_tree_free_item(data->item_list[i]); free(data->item_list); @@ -881,6 +880,7 @@ window_tree_free(struct window_pane *wp) return; data->dead = 1; + mode_tree_free(data->data); window_tree_destroy(data); } @@ -965,7 +965,7 @@ window_tree_command_callback(struct client *c, void *modedata, const char *s, { struct window_tree_modedata *data = modedata; - if (s == NULL || data->dead) + if (s == NULL || *s == '\0' || data->dead) return (0); data->entered = s; @@ -987,6 +987,77 @@ window_tree_command_free(void *modedata) window_tree_destroy(data); } +static void +window_tree_kill_each(__unused void* modedata, void* itemdata, + __unused struct client *c, __unused key_code key) +{ + struct window_tree_itemdata *item = itemdata; + struct session *s; + struct winlink *wl; + struct window_pane *wp; + + window_tree_pull_item(item, &s, &wl, &wp); + + switch (item->type) { + case WINDOW_TREE_NONE: + break; + case WINDOW_TREE_SESSION: + if (s != NULL) { + server_destroy_session(s); + session_destroy(s, __func__); + } + break; + case WINDOW_TREE_WINDOW: + if (wl != NULL) + server_kill_window(wl->window); + break; + case WINDOW_TREE_PANE: + if (wp != NULL) + server_kill_pane(wp); + break; + } +} + +static int +window_tree_kill_current_callback(struct client *c, void *modedata, + const char *s, __unused int done) +{ + struct window_tree_modedata *data = modedata; + struct mode_tree_data *mtd = data->data; + + if (s == NULL || *s == '\0' || data->dead) + return (0); + if (tolower((u_char) s[0]) != 'y' || s[1] != '\0') + return (0); + + window_tree_kill_each(data, mode_tree_get_current(mtd), c, KEYC_NONE); + + data->references++; + cmdq_append(c, cmdq_get_callback(window_tree_command_done, data)); + + return (0); +} + +static int +window_tree_kill_tagged_callback(struct client *c, void *modedata, + const char *s, __unused int done) +{ + struct window_tree_modedata *data = modedata; + struct mode_tree_data *mtd = data->data; + + if (s == NULL || *s == '\0' || data->dead) + return (0); + if (tolower((u_char) s[0]) != 'y' || s[1] != '\0') + return (0); + + mode_tree_each_tagged(mtd, window_tree_kill_each, c, KEYC_NONE, 1); + + data->references++; + cmdq_append(c, cmdq_get_callback(window_tree_command_done, data)); + + return (0); +} + static key_code window_tree_mouse(struct window_tree_modedata *data, key_code key, u_int x, struct window_tree_itemdata *item) @@ -1054,10 +1125,13 @@ window_tree_key(struct window_pane *wp, struct client *c, { struct window_tree_modedata *data = wp->modedata; struct window_tree_itemdata *item, *new_item; - char *name, *prompt; + char *name, *prompt = NULL; struct cmd_find_state fs; int finished; - u_int tagged, x, y; + u_int tagged, x, y, idx; + struct session *ns; + struct winlink *nwl; + struct window_pane *nwp; item = mode_tree_get_current(data->data); finished = mode_tree_key(data->data, c, &key, m, &x, &y); @@ -1074,6 +1148,46 @@ window_tree_key(struct window_pane *wp, struct client *c, case '>': data->offset++; break; + case 'x': + window_tree_pull_item(item, &ns, &nwl, &nwp); + switch (item->type) { + case WINDOW_TREE_NONE: + break; + case WINDOW_TREE_SESSION: + if (ns == NULL) + break; + xasprintf(&prompt, "Kill session %s? ", ns->name); + break; + case WINDOW_TREE_WINDOW: + if (nwl == NULL) + break; + xasprintf(&prompt, "Kill window %u? ", nwl->idx); + break; + case WINDOW_TREE_PANE: + if (nwp == NULL || window_pane_index(nwp, &idx) != 0) + break; + xasprintf(&prompt, "Kill pane %u? ", idx); + break; + } + if (prompt == NULL) + break; + data->references++; + status_prompt_set(c, prompt, "", + window_tree_kill_current_callback, window_tree_command_free, + data, PROMPT_SINGLE|PROMPT_NOFORMAT); + free(prompt); + break; + case 'X': + tagged = mode_tree_count_tagged(data->data); + if (tagged == 0) + break; + xasprintf(&prompt, "Kill %u tagged? ", tagged); + data->references++; + status_prompt_set(c, prompt, "", + window_tree_kill_tagged_callback, window_tree_command_free, + data, PROMPT_SINGLE|PROMPT_NOFORMAT); + free(prompt); + break; case ':': tagged = mode_tree_count_tagged(data->data); if (tagged != 0) -- cgit v1.2.3