mirror of
https://github.com/tmux/tmux.git
synced 2025-03-22 12:58:48 +00:00
Merge branch 'obsd-master'
This commit is contained in:
commit
c67b702588
cfg.ccmd-attach-session.ccmd-command-prompt.ccmd-confirm-before.ccmd-copy-mode.ccmd-display-panes.ccmd-find.ccmd-if-shell.ccmd-load-buffer.ccmd-new-session.ccmd-new-window.ccmd-queue.ccmd-resize-pane.ccmd-run-shell.ccmd-send-keys.ccmd-source-file.ccmd-split-window.ccmd-wait-for.ccmd.ccontrol.cformat.chooks.ckey-bindings.cnotify.cserver-client.cserver.ctmux.1tmux.hwindow-choose.c
70
cfg.c
70
cfg.c
@ -28,14 +28,25 @@
|
||||
#include "tmux.h"
|
||||
|
||||
char *cfg_file;
|
||||
static struct cmd_q *cfg_cmd_q;
|
||||
int cfg_finished;
|
||||
int cfg_references;
|
||||
static char **cfg_causes;
|
||||
static u_int cfg_ncauses;
|
||||
struct client *cfg_client;
|
||||
|
||||
static void cfg_default_done(struct cmd_q *);
|
||||
static enum cmd_retval
|
||||
cfg_done(__unused struct cmd_q *cmdq, __unused void *data)
|
||||
{
|
||||
if (cfg_finished)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
cfg_finished = 1;
|
||||
|
||||
if (!RB_EMPTY(&sessions))
|
||||
cfg_show_causes(RB_MIN(sessions, &sessions));
|
||||
|
||||
if (cfg_client != NULL)
|
||||
server_client_unref(cfg_client);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
set_cfg_file(const char *path)
|
||||
@ -50,30 +61,24 @@ start_cfg(void)
|
||||
const char *home;
|
||||
int quiet = 0;
|
||||
|
||||
cfg_cmd_q = cmdq_new(NULL);
|
||||
cfg_cmd_q->emptyfn = cfg_default_done;
|
||||
|
||||
cfg_finished = 0;
|
||||
cfg_references = 1;
|
||||
|
||||
cfg_client = TAILQ_FIRST(&clients);
|
||||
if (cfg_client != NULL)
|
||||
cfg_client->references++;
|
||||
|
||||
load_cfg(TMUX_CONF, cfg_cmd_q, 1);
|
||||
load_cfg(TMUX_CONF, cfg_client, NULL, 1);
|
||||
|
||||
if (cfg_file == NULL && (home = find_home()) != NULL) {
|
||||
xasprintf(&cfg_file, "%s/.tmux.conf", home);
|
||||
quiet = 1;
|
||||
}
|
||||
if (cfg_file != NULL)
|
||||
load_cfg(cfg_file, cfg_cmd_q, quiet);
|
||||
load_cfg(cfg_file, cfg_client, NULL, quiet);
|
||||
|
||||
cmdq_continue(cfg_cmd_q);
|
||||
cmdq_append(cfg_client, cmdq_get_callback(cfg_done, NULL));
|
||||
}
|
||||
|
||||
int
|
||||
load_cfg(const char *path, struct cmd_q *cmdq, int quiet)
|
||||
load_cfg(const char *path, struct client *c, struct cmd_q *cmdq, int quiet)
|
||||
{
|
||||
FILE *f;
|
||||
char delim[3] = { '\\', '\\', '\0' };
|
||||
@ -81,6 +86,7 @@ load_cfg(const char *path, struct cmd_q *cmdq, int quiet)
|
||||
size_t line = 0;
|
||||
char *buf, *cause1, *p;
|
||||
struct cmd_list *cmdlist;
|
||||
struct cmd_q *new_cmdq;
|
||||
|
||||
log_debug("loading %s", path);
|
||||
if ((f = fopen(path, "rb")) == NULL) {
|
||||
@ -116,8 +122,13 @@ load_cfg(const char *path, struct cmd_q *cmdq, int quiet)
|
||||
|
||||
if (cmdlist == NULL)
|
||||
continue;
|
||||
cmdq_append(cmdq, cmdlist, NULL);
|
||||
new_cmdq = cmdq_get_command(cmdlist, NULL, NULL, 0);
|
||||
if (cmdq != NULL)
|
||||
cmdq_insert_after(cmdq, new_cmdq);
|
||||
else
|
||||
cmdq_append(c, new_cmdq);
|
||||
cmd_list_free(cmdlist);
|
||||
|
||||
found++;
|
||||
}
|
||||
fclose(f);
|
||||
@ -125,37 +136,6 @@ load_cfg(const char *path, struct cmd_q *cmdq, int quiet)
|
||||
return (found);
|
||||
}
|
||||
|
||||
static void
|
||||
cfg_default_done(__unused struct cmd_q *cmdq)
|
||||
{
|
||||
log_debug("%s: %u references%s", __func__, cfg_references,
|
||||
cfg_finished ? " (finished)" : "");
|
||||
|
||||
if (cfg_finished || --cfg_references != 0)
|
||||
return;
|
||||
cfg_finished = 1;
|
||||
|
||||
if (!RB_EMPTY(&sessions))
|
||||
cfg_show_causes(RB_MIN(sessions, &sessions));
|
||||
|
||||
cmdq_free(cfg_cmd_q);
|
||||
cfg_cmd_q = NULL;
|
||||
|
||||
if (cfg_client != NULL) {
|
||||
/*
|
||||
* The client command queue starts with client_exit set to 1 so
|
||||
* only continue if not empty (that is, we have been delayed
|
||||
* during configuration parsing for long enough that the
|
||||
* MSG_COMMAND has arrived), else the client will exit before
|
||||
* the MSG_COMMAND which might tell it not to.
|
||||
*/
|
||||
if (!TAILQ_EMPTY(&cfg_client->cmdq->queue))
|
||||
cmdq_continue(cfg_client->cmdq);
|
||||
server_client_unref(cfg_client);
|
||||
cfg_client = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cfg_add_cause(const char *fmt, ...)
|
||||
{
|
||||
|
@ -145,7 +145,7 @@ cmd_attach_session(struct cmd_q *cmdq, int dflag, int rflag, const char *cflag,
|
||||
if (~c->flags & CLIENT_CONTROL)
|
||||
proc_send(c->peer, MSG_READY, -1, NULL, 0);
|
||||
hooks_run(c->session->hooks, c, NULL, "client-attached");
|
||||
cmdq->client_exit = 0;
|
||||
c->flags |= CLIENT_ATTACHED;
|
||||
}
|
||||
recalculate_sizes();
|
||||
alerts_check_session(s);
|
||||
|
@ -121,12 +121,24 @@ cmd_command_prompt_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_command_prompt_error(struct cmd_q *cmdq, void *data)
|
||||
{
|
||||
char *error = data;
|
||||
|
||||
cmdq_error(cmdq, "%s", error);
|
||||
free(error);
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
static int
|
||||
cmd_command_prompt_callback(void *data, const char *s)
|
||||
{
|
||||
struct cmd_command_prompt_cdata *cdata = data;
|
||||
struct client *c = cdata->c;
|
||||
struct cmd_list *cmdlist;
|
||||
struct cmd_q *new_cmdq;
|
||||
char *cause, *new_template, *prompt, *ptr;
|
||||
char *input = NULL;
|
||||
|
||||
@ -153,17 +165,19 @@ cmd_command_prompt_callback(void *data, const char *s)
|
||||
|
||||
if (cmd_string_parse(new_template, &cmdlist, NULL, 0, &cause) != 0) {
|
||||
if (cause != NULL) {
|
||||
*cause = toupper((u_char) *cause);
|
||||
status_message_set(c, "%s", cause);
|
||||
free(cause);
|
||||
}
|
||||
return (0);
|
||||
new_cmdq = cmdq_get_callback(cmd_command_prompt_error,
|
||||
cause);
|
||||
} else
|
||||
new_cmdq = NULL;
|
||||
} else {
|
||||
new_cmdq = cmdq_get_command(cmdlist, NULL, NULL, 0);
|
||||
cmd_list_free(cmdlist);
|
||||
}
|
||||
|
||||
cmdq_run(c->cmdq, cmdlist, NULL);
|
||||
cmd_list_free(cmdlist);
|
||||
if (new_cmdq != NULL)
|
||||
cmdq_append(c, new_cmdq);
|
||||
|
||||
if (c->prompt_callbackfn != (void *) &cmd_command_prompt_callback)
|
||||
if (c->prompt_callbackfn != (void *)&cmd_command_prompt_callback)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
@ -83,12 +83,24 @@ cmd_confirm_before_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_confirm_before_error(struct cmd_q *cmdq, void *data)
|
||||
{
|
||||
char *error = data;
|
||||
|
||||
cmdq_error(cmdq, "%s", error);
|
||||
free(error);
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
static int
|
||||
cmd_confirm_before_callback(void *data, const char *s)
|
||||
{
|
||||
struct cmd_confirm_before_data *cdata = data;
|
||||
struct client *c = cdata->client;
|
||||
struct cmd_list *cmdlist;
|
||||
struct cmd_q *new_cmdq;
|
||||
char *cause;
|
||||
|
||||
if (c->flags & CLIENT_DEAD)
|
||||
@ -101,14 +113,17 @@ cmd_confirm_before_callback(void *data, const char *s)
|
||||
|
||||
if (cmd_string_parse(cdata->cmd, &cmdlist, NULL, 0, &cause) != 0) {
|
||||
if (cause != NULL) {
|
||||
cmdq_error(c->cmdq, "%s", cause);
|
||||
free(cause);
|
||||
}
|
||||
return (0);
|
||||
new_cmdq = cmdq_get_callback(cmd_confirm_before_error,
|
||||
cause);
|
||||
} else
|
||||
new_cmdq = NULL;
|
||||
} else {
|
||||
new_cmdq = cmdq_get_command(cmdlist, NULL, NULL, 0);
|
||||
cmd_list_free(cmdlist);
|
||||
}
|
||||
|
||||
cmdq_run(c->cmdq, cmdlist, NULL);
|
||||
cmd_list_free(cmdlist);
|
||||
if (new_cmdq != NULL)
|
||||
cmdq_append(c, new_cmdq);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct window_pane *wp = cmdq->state.tflag.wp;
|
||||
|
||||
if (args_has(args, 'M')) {
|
||||
if ((wp = cmd_mouse_pane(&cmdq->item->mouse, &s, NULL)) == NULL)
|
||||
if ((wp = cmd_mouse_pane(&cmdq->mouse, &s, NULL)) == NULL)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
if (c == NULL || c->session != s)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
@ -80,7 +80,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
if (args_has(args, 'M')) {
|
||||
if (wp->mode != NULL && wp->mode != &window_copy_mode)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
window_copy_start_drag(c, &cmdq->item->mouse);
|
||||
window_copy_start_drag(c, &cmdq->mouse);
|
||||
}
|
||||
if (wp->mode == &window_copy_mode && args_has(self->args, 'u'))
|
||||
window_copy_pageup(wp, 0);
|
||||
|
@ -65,32 +65,48 @@ cmd_display_panes_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_display_panes_error(struct cmd_q *cmdq, void *data)
|
||||
{
|
||||
char *error = data;
|
||||
|
||||
cmdq_error(cmdq, "%s", error);
|
||||
free(error);
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_display_panes_callback(struct client *c, struct window_pane *wp)
|
||||
{
|
||||
struct cmd_list *cmdlist;
|
||||
struct cmd_q *new_cmdq;
|
||||
char *template, *cmd, *expanded, *cause;
|
||||
|
||||
template = c->identify_callback_data;
|
||||
if (wp != NULL) {
|
||||
xasprintf(&expanded, "%%%u", wp->id);
|
||||
cmd = cmd_template_replace(template, expanded, 1);
|
||||
if (wp == NULL)
|
||||
goto out;
|
||||
xasprintf(&expanded, "%%%u", wp->id);
|
||||
cmd = cmd_template_replace(template, expanded, 1);
|
||||
|
||||
if (cmd_string_parse(cmd, &cmdlist, NULL, 0, &cause) != 0) {
|
||||
if (cause != NULL) {
|
||||
*cause = toupper((u_char) *cause);
|
||||
status_message_set(c, "%s", cause);
|
||||
free(cause);
|
||||
}
|
||||
} else {
|
||||
cmdq_run(c->cmdq, cmdlist, NULL);
|
||||
cmd_list_free(cmdlist);
|
||||
}
|
||||
|
||||
free(cmd);
|
||||
free(expanded);
|
||||
if (cmd_string_parse(cmd, &cmdlist, NULL, 0, &cause) != 0) {
|
||||
if (cause != NULL) {
|
||||
new_cmdq = cmdq_get_callback(cmd_display_panes_error,
|
||||
cause);
|
||||
} else
|
||||
new_cmdq = NULL;
|
||||
} else {
|
||||
new_cmdq = cmdq_get_command(cmdlist, NULL, NULL, 0);
|
||||
cmd_list_free(cmdlist);
|
||||
}
|
||||
|
||||
if (new_cmdq != NULL)
|
||||
cmdq_append(c, new_cmdq);
|
||||
|
||||
free(cmd);
|
||||
free(expanded);
|
||||
|
||||
out:
|
||||
free(c->identify_callback_data);
|
||||
c->identify_callback_data = NULL;
|
||||
c->identify_callback = NULL;
|
||||
|
@ -1005,7 +1005,7 @@ cmd_find_target(struct cmd_find_state *fs, struct cmd_find_state *current,
|
||||
|
||||
/* Mouse target is a plain = or {mouse}. */
|
||||
if (strcmp(target, "=") == 0 || strcmp(target, "{mouse}") == 0) {
|
||||
m = &cmdq->item->mouse;
|
||||
m = &cmdq->mouse;
|
||||
switch (type) {
|
||||
case CMD_FIND_PANE:
|
||||
fs->wp = cmd_mouse_pane(m, &fs->s, &fs->wl);
|
||||
|
110
cmd-if-shell.c
110
cmd-if-shell.c
@ -31,9 +31,9 @@
|
||||
|
||||
static enum cmd_retval cmd_if_shell_exec(struct cmd *, struct cmd_q *);
|
||||
|
||||
static void cmd_if_shell_callback(struct job *);
|
||||
static void cmd_if_shell_done(struct cmd_q *);
|
||||
static void cmd_if_shell_free(void *);
|
||||
static enum cmd_retval cmd_if_shell_error(struct cmd_q *, void *);
|
||||
static void cmd_if_shell_callback(struct job *);
|
||||
static void cmd_if_shell_free(void *);
|
||||
|
||||
const struct cmd_entry cmd_if_shell_entry = {
|
||||
.name = "if-shell",
|
||||
@ -56,11 +56,9 @@ struct cmd_if_shell_data {
|
||||
char *cmd_if;
|
||||
char *cmd_else;
|
||||
|
||||
struct client *client;
|
||||
struct cmd_q *cmdq;
|
||||
struct mouse_event mouse;
|
||||
|
||||
int bflag;
|
||||
int references;
|
||||
};
|
||||
|
||||
static enum cmd_retval
|
||||
@ -70,6 +68,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct cmd_if_shell_data *cdata;
|
||||
char *shellcmd, *cmd, *cause;
|
||||
struct cmd_list *cmdlist;
|
||||
struct cmd_q *new_cmdq;
|
||||
struct session *s = cmdq->state.tflag.s;
|
||||
struct winlink *wl = cmdq->state.tflag.wl;
|
||||
struct window_pane *wp = cmdq->state.tflag.wp;
|
||||
@ -104,7 +103,8 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
}
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
cmdq_run(cmdq, cmdlist, &cmdq->item->mouse);
|
||||
new_cmdq = cmdq_get_command(cmdlist, NULL, &cmdq->mouse, 0);
|
||||
cmdq_insert_after(cmdq, new_cmdq);
|
||||
cmd_list_free(cmdlist);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
@ -121,92 +121,80 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
else
|
||||
cdata->cmd_else = NULL;
|
||||
|
||||
cdata->bflag = args_has(args, 'b');
|
||||
cdata->client = cmdq->client;
|
||||
cdata->client->references++;
|
||||
|
||||
cdata->cmdq = cmdq;
|
||||
memcpy(&cdata->mouse, &cmdq->item->mouse, sizeof cdata->mouse);
|
||||
cmdq->references++;
|
||||
if (!args_has(args, 'b'))
|
||||
cdata->cmdq = cmdq;
|
||||
else
|
||||
cdata->cmdq = NULL;
|
||||
memcpy(&cdata->mouse, &cmdq->mouse, sizeof cdata->mouse);
|
||||
|
||||
cdata->references = 1;
|
||||
job_run(shellcmd, s, cwd, cmd_if_shell_callback, cmd_if_shell_free,
|
||||
cdata);
|
||||
free(shellcmd);
|
||||
|
||||
if (cdata->bflag)
|
||||
if (args_has(args, 'b'))
|
||||
return (CMD_RETURN_NORMAL);
|
||||
return (CMD_RETURN_WAIT);
|
||||
}
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_if_shell_error(struct cmd_q *cmdq, void *data)
|
||||
{
|
||||
char *error = data;
|
||||
|
||||
cmdq_error(cmdq, "%s", error);
|
||||
free(error);
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_if_shell_callback(struct job *job)
|
||||
{
|
||||
struct cmd_if_shell_data *cdata = job->data;
|
||||
struct cmd_q *cmdq = cdata->cmdq, *cmdq1;
|
||||
struct client *c = cdata->client;
|
||||
struct cmd_list *cmdlist;
|
||||
char *cause, *cmd;
|
||||
|
||||
if (cmdq->flags & CMD_Q_DEAD)
|
||||
return;
|
||||
struct cmd_q *new_cmdq;
|
||||
char *cause, *cmd, *file = cdata->file;
|
||||
u_int line = cdata->line;
|
||||
|
||||
if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0)
|
||||
cmd = cdata->cmd_else;
|
||||
else
|
||||
cmd = cdata->cmd_if;
|
||||
if (cmd == NULL)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
if (cmd_string_parse(cmd, &cmdlist, cdata->file, cdata->line,
|
||||
&cause) != 0) {
|
||||
if (cause != NULL) {
|
||||
cmdq_error(cmdq, "%s", cause);
|
||||
free(cause);
|
||||
}
|
||||
return;
|
||||
if (cmd_string_parse(cmd, &cmdlist, file, line, &cause) != 0) {
|
||||
if (cause != NULL)
|
||||
new_cmdq = cmdq_get_callback(cmd_if_shell_error, cause);
|
||||
else
|
||||
new_cmdq = NULL;
|
||||
} else {
|
||||
new_cmdq = cmdq_get_command(cmdlist, NULL, &cdata->mouse, 0);
|
||||
cmd_list_free(cmdlist);
|
||||
}
|
||||
|
||||
cmdq1 = cmdq_new(cmdq->client);
|
||||
cmdq1->emptyfn = cmd_if_shell_done;
|
||||
cmdq1->data = cdata;
|
||||
if (new_cmdq != NULL) {
|
||||
if (cdata->cmdq == NULL)
|
||||
cmdq_append(c, new_cmdq);
|
||||
else
|
||||
cmdq_insert_after(cdata->cmdq, new_cmdq);
|
||||
}
|
||||
|
||||
cdata->references++;
|
||||
cmdq_run(cmdq1, cmdlist, &cdata->mouse);
|
||||
cmd_list_free(cmdlist);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_if_shell_done(struct cmd_q *cmdq1)
|
||||
{
|
||||
struct cmd_if_shell_data *cdata = cmdq1->data;
|
||||
struct cmd_q *cmdq = cdata->cmdq;
|
||||
|
||||
if (cmdq1->client_exit >= 0)
|
||||
cmdq->client_exit = cmdq1->client_exit;
|
||||
cmdq_free(cmdq1);
|
||||
|
||||
if (--cdata->references != 0)
|
||||
return;
|
||||
|
||||
if (!cmdq_free(cmdq) && !cdata->bflag)
|
||||
cmdq_continue(cmdq);
|
||||
|
||||
free(cdata->cmd_else);
|
||||
free(cdata->cmd_if);
|
||||
|
||||
free(cdata->file);
|
||||
free(cdata);
|
||||
out:
|
||||
if (cdata->cmdq != NULL)
|
||||
cdata->cmdq->flags &= ~CMD_Q_WAITING;
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_if_shell_free(void *data)
|
||||
{
|
||||
struct cmd_if_shell_data *cdata = data;
|
||||
struct cmd_q *cmdq = cdata->cmdq;
|
||||
|
||||
if (--cdata->references != 0)
|
||||
return;
|
||||
|
||||
if (!cmdq_free(cmdq) && !cdata->bflag)
|
||||
cmdq_continue(cmdq);
|
||||
server_client_unref(cdata->client);
|
||||
|
||||
free(cdata->cmd_else);
|
||||
free(cdata->cmd_if);
|
||||
|
@ -46,17 +46,24 @@ const struct cmd_entry cmd_load_buffer_entry = {
|
||||
.exec = cmd_load_buffer_exec
|
||||
};
|
||||
|
||||
struct cmd_load_buffer_data {
|
||||
struct cmd_q *cmdq;
|
||||
char *bufname;
|
||||
};
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct client *c = cmdq->client;
|
||||
struct session *s;
|
||||
FILE *f;
|
||||
const char *path, *bufname, *cwd;
|
||||
char *pdata, *new_pdata, *cause, *file, resolved[PATH_MAX];
|
||||
size_t psize;
|
||||
int ch, error;
|
||||
struct args *args = self->args;
|
||||
struct cmd_load_buffer_data *cdata;
|
||||
struct client *c = cmdq->client;
|
||||
struct session *s;
|
||||
FILE *f;
|
||||
const char *path, *bufname, *cwd;
|
||||
char *pdata, *new_pdata, *cause, *file;
|
||||
char resolved[PATH_MAX];
|
||||
size_t psize;
|
||||
int ch, error;
|
||||
|
||||
bufname = NULL;
|
||||
if (args_has(args, 'b'))
|
||||
@ -64,8 +71,12 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
|
||||
path = args->argv[0];
|
||||
if (strcmp(path, "-") == 0) {
|
||||
cdata = xcalloc(1, sizeof *cdata);
|
||||
cdata->cmdq = cmdq;
|
||||
cdata->bufname = xstrdup(bufname);
|
||||
|
||||
error = server_set_stdin_callback(c, cmd_load_buffer_callback,
|
||||
(void *)bufname, &cause);
|
||||
cdata, &cause);
|
||||
if (error != 0) {
|
||||
cmdq_error(cmdq, "%s: %s", path, cause);
|
||||
free(cause);
|
||||
@ -136,9 +147,9 @@ error:
|
||||
static void
|
||||
cmd_load_buffer_callback(struct client *c, int closed, void *data)
|
||||
{
|
||||
const char *bufname = data;
|
||||
char *pdata, *cause, *saved;
|
||||
size_t psize;
|
||||
struct cmd_load_buffer_data *cdata = data;
|
||||
char *pdata, *cause, *saved;
|
||||
size_t psize;
|
||||
|
||||
if (!closed)
|
||||
return;
|
||||
@ -146,7 +157,7 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data)
|
||||
|
||||
server_client_unref(c);
|
||||
if (c->flags & CLIENT_DEAD)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
psize = EVBUFFER_LENGTH(c->stdin_data);
|
||||
if (psize == 0 || (pdata = malloc(psize + 1)) == NULL)
|
||||
@ -156,7 +167,7 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data)
|
||||
pdata[psize] = '\0';
|
||||
evbuffer_drain(c->stdin_data, psize);
|
||||
|
||||
if (paste_set(pdata, psize, bufname, &cause) != 0) {
|
||||
if (paste_set(pdata, psize, cdata->bufname, &cause) != 0) {
|
||||
/* No context so can't use server_client_msg_error. */
|
||||
if (~c->flags & CLIENT_UTF8) {
|
||||
saved = cause;
|
||||
@ -168,7 +179,9 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data)
|
||||
free(pdata);
|
||||
free(cause);
|
||||
}
|
||||
|
||||
out:
|
||||
cmdq_continue(c->cmdq);
|
||||
cdata->cmdq->flags &= ~CMD_Q_WAITING;
|
||||
|
||||
free(cdata->bufname);
|
||||
free(cdata);
|
||||
}
|
||||
|
@ -312,14 +312,14 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
}
|
||||
|
||||
if (!detached)
|
||||
cmdq->client_exit = 0;
|
||||
c->flags |= CLIENT_ATTACHED;
|
||||
|
||||
if (to_free != NULL)
|
||||
free((void *)to_free);
|
||||
|
||||
cmd_find_from_session(&fs, s);
|
||||
if (hooks_wait(s->hooks, cmdq, &fs, "after-new-session") == 0)
|
||||
return (CMD_RETURN_WAIT);
|
||||
hooks_insert(s->hooks, cmdq, &fs, "after-new-session");
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
error:
|
||||
|
@ -157,8 +157,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
free((void *)to_free);
|
||||
|
||||
cmd_find_from_winlink(&fs, s, wl);
|
||||
if (hooks_wait(s->hooks, cmdq, &fs, "after-new-window") == 0)
|
||||
return (CMD_RETURN_WAIT);
|
||||
hooks_insert(s->hooks, cmdq, &fs, "after-new-window");
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
error:
|
||||
|
489
cmd-queue.c
489
cmd-queue.c
@ -25,47 +25,316 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
static enum cmd_retval cmdq_continue_one(struct cmd_q *);
|
||||
static void cmdq_flush(struct cmd_q *);
|
||||
/* Global command queue. */
|
||||
static struct cmd_q_list global_queue = TAILQ_HEAD_INITIALIZER(global_queue);
|
||||
|
||||
/* Create new command queue. */
|
||||
/* Get command queue name. */
|
||||
static const char *
|
||||
cmdq_name(struct client *c)
|
||||
{
|
||||
static char s[32];
|
||||
|
||||
if (c == NULL)
|
||||
return ("<global>");
|
||||
xsnprintf(s, sizeof s, "<%p>", c);
|
||||
return (s);
|
||||
}
|
||||
|
||||
/* Get command queue from client. */
|
||||
static struct cmd_q_list *
|
||||
cmdq_get(struct client *c)
|
||||
{
|
||||
if (c == NULL)
|
||||
return (&global_queue);
|
||||
return (&c->queue);
|
||||
}
|
||||
|
||||
/* Append an item. */
|
||||
void
|
||||
cmdq_append(struct client *c, struct cmd_q *cmdq)
|
||||
{
|
||||
struct cmd_q_list *queue = cmdq_get(c);
|
||||
struct cmd_q *next;
|
||||
|
||||
do {
|
||||
next = cmdq->next;
|
||||
cmdq->next = NULL;
|
||||
|
||||
if (c != NULL)
|
||||
c->references++;
|
||||
cmdq->client = c;
|
||||
|
||||
cmdq->queue = queue;
|
||||
TAILQ_INSERT_TAIL(queue, cmdq, entry);
|
||||
|
||||
cmdq = next;
|
||||
} while (cmdq != NULL);
|
||||
}
|
||||
|
||||
/* Insert an item. */
|
||||
void
|
||||
cmdq_insert_after(struct cmd_q *after, struct cmd_q *cmdq)
|
||||
{
|
||||
struct client *c = after->client;
|
||||
struct cmd_q_list *queue = after->queue;
|
||||
struct cmd_q *next;
|
||||
|
||||
do {
|
||||
next = cmdq->next;
|
||||
cmdq->next = NULL;
|
||||
|
||||
if (c != NULL)
|
||||
c->references++;
|
||||
cmdq->client = c;
|
||||
|
||||
cmdq->queue = queue;
|
||||
if (after->next != NULL)
|
||||
TAILQ_INSERT_AFTER(queue, after->next, cmdq, entry);
|
||||
else
|
||||
TAILQ_INSERT_AFTER(queue, after, cmdq, entry);
|
||||
after->next = cmdq;
|
||||
|
||||
cmdq = next;
|
||||
} while (cmdq != NULL);
|
||||
}
|
||||
|
||||
/* Remove an item. */
|
||||
static void
|
||||
cmdq_remove(struct cmd_q *cmdq)
|
||||
{
|
||||
free((void *)cmdq->hook);
|
||||
|
||||
if (cmdq->client != NULL)
|
||||
server_client_unref(cmdq->client);
|
||||
|
||||
if (cmdq->type == CMD_Q_COMMAND)
|
||||
cmd_list_free(cmdq->cmdlist);
|
||||
|
||||
TAILQ_REMOVE(cmdq->queue, cmdq, entry);
|
||||
free(cmdq);
|
||||
}
|
||||
|
||||
/* Set command group. */
|
||||
static u_int
|
||||
cmdq_next_group(void)
|
||||
{
|
||||
static u_int group;
|
||||
|
||||
return (++group);
|
||||
}
|
||||
|
||||
/* Remove all subsequent items that match this item's group. */
|
||||
static void
|
||||
cmdq_remove_group(struct cmd_q *cmdq)
|
||||
{
|
||||
struct cmd_q *this, *next;
|
||||
|
||||
this = TAILQ_NEXT(cmdq, entry);
|
||||
while (this != NULL) {
|
||||
next = TAILQ_NEXT(this, entry);
|
||||
if (this->group == cmdq->group)
|
||||
cmdq_remove(this);
|
||||
this = next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get a command for the command queue. */
|
||||
struct cmd_q *
|
||||
cmdq_new(struct client *c)
|
||||
cmdq_get_command(struct cmd_list *cmdlist, struct cmd_find_state *current,
|
||||
struct mouse_event *m, int flags)
|
||||
{
|
||||
struct cmd_q *cmdq, *first = NULL, *last = NULL;
|
||||
struct cmd *cmd;
|
||||
u_int group = cmdq_next_group();
|
||||
|
||||
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
|
||||
cmdq = xcalloc(1, sizeof *cmdq);
|
||||
cmdq->type = CMD_Q_COMMAND;
|
||||
cmdq->group = group;
|
||||
cmdq->flags = flags;
|
||||
|
||||
cmdq->cmdlist = cmdlist;
|
||||
cmdq->cmd = cmd;
|
||||
|
||||
if (current != NULL)
|
||||
cmd_find_copy_state(&cmdq->current, current);
|
||||
if (m != NULL)
|
||||
memcpy(&cmdq->mouse, m, sizeof cmdq->mouse);
|
||||
cmdlist->references++;
|
||||
|
||||
if (first == NULL)
|
||||
first = cmdq;
|
||||
if (last != NULL)
|
||||
last->next = cmdq;
|
||||
last = cmdq;
|
||||
}
|
||||
return (first);
|
||||
}
|
||||
|
||||
/* Fire command on command queue. */
|
||||
static enum cmd_retval
|
||||
cmdq_fire_command(struct cmd_q *cmdq)
|
||||
{
|
||||
struct client *c = cmdq->client;
|
||||
struct cmd *cmd = cmdq->cmd;
|
||||
enum cmd_retval retval;
|
||||
const char *name;
|
||||
struct cmd_find_state *fsp, fs;
|
||||
int flags;
|
||||
|
||||
flags = !!(cmd->flags & CMD_CONTROL);
|
||||
cmdq_guard(cmdq, "begin", flags);
|
||||
|
||||
if (cmd_prepare_state(cmd, cmdq) != 0) {
|
||||
retval = CMD_RETURN_ERROR;
|
||||
goto out;
|
||||
}
|
||||
if (cmdq->client == NULL)
|
||||
cmdq->client = cmd_find_client(cmdq, NULL, CMD_FIND_QUIET);
|
||||
|
||||
retval = cmd->entry->exec(cmd, cmdq);
|
||||
if (retval == CMD_RETURN_ERROR)
|
||||
goto out;
|
||||
|
||||
if (cmd->entry->flags & CMD_AFTERHOOK) {
|
||||
name = cmd->entry->name;
|
||||
if (cmd_find_valid_state(&cmdq->state.tflag))
|
||||
fsp = &cmdq->state.tflag;
|
||||
else {
|
||||
if (cmd_find_current(&fs, cmdq, CMD_FIND_QUIET) != 0)
|
||||
goto out;
|
||||
fsp = &fs;
|
||||
}
|
||||
hooks_insert(fsp->s->hooks, cmdq, fsp, "after-%s", name);
|
||||
}
|
||||
|
||||
out:
|
||||
cmdq->client = c;
|
||||
if (retval == CMD_RETURN_ERROR)
|
||||
cmdq_guard(cmdq, "error", flags);
|
||||
else
|
||||
cmdq_guard(cmdq, "end", flags);
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/* Get a callback for the command queue. */
|
||||
struct cmd_q *
|
||||
cmdq_get_callback(cmd_q_cb cb, void *data)
|
||||
{
|
||||
struct cmd_q *cmdq;
|
||||
|
||||
cmdq = xcalloc(1, sizeof *cmdq);
|
||||
cmdq->references = 1;
|
||||
cmdq->type = CMD_Q_CALLBACK;
|
||||
cmdq->group = 0;
|
||||
cmdq->flags = 0;
|
||||
|
||||
cmdq->client = c;
|
||||
cmdq->client_exit = -1;
|
||||
|
||||
TAILQ_INIT(&cmdq->queue);
|
||||
cmdq->item = NULL;
|
||||
cmdq->cmd = NULL;
|
||||
|
||||
cmd_find_clear_state(&cmdq->current, NULL, 0);
|
||||
cmdq->parent = NULL;
|
||||
cmdq->cb = cb;
|
||||
cmdq->data = data;
|
||||
|
||||
return (cmdq);
|
||||
}
|
||||
|
||||
/* Free command queue */
|
||||
int
|
||||
cmdq_free(struct cmd_q *cmdq)
|
||||
/* Fire callback on callback queue. */
|
||||
static enum cmd_retval
|
||||
cmdq_fire_callback(struct cmd_q *cmdq)
|
||||
{
|
||||
log_debug("cmdq %p free: %u references", cmdq, cmdq->references);
|
||||
return (cmdq->cb(cmdq, cmdq->data));
|
||||
}
|
||||
|
||||
if (--cmdq->references != 0) {
|
||||
if (cmdq->flags & CMD_Q_DEAD)
|
||||
return (1);
|
||||
/* Process next item on command queue. */
|
||||
u_int
|
||||
cmdq_next(struct client *c)
|
||||
{
|
||||
struct cmd_q_list *queue = cmdq_get(c);
|
||||
const char *name = cmdq_name(c);
|
||||
struct cmd_q *cmdq;
|
||||
enum cmd_retval retval;
|
||||
u_int items = 0;
|
||||
static u_int number;
|
||||
|
||||
if (TAILQ_EMPTY(queue)) {
|
||||
log_debug("%s %s: empty", __func__, name);
|
||||
return (0);
|
||||
}
|
||||
if (TAILQ_FIRST(queue)->flags & CMD_Q_WAITING) {
|
||||
log_debug("%s %s: waiting", __func__, name);
|
||||
return (0);
|
||||
}
|
||||
|
||||
cmdq_flush(cmdq);
|
||||
free(cmdq);
|
||||
return (1);
|
||||
log_debug("%s %s: enter", __func__, name);
|
||||
for (;;) {
|
||||
cmdq = TAILQ_FIRST(queue);
|
||||
if (cmdq == NULL)
|
||||
break;
|
||||
log_debug("%s %s: type %d, flags %x", __func__, name,
|
||||
cmdq->type, cmdq->flags);
|
||||
|
||||
/*
|
||||
* Any item with the waiting flag set waits until an external
|
||||
* event clears the flag (for example, a job - look at
|
||||
* run-shell).
|
||||
*/
|
||||
if (cmdq->flags & CMD_Q_WAITING)
|
||||
goto waiting;
|
||||
|
||||
/*
|
||||
* Items are only fired once, once the fired flag is set, a
|
||||
* waiting flag can only be cleared by an external event.
|
||||
*/
|
||||
if (~cmdq->flags & CMD_Q_FIRED) {
|
||||
cmdq->time = time(NULL);
|
||||
cmdq->number = ++number;
|
||||
|
||||
switch (cmdq->type)
|
||||
{
|
||||
case CMD_Q_COMMAND:
|
||||
retval = cmdq_fire_command(cmdq);
|
||||
|
||||
/*
|
||||
* If a command returns an error, remove any
|
||||
* subsequent commands in the same group.
|
||||
*/
|
||||
if (retval == CMD_RETURN_ERROR)
|
||||
cmdq_remove_group(cmdq);
|
||||
break;
|
||||
case CMD_Q_CALLBACK:
|
||||
retval = cmdq_fire_callback(cmdq);
|
||||
break;
|
||||
default:
|
||||
retval = CMD_RETURN_ERROR;
|
||||
break;
|
||||
}
|
||||
cmdq->flags |= CMD_Q_FIRED;
|
||||
|
||||
if (retval == CMD_RETURN_WAIT) {
|
||||
cmdq->flags |= CMD_Q_WAITING;
|
||||
goto waiting;
|
||||
}
|
||||
items++;
|
||||
}
|
||||
cmdq_remove(cmdq);
|
||||
}
|
||||
|
||||
log_debug("%s %s: exit (empty)", __func__, name);
|
||||
return (items);
|
||||
|
||||
waiting:
|
||||
log_debug("%s %s: exit (wait)", __func__, name);
|
||||
return (items);
|
||||
}
|
||||
|
||||
/* Print a guard line. */
|
||||
void
|
||||
cmdq_guard(struct cmd_q *cmdq, const char *guard, int flags)
|
||||
{
|
||||
struct client *c = cmdq->client;
|
||||
|
||||
if (c == NULL || !(c->flags & CLIENT_CONTROL))
|
||||
return;
|
||||
|
||||
evbuffer_add_printf(c->stdout_data, "%%%s %ld %u %d\n", guard,
|
||||
(long)cmdq->time, cmdq->number, flags);
|
||||
server_client_push_stdout(c);
|
||||
}
|
||||
|
||||
/* Show message from command. */
|
||||
@ -140,175 +409,3 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
|
||||
|
||||
free(msg);
|
||||
}
|
||||
|
||||
/* Print a guard line. */
|
||||
void
|
||||
cmdq_guard(struct cmd_q *cmdq, const char *guard, int flags)
|
||||
{
|
||||
struct client *c = cmdq->client;
|
||||
|
||||
if (c == NULL || !(c->flags & CLIENT_CONTROL))
|
||||
return;
|
||||
|
||||
evbuffer_add_printf(c->stdout_data, "%%%s %ld %u %d\n", guard,
|
||||
(long) cmdq->time, cmdq->number, flags);
|
||||
server_client_push_stdout(c);
|
||||
}
|
||||
|
||||
/* Add command list to queue and begin processing if needed. */
|
||||
void
|
||||
cmdq_run(struct cmd_q *cmdq, struct cmd_list *cmdlist, struct mouse_event *m)
|
||||
{
|
||||
cmdq_append(cmdq, cmdlist, m);
|
||||
|
||||
if (cmdq->item == NULL) {
|
||||
cmdq->cmd = NULL;
|
||||
cmdq_continue(cmdq);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add command list to queue. */
|
||||
void
|
||||
cmdq_append(struct cmd_q *cmdq, struct cmd_list *cmdlist, struct mouse_event *m)
|
||||
{
|
||||
struct cmd_q_item *item;
|
||||
|
||||
item = xcalloc(1, sizeof *item);
|
||||
item->cmdlist = cmdlist;
|
||||
TAILQ_INSERT_TAIL(&cmdq->queue, item, qentry);
|
||||
cmdlist->references++;
|
||||
|
||||
if (m != NULL)
|
||||
memcpy(&item->mouse, m, sizeof item->mouse);
|
||||
else
|
||||
item->mouse.valid = 0;
|
||||
}
|
||||
|
||||
/* Process one command. */
|
||||
static enum cmd_retval
|
||||
cmdq_continue_one(struct cmd_q *cmdq)
|
||||
{
|
||||
struct cmd_list *cmdlist = cmdq->item->cmdlist;
|
||||
struct cmd *cmd = cmdq->cmd;
|
||||
enum cmd_retval retval;
|
||||
char *tmp;
|
||||
int flags = !!(cmd->flags & CMD_CONTROL);
|
||||
const char *name;
|
||||
struct cmd_find_state *fsp, fs;
|
||||
|
||||
cmdlist->references++;
|
||||
|
||||
tmp = cmd_print(cmd);
|
||||
log_debug("cmdq %p: %s", cmdq, tmp);
|
||||
free(tmp);
|
||||
|
||||
cmdq->time = time(NULL);
|
||||
cmdq->number++;
|
||||
|
||||
cmdq_guard(cmdq, "begin", flags);
|
||||
|
||||
if (cmd_prepare_state(cmd, cmdq, cmdq->parent) != 0)
|
||||
goto error;
|
||||
|
||||
retval = cmd->entry->exec(cmd, cmdq);
|
||||
if (retval == CMD_RETURN_ERROR)
|
||||
goto error;
|
||||
|
||||
if (~cmd->entry->flags & CMD_AFTERHOOK)
|
||||
goto end;
|
||||
|
||||
if (cmd_find_valid_state(&cmdq->state.tflag))
|
||||
fsp = &cmdq->state.tflag;
|
||||
else {
|
||||
if (cmd_find_current(&fs, cmdq, CMD_FIND_QUIET) != 0)
|
||||
goto end;
|
||||
fsp = &fs;
|
||||
}
|
||||
name = cmd->entry->name;
|
||||
if (hooks_wait(fsp->s->hooks, cmdq, fsp, "after-%s", name) == 0)
|
||||
retval = CMD_RETURN_WAIT;
|
||||
|
||||
end:
|
||||
cmdq_guard(cmdq, "end", flags);
|
||||
cmd_list_free(cmdlist);
|
||||
return (retval);
|
||||
|
||||
error:
|
||||
cmdq_guard(cmdq, "error", flags);
|
||||
cmd_list_free(cmdlist);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
/* Continue processing command queue. Returns 1 if finishes empty. */
|
||||
int
|
||||
cmdq_continue(struct cmd_q *cmdq)
|
||||
{
|
||||
struct client *c = cmdq->client;
|
||||
struct cmd_q_item *next;
|
||||
enum cmd_retval retval;
|
||||
int empty;
|
||||
|
||||
log_debug("continuing cmdq %p: flags %#x (%p)", cmdq, cmdq->flags, c);
|
||||
cmdq->references++;
|
||||
|
||||
empty = TAILQ_EMPTY(&cmdq->queue);
|
||||
if (empty)
|
||||
goto empty;
|
||||
|
||||
if (cmdq->item == NULL) {
|
||||
cmdq->item = TAILQ_FIRST(&cmdq->queue);
|
||||
cmdq->cmd = TAILQ_FIRST(&cmdq->item->cmdlist->list);
|
||||
} else
|
||||
cmdq->cmd = TAILQ_NEXT(cmdq->cmd, qentry);
|
||||
|
||||
do {
|
||||
while (cmdq->cmd != NULL) {
|
||||
retval = cmdq_continue_one(cmdq);
|
||||
if (retval == CMD_RETURN_ERROR)
|
||||
break;
|
||||
if (retval == CMD_RETURN_WAIT)
|
||||
goto out;
|
||||
if (retval == CMD_RETURN_STOP) {
|
||||
cmdq_flush(cmdq);
|
||||
goto empty;
|
||||
}
|
||||
cmdq->cmd = TAILQ_NEXT(cmdq->cmd, qentry);
|
||||
}
|
||||
next = TAILQ_NEXT(cmdq->item, qentry);
|
||||
|
||||
TAILQ_REMOVE(&cmdq->queue, cmdq->item, qentry);
|
||||
cmd_list_free(cmdq->item->cmdlist);
|
||||
free(cmdq->item);
|
||||
|
||||
cmdq->item = next;
|
||||
if (cmdq->item != NULL)
|
||||
cmdq->cmd = TAILQ_FIRST(&cmdq->item->cmdlist->list);
|
||||
} while (cmdq->item != NULL);
|
||||
|
||||
empty:
|
||||
log_debug("cmdq %p empty", cmdq);
|
||||
if (cmdq->client_exit > 0)
|
||||
cmdq->client->flags |= CLIENT_EXIT;
|
||||
if (cmdq->emptyfn != NULL)
|
||||
cmdq->emptyfn(cmdq);
|
||||
empty = 1;
|
||||
|
||||
out:
|
||||
cmdq_free(cmdq);
|
||||
return (empty);
|
||||
}
|
||||
|
||||
/* Flush command queue. */
|
||||
static void
|
||||
cmdq_flush(struct cmd_q *cmdq)
|
||||
{
|
||||
struct cmd_q_item *item, *item1;
|
||||
|
||||
TAILQ_FOREACH_SAFE(item, &cmdq->queue, qentry, item1) {
|
||||
TAILQ_REMOVE(&cmdq->queue, item, qentry);
|
||||
cmd_list_free(item->cmdlist);
|
||||
free(item);
|
||||
}
|
||||
cmdq->item = NULL;
|
||||
}
|
||||
|
||||
|
@ -60,12 +60,12 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
int x, y;
|
||||
|
||||
if (args_has(args, 'M')) {
|
||||
if (cmd_mouse_window(&cmdq->item->mouse, &s) == NULL)
|
||||
if (cmd_mouse_window(&cmdq->mouse, &s) == NULL)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
if (c == NULL || c->session != s)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update;
|
||||
cmd_resize_pane_mouse_update(c, &cmdq->item->mouse);
|
||||
cmd_resize_pane_mouse_update(c, &cmdq->mouse);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,6 @@ const struct cmd_entry cmd_run_shell_entry = {
|
||||
struct cmd_run_shell_data {
|
||||
char *cmd;
|
||||
struct cmd_q *cmdq;
|
||||
int bflag;
|
||||
int wp_id;
|
||||
};
|
||||
|
||||
@ -92,6 +91,7 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
cwd = s->cwd;
|
||||
else
|
||||
cwd = NULL;
|
||||
|
||||
ft = format_create(cmdq, 0);
|
||||
format_defaults(ft, cmdq->state.c, s, wl, wp);
|
||||
shellcmd = format_expand(ft, args->argv[0]);
|
||||
@ -99,20 +99,24 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
|
||||
cdata = xcalloc(1, sizeof *cdata);
|
||||
cdata->cmd = shellcmd;
|
||||
cdata->bflag = args_has(args, 'b');
|
||||
|
||||
if (args_has(args, 't') && wp != NULL)
|
||||
cdata->wp_id = wp->id;
|
||||
else
|
||||
cdata->wp_id = -1;
|
||||
|
||||
cdata->cmdq = cmdq;
|
||||
cmdq->references++;
|
||||
if (args_has(args, 't') && wp != NULL)
|
||||
cdata->wp_id = wp->id;
|
||||
else
|
||||
cdata->wp_id = -1;
|
||||
|
||||
if (!args_has(args, 'b'))
|
||||
cdata->cmdq = cmdq;
|
||||
|
||||
job_run(shellcmd, s, cwd, cmd_run_shell_callback, cmd_run_shell_free,
|
||||
cdata);
|
||||
|
||||
if (cdata->bflag)
|
||||
if (args_has(args, 'b'))
|
||||
return (CMD_RETURN_NORMAL);
|
||||
return (CMD_RETURN_WAIT);
|
||||
}
|
||||
@ -121,16 +125,11 @@ static void
|
||||
cmd_run_shell_callback(struct job *job)
|
||||
{
|
||||
struct cmd_run_shell_data *cdata = job->data;
|
||||
struct cmd_q *cmdq = cdata->cmdq;
|
||||
char *cmd, *msg, *line;
|
||||
char *cmd = cdata->cmd, *msg, *line;
|
||||
size_t size;
|
||||
int retcode;
|
||||
u_int lines;
|
||||
|
||||
if (cmdq->flags & CMD_Q_DEAD)
|
||||
return;
|
||||
cmd = cdata->cmd;
|
||||
|
||||
lines = 0;
|
||||
do {
|
||||
if ((line = evbuffer_readline(job->event->input)) != NULL) {
|
||||
@ -163,16 +162,15 @@ cmd_run_shell_callback(struct job *job)
|
||||
if (msg != NULL)
|
||||
cmd_run_shell_print(job, msg);
|
||||
free(msg);
|
||||
|
||||
if (cdata->cmdq != NULL)
|
||||
cdata->cmdq->flags &= ~CMD_Q_WAITING;
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_run_shell_free(void *data)
|
||||
{
|
||||
struct cmd_run_shell_data *cdata = data;
|
||||
struct cmd_q *cmdq = cdata->cmdq;
|
||||
|
||||
if (!cmdq_free(cmdq) && !cdata->bflag)
|
||||
cmdq_continue(cmdq);
|
||||
|
||||
free(cdata->cmd);
|
||||
free(cdata);
|
||||
|
@ -62,7 +62,7 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct client *c = cmdq->state.c;
|
||||
struct window_pane *wp = cmdq->state.tflag.wp;
|
||||
struct session *s = cmdq->state.tflag.s;
|
||||
struct mouse_event *m = &cmdq->item->mouse;
|
||||
struct mouse_event *m = &cmdq->mouse;
|
||||
const u_char *keystr;
|
||||
int i, literal;
|
||||
key_code key;
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
static enum cmd_retval cmd_source_file_exec(struct cmd *, struct cmd_q *);
|
||||
|
||||
static void cmd_source_file_done(struct cmd_q *);
|
||||
static enum cmd_retval cmd_source_file_done(struct cmd_q *, void *);
|
||||
|
||||
const struct cmd_entry cmd_source_file_entry = {
|
||||
.name = "source-file",
|
||||
@ -45,53 +45,31 @@ static enum cmd_retval
|
||||
cmd_source_file_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct cmd_q *cmdq1;
|
||||
struct client *c = cmdq->client;
|
||||
int quiet;
|
||||
|
||||
cmdq1 = cmdq_new(cmdq->client);
|
||||
cmdq1->emptyfn = cmd_source_file_done;
|
||||
cmdq1->data = cmdq;
|
||||
struct cmd_q *new_cmdq;
|
||||
|
||||
quiet = args_has(args, 'q');
|
||||
switch (load_cfg(args->argv[0], cmdq1, quiet)) {
|
||||
switch (load_cfg(args->argv[0], c, cmdq, quiet)) {
|
||||
case -1:
|
||||
cmdq_free(cmdq1);
|
||||
if (cfg_references == 0) {
|
||||
if (cfg_finished)
|
||||
cfg_print_causes(cmdq);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
return (CMD_RETURN_NORMAL);
|
||||
return (CMD_RETURN_ERROR);
|
||||
case 0:
|
||||
cmdq_free(cmdq1);
|
||||
if (cfg_references == 0)
|
||||
if (cfg_finished)
|
||||
cfg_print_causes(cmdq);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
log_debug("%s: cmdq %p, parent %p", __func__, cmdq1, cmdq);
|
||||
|
||||
cmdq->references++;
|
||||
cfg_references++;
|
||||
|
||||
cmdq_continue(cmdq1);
|
||||
return (CMD_RETURN_WAIT);
|
||||
if (cfg_finished) {
|
||||
new_cmdq = cmdq_get_callback(cmd_source_file_done, NULL);
|
||||
cmdq_insert_after(cmdq, new_cmdq);
|
||||
}
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_source_file_done(struct cmd_q *cmdq1)
|
||||
static enum cmd_retval
|
||||
cmd_source_file_done(struct cmd_q *cmdq, __unused void *data)
|
||||
{
|
||||
struct cmd_q *cmdq = cmdq1->data;
|
||||
|
||||
log_debug("%s: cmdq %p, parent %p", __func__, cmdq1, cmdq);
|
||||
|
||||
if (cmdq1->client_exit >= 0)
|
||||
cmdq->client_exit = cmdq1->client_exit;
|
||||
cmdq_free(cmdq1);
|
||||
|
||||
cfg_references--;
|
||||
if (cmdq_free(cmdq))
|
||||
return;
|
||||
if (cfg_references == 0)
|
||||
cfg_print_causes(cmdq);
|
||||
cmdq_continue(cmdq);
|
||||
cfg_print_causes(cmdq);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
@ -187,8 +187,8 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
fs.w = w;
|
||||
fs.wp = new_wp;
|
||||
cmd_find_log_state(__func__, &fs);
|
||||
if (hooks_wait(s->hooks, cmdq, &fs, "after-split-window") == 0)
|
||||
return (CMD_RETURN_WAIT);
|
||||
hooks_insert(s->hooks, cmdq, &fs, "after-split-window");
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
error:
|
||||
|
@ -41,13 +41,18 @@ const struct cmd_entry cmd_wait_for_entry = {
|
||||
.exec = cmd_wait_for_exec
|
||||
};
|
||||
|
||||
struct wait_item {
|
||||
struct cmd_q *cmdq;
|
||||
TAILQ_ENTRY(wait_item) entry;
|
||||
};
|
||||
|
||||
struct wait_channel {
|
||||
const char *name;
|
||||
int locked;
|
||||
int woken;
|
||||
|
||||
TAILQ_HEAD(, cmd_q) waiters;
|
||||
TAILQ_HEAD(, cmd_q) lockers;
|
||||
TAILQ_HEAD(, wait_item) waiters;
|
||||
TAILQ_HEAD(, wait_item) lockers;
|
||||
|
||||
RB_ENTRY(wait_channel) entry;
|
||||
};
|
||||
@ -135,7 +140,7 @@ static enum cmd_retval
|
||||
cmd_wait_for_signal(__unused struct cmd_q *cmdq, const char *name,
|
||||
struct wait_channel *wc)
|
||||
{
|
||||
struct cmd_q *wq, *wq1;
|
||||
struct wait_item *wi, *wi1;
|
||||
|
||||
if (wc == NULL)
|
||||
wc = cmd_wait_for_add(name);
|
||||
@ -147,10 +152,11 @@ cmd_wait_for_signal(__unused struct cmd_q *cmdq, const char *name,
|
||||
}
|
||||
log_debug("signal wait channel %s, with waiters", wc->name);
|
||||
|
||||
TAILQ_FOREACH_SAFE(wq, &wc->waiters, waitentry, wq1) {
|
||||
TAILQ_REMOVE(&wc->waiters, wq, waitentry);
|
||||
if (!cmdq_free(wq))
|
||||
cmdq_continue(wq);
|
||||
TAILQ_FOREACH_SAFE(wi, &wc->waiters, entry, wi1) {
|
||||
wi->cmdq->flags &= ~CMD_Q_WAITING;
|
||||
|
||||
TAILQ_REMOVE(&wc->waiters, wi, entry);
|
||||
free(wi);
|
||||
}
|
||||
|
||||
cmd_wait_for_remove(wc);
|
||||
@ -158,10 +164,10 @@ cmd_wait_for_signal(__unused struct cmd_q *cmdq, const char *name,
|
||||
}
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_wait_for_wait(struct cmd_q *cmdq, const char *name,
|
||||
struct wait_channel *wc)
|
||||
cmd_wait_for_wait(struct cmd_q *cmdq, const char *name, struct wait_channel *wc)
|
||||
{
|
||||
struct client *c = cmdq->client;
|
||||
struct client *c = cmdq->client;
|
||||
struct wait_item *wi;
|
||||
|
||||
if (c == NULL || c->session != NULL) {
|
||||
cmdq_error(cmdq, "not able to wait");
|
||||
@ -178,16 +184,18 @@ cmd_wait_for_wait(struct cmd_q *cmdq, const char *name,
|
||||
}
|
||||
log_debug("wait channel %s not woken (%p)", wc->name, c);
|
||||
|
||||
TAILQ_INSERT_TAIL(&wc->waiters, cmdq, waitentry);
|
||||
cmdq->references++;
|
||||
wi = xcalloc(1, sizeof *wi);
|
||||
wi->cmdq = cmdq;
|
||||
TAILQ_INSERT_TAIL(&wc->waiters, wi, entry);
|
||||
|
||||
return (CMD_RETURN_WAIT);
|
||||
}
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_wait_for_lock(struct cmd_q *cmdq, const char *name,
|
||||
struct wait_channel *wc)
|
||||
cmd_wait_for_lock(struct cmd_q *cmdq, const char *name, struct wait_channel *wc)
|
||||
{
|
||||
struct wait_item *wi;
|
||||
|
||||
if (cmdq->client == NULL || cmdq->client->session != NULL) {
|
||||
cmdq_error(cmdq, "not able to lock");
|
||||
return (CMD_RETURN_ERROR);
|
||||
@ -197,8 +205,9 @@ cmd_wait_for_lock(struct cmd_q *cmdq, const char *name,
|
||||
wc = cmd_wait_for_add(name);
|
||||
|
||||
if (wc->locked) {
|
||||
TAILQ_INSERT_TAIL(&wc->lockers, cmdq, waitentry);
|
||||
cmdq->references++;
|
||||
wi = xcalloc(1, sizeof *wi);
|
||||
wi->cmdq = cmdq;
|
||||
TAILQ_INSERT_TAIL(&wc->lockers, wi, entry);
|
||||
return (CMD_RETURN_WAIT);
|
||||
}
|
||||
wc->locked = 1;
|
||||
@ -210,17 +219,17 @@ static enum cmd_retval
|
||||
cmd_wait_for_unlock(struct cmd_q *cmdq, const char *name,
|
||||
struct wait_channel *wc)
|
||||
{
|
||||
struct cmd_q *wq;
|
||||
struct wait_item *wi;
|
||||
|
||||
if (wc == NULL || !wc->locked) {
|
||||
cmdq_error(cmdq, "channel %s not locked", name);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
if ((wq = TAILQ_FIRST(&wc->lockers)) != NULL) {
|
||||
TAILQ_REMOVE(&wc->lockers, wq, waitentry);
|
||||
if (!cmdq_free(wq))
|
||||
cmdq_continue(wq);
|
||||
if ((wi = TAILQ_FIRST(&wc->lockers)) != NULL) {
|
||||
wi->cmdq->flags &= ~CMD_Q_WAITING;
|
||||
TAILQ_REMOVE(&wc->lockers, wi, entry);
|
||||
free(wi);
|
||||
} else {
|
||||
wc->locked = 0;
|
||||
cmd_wait_for_remove(wc);
|
||||
@ -233,19 +242,19 @@ void
|
||||
cmd_wait_for_flush(void)
|
||||
{
|
||||
struct wait_channel *wc, *wc1;
|
||||
struct cmd_q *wq, *wq1;
|
||||
struct wait_item *wi, *wi1;
|
||||
|
||||
RB_FOREACH_SAFE(wc, wait_channels, &wait_channels, wc1) {
|
||||
TAILQ_FOREACH_SAFE(wq, &wc->waiters, waitentry, wq1) {
|
||||
TAILQ_REMOVE(&wc->waiters, wq, waitentry);
|
||||
if (!cmdq_free(wq))
|
||||
cmdq_continue(wq);
|
||||
TAILQ_FOREACH_SAFE(wi, &wc->waiters, entry, wi1) {
|
||||
wi->cmdq->flags &= ~CMD_Q_WAITING;
|
||||
TAILQ_REMOVE(&wc->waiters, wi, entry);
|
||||
free(wi);
|
||||
}
|
||||
wc->woken = 1;
|
||||
TAILQ_FOREACH_SAFE(wq, &wc->lockers, waitentry, wq1) {
|
||||
TAILQ_REMOVE(&wc->lockers, wq, waitentry);
|
||||
if (!cmdq_free(wq))
|
||||
cmdq_continue(wq);
|
||||
TAILQ_FOREACH_SAFE(wi, &wc->lockers, entry, wi1) {
|
||||
wi->cmdq->flags &= ~CMD_Q_WAITING;
|
||||
TAILQ_REMOVE(&wc->lockers, wi, entry);
|
||||
free(wi);
|
||||
}
|
||||
wc->locked = 0;
|
||||
cmd_wait_for_remove(wc);
|
||||
|
51
cmd.c
51
cmd.c
@ -389,12 +389,11 @@ usage:
|
||||
|
||||
static int
|
||||
cmd_prepare_state_flag(char c, const char *target, enum cmd_entry_flag flag,
|
||||
struct cmd_q *cmdq, struct cmd_q *parent)
|
||||
struct cmd_q *cmdq)
|
||||
{
|
||||
int targetflags, error;
|
||||
struct cmd_find_state *fs = NULL;
|
||||
struct cmd_find_state *current = NULL;
|
||||
struct cmd_find_state tmp;
|
||||
struct cmd_find_state current;
|
||||
|
||||
if (flag == CMD_NONE ||
|
||||
flag == CMD_CLIENT ||
|
||||
@ -448,21 +447,12 @@ cmd_prepare_state_flag(char c, const char *target, enum cmd_entry_flag flag,
|
||||
default:
|
||||
fatalx("unknown %cflag %d", c, flag);
|
||||
}
|
||||
|
||||
log_debug("%s: flag %c %d %#x", __func__, c, flag, targetflags);
|
||||
if (parent != NULL) {
|
||||
if (c == 't')
|
||||
current = &parent->state.tflag;
|
||||
else if (c == 's')
|
||||
current = &parent->state.sflag;
|
||||
}
|
||||
if (current == NULL || !cmd_find_valid_state(current)) {
|
||||
error = cmd_find_current(&tmp, cmdq, targetflags);
|
||||
if (error != 0 && ~targetflags & CMD_FIND_QUIET)
|
||||
return (-1);
|
||||
current = &tmp;
|
||||
}
|
||||
if (!cmd_find_empty_state(current) && !cmd_find_valid_state(current))
|
||||
|
||||
error = cmd_find_current(¤t, cmdq, targetflags);
|
||||
if (error != 0 && ~targetflags & CMD_FIND_QUIET)
|
||||
return (-1);
|
||||
if (!cmd_find_empty_state(¤t) && !cmd_find_valid_state(¤t))
|
||||
fatalx("invalid current state");
|
||||
|
||||
switch (flag) {
|
||||
@ -474,13 +464,13 @@ cmd_prepare_state_flag(char c, const char *target, enum cmd_entry_flag flag,
|
||||
case CMD_SESSION_CANFAIL:
|
||||
case CMD_SESSION_PREFERUNATTACHED:
|
||||
case CMD_SESSION_WITHPANE:
|
||||
error = cmd_find_target(fs, current, cmdq, target,
|
||||
error = cmd_find_target(fs, ¤t, cmdq, target,
|
||||
CMD_FIND_SESSION, targetflags);
|
||||
if (error != 0 && ~targetflags & CMD_FIND_QUIET)
|
||||
return (-1);
|
||||
break;
|
||||
case CMD_MOVEW_R:
|
||||
error = cmd_find_target(fs, current, cmdq, target,
|
||||
error = cmd_find_target(fs, ¤t, cmdq, target,
|
||||
CMD_FIND_SESSION, CMD_FIND_QUIET);
|
||||
if (error == 0)
|
||||
break;
|
||||
@ -489,7 +479,7 @@ cmd_prepare_state_flag(char c, const char *target, enum cmd_entry_flag flag,
|
||||
case CMD_WINDOW_CANFAIL:
|
||||
case CMD_WINDOW_MARKED:
|
||||
case CMD_WINDOW_INDEX:
|
||||
error = cmd_find_target(fs, current, cmdq, target,
|
||||
error = cmd_find_target(fs, ¤t, cmdq, target,
|
||||
CMD_FIND_WINDOW, targetflags);
|
||||
if (error != 0 && ~targetflags & CMD_FIND_QUIET)
|
||||
return (-1);
|
||||
@ -497,7 +487,7 @@ cmd_prepare_state_flag(char c, const char *target, enum cmd_entry_flag flag,
|
||||
case CMD_PANE:
|
||||
case CMD_PANE_CANFAIL:
|
||||
case CMD_PANE_MARKED:
|
||||
error = cmd_find_target(fs, current, cmdq, target,
|
||||
error = cmd_find_target(fs, ¤t, cmdq, target,
|
||||
CMD_FIND_PANE, targetflags);
|
||||
if (error != 0 && ~targetflags & CMD_FIND_QUIET)
|
||||
return (-1);
|
||||
@ -509,14 +499,14 @@ cmd_prepare_state_flag(char c, const char *target, enum cmd_entry_flag flag,
|
||||
}
|
||||
|
||||
int
|
||||
cmd_prepare_state(struct cmd *cmd, struct cmd_q *cmdq, struct cmd_q *parent)
|
||||
cmd_prepare_state(struct cmd *cmd, struct cmd_q *cmdq)
|
||||
{
|
||||
const struct cmd_entry *entry = cmd->entry;
|
||||
struct cmd_state *state = &cmdq->state;
|
||||
char *tmp;
|
||||
enum cmd_entry_flag flag;
|
||||
const char *s;
|
||||
int error;
|
||||
const struct cmd_entry *entry = cmd->entry;
|
||||
struct cmd_state *state = &cmdq->state;
|
||||
char *tmp;
|
||||
enum cmd_entry_flag flag;
|
||||
const char *s;
|
||||
int error;
|
||||
|
||||
tmp = cmd_print(cmd);
|
||||
log_debug("preparing state for %s (client %p)", tmp, cmdq->client);
|
||||
@ -545,18 +535,19 @@ cmd_prepare_state(struct cmd *cmd, struct cmd_q *cmdq, struct cmd_q *parent)
|
||||
state->c = cmd_find_client(cmdq, s, 1);
|
||||
break;
|
||||
}
|
||||
log_debug("using client %p", state->c);
|
||||
|
||||
s = args_get(cmd->args, 't');
|
||||
log_debug("preparing -t state: target %s", s == NULL ? "none" : s);
|
||||
|
||||
error = cmd_prepare_state_flag('t', s, entry->tflag, cmdq, parent);
|
||||
error = cmd_prepare_state_flag('t', s, entry->tflag, cmdq);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
s = args_get(cmd->args, 's');
|
||||
log_debug("preparing -s state: target %s", s == NULL ? "none" : s);
|
||||
|
||||
error = cmd_prepare_state_flag('s', s, entry->sflag, cmdq, parent);
|
||||
error = cmd_prepare_state_flag('s', s, entry->sflag, cmdq);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
|
29
control.c
29
control.c
@ -49,6 +49,21 @@ control_write_buffer(struct client *c, struct evbuffer *buffer)
|
||||
server_client_push_stdout(c);
|
||||
}
|
||||
|
||||
/* Control error callback. */
|
||||
static enum cmd_retval
|
||||
control_error(struct cmd_q *cmdq, void *data)
|
||||
{
|
||||
struct client *c = cmdq->client;
|
||||
char *error = data;
|
||||
|
||||
cmdq_guard(cmdq, "begin", 1);
|
||||
control_write(c, "parse error: %s", error);
|
||||
cmdq_guard(cmdq, "error", 1);
|
||||
|
||||
free(error);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
/* Control input callback. Read lines and fire commands. */
|
||||
void
|
||||
control_callback(struct client *c, int closed, __unused void *data)
|
||||
@ -56,6 +71,7 @@ control_callback(struct client *c, int closed, __unused void *data)
|
||||
char *line, *cause;
|
||||
struct cmd_list *cmdlist;
|
||||
struct cmd *cmd;
|
||||
struct cmd_q *cmdq;
|
||||
|
||||
if (closed)
|
||||
c->flags |= CLIENT_EXIT;
|
||||
@ -70,18 +86,13 @@ control_callback(struct client *c, int closed, __unused void *data)
|
||||
}
|
||||
|
||||
if (cmd_string_parse(line, &cmdlist, NULL, 0, &cause) != 0) {
|
||||
c->cmdq->time = time(NULL);
|
||||
c->cmdq->number++;
|
||||
|
||||
cmdq_guard(c->cmdq, "begin", 1);
|
||||
control_write(c, "parse error: %s", cause);
|
||||
cmdq_guard(c->cmdq, "error", 1);
|
||||
|
||||
free(cause);
|
||||
cmdq = cmdq_get_callback(control_error, cause);
|
||||
cmdq_append(c, cmdq);
|
||||
} else {
|
||||
TAILQ_FOREACH(cmd, &cmdlist->list, qentry)
|
||||
cmd->flags |= CMD_CONTROL;
|
||||
cmdq_run(c->cmdq, cmdlist, NULL);
|
||||
cmdq = cmdq_get_command(cmdlist, NULL, NULL, 0);
|
||||
cmdq_append(c, cmdq);
|
||||
cmd_list_free(cmdlist);
|
||||
}
|
||||
|
||||
|
9
format.c
9
format.c
@ -492,7 +492,6 @@ struct format_tree *
|
||||
format_create(struct cmd_q *cmdq, int flags)
|
||||
{
|
||||
struct format_tree *ft;
|
||||
struct cmd *cmd;
|
||||
|
||||
if (!event_initialized(&format_job_event)) {
|
||||
evtimer_set(&format_job_event, format_job_timer, NULL);
|
||||
@ -510,11 +509,9 @@ format_create(struct cmd_q *cmdq, int flags)
|
||||
format_add_tv(ft, "start_time", &start_time);
|
||||
|
||||
if (cmdq != NULL && cmdq->cmd != NULL)
|
||||
format_add(ft, "command_name", "%s", cmdq->cmd->entry->name);
|
||||
if (cmdq != NULL && cmdq->parent != NULL) {
|
||||
cmd = cmdq->parent->cmd;
|
||||
format_add(ft, "command_hooked", "%s", cmd->entry->name);
|
||||
}
|
||||
format_add(ft, "command", "%s", cmdq->cmd->entry->name);
|
||||
if (cmdq != NULL && cmdq->hook != NULL)
|
||||
format_add(ft, "hook", "%s", cmdq->hook);
|
||||
|
||||
return (ft);
|
||||
}
|
||||
|
68
hooks.c
68
hooks.c
@ -33,7 +33,6 @@ RB_GENERATE_STATIC(hooks_tree, hook, entry, hooks_cmp);
|
||||
|
||||
static struct hook *hooks_find1(struct hooks *, const char *);
|
||||
static void hooks_free1(struct hooks *, struct hook *);
|
||||
static void hooks_emptyfn(struct cmd_q *);
|
||||
|
||||
static int
|
||||
hooks_cmp(struct hook *hook1, struct hook *hook2)
|
||||
@ -140,28 +139,14 @@ hooks_find(struct hooks *hooks, const char *name)
|
||||
return (hook);
|
||||
}
|
||||
|
||||
static void
|
||||
hooks_emptyfn(struct cmd_q *hooks_cmdq)
|
||||
{
|
||||
struct cmd_q *cmdq = hooks_cmdq->data;
|
||||
|
||||
if (cmdq != NULL) {
|
||||
if (hooks_cmdq->client_exit >= 0)
|
||||
cmdq->client_exit = hooks_cmdq->client_exit;
|
||||
if (!cmdq_free(cmdq))
|
||||
cmdq_continue(cmdq);
|
||||
}
|
||||
cmdq_free(hooks_cmdq);
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
hooks_run(struct hooks *hooks, struct client *c, struct cmd_find_state *fs,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
struct hook *hook;
|
||||
struct cmd_q *hooks_cmdq;
|
||||
va_list ap;
|
||||
char *name;
|
||||
struct cmd_q *new_cmdq, *loop;
|
||||
|
||||
va_start(ap, fmt);
|
||||
xvasprintf(&name, fmt, ap);
|
||||
@ -170,34 +155,30 @@ hooks_run(struct hooks *hooks, struct client *c, struct cmd_find_state *fs,
|
||||
hook = hooks_find(hooks, name);
|
||||
if (hook == NULL) {
|
||||
free(name);
|
||||
return (-1);
|
||||
return;
|
||||
}
|
||||
log_debug("running hook %s", name);
|
||||
|
||||
new_cmdq = cmdq_get_command(hook->cmdlist, fs, NULL, CMD_Q_NOHOOKS);
|
||||
|
||||
for (loop = new_cmdq; loop != NULL; loop = loop->next)
|
||||
loop->hook = xstrdup(name);
|
||||
free(name);
|
||||
|
||||
hooks_cmdq = cmdq_new(c);
|
||||
hooks_cmdq->flags |= CMD_Q_NOHOOKS;
|
||||
|
||||
if (fs != NULL)
|
||||
cmd_find_copy_state(&hooks_cmdq->current, fs);
|
||||
hooks_cmdq->parent = NULL;
|
||||
|
||||
cmdq_run(hooks_cmdq, hook->cmdlist, NULL);
|
||||
cmdq_free(hooks_cmdq);
|
||||
return (0);
|
||||
cmdq_append(c, new_cmdq);
|
||||
}
|
||||
|
||||
int
|
||||
hooks_wait(struct hooks *hooks, struct cmd_q *cmdq, struct cmd_find_state *fs,
|
||||
void
|
||||
hooks_insert(struct hooks *hooks, struct cmd_q *cmdq, struct cmd_find_state *fs,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
struct hook *hook;
|
||||
struct cmd_q *hooks_cmdq;
|
||||
va_list ap;
|
||||
char *name;
|
||||
struct cmd_q *new_cmdq, *loop;
|
||||
|
||||
if (cmdq->flags & CMD_Q_NOHOOKS)
|
||||
return (-1);
|
||||
return;
|
||||
|
||||
va_start(ap, fmt);
|
||||
xvasprintf(&name, fmt, ap);
|
||||
@ -206,23 +187,18 @@ hooks_wait(struct hooks *hooks, struct cmd_q *cmdq, struct cmd_find_state *fs,
|
||||
hook = hooks_find(hooks, name);
|
||||
if (hook == NULL) {
|
||||
free(name);
|
||||
return (-1);
|
||||
return;
|
||||
}
|
||||
log_debug("running hook %s (parent %p)", name, cmdq);
|
||||
|
||||
new_cmdq = cmdq_get_command(hook->cmdlist, fs, NULL, CMD_Q_NOHOOKS);
|
||||
|
||||
for (loop = new_cmdq; loop != NULL; loop = loop->next)
|
||||
loop->hook = xstrdup(name);
|
||||
free(name);
|
||||
|
||||
hooks_cmdq = cmdq_new(cmdq->client);
|
||||
hooks_cmdq->flags |= CMD_Q_NOHOOKS;
|
||||
|
||||
if (fs != NULL)
|
||||
cmd_find_copy_state(&hooks_cmdq->current, fs);
|
||||
hooks_cmdq->parent = cmdq;
|
||||
|
||||
hooks_cmdq->emptyfn = hooks_emptyfn;
|
||||
hooks_cmdq->data = cmdq;
|
||||
|
||||
if (cmdq != NULL)
|
||||
cmdq->references++;
|
||||
cmdq_run(hooks_cmdq, hook->cmdlist, NULL);
|
||||
return (0);
|
||||
cmdq_insert_after(cmdq, new_cmdq);
|
||||
else
|
||||
cmdq_append(NULL, new_cmdq);
|
||||
}
|
||||
|
@ -377,18 +377,22 @@ key_bindings_init(void)
|
||||
struct cmd_list *cmdlist;
|
||||
char *cause;
|
||||
int error;
|
||||
struct cmd_q *cmdq;
|
||||
|
||||
cmdq = cmdq_new(NULL);
|
||||
for (i = 0; i < nitems(defaults); i++) {
|
||||
error = cmd_string_parse(defaults[i], &cmdlist,
|
||||
"<default-keys>", i, &cause);
|
||||
if (error != 0)
|
||||
fatalx("bad default key");
|
||||
cmdq_run(cmdq, cmdlist, NULL);
|
||||
cmdq_append(NULL, cmdq_get_command(cmdlist, NULL, NULL, 0));
|
||||
cmd_list_free(cmdlist);
|
||||
}
|
||||
cmdq_free(cmdq);
|
||||
}
|
||||
|
||||
static enum cmd_retval
|
||||
key_bindings_read_only(struct cmd_q *cmdq, __unused void *data)
|
||||
{
|
||||
cmdq_error(cmdq, "client is read-only");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
void
|
||||
@ -403,10 +407,8 @@ key_bindings_dispatch(struct key_binding *bd, struct client *c,
|
||||
if (!(cmd->entry->flags & CMD_READONLY))
|
||||
readonly = 0;
|
||||
}
|
||||
if (!readonly && (c->flags & CLIENT_READONLY)) {
|
||||
cmdq_error(c->cmdq, "client is read-only");
|
||||
return;
|
||||
}
|
||||
|
||||
cmdq_run(c->cmdq, bd->cmdlist, m);
|
||||
if (!readonly && (c->flags & CLIENT_READONLY))
|
||||
cmdq_append(c, cmdq_get_callback(key_bindings_read_only, NULL));
|
||||
else
|
||||
cmdq_append(c, cmdq_get_command(bd->cmdlist, NULL, m, 0));
|
||||
}
|
||||
|
12
notify.c
12
notify.c
@ -65,7 +65,7 @@ notify_hook(struct notify_entry *ne)
|
||||
const char *name;
|
||||
struct cmd_find_state fs;
|
||||
struct hook *hook;
|
||||
struct cmd_q *hooks_cmdq;
|
||||
struct cmd_q *new_cmdq, *loop;
|
||||
|
||||
name = notify_hooks[ne->type];
|
||||
if (name == NULL)
|
||||
@ -86,14 +86,12 @@ notify_hook(struct notify_entry *ne)
|
||||
return;
|
||||
log_debug("notify hook %s", name);
|
||||
|
||||
hooks_cmdq = cmdq_new(NULL);
|
||||
hooks_cmdq->flags |= CMD_Q_NOHOOKS;
|
||||
new_cmdq = cmdq_get_command(hook->cmdlist, &fs, NULL, CMD_Q_NOHOOKS);
|
||||
|
||||
cmd_find_copy_state(&hooks_cmdq->current, &fs);
|
||||
hooks_cmdq->parent = NULL;
|
||||
for (loop = new_cmdq; loop != NULL; loop = loop->next)
|
||||
loop->hook = xstrdup(name);
|
||||
|
||||
cmdq_run(hooks_cmdq, hook->cmdlist, NULL);
|
||||
cmdq_free(hooks_cmdq);
|
||||
cmdq_append(NULL, new_cmdq);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -124,8 +124,7 @@ server_client_create(int fd)
|
||||
c->fd = -1;
|
||||
c->cwd = NULL;
|
||||
|
||||
c->cmdq = cmdq_new(c);
|
||||
c->cmdq->client_exit = 1;
|
||||
TAILQ_INIT(&c->queue);
|
||||
|
||||
c->stdin_data = evbuffer_new();
|
||||
c->stdout_data = evbuffer_new();
|
||||
@ -242,10 +241,6 @@ server_client_lost(struct client *c)
|
||||
free(c->prompt_string);
|
||||
free(c->prompt_buffer);
|
||||
|
||||
c->cmdq->flags |= CMD_Q_DEAD;
|
||||
cmdq_free(c->cmdq);
|
||||
c->cmdq = NULL;
|
||||
|
||||
environ_free(c->environ);
|
||||
|
||||
proc_remove_peer(c->peer);
|
||||
@ -279,6 +274,9 @@ server_client_free(__unused int fd, __unused short events, void *arg)
|
||||
|
||||
log_debug("free client %p (%d references)", c, c->references);
|
||||
|
||||
if (!TAILQ_EMPTY(&c->queue))
|
||||
fatalx("queue not empty");
|
||||
|
||||
if (c->references == 0)
|
||||
free(c);
|
||||
}
|
||||
@ -1262,6 +1260,29 @@ server_client_dispatch(struct imsg *imsg, void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
/* Callback when command is done. */
|
||||
static enum cmd_retval
|
||||
server_client_command_done(struct cmd_q *cmdq, __unused void *data)
|
||||
{
|
||||
struct client *c = cmdq->client;
|
||||
|
||||
if (~c->flags & CLIENT_ATTACHED)
|
||||
c->flags |= CLIENT_EXIT;
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
/* Show an error message. */
|
||||
static enum cmd_retval
|
||||
server_client_command_error(struct cmd_q *cmdq, void *data)
|
||||
{
|
||||
char *error = data;
|
||||
|
||||
cmdq_error(cmdq, "%s", error);
|
||||
free(error);
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
/* Handle command message. */
|
||||
static void
|
||||
server_client_dispatch_command(struct client *c, struct imsg *imsg)
|
||||
@ -1284,7 +1305,7 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg)
|
||||
|
||||
argc = data.argc;
|
||||
if (cmd_unpack_argv(buf, len, argc, &argv) != 0) {
|
||||
cmdq_error(c->cmdq, "command too long");
|
||||
cause = xstrdup("command too long");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -1295,20 +1316,19 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg)
|
||||
}
|
||||
|
||||
if ((cmdlist = cmd_list_parse(argc, argv, NULL, 0, &cause)) == NULL) {
|
||||
cmdq_error(c->cmdq, "%s", cause);
|
||||
cmd_free_argv(argc, argv);
|
||||
goto error;
|
||||
}
|
||||
cmd_free_argv(argc, argv);
|
||||
|
||||
if (c != cfg_client || cfg_finished)
|
||||
cmdq_run(c->cmdq, cmdlist, NULL);
|
||||
else
|
||||
cmdq_append(c->cmdq, cmdlist, NULL);
|
||||
cmdq_append(c, cmdq_get_command(cmdlist, NULL, NULL, 0));
|
||||
cmdq_append(c, cmdq_get_callback(server_client_command_done, NULL));
|
||||
cmd_list_free(cmdlist);
|
||||
return;
|
||||
|
||||
error:
|
||||
cmdq_append(c, cmdq_get_callback(server_client_command_error, cause));
|
||||
|
||||
if (cmdlist != NULL)
|
||||
cmd_list_free(cmdlist);
|
||||
|
||||
|
10
server.c
10
server.c
@ -192,9 +192,17 @@ static int
|
||||
server_loop(void)
|
||||
{
|
||||
struct client *c;
|
||||
u_int items;
|
||||
|
||||
notify_drain();
|
||||
|
||||
do {
|
||||
items = cmdq_next(NULL);
|
||||
TAILQ_FOREACH(c, &clients, entry)
|
||||
items += cmdq_next(c);
|
||||
} while (items != 0);
|
||||
|
||||
server_client_loop();
|
||||
notify_drain();
|
||||
|
||||
if (!options_get_number(global_options, "exit-unattached")) {
|
||||
if (!RB_EMPTY(&sessions))
|
||||
|
4
tmux.1
4
tmux.1
@ -3460,8 +3460,7 @@ The following variables are available, where appropriate:
|
||||
.It Li "client_tty" Ta "" Ta "Pseudo terminal of client"
|
||||
.It Li "client_utf8" Ta "" Ta "1 if client supports utf8"
|
||||
.It Li "client_width" Ta "" Ta "Width of client"
|
||||
.It Li "command_hooked" Ta "" Ta "Name of command hooked, if any"
|
||||
.It Li "command_name" Ta "" Ta "Name of command in use, if any"
|
||||
.It Li "command" Ta "" Ta "Name of command in use, if any"
|
||||
.It Li "command_list_name" Ta "" Ta "Command name if listing commands"
|
||||
.It Li "command_list_alias" Ta "" Ta "Command alias if listing commands"
|
||||
.It Li "command_list_usage" Ta "" Ta "Command usage if listing commands"
|
||||
@ -3471,6 +3470,7 @@ The following variables are available, where appropriate:
|
||||
.It Li "history_bytes" Ta "" Ta "Number of bytes in window history"
|
||||
.It Li "history_limit" Ta "" Ta "Maximum window history lines"
|
||||
.It Li "history_size" Ta "" Ta "Size of history in bytes"
|
||||
.It Li "hook" Ta "" Ta "Name of running hook, if any"
|
||||
.It Li "host" Ta "#H" Ta "Hostname of local host"
|
||||
.It Li "host_short" Ta "#h" Ta "Hostname of local host (no domain name)"
|
||||
.It Li "insert_flag" Ta "" Ta "Pane insert flag"
|
||||
|
268
tmux.h
268
tmux.h
@ -42,6 +42,8 @@ extern char **environ;
|
||||
|
||||
struct args;
|
||||
struct client;
|
||||
struct cmd_q;
|
||||
struct cmd_q_list;
|
||||
struct environ;
|
||||
struct input_ctx;
|
||||
struct mode_key_cmdstr;
|
||||
@ -633,7 +635,6 @@ struct grid {
|
||||
struct hook {
|
||||
const char *name;
|
||||
|
||||
struct cmd_q *cmdq;
|
||||
struct cmd_list *cmdlist;
|
||||
|
||||
RB_ENTRY(hook) entry;
|
||||
@ -1162,101 +1163,6 @@ struct message_entry {
|
||||
TAILQ_ENTRY(message_entry) entry;
|
||||
};
|
||||
|
||||
/* Client connection. */
|
||||
struct client {
|
||||
struct tmuxpeer *peer;
|
||||
|
||||
pid_t pid;
|
||||
int fd;
|
||||
struct event event;
|
||||
int retval;
|
||||
|
||||
struct timeval creation_time;
|
||||
struct timeval activity_time;
|
||||
|
||||
struct environ *environ;
|
||||
|
||||
char *title;
|
||||
const char *cwd;
|
||||
|
||||
char *term;
|
||||
char *ttyname;
|
||||
struct tty tty;
|
||||
|
||||
void (*stdin_callback)(struct client *, int, void *);
|
||||
void *stdin_callback_data;
|
||||
struct evbuffer *stdin_data;
|
||||
int stdin_closed;
|
||||
struct evbuffer *stdout_data;
|
||||
struct evbuffer *stderr_data;
|
||||
|
||||
struct event repeat_timer;
|
||||
|
||||
struct event click_timer;
|
||||
u_int click_button;
|
||||
|
||||
struct event status_timer;
|
||||
struct screen status;
|
||||
|
||||
#define CLIENT_TERMINAL 0x1
|
||||
#define CLIENT_LOGIN 0x2
|
||||
#define CLIENT_EXIT 0x4
|
||||
#define CLIENT_REDRAW 0x8
|
||||
#define CLIENT_STATUS 0x10
|
||||
#define CLIENT_REPEAT 0x20
|
||||
#define CLIENT_SUSPENDED 0x40
|
||||
/* 0x80 unused */
|
||||
#define CLIENT_IDENTIFY 0x100
|
||||
#define CLIENT_DEAD 0x200
|
||||
#define CLIENT_BORDERS 0x400
|
||||
#define CLIENT_READONLY 0x800
|
||||
#define CLIENT_REDRAWWINDOW 0x1000
|
||||
#define CLIENT_CONTROL 0x2000
|
||||
#define CLIENT_CONTROLCONTROL 0x4000
|
||||
#define CLIENT_FOCUSED 0x8000
|
||||
#define CLIENT_UTF8 0x10000
|
||||
#define CLIENT_256COLOURS 0x20000
|
||||
#define CLIENT_IDENTIFIED 0x40000
|
||||
#define CLIENT_STATUSFORCE 0x80000
|
||||
#define CLIENT_DOUBLECLICK 0x100000
|
||||
#define CLIENT_TRIPLECLICK 0x200000
|
||||
int flags;
|
||||
struct key_table *keytable;
|
||||
|
||||
struct event identify_timer;
|
||||
void (*identify_callback)(struct client *, struct window_pane *);
|
||||
void *identify_callback_data;
|
||||
|
||||
char *message_string;
|
||||
struct event message_timer;
|
||||
u_int message_next;
|
||||
TAILQ_HEAD(, message_entry) message_log;
|
||||
|
||||
char *prompt_string;
|
||||
struct utf8_data *prompt_buffer;
|
||||
size_t prompt_index;
|
||||
int (*prompt_callbackfn)(void *, const char *);
|
||||
void (*prompt_freefn)(void *);
|
||||
void *prompt_data;
|
||||
u_int prompt_hindex;
|
||||
enum { PROMPT_ENTRY, PROMPT_COMMAND } prompt_mode;
|
||||
|
||||
#define PROMPT_SINGLE 0x1
|
||||
#define PROMPT_NUMERIC 0x2
|
||||
int prompt_flags;
|
||||
|
||||
struct session *session;
|
||||
struct session *last_session;
|
||||
|
||||
int wlmouse;
|
||||
|
||||
struct cmd_q *cmdq;
|
||||
int references;
|
||||
|
||||
TAILQ_ENTRY(client) entry;
|
||||
};
|
||||
TAILQ_HEAD(clients, client);
|
||||
|
||||
/* Parsed arguments structures. */
|
||||
struct args_entry;
|
||||
RB_HEAD(args_tree, args_entry);
|
||||
@ -1326,42 +1232,46 @@ enum cmd_retval {
|
||||
CMD_RETURN_STOP
|
||||
};
|
||||
|
||||
/* Command queue entry. */
|
||||
struct cmd_q_item {
|
||||
struct cmd_list *cmdlist;
|
||||
|
||||
struct mouse_event mouse;
|
||||
|
||||
TAILQ_ENTRY(cmd_q_item) qentry;
|
||||
/* Command queue item type. */
|
||||
enum cmd_q_type {
|
||||
CMD_Q_COMMAND,
|
||||
CMD_Q_CALLBACK,
|
||||
};
|
||||
TAILQ_HEAD(cmd_q_items, cmd_q_item);
|
||||
|
||||
/* Command queue. */
|
||||
/* Command queue item. */
|
||||
typedef enum cmd_retval (*cmd_q_cb) (struct cmd_q *, void *);
|
||||
struct cmd_q {
|
||||
int references;
|
||||
int flags;
|
||||
#define CMD_Q_DEAD 0x1
|
||||
#define CMD_Q_NOHOOKS 0x2
|
||||
struct cmd_q_list *queue;
|
||||
struct cmd_q *next;
|
||||
|
||||
struct client *client;
|
||||
int client_exit;
|
||||
|
||||
struct cmd_q_items queue;
|
||||
struct cmd_q_item *item;
|
||||
enum cmd_q_type type;
|
||||
u_int group;
|
||||
|
||||
u_int number;
|
||||
time_t time;
|
||||
|
||||
const char *hook;
|
||||
int flags;
|
||||
#define CMD_Q_FIRED 0x1
|
||||
#define CMD_Q_WAITING 0x2
|
||||
#define CMD_Q_NOHOOKS 0x4
|
||||
|
||||
struct cmd_list *cmdlist;
|
||||
struct cmd *cmd;
|
||||
struct cmd_q *parent;
|
||||
|
||||
cmd_q_cb cb;
|
||||
void *data;
|
||||
|
||||
struct cmd_find_state current;
|
||||
struct cmd_state state;
|
||||
|
||||
time_t time;
|
||||
u_int number;
|
||||
struct mouse_event mouse;
|
||||
|
||||
void (*emptyfn)(struct cmd_q *);
|
||||
void *data;
|
||||
|
||||
TAILQ_ENTRY(cmd_q) waitentry;
|
||||
TAILQ_ENTRY(cmd_q) entry;
|
||||
};
|
||||
TAILQ_HEAD(cmd_q_list, cmd_q);
|
||||
|
||||
/* Command -c, -t or -s flags. */
|
||||
enum cmd_entry_flag {
|
||||
@ -1411,6 +1321,101 @@ struct cmd_entry {
|
||||
enum cmd_retval (*exec)(struct cmd *, struct cmd_q *);
|
||||
};
|
||||
|
||||
/* Client connection. */
|
||||
struct client {
|
||||
struct tmuxpeer *peer;
|
||||
struct cmd_q_list queue;
|
||||
|
||||
pid_t pid;
|
||||
int fd;
|
||||
struct event event;
|
||||
int retval;
|
||||
|
||||
struct timeval creation_time;
|
||||
struct timeval activity_time;
|
||||
|
||||
struct environ *environ;
|
||||
|
||||
char *title;
|
||||
const char *cwd;
|
||||
|
||||
char *term;
|
||||
char *ttyname;
|
||||
struct tty tty;
|
||||
|
||||
void (*stdin_callback)(struct client *, int, void *);
|
||||
void *stdin_callback_data;
|
||||
struct evbuffer *stdin_data;
|
||||
int stdin_closed;
|
||||
struct evbuffer *stdout_data;
|
||||
struct evbuffer *stderr_data;
|
||||
|
||||
struct event repeat_timer;
|
||||
|
||||
struct event click_timer;
|
||||
u_int click_button;
|
||||
|
||||
struct event status_timer;
|
||||
struct screen status;
|
||||
|
||||
#define CLIENT_TERMINAL 0x1
|
||||
#define CLIENT_LOGIN 0x2
|
||||
#define CLIENT_EXIT 0x4
|
||||
#define CLIENT_REDRAW 0x8
|
||||
#define CLIENT_STATUS 0x10
|
||||
#define CLIENT_REPEAT 0x20
|
||||
#define CLIENT_SUSPENDED 0x40
|
||||
#define CLIENT_ATTACHED 0x80
|
||||
#define CLIENT_IDENTIFY 0x100
|
||||
#define CLIENT_DEAD 0x200
|
||||
#define CLIENT_BORDERS 0x400
|
||||
#define CLIENT_READONLY 0x800
|
||||
#define CLIENT_REDRAWWINDOW 0x1000
|
||||
#define CLIENT_CONTROL 0x2000
|
||||
#define CLIENT_CONTROLCONTROL 0x4000
|
||||
#define CLIENT_FOCUSED 0x8000
|
||||
#define CLIENT_UTF8 0x10000
|
||||
#define CLIENT_256COLOURS 0x20000
|
||||
#define CLIENT_IDENTIFIED 0x40000
|
||||
#define CLIENT_STATUSFORCE 0x80000
|
||||
#define CLIENT_DOUBLECLICK 0x100000
|
||||
#define CLIENT_TRIPLECLICK 0x200000
|
||||
int flags;
|
||||
struct key_table *keytable;
|
||||
|
||||
struct event identify_timer;
|
||||
void (*identify_callback)(struct client *, struct window_pane *);
|
||||
void *identify_callback_data;
|
||||
|
||||
char *message_string;
|
||||
struct event message_timer;
|
||||
u_int message_next;
|
||||
TAILQ_HEAD(, message_entry) message_log;
|
||||
|
||||
char *prompt_string;
|
||||
struct utf8_data *prompt_buffer;
|
||||
size_t prompt_index;
|
||||
int (*prompt_callbackfn)(void *, const char *);
|
||||
void (*prompt_freefn)(void *);
|
||||
void *prompt_data;
|
||||
u_int prompt_hindex;
|
||||
enum { PROMPT_ENTRY, PROMPT_COMMAND } prompt_mode;
|
||||
|
||||
#define PROMPT_SINGLE 0x1
|
||||
#define PROMPT_NUMERIC 0x2
|
||||
int prompt_flags;
|
||||
|
||||
struct session *session;
|
||||
struct session *last_session;
|
||||
|
||||
int wlmouse;
|
||||
|
||||
int references;
|
||||
|
||||
TAILQ_ENTRY(client) entry;
|
||||
};
|
||||
TAILQ_HEAD(clients, client);
|
||||
|
||||
/* Key binding and key table. */
|
||||
struct key_binding {
|
||||
key_code key;
|
||||
@ -1506,10 +1511,9 @@ void proc_kill_peer(struct tmuxpeer *);
|
||||
|
||||
/* cfg.c */
|
||||
extern int cfg_finished;
|
||||
extern int cfg_references;
|
||||
extern struct client *cfg_client;
|
||||
void start_cfg(void);
|
||||
int load_cfg(const char *, struct cmd_q *, int);
|
||||
int load_cfg(const char *, struct client *, struct cmd_q *, int);
|
||||
void set_cfg_file(const char *);
|
||||
void printflike(1, 2) cfg_add_cause(const char *, ...);
|
||||
void cfg_print_causes(struct cmd_q *);
|
||||
@ -1559,9 +1563,9 @@ void hooks_add(struct hooks *, const char *, struct cmd_list *);
|
||||
void hooks_copy(struct hooks *, struct hooks *);
|
||||
void hooks_remove(struct hooks *, const char *);
|
||||
struct hook *hooks_find(struct hooks *, const char *);
|
||||
int printflike(4, 5) hooks_run(struct hooks *, struct client *,
|
||||
void printflike(4, 5) hooks_run(struct hooks *, struct client *,
|
||||
struct cmd_find_state *, const char *, ...);
|
||||
int printflike(4, 5) hooks_wait(struct hooks *, struct cmd_q *,
|
||||
void printflike(4, 5) hooks_insert(struct hooks *, struct cmd_q *,
|
||||
struct cmd_find_state *, const char *, ...);
|
||||
|
||||
/* mode-key.c */
|
||||
@ -1757,8 +1761,7 @@ char **cmd_copy_argv(int, char **);
|
||||
void cmd_free_argv(int, char **);
|
||||
char *cmd_stringify_argv(int, char **);
|
||||
struct cmd *cmd_parse(int, char **, const char *, u_int, char **);
|
||||
int cmd_prepare_state(struct cmd *, struct cmd_q *,
|
||||
struct cmd_q *);
|
||||
int cmd_prepare_state(struct cmd *, struct cmd_q *);
|
||||
char *cmd_print(struct cmd *);
|
||||
int cmd_mouse_at(struct window_pane *, struct mouse_event *,
|
||||
u_int *, u_int *, int);
|
||||
@ -1778,16 +1781,15 @@ void cmd_list_free(struct cmd_list *);
|
||||
char *cmd_list_print(struct cmd_list *);
|
||||
|
||||
/* cmd-queue.c */
|
||||
struct cmd_q *cmdq_new(struct client *);
|
||||
int cmdq_free(struct cmd_q *);
|
||||
struct cmd_q *cmdq_get_command(struct cmd_list *, struct cmd_find_state *,
|
||||
struct mouse_event *, int);
|
||||
struct cmd_q *cmdq_get_callback(cmd_q_cb, void *);
|
||||
void cmdq_insert_after(struct cmd_q *, struct cmd_q *);
|
||||
void cmdq_append(struct client *, struct cmd_q *);
|
||||
u_int cmdq_next(struct client *);
|
||||
void cmdq_guard(struct cmd_q *, const char *, int);
|
||||
void printflike(2, 3) cmdq_print(struct cmd_q *, const char *, ...);
|
||||
void printflike(2, 3) cmdq_error(struct cmd_q *, const char *, ...);
|
||||
void cmdq_guard(struct cmd_q *, const char *, int);
|
||||
void cmdq_run(struct cmd_q *, struct cmd_list *,
|
||||
struct mouse_event *);
|
||||
void cmdq_append(struct cmd_q *, struct cmd_list *,
|
||||
struct mouse_event *);
|
||||
int cmdq_continue(struct cmd_q *);
|
||||
|
||||
/* cmd-string.c */
|
||||
int cmd_string_parse(const char *, struct cmd_list **, const char *,
|
||||
|
@ -246,6 +246,7 @@ window_choose_data_run(struct window_choose_data *cdata)
|
||||
{
|
||||
struct cmd_list *cmdlist;
|
||||
char *cause;
|
||||
struct cmd_q *cmdq;
|
||||
|
||||
/*
|
||||
* The command template will have already been replaced. But if it's
|
||||
@ -263,7 +264,8 @@ window_choose_data_run(struct window_choose_data *cdata)
|
||||
return;
|
||||
}
|
||||
|
||||
cmdq_run(cdata->start_client->cmdq, cmdlist, NULL);
|
||||
cmdq = cmdq_get_command(cmdlist, NULL, NULL, 0);
|
||||
cmdq_append(cdata->start_client, cmdq);
|
||||
cmd_list_free(cmdlist);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user