aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Adam <thomas@xteddy.org>2016-04-29 16:01:12 +0100
committerThomas Adam <thomas@xteddy.org>2016-04-29 16:01:12 +0100
commitba9f32b464effc09b7ceaef21b1804c49ece17db (patch)
treeb49dce19c8650ec83f435d66c4c35ccf3ee545bf
parente7de2fe552a7b4392f208533b72e7fcbe41c0537 (diff)
parent0d84fdd95303a6ed4dcd761425e35f3731b86725 (diff)
downloadrtmux-ba9f32b464effc09b7ceaef21b1804c49ece17db.tar.gz
rtmux-ba9f32b464effc09b7ceaef21b1804c49ece17db.tar.bz2
rtmux-ba9f32b464effc09b7ceaef21b1804c49ece17db.zip
Merge branch 'obsd-master'
-rw-r--r--cmd-if-shell.c1
-rw-r--r--cmd-queue.c56
-rw-r--r--cmd-source-file.c1
-rw-r--r--format.c5
-rw-r--r--screen-write.c100
-rw-r--r--tmux.133
-rw-r--r--tmux.h22
-rw-r--r--window.c39
8 files changed, 146 insertions, 111 deletions
diff --git a/cmd-if-shell.c b/cmd-if-shell.c
index 3e2a5251..2f47a0d7 100644
--- a/cmd-if-shell.c
+++ b/cmd-if-shell.c
@@ -157,6 +157,7 @@ cmd_if_shell_callback(struct job *job)
}
cmdq1 = cmdq_new(cmdq->client);
+ cmdq1->flags |= cmdq->flags & CMD_Q_NOHOOKS;
cmdq1->emptyfn = cmd_if_shell_done;
cmdq1->data = cdata;
diff --git a/cmd-queue.c b/cmd-queue.c
index 1c80c59d..c35d0c62 100644
--- a/cmd-queue.c
+++ b/cmd-queue.c
@@ -186,6 +186,9 @@ static enum cmd_retval
cmdq_continue_one(struct cmd_q *cmdq)
{
struct cmd *cmd = cmdq->cmd;
+ const char *name = cmd->entry->name;
+ struct session *s;
+ struct hooks *hooks;
enum cmd_retval retval;
char *tmp;
int flags = !!(cmd->flags & CMD_CONTROL);
@@ -197,19 +200,51 @@ cmdq_continue_one(struct cmd_q *cmdq)
cmdq->time = time(NULL);
cmdq->number++;
- cmdq_guard(cmdq, "begin", flags);
+ if (~cmdq->flags & CMD_Q_REENTRY)
+ cmdq_guard(cmdq, "begin", flags);
- if (cmd_prepare_state(cmd, cmdq, NULL) != 0)
+ if (cmd_prepare_state(cmd, cmdq, cmdq->parent) != 0)
goto error;
+
+ if (~cmdq->flags & CMD_Q_NOHOOKS) {
+ s = NULL;
+ if (cmdq->state.tflag.s != NULL)
+ s = cmdq->state.tflag.s;
+ else if (cmdq->state.sflag.s != NULL)
+ s = cmdq->state.sflag.s;
+ else if (cmdq->state.c != NULL)
+ s = cmdq->state.c->session;
+ if (s != NULL)
+ hooks = s->hooks;
+ else
+ hooks = global_hooks;
+
+ if (~cmdq->flags & CMD_Q_REENTRY) {
+ cmdq->flags |= CMD_Q_REENTRY;
+ if (hooks_wait(hooks, cmdq, NULL,
+ "before-%s", name) == 0)
+ return (CMD_RETURN_WAIT);
+ if (cmd_prepare_state(cmd, cmdq, cmdq->parent) != 0)
+ goto error;
+ }
+ } else
+ hooks = NULL;
+ cmdq->flags &= ~CMD_Q_REENTRY;
+
retval = cmd->entry->exec(cmd, cmdq);
if (retval == CMD_RETURN_ERROR)
goto error;
+ if (hooks != NULL && hooks_wait(hooks, cmdq, NULL,
+ "after-%s", name) == 0)
+ retval = CMD_RETURN_WAIT;
cmdq_guard(cmdq, "end", flags);
+
return (retval);
error:
cmdq_guard(cmdq, "error", flags);
+ cmdq->flags &= ~CMD_Q_REENTRY;
return (CMD_RETURN_ERROR);
}
@@ -232,11 +267,18 @@ cmdq_continue(struct cmd_q *cmdq)
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);
+ /*
+ * If the command isn't in the middle of running hooks (due to
+ * CMD_RETURN_WAIT), move onto the next command; otherwise, leave the
+ * state of the queue as it is.
+ */
+ if (~cmdq->flags & CMD_Q_REENTRY) {
+ 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) {
diff --git a/cmd-source-file.c b/cmd-source-file.c
index 9d2d6d68..d5f5209a 100644
--- a/cmd-source-file.c
+++ b/cmd-source-file.c
@@ -49,6 +49,7 @@ cmd_source_file_exec(struct cmd *self, struct cmd_q *cmdq)
char *cause;
cmdq1 = cmdq_new(cmdq->client);
+ cmdq1->flags |= cmdq->flags & CMD_Q_NOHOOKS;
cmdq1->emptyfn = cmd_source_file_done;
cmdq1->data = cmdq;
diff --git a/format.c b/format.c
index d263cb0c..e62738d5 100644
--- a/format.c
+++ b/format.c
@@ -485,6 +485,7 @@ 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);
@@ -503,6 +504,10 @@ format_create(struct cmd_q *cmdq, int flags)
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);
+ }
return (ft);
}
diff --git a/screen-write.c b/screen-write.c
index e58d744c..63801dee 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -64,11 +64,15 @@ screen_write_reset(struct screen_write_ctx *ctx)
/* Write character. */
void
-screen_write_putc(struct screen_write_ctx *ctx, struct grid_cell *gc,
+screen_write_putc(struct screen_write_ctx *ctx, const struct grid_cell *gcp,
u_char ch)
{
- utf8_set(&gc->data, ch);
- screen_write_cell(ctx, gc);
+ struct grid_cell gc;
+
+ memcpy(&gc, gcp, sizeof gc);
+
+ utf8_set(&gc.data, ch);
+ screen_write_cell(ctx, &gc);
}
/* Calculate string length, with embedded formatting. */
@@ -148,75 +152,74 @@ screen_write_strlen(const char *fmt, ...)
/* Write simple string (no UTF-8 or maximum length). */
void
-screen_write_puts(struct screen_write_ctx *ctx, struct grid_cell *gc,
+screen_write_puts(struct screen_write_ctx *ctx, const struct grid_cell *gcp,
const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
- screen_write_vnputs(ctx, -1, gc, fmt, ap);
+ screen_write_vnputs(ctx, -1, gcp, fmt, ap);
va_end(ap);
}
/* Write string with length limit (-1 for unlimited). */
void
screen_write_nputs(struct screen_write_ctx *ctx, ssize_t maxlen,
- struct grid_cell *gc, const char *fmt, ...)
+ const struct grid_cell *gcp, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
- screen_write_vnputs(ctx, maxlen, gc, fmt, ap);
+ screen_write_vnputs(ctx, maxlen, gcp, fmt, ap);
va_end(ap);
}
void
screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
- struct grid_cell *gc, const char *fmt, va_list ap)
+ const struct grid_cell *gcp, const char *fmt, va_list ap)
{
+ struct grid_cell gc;
+ struct utf8_data *ud = &gc.data;
char *msg;
- struct utf8_data ud;
u_char *ptr;
size_t left, size = 0;
enum utf8_state more;
+ memcpy(&gc, gcp, sizeof gc);
xvasprintf(&msg, fmt, ap);
ptr = msg;
while (*ptr != '\0') {
- if (*ptr > 0x7f && utf8_open(&ud, *ptr) == UTF8_MORE) {
+ if (*ptr > 0x7f && utf8_open(ud, *ptr) == UTF8_MORE) {
ptr++;
left = strlen(ptr);
- if (left < (size_t)ud.size - 1)
+ if (left < (size_t)ud->size - 1)
break;
- while ((more = utf8_append(&ud, *ptr)) == UTF8_MORE)
+ while ((more = utf8_append(ud, *ptr)) == UTF8_MORE)
ptr++;
ptr++;
- if (more == UTF8_DONE) {
- if (maxlen > 0 &&
- size + ud.width > (size_t) maxlen) {
- while (size < (size_t) maxlen) {
- screen_write_putc(ctx, gc, ' ');
- size++;
- }
- break;
+ if (more != UTF8_DONE)
+ continue;
+ if (maxlen > 0 && size + ud->width > (size_t)maxlen) {
+ while (size < (size_t)maxlen) {
+ screen_write_putc(ctx, &gc, ' ');
+ size++;
}
- size += ud.width;
-
- utf8_copy(&gc->data, &ud);
- screen_write_cell(ctx, gc);
+ break;
}
+ size += ud->width;
+ screen_write_cell(ctx, &gc);
} else {
- if (maxlen > 0 && size + 1 > (size_t) maxlen)
+ if (maxlen > 0 && size + 1 > (size_t)maxlen)
break;
if (*ptr == '\001')
- gc->attr ^= GRID_ATTR_CHARSET;
+ gc.attr ^= GRID_ATTR_CHARSET;
else if (*ptr > 0x1f && *ptr < 0x7f) {
size++;
- screen_write_putc(ctx, gc, *ptr);
+ screen_write_putc(ctx, &gc, *ptr);
}
ptr++;
}
@@ -228,22 +231,22 @@ screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
/* Write string, similar to nputs, but with embedded formatting (#[]). */
void
screen_write_cnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
- struct grid_cell *gc, const char *fmt, ...)
+ const struct grid_cell *gcp, const char *fmt, ...)
{
- struct grid_cell lgc;
- struct utf8_data ud;
+ struct grid_cell gc;
+ struct utf8_data *ud = &gc.data;
va_list ap;
char *msg;
u_char *ptr, *last;
size_t left, size = 0;
enum utf8_state more;
+ memcpy(&gc, gcp, sizeof gc);
+
va_start(ap, fmt);
xvasprintf(&msg, fmt, ap);
va_end(ap);
- memcpy(&lgc, gc, sizeof lgc);
-
ptr = msg;
while (*ptr != '\0') {
if (ptr[0] == '#' && ptr[1] == '[') {
@@ -255,42 +258,39 @@ screen_write_cnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
}
*last = '\0';
- style_parse(gc, &lgc, ptr);
+ style_parse(gcp, &gc, ptr);
ptr = last + 1;
continue;
}
- if (*ptr > 0x7f && utf8_open(&ud, *ptr) == UTF8_MORE) {
+ if (*ptr > 0x7f && utf8_open(ud, *ptr) == UTF8_MORE) {
ptr++;
left = strlen(ptr);
- if (left < (size_t)ud.size - 1)
+ if (left < (size_t)ud->size - 1)
break;
- while ((more = utf8_append(&ud, *ptr)) == UTF8_MORE)
+ while ((more = utf8_append(ud, *ptr)) == UTF8_MORE)
ptr++;
ptr++;
- if (more == UTF8_DONE) {
- if (maxlen > 0 &&
- size + ud.width > (size_t) maxlen) {
- while (size < (size_t) maxlen) {
- screen_write_putc(ctx, gc, ' ');
- size++;
- }
- break;
+ if (more != UTF8_DONE)
+ continue;
+ if (maxlen > 0 && size + ud->width > (size_t)maxlen) {
+ while (size < (size_t)maxlen) {
+ screen_write_putc(ctx, &gc, ' ');
+ size++;
}
- size += ud.width;
-
- utf8_copy(&lgc.data, &ud);
- screen_write_cell(ctx, &lgc);
+ break;
}
+ size += ud->width;
+ screen_write_cell(ctx, &gc);
} else {
- if (maxlen > 0 && size + 1 > (size_t) maxlen)
+ if (maxlen > 0 && size + 1 > (size_t)maxlen)
break;
if (*ptr > 0x1f && *ptr < 0x7f) {
size++;
- screen_write_putc(ctx, &lgc, *ptr);
+ screen_write_putc(ctx, &gc, *ptr);
}
ptr++;
}
diff --git a/tmux.1 b/tmux.1
index b0d5afae..a9be31bf 100644
--- a/tmux.1
+++ b/tmux.1
@@ -3225,9 +3225,35 @@ shows only the option value, not the name.
.Nm
allows commands to run on various triggers, called
.Em hooks .
-Each hook has a
-.Em name .
-The following hooks are available:
+Each
+.Nm
+command has a
+.Em before
+hook and an
+.Em after
+hook and there are a number of hooks not associated with commands.
+.Pp
+A command's before hook is run before the command is executed and its after
+hook is run afterwards, except when the command is run as part of a hook
+itself.
+Before hooks are named using the
+.Ql before-
+prefix and after hooks the
+.Ql after-
+prefix.
+For example, the following command adds a hook to select the even-vertical
+layout after every
+.Ic split-window :
+.Bd -literal -offset indent
+set-hook after-split-window "selectl even-vertical"
+.Ed
+.Pp
+Or to write when each new window is created to a file:
+.Bd -literal -offset indent
+set-hook before-new-window 'run "date >>/tmp/log"'
+.Ed
+.Pp
+In addition, the following hooks are available:
.Bl -tag -width "XXXXXXXXXXXXXXXX"
.It alert-activity
Run when a window has activity.
@@ -3454,6 +3480,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 "cursor_flag" Ta "" Ta "Pane cursor flag"
.It Li "cursor_x" Ta "" Ta "Cursor X position in pane"
diff --git a/tmux.h b/tmux.h
index b0b13f5c..ddf70d4a 100644
--- a/tmux.h
+++ b/tmux.h
@@ -62,15 +62,8 @@ struct tmuxproc;
/* Automatic name refresh interval, in microseconds. Must be < 1 second. */
#define NAME_INTERVAL 500000
-/*
- * READ_SIZE is the maximum size of data to hold from a pty (the event high
- * watermark). READ_BACKOFF is the amount of data waiting to be output to a tty
- * before pty reads will be backed off. READ_TIME is how long to back off
- * before the next read (in microseconds) if a tty is above READ_BACKOFF.
- */
-#define READ_SIZE 1024
-#define READ_BACKOFF 512
-#define READ_TIME 100
+/* The maximum amount of data to hold from a pty (the event high watermark). */
+#define READ_SIZE 128
/* Attribute to make gcc check printf-like arguments. */
#define printflike(a, b) __attribute__ ((format (printf, a, b)))
@@ -891,7 +884,6 @@ struct window_pane {
int fd;
struct bufferevent *event;
- struct event timer;
struct input_ctx *ictx;
@@ -2036,15 +2028,15 @@ void screen_write_stop(struct screen_write_ctx *);
void screen_write_reset(struct screen_write_ctx *);
size_t printflike(1, 2) screen_write_cstrlen(const char *, ...);
void printflike(4, 5) screen_write_cnputs(struct screen_write_ctx *,
- ssize_t, struct grid_cell *, const char *, ...);
+ ssize_t, const struct grid_cell *, const char *, ...);
size_t printflike(1, 2) screen_write_strlen(const char *, ...);
void printflike(3, 4) screen_write_puts(struct screen_write_ctx *,
- struct grid_cell *, const char *, ...);
+ const struct grid_cell *, const char *, ...);
void printflike(4, 5) screen_write_nputs(struct screen_write_ctx *,
- ssize_t, struct grid_cell *, const char *, ...);
+ ssize_t, const struct grid_cell *, const char *, ...);
void screen_write_vnputs(struct screen_write_ctx *, ssize_t,
- struct grid_cell *, const char *, va_list);
-void screen_write_putc(struct screen_write_ctx *, struct grid_cell *,
+ const struct grid_cell *, const char *, va_list);
+void screen_write_putc(struct screen_write_ctx *, const struct grid_cell *,
u_char);
void screen_write_copy(struct screen_write_ctx *, struct screen *, u_int,
u_int, u_int, u_int);
diff --git a/window.c b/window.c
index 236d2436..8e837c5f 100644
--- a/window.c
+++ b/window.c
@@ -777,9 +777,6 @@ window_pane_destroy(struct window_pane *wp)
{
window_pane_reset_mode(wp);
- if (event_initialized(&wp->timer))
- evtimer_del(&wp->timer);
-
if (wp->fd != -1) {
#ifdef HAVE_UTEMPTER
utempter_remove_record(wp->fd);
@@ -932,34 +929,15 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
}
void
-window_pane_timer_callback(__unused int fd, __unused short events, void *data)
-{
- window_pane_read_callback(NULL, data);
-}
-
-void
window_pane_read_callback(__unused struct bufferevent *bufev, void *data)
{
struct window_pane *wp = data;
struct evbuffer *evb = wp->event->input;
char *new_data;
- size_t new_size, available;
- struct client *c;
- struct timeval tv;
-
- if (event_initialized(&wp->timer))
- evtimer_del(&wp->timer);
+ size_t new_size;
- log_debug("%%%u has %zu bytes", wp->id, EVBUFFER_LENGTH(evb));
-
- TAILQ_FOREACH(c, &clients, entry) {
- if (!tty_client_ready(c, wp))
- continue;
-
- available = EVBUFFER_LENGTH(c->tty.event->output);
- if (available > READ_BACKOFF)
- goto start_timer;
- }
+ log_debug("%%%u has %zu bytes (of %zu)", wp->id, EVBUFFER_LENGTH(evb),
+ (size_t)READ_SIZE);
new_size = EVBUFFER_LENGTH(evb) - wp->pipe_off;
if (wp->pipe_fd != -1 && new_size > 0) {
@@ -970,17 +948,6 @@ window_pane_read_callback(__unused struct bufferevent *bufev, void *data)
input_parse(wp);
wp->pipe_off = EVBUFFER_LENGTH(evb);
- return;
-
-start_timer:
- log_debug("%%%u backing off (%s %zu > %d)", wp->id, c->ttyname,
- available, READ_BACKOFF);
-
- tv.tv_sec = 0;
- tv.tv_usec = READ_TIME;
-
- evtimer_set(&wp->timer, window_pane_timer_callback, wp);
- evtimer_add(&wp->timer, &tv);
}
void