Add -W and -T flags to command-prompt to only complete a window and a

target, also complete aliases.
pull/2219/head
nicm 2020-05-16 15:16:36 +00:00
parent 2391fe23ab
commit 463864f5a2
5 changed files with 95 additions and 41 deletions

View File

@ -40,8 +40,8 @@ const struct cmd_entry cmd_command_prompt_entry = {
.name = "command-prompt", .name = "command-prompt",
.alias = NULL, .alias = NULL,
.args = { "1kiI:Np:t:", 0, 1 }, .args = { "1kiI:Np:Tt:W", 0, 1 },
.usage = "[-1kiN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " " .usage = "[-1kiNTW] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " "
"[template]", "[template]",
.flags = CMD_CLIENT_TFLAG, .flags = CMD_CLIENT_TFLAG,
@ -121,6 +121,10 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
cdata->flags |= PROMPT_INCREMENTAL; cdata->flags |= PROMPT_INCREMENTAL;
else if (args_has(args, 'k')) else if (args_has(args, 'k'))
cdata->flags |= PROMPT_KEY; cdata->flags |= PROMPT_KEY;
else if (args_has(args, 'W'))
cdata->flags |= PROMPT_WINDOW;
else if (args_has(args, 'T'))
cdata->flags |= PROMPT_TARGET;
status_prompt_set(tc, prompt, input, cmd_command_prompt_callback, status_prompt_set(tc, prompt, input, cmd_command_prompt_callback,
cmd_command_prompt_free, cdata, cdata->flags); cmd_command_prompt_free, cdata, cdata->flags);
free(prompt); free(prompt);

View File

@ -243,12 +243,12 @@ key_bindings_init(void)
"bind -N 'Rename current session' '$' command-prompt -I'#S' \"rename-session -- '%%'\"", "bind -N 'Rename current session' '$' command-prompt -I'#S' \"rename-session -- '%%'\"",
"bind -N 'Split window horizontally' % split-window -h", "bind -N 'Split window horizontally' % split-window -h",
"bind -N 'Kill current window' & confirm-before -p\"kill-window #W? (y/n)\" kill-window", "bind -N 'Kill current window' & confirm-before -p\"kill-window #W? (y/n)\" kill-window",
"bind -N 'Prompt for window index to select' \"'\" command-prompt -pindex \"select-window -t ':%%'\"", "bind -N 'Prompt for window index to select' \"'\" command-prompt -Wpindex \"select-window -t ':%%'\"",
"bind -N 'Switch to previous client' ( switch-client -p", "bind -N 'Switch to previous client' ( switch-client -p",
"bind -N 'Switch to next client' ) switch-client -n", "bind -N 'Switch to next client' ) switch-client -n",
"bind -N 'Rename current window' , command-prompt -I'#W' \"rename-window -- '%%'\"", "bind -N 'Rename current window' , command-prompt -I'#W' \"rename-window -- '%%'\"",
"bind -N 'Delete the most recent paste buffer' - delete-buffer", "bind -N 'Delete the most recent paste buffer' - delete-buffer",
"bind -N 'Move the current window' . command-prompt \"move-window -t '%%'\"", "bind -N 'Move the current window' . command-prompt -T \"move-window -t '%%'\"",
"bind -N 'Describe key binding' '/' command-prompt -kpkey 'list-keys -1N \"%%%\"'", "bind -N 'Describe key binding' '/' command-prompt -kpkey 'list-keys -1N \"%%%\"'",
"bind -N 'Select window 0' 0 select-window -t:=0", "bind -N 'Select window 0' 0 select-window -t:=0",
"bind -N 'Select window 1' 1 select-window -t:=1", "bind -N 'Select window 1' 1 select-window -t:=1",

112
status.c
View File

@ -38,6 +38,8 @@ static const char *status_prompt_down_history(u_int *);
static void status_prompt_add_history(const char *); static void status_prompt_add_history(const char *);
static char *status_prompt_complete(struct client *, const char *, u_int); static char *status_prompt_complete(struct client *, const char *, u_int);
static char *status_prompt_complete_window_menu(struct client *,
struct session *, u_int, char);
struct status_prompt_menu { struct status_prompt_menu {
struct client *c; struct client *c;
@ -933,13 +935,11 @@ status_prompt_replace_complete(struct client *c, const char *s)
size_t size, n, off, idx, used; size_t size, n, off, idx, used;
struct utf8_data *first, *last, *ud; struct utf8_data *first, *last, *ud;
if (c->prompt_buffer[0].size == 0) /* Work out where the cursor currently is. */
return (0);
size = utf8_strlen(c->prompt_buffer);
idx = c->prompt_index; idx = c->prompt_index;
if (idx != 0) if (idx != 0)
idx--; idx--;
size = utf8_strlen(c->prompt_buffer);
/* Find the word we are in. */ /* Find the word we are in. */
first = &c->prompt_buffer[idx]; first = &c->prompt_buffer[idx];
@ -954,7 +954,7 @@ status_prompt_replace_complete(struct client *c, const char *s)
last--; last--;
if (last->size != 0) if (last->size != 0)
last++; last++;
if (last <= first) if (last < first)
return (0); return (0);
if (s == NULL) { if (s == NULL) {
used = 0; used = 0;
@ -1071,7 +1071,15 @@ process_key:
} }
break; break;
case '\011': /* Tab */ case '\011': /* Tab */
if (status_prompt_replace_complete(c, NULL)) if (c->prompt_flags & PROMPT_WINDOW) {
s = status_prompt_complete_window_menu(c, c->session,
0, '\0');
if (s != NULL) {
free(c->prompt_buffer);
c->prompt_buffer = utf8_fromcstr(s);
c->prompt_index = utf8_strlen(c->prompt_buffer);
}
} else if (status_prompt_replace_complete(c, NULL))
goto changed; goto changed;
break; break;
case KEYC_BSPACE: case KEYC_BSPACE:
@ -1376,6 +1384,11 @@ status_prompt_complete_list(u_int *size, const char *s, int at_start)
list = xreallocarray(list, (*size) + 1, sizeof *list); list = xreallocarray(list, (*size) + 1, sizeof *list);
list[(*size)++] = xstrdup((*cmdent)->name); list[(*size)++] = xstrdup((*cmdent)->name);
} }
if ((*cmdent)->alias != NULL &&
strncmp((*cmdent)->alias, s, slen) == 0) {
list = xreallocarray(list, (*size) + 1, sizeof *list);
list[(*size)++] = xstrdup((*cmdent)->alias);
}
} }
o = options_get_only(global_options, "command-alias"); o = options_get_only(global_options, "command-alias");
if (o != NULL) { if (o != NULL) {
@ -1450,7 +1463,12 @@ status_prompt_menu_callback(__unused struct menu *menu, u_int idx, key_code key,
s = xstrdup(spm->list[idx]); s = xstrdup(spm->list[idx]);
else else
xasprintf(&s, "-%c%s", spm->flag, spm->list[idx]); xasprintf(&s, "-%c%s", spm->flag, spm->list[idx]);
if (status_prompt_replace_complete(c, s)) if (c->prompt_flags & PROMPT_WINDOW) {
free(c->prompt_buffer);
c->prompt_buffer = utf8_fromcstr(s);
c->prompt_index = utf8_strlen(c->prompt_buffer);
c->flags |= CLIENT_REDRAWSTATUS;
} else if (status_prompt_replace_complete(c, s))
c->flags |= CLIENT_REDRAWSTATUS; c->flags |= CLIENT_REDRAWSTATUS;
free(s); free(s);
} }
@ -1544,10 +1562,14 @@ status_prompt_complete_window_menu(struct client *c, struct session *s,
menu = menu_create(""); menu = menu_create("");
RB_FOREACH(wl, winlinks, &s->windows) { RB_FOREACH(wl, winlinks, &s->windows) {
list = xreallocarray(list, size + 1, sizeof *list); list = xreallocarray(list, size + 1, sizeof *list);
xasprintf(&list[size++], "%s:%d", s->name, wl->idx); if (c->prompt_flags & PROMPT_WINDOW) {
xasprintf(&tmp, "%d (%s)", wl->idx, wl->window->name);
xasprintf(&tmp, "%s:%d (%s)", s->name, wl->idx, xasprintf(&list[size++], "%d", wl->idx);
wl->window->name); } else {
xasprintf(&tmp, "%s:%d (%s)", s->name, wl->idx,
wl->window->name);
xasprintf(&list[size++], "%s:%d", s->name, wl->idx);
}
item.name = tmp; item.name = tmp;
item.key = '0' + size - 1; item.key = '0' + size - 1;
item.command = NULL; item.command = NULL;
@ -1559,8 +1581,11 @@ status_prompt_complete_window_menu(struct client *c, struct session *s,
} }
if (size == 1) { if (size == 1) {
menu_free(menu); menu_free(menu);
xasprintf(&tmp, "-%c%s", flag, list[0]); if (flag != '\0') {
free(list[0]); xasprintf(&tmp, "-%c%s", flag, list[0]);
free(list[0]);
} else
tmp = list[0];
free(list); free(list);
return (tmp); return (tmp);
} }
@ -1598,21 +1623,45 @@ status_prompt_complete_sort(const void *a, const void *b)
return (strcmp(*aa, *bb)); return (strcmp(*aa, *bb));
} }
/* Complete a session. */
static char *
status_prompt_complete_session(char ***list, u_int *size, const char *s,
char flag)
{
struct session *loop;
char *out, *tmp;
RB_FOREACH(loop, sessions, &sessions) {
if (*s != '\0' && strncmp(loop->name, s, strlen(s)) != 0)
continue;
*list = xreallocarray(*list, (*size) + 2, sizeof **list);
xasprintf(&(*list)[(*size)++], "%s:", loop->name);
}
out = status_prompt_complete_prefix(*list, *size);
if (out != NULL && flag != '\0') {
xasprintf(&tmp, "-%c%s", flag, out);
free(out);
out = tmp;
}
return (out);
}
/* Complete word. */ /* Complete word. */
static char * static char *
status_prompt_complete(struct client *c, const char *word, u_int offset) status_prompt_complete(struct client *c, const char *word, u_int offset)
{ {
struct session *session, *loop; struct session *session;
const char *s, *colon; const char *s, *colon;
size_t slen; char **list = NULL, *copy = NULL, *out = NULL;
char **list = NULL, *copy = NULL, *out = NULL, *tmp;
char flag = '\0'; char flag = '\0';
u_int size = 0, i; u_int size = 0, i;
if (*word == '\0') if (*word == '\0' && (~c->prompt_flags & PROMPT_TARGET))
return (NULL); return (NULL);
if (strncmp(word, "-t", 2) != 0 && strncmp(word, "-s", 2) != 0) { if ((~c->prompt_flags & PROMPT_TARGET) &&
strncmp(word, "-t", 2) != 0 &&
strncmp(word, "-s", 2) != 0) {
list = status_prompt_complete_list(&size, word, offset == 0); list = status_prompt_complete_list(&size, word, offset == 0);
if (size == 0) if (size == 0)
out = NULL; out = NULL;
@ -1623,28 +1672,19 @@ status_prompt_complete(struct client *c, const char *word, u_int offset)
goto found; goto found;
} }
s = word + 2; if (c->prompt_flags & PROMPT_TARGET) {
slen = strlen(s); s = word;
flag = '\0';
flag = word[1]; } else {
offset += 2; s = word + 2;
flag = word[1];
offset += 2;
}
colon = strchr(s, ':'); colon = strchr(s, ':');
/* If there is no colon, complete as a session. */ /* If there is no colon, complete as a session. */
if (colon == NULL) { if (colon == NULL) {
RB_FOREACH(loop, sessions, &sessions) { out = status_prompt_complete_session(&list, &size, s, flag);
if (strncmp(loop->name, s, strlen(s)) != 0)
continue;
list = xreallocarray(list, size + 2, sizeof *list);
xasprintf(&list[size++], "%s:", loop->name);
}
out = status_prompt_complete_prefix(list, size);
if (out != NULL) {
xasprintf(&tmp, "-%c%s", flag, out);
free(out);
out = tmp;
}
goto found; goto found;
} }

10
tmux.1
View File

@ -4969,7 +4969,7 @@ session option.
Commands related to the status line are as follows: Commands related to the status line are as follows:
.Bl -tag -width Ds .Bl -tag -width Ds
.It Xo Ic command-prompt .It Xo Ic command-prompt
.Op Fl 1ikN .Op Fl 1ikNTW
.Op Fl I Ar inputs .Op Fl I Ar inputs
.Op Fl p Ar prompts .Op Fl p Ar prompts
.Op Fl t Ar target-client .Op Fl t Ar target-client
@ -5028,6 +5028,14 @@ makes the prompt only accept numeric key presses.
.Fl i .Fl i
executes the command every time the prompt input changes instead of when the executes the command every time the prompt input changes instead of when the
user exits the command prompt. user exits the command prompt.
.Fl T
tells
.Nm
that the prompt is for a target which affects what completions are offered when
.Em Tab
is pressed;
.Fl W
is similar but indicates the prompt is for a window.
.Pp .Pp
The following keys have a special meaning in the command prompt, depending The following keys have a special meaning in the command prompt, depending
on the value of the on the value of the

2
tmux.h
View File

@ -1602,6 +1602,8 @@ struct client {
#define PROMPT_INCREMENTAL 0x4 #define PROMPT_INCREMENTAL 0x4
#define PROMPT_NOFORMAT 0x8 #define PROMPT_NOFORMAT 0x8
#define PROMPT_KEY 0x10 #define PROMPT_KEY 0x10
#define PROMPT_WINDOW 0x20
#define PROMPT_TARGET 0x40
int prompt_flags; int prompt_flags;
struct session *session; struct session *session;