mirror of
https://github.com/tmux/tmux.git
synced 2025-01-14 04:28:48 +00:00
Add -W and -T flags to command-prompt to only complete a window and a target.
This commit is contained in:
parent
5af6943940
commit
25487757bc
@ -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);
|
||||||
|
@ -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",
|
||||||
|
107
status.c
107
status.c
@ -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:
|
||||||
@ -1455,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);
|
||||||
}
|
}
|
||||||
@ -1549,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;
|
||||||
@ -1564,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);
|
||||||
}
|
}
|
||||||
@ -1603,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;
|
||||||
@ -1628,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
10
tmux.1
@ -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
2
tmux.h
@ -1604,6 +1604,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;
|
||||||
|
Loading…
Reference in New Issue
Block a user