mirror of
https://github.com/tmate-io/tmate.git
synced 2025-01-01 19:49:08 +01:00
Merge branch 'master' of github.com:tmux/tmux
This commit is contained in:
commit
8b8a007e8e
8
client.c
8
client.c
@ -352,9 +352,10 @@ client_main(int argc, char **argv, int flags)
|
|||||||
void
|
void
|
||||||
client_send_identify(int flags)
|
client_send_identify(int flags)
|
||||||
{
|
{
|
||||||
const char *s;
|
const char *s;
|
||||||
char **ss;
|
char **ss;
|
||||||
int fd;
|
int fd;
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
client_write_one(MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags);
|
client_write_one(MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags);
|
||||||
|
|
||||||
@ -374,6 +375,9 @@ client_send_identify(int flags)
|
|||||||
fatal("dup failed");
|
fatal("dup failed");
|
||||||
client_write_one(MSG_IDENTIFY_STDIN, fd, NULL, 0);
|
client_write_one(MSG_IDENTIFY_STDIN, fd, NULL, 0);
|
||||||
|
|
||||||
|
pid = getpid();
|
||||||
|
client_write_one(MSG_IDENTIFY_CLIENTPID, -1, &pid, sizeof pid);
|
||||||
|
|
||||||
for (ss = environ; *ss != NULL; ss++)
|
for (ss = environ; *ss != NULL; ss++)
|
||||||
client_write_one(MSG_IDENTIFY_ENVIRON, -1, *ss, strlen(*ss) + 1);
|
client_write_one(MSG_IDENTIFY_ENVIRON, -1, *ss, strlen(*ss) + 1);
|
||||||
|
|
||||||
|
@ -32,8 +32,8 @@ enum cmd_retval cmd_break_pane_exec(struct cmd *, struct cmd_q *);
|
|||||||
|
|
||||||
const struct cmd_entry cmd_break_pane_entry = {
|
const struct cmd_entry cmd_break_pane_entry = {
|
||||||
"break-pane", "breakp",
|
"break-pane", "breakp",
|
||||||
"dPF:t:", 0, 0,
|
"dPF:s:t:", 0, 0,
|
||||||
"[-dP] [-F format] " CMD_TARGET_PANE_USAGE,
|
"[-dP] [-F format] " CMD_SRCDST_PANE_USAGE,
|
||||||
0,
|
0,
|
||||||
cmd_break_pane_exec
|
cmd_break_pane_exec
|
||||||
};
|
};
|
||||||
@ -48,13 +48,19 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
struct window *w;
|
struct window *w;
|
||||||
char *name;
|
char *name;
|
||||||
char *cause;
|
char *cause;
|
||||||
int base_idx;
|
int idx;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
const char *template;
|
const char *template;
|
||||||
char *cp;
|
char *cp;
|
||||||
|
|
||||||
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
|
if ((wl = cmd_find_pane(cmdq, args_get(args, 's'), &s, &wp)) == NULL)
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
|
if ((idx = cmd_find_index(cmdq, args_get(args, 't'), &s)) == -2)
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
if (idx != -1 && winlink_find_by_index(&s->windows, idx) != NULL) {
|
||||||
|
cmdq_error(cmdq, "index %d already in use", idx);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
if (window_count_panes(wl->window) == 1) {
|
if (window_count_panes(wl->window) == 1) {
|
||||||
cmdq_error(cmdq, "can't break with only one pane");
|
cmdq_error(cmdq, "can't break with only one pane");
|
||||||
@ -76,8 +82,9 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
free(name);
|
free(name);
|
||||||
layout_init(w, wp);
|
layout_init(w, wp);
|
||||||
|
|
||||||
base_idx = options_get_number(&s->options, "base-index");
|
if (idx == -1)
|
||||||
wl = session_attach(s, w, -1 - base_idx, &cause); /* can't fail */
|
idx = -1 - options_get_number(&s->options, "base-index");
|
||||||
|
wl = session_attach(s, w, idx, &cause); /* can't fail */
|
||||||
if (!args_has(self->args, 'd'))
|
if (!args_has(self->args, 'd'))
|
||||||
session_select(s, wl->idx);
|
session_select(s, wl->idx);
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ enum cmd_retval join_pane(struct cmd *, struct cmd_q *, int);
|
|||||||
const struct cmd_entry cmd_join_pane_entry = {
|
const struct cmd_entry cmd_join_pane_entry = {
|
||||||
"join-pane", "joinp",
|
"join-pane", "joinp",
|
||||||
"bdhvp:l:s:t:", 0, 0,
|
"bdhvp:l:s:t:", 0, 0,
|
||||||
"[-bdhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]",
|
"[-bdhv] [-p percentage|-l size] " CMD_SRCDST_PANE_USAGE,
|
||||||
0,
|
0,
|
||||||
cmd_join_pane_exec
|
cmd_join_pane_exec
|
||||||
};
|
};
|
||||||
@ -43,7 +43,7 @@ const struct cmd_entry cmd_join_pane_entry = {
|
|||||||
const struct cmd_entry cmd_move_pane_entry = {
|
const struct cmd_entry cmd_move_pane_entry = {
|
||||||
"move-pane", "movep",
|
"move-pane", "movep",
|
||||||
"bdhvp:l:s:t:", 0, 0,
|
"bdhvp:l:s:t:", 0, 0,
|
||||||
"[-bdhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]",
|
"[-bdhv] [-p percentage|-l size] " CMD_SRCDST_PANE_USAGE,
|
||||||
0,
|
0,
|
||||||
cmd_join_pane_exec
|
cmd_join_pane_exec
|
||||||
};
|
};
|
||||||
|
@ -30,7 +30,7 @@ enum cmd_retval cmd_move_window_exec(struct cmd *, struct cmd_q *);
|
|||||||
|
|
||||||
const struct cmd_entry cmd_move_window_entry = {
|
const struct cmd_entry cmd_move_window_entry = {
|
||||||
"move-window", "movew",
|
"move-window", "movew",
|
||||||
"dkrs:t:", 0, 0,
|
"adkrs:t:", 0, 0,
|
||||||
"[-dkr] " CMD_SRCDST_WINDOW_USAGE,
|
"[-dkr] " CMD_SRCDST_WINDOW_USAGE,
|
||||||
0,
|
0,
|
||||||
cmd_move_window_exec
|
cmd_move_window_exec
|
||||||
@ -38,7 +38,7 @@ const struct cmd_entry cmd_move_window_entry = {
|
|||||||
|
|
||||||
const struct cmd_entry cmd_link_window_entry = {
|
const struct cmd_entry cmd_link_window_entry = {
|
||||||
"link-window", "linkw",
|
"link-window", "linkw",
|
||||||
"dks:t:", 0, 0,
|
"adks:t:", 0, 0,
|
||||||
"[-dk] " CMD_SRCDST_WINDOW_USAGE,
|
"[-dk] " CMD_SRCDST_WINDOW_USAGE,
|
||||||
0,
|
0,
|
||||||
cmd_move_window_exec
|
cmd_move_window_exec
|
||||||
@ -72,6 +72,15 @@ cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
kflag = args_has(self->args, 'k');
|
kflag = args_has(self->args, 'k');
|
||||||
dflag = args_has(self->args, 'd');
|
dflag = args_has(self->args, 'd');
|
||||||
sflag = args_has(self->args, 's');
|
sflag = args_has(self->args, 's');
|
||||||
|
|
||||||
|
if (args_has(self->args, 'a')) {
|
||||||
|
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
|
||||||
|
if (s == NULL)
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
if ((idx = winlink_shuffle_up(s, s->curw)) == -1)
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
if (server_link_window(src, wl, dst, idx, kflag, !dflag,
|
if (server_link_window(src, wl, dst, idx, kflag, !dflag,
|
||||||
&cause) != 0) {
|
&cause) != 0) {
|
||||||
cmdq_error(cmdq, "can't link window: %s", cause);
|
cmdq_error(cmdq, "can't link window: %s", cause);
|
||||||
|
@ -51,7 +51,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
const char *cmd, *path, *template;
|
const char *cmd, *path, *template;
|
||||||
char **argv, *cause, *cp;
|
char **argv, *cause, *cp;
|
||||||
int argc, idx, last, detached, cwd, fd = -1;
|
int argc, idx, detached, cwd, fd = -1;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
struct environ_entry *envent;
|
struct environ_entry *envent;
|
||||||
|
|
||||||
@ -59,24 +59,10 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
wl = cmd_find_window(cmdq, args_get(args, 't'), &s);
|
wl = cmd_find_window(cmdq, args_get(args, 't'), &s);
|
||||||
if (wl == NULL)
|
if (wl == NULL)
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
idx = wl->idx + 1;
|
if ((idx = winlink_shuffle_up(s, wl)) == -1) {
|
||||||
|
|
||||||
/* Find the next free index. */
|
|
||||||
for (last = idx; last < INT_MAX; last++) {
|
|
||||||
if (winlink_find_by_index(&s->windows, last) == NULL)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (last == INT_MAX) {
|
|
||||||
cmdq_error(cmdq, "no free window indexes");
|
cmdq_error(cmdq, "no free window indexes");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move everything from last - 1 to idx up a bit. */
|
|
||||||
for (; last > idx; last--) {
|
|
||||||
wl = winlink_find_by_index(&s->windows, last - 1);
|
|
||||||
server_link_window(s, wl, s, last, 0, 0, NULL);
|
|
||||||
server_unlink_window(s, wl);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
idx = cmd_find_index(cmdq, args_get(args, 't'), &s);
|
idx = cmd_find_index(cmdq, args_get(args, 't'), &s);
|
||||||
if (idx == -2)
|
if (idx == -2)
|
||||||
|
50
cmd-queue.c
50
cmd-queue.c
@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
|
enum cmd_retval cmdq_continue_one(struct cmd_q *);
|
||||||
|
|
||||||
/* Create new command queue. */
|
/* Create new command queue. */
|
||||||
struct cmd_q *
|
struct cmd_q *
|
||||||
cmdq_new(struct client *c)
|
cmdq_new(struct client *c)
|
||||||
@ -160,14 +162,39 @@ cmdq_append(struct cmd_q *cmdq, struct cmd_list *cmdlist, struct mouse_event *m)
|
|||||||
item->mouse.valid = 0;
|
item->mouse.valid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Process one command. */
|
||||||
|
enum cmd_retval
|
||||||
|
cmdq_continue_one(struct cmd_q *cmdq)
|
||||||
|
{
|
||||||
|
struct cmd *cmd = cmdq->cmd;
|
||||||
|
enum cmd_retval retval;
|
||||||
|
char tmp[1024];
|
||||||
|
int flags = !!(cmd->flags & CMD_CONTROL);
|
||||||
|
|
||||||
|
cmd_print(cmd, tmp, sizeof tmp);
|
||||||
|
log_debug("cmdq %p: %s", cmdq, tmp);
|
||||||
|
|
||||||
|
cmdq->time = time(NULL);
|
||||||
|
cmdq->number++;
|
||||||
|
|
||||||
|
cmdq_guard(cmdq, "begin", flags);
|
||||||
|
|
||||||
|
retval = cmd->entry->exec(cmd, cmdq);
|
||||||
|
|
||||||
|
if (retval == CMD_RETURN_ERROR)
|
||||||
|
cmdq_guard(cmdq, "error", flags);
|
||||||
|
else
|
||||||
|
cmdq_guard(cmdq, "end", flags);
|
||||||
|
return (retval);
|
||||||
|
}
|
||||||
|
|
||||||
/* Continue processing command queue. Returns 1 if finishes empty. */
|
/* Continue processing command queue. Returns 1 if finishes empty. */
|
||||||
int
|
int
|
||||||
cmdq_continue(struct cmd_q *cmdq)
|
cmdq_continue(struct cmd_q *cmdq)
|
||||||
{
|
{
|
||||||
struct cmd_q_item *next;
|
struct cmd_q_item *next;
|
||||||
enum cmd_retval retval;
|
enum cmd_retval retval;
|
||||||
int empty, flags;
|
int empty;
|
||||||
char s[1024];
|
|
||||||
|
|
||||||
cmdq->references++;
|
cmdq->references++;
|
||||||
notify_disable();
|
notify_disable();
|
||||||
@ -184,23 +211,7 @@ cmdq_continue(struct cmd_q *cmdq)
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
while (cmdq->cmd != NULL) {
|
while (cmdq->cmd != NULL) {
|
||||||
cmd_print(cmdq->cmd, s, sizeof s);
|
retval = cmdq_continue_one(cmdq);
|
||||||
log_debug("cmdq %p: %s (client %d)", cmdq, s,
|
|
||||||
cmdq->client != NULL ? cmdq->client->ibuf.fd : -1);
|
|
||||||
|
|
||||||
cmdq->time = time(NULL);
|
|
||||||
cmdq->number++;
|
|
||||||
|
|
||||||
flags = !!(cmdq->cmd->flags & CMD_CONTROL);
|
|
||||||
cmdq_guard(cmdq, "begin", flags);
|
|
||||||
|
|
||||||
retval = cmdq->cmd->entry->exec(cmdq->cmd, cmdq);
|
|
||||||
|
|
||||||
if (retval == CMD_RETURN_ERROR)
|
|
||||||
cmdq_guard(cmdq, "error", flags);
|
|
||||||
else
|
|
||||||
cmdq_guard(cmdq, "end", flags);
|
|
||||||
|
|
||||||
if (retval == CMD_RETURN_ERROR)
|
if (retval == CMD_RETURN_ERROR)
|
||||||
break;
|
break;
|
||||||
if (retval == CMD_RETURN_WAIT)
|
if (retval == CMD_RETURN_WAIT)
|
||||||
@ -209,7 +220,6 @@ cmdq_continue(struct cmd_q *cmdq)
|
|||||||
cmdq_flush(cmdq);
|
cmdq_flush(cmdq);
|
||||||
goto empty;
|
goto empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdq->cmd = TAILQ_NEXT(cmdq->cmd, qentry);
|
cmdq->cmd = TAILQ_NEXT(cmdq->cmd, qentry);
|
||||||
}
|
}
|
||||||
next = TAILQ_NEXT(cmdq->item, qentry);
|
next = TAILQ_NEXT(cmdq->item, qentry);
|
||||||
|
14
format.c
14
format.c
@ -272,6 +272,7 @@ format_create_status(int status)
|
|||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
format_add(ft, "host_short", "%s", host);
|
format_add(ft, "host_short", "%s", host);
|
||||||
}
|
}
|
||||||
|
format_add(ft, "pid", "%ld", (long) getpid());
|
||||||
|
|
||||||
return (ft);
|
return (ft);
|
||||||
}
|
}
|
||||||
@ -338,7 +339,7 @@ format_find(struct format_tree *ft, const char *key)
|
|||||||
case OPTIONS_STRING:
|
case OPTIONS_STRING:
|
||||||
return (o->str);
|
return (o->str);
|
||||||
case OPTIONS_NUMBER:
|
case OPTIONS_NUMBER:
|
||||||
snprintf(s, sizeof s, "%lld", o->num);
|
xsnprintf(s, sizeof s, "%lld", o->num);
|
||||||
return (s);
|
return (s);
|
||||||
case OPTIONS_STYLE:
|
case OPTIONS_STYLE:
|
||||||
return (style_tostring(&o->style));
|
return (style_tostring(&o->style));
|
||||||
@ -679,7 +680,7 @@ format_defaults_session(struct format_tree *ft, struct session *s)
|
|||||||
RB_FOREACH (wl, winlinks, &s->windows) {
|
RB_FOREACH (wl, winlinks, &s->windows) {
|
||||||
if ((wl->flags & WINLINK_ALERTFLAGS) == 0)
|
if ((wl->flags & WINLINK_ALERTFLAGS) == 0)
|
||||||
continue;
|
continue;
|
||||||
snprintf(tmp, sizeof tmp, "%u", wl->idx);
|
xsnprintf(tmp, sizeof tmp, "%u", wl->idx);
|
||||||
|
|
||||||
if (*alerts != '\0')
|
if (*alerts != '\0')
|
||||||
strlcat(alerts, ",", sizeof alerts);
|
strlcat(alerts, ",", sizeof alerts);
|
||||||
@ -704,6 +705,7 @@ format_defaults_client(struct format_tree *ft, struct client *c)
|
|||||||
if (ft->s == NULL)
|
if (ft->s == NULL)
|
||||||
ft->s = c->session;
|
ft->s = c->session;
|
||||||
|
|
||||||
|
format_add(ft, "client_pid", "%ld", (long) c->pid);
|
||||||
format_add(ft, "client_height", "%u", c->tty.sy);
|
format_add(ft, "client_height", "%u", c->tty.sy);
|
||||||
format_add(ft, "client_width", "%u", c->tty.sx);
|
format_add(ft, "client_width", "%u", c->tty.sx);
|
||||||
if (c->tty.path != NULL)
|
if (c->tty.path != NULL)
|
||||||
@ -748,6 +750,7 @@ void
|
|||||||
format_defaults_window(struct format_tree *ft, struct window *w)
|
format_defaults_window(struct format_tree *ft, struct window *w)
|
||||||
{
|
{
|
||||||
char *layout;
|
char *layout;
|
||||||
|
time_t t;
|
||||||
|
|
||||||
ft->w = w;
|
ft->w = w;
|
||||||
|
|
||||||
@ -756,6 +759,10 @@ format_defaults_window(struct format_tree *ft, struct window *w)
|
|||||||
else
|
else
|
||||||
layout = layout_dump(w->layout_root);
|
layout = layout_dump(w->layout_root);
|
||||||
|
|
||||||
|
t = w->activity_time.tv_sec;
|
||||||
|
format_add(ft, "window_activity", "%lld", (long long) t);
|
||||||
|
format_add(ft, "window_activity_string", "%s", format_time_string(t));
|
||||||
|
|
||||||
format_add(ft, "window_id", "@%u", w->id);
|
format_add(ft, "window_id", "@%u", w->id);
|
||||||
format_add(ft, "window_name", "%s", w->name);
|
format_add(ft, "window_name", "%s", w->name);
|
||||||
format_add(ft, "window_width", "%u", w->sx);
|
format_add(ft, "window_width", "%u", w->sx);
|
||||||
@ -873,8 +880,7 @@ format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
|
|||||||
format_add(ft, "pane_synchronized", "%d",
|
format_add(ft, "pane_synchronized", "%d",
|
||||||
!!options_get_number(&wp->window->options, "synchronize-panes"));
|
!!options_get_number(&wp->window->options, "synchronize-panes"));
|
||||||
|
|
||||||
if (wp->tty != NULL)
|
format_add(ft, "pane_tty", "%s", wp->tty);
|
||||||
format_add(ft, "pane_tty", "%s", wp->tty);
|
|
||||||
format_add(ft, "pane_pid", "%ld", (long) wp->pid);
|
format_add(ft, "pane_pid", "%ld", (long) wp->pid);
|
||||||
if ((cwd = osdep_get_cwd(wp->fd)) != NULL)
|
if ((cwd = osdep_get_cwd(wp->fd)) != NULL)
|
||||||
format_add(ft, "pane_current_path", "%s", cwd);
|
format_add(ft, "pane_current_path", "%s", cwd);
|
||||||
|
4
input.c
4
input.c
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
@ -849,6 +850,9 @@ input_parse(struct window_pane *wp)
|
|||||||
wp->window->flags |= WINDOW_ACTIVITY;
|
wp->window->flags |= WINDOW_ACTIVITY;
|
||||||
wp->window->flags &= ~WINDOW_SILENCE;
|
wp->window->flags &= ~WINDOW_SILENCE;
|
||||||
|
|
||||||
|
if (gettimeofday(&wp->window->activity_time, NULL) != 0)
|
||||||
|
fatal("gettimeofday failed");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open the screen. Use NULL wp if there is a mode set as don't want to
|
* Open the screen. Use NULL wp if there is a mode set as don't want to
|
||||||
* update the tty.
|
* update the tty.
|
||||||
|
13
job.c
13
job.c
@ -99,6 +99,8 @@ job_run(const char *cmd, struct session *s, int cwd,
|
|||||||
close(out[1]);
|
close(out[1]);
|
||||||
|
|
||||||
job = xmalloc(sizeof *job);
|
job = xmalloc(sizeof *job);
|
||||||
|
job->state = JOB_RUNNING;
|
||||||
|
|
||||||
job->cmd = xstrdup(cmd);
|
job->cmd = xstrdup(cmd);
|
||||||
job->pid = pid;
|
job->pid = pid;
|
||||||
job->status = 0;
|
job->status = 0;
|
||||||
@ -166,14 +168,13 @@ job_callback(unused struct bufferevent *bufev, unused short events, void *data)
|
|||||||
|
|
||||||
log_debug("job error %p: %s, pid %ld", job, job->cmd, (long) job->pid);
|
log_debug("job error %p: %s, pid %ld", job, job->cmd, (long) job->pid);
|
||||||
|
|
||||||
if (job->pid == -1) {
|
if (job->state == JOB_DEAD) {
|
||||||
if (job->callbackfn != NULL)
|
if (job->callbackfn != NULL)
|
||||||
job->callbackfn(job);
|
job->callbackfn(job);
|
||||||
job_free(job);
|
job_free(job);
|
||||||
} else {
|
} else {
|
||||||
bufferevent_disable(job->event, EV_READ);
|
bufferevent_disable(job->event, EV_READ);
|
||||||
close(job->fd);
|
job->state = JOB_CLOSED;
|
||||||
job->fd = -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,10 +186,12 @@ job_died(struct job *job, int status)
|
|||||||
|
|
||||||
job->status = status;
|
job->status = status;
|
||||||
|
|
||||||
if (job->fd == -1) {
|
if (job->state == JOB_CLOSED) {
|
||||||
if (job->callbackfn != NULL)
|
if (job->callbackfn != NULL)
|
||||||
job->callbackfn(job);
|
job->callbackfn(job);
|
||||||
job_free(job);
|
job_free(job);
|
||||||
} else
|
} else {
|
||||||
job->pid = -1;
|
job->pid = -1;
|
||||||
|
job->state = JOB_DEAD;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1053,6 +1053,7 @@ server_client_msg_dispatch(struct client *c)
|
|||||||
case MSG_IDENTIFY_CWD:
|
case MSG_IDENTIFY_CWD:
|
||||||
case MSG_IDENTIFY_STDIN:
|
case MSG_IDENTIFY_STDIN:
|
||||||
case MSG_IDENTIFY_ENVIRON:
|
case MSG_IDENTIFY_ENVIRON:
|
||||||
|
case MSG_IDENTIFY_CLIENTPID:
|
||||||
case MSG_IDENTIFY_DONE:
|
case MSG_IDENTIFY_DONE:
|
||||||
server_client_msg_identify(c, &imsg);
|
server_client_msg_identify(c, &imsg);
|
||||||
break;
|
break;
|
||||||
@ -1227,6 +1228,11 @@ server_client_msg_identify(struct client *c, struct imsg *imsg)
|
|||||||
if (strchr(data, '=') != NULL)
|
if (strchr(data, '=') != NULL)
|
||||||
environ_put(&c->environ, data);
|
environ_put(&c->environ, data);
|
||||||
break;
|
break;
|
||||||
|
case MSG_IDENTIFY_CLIENTPID:
|
||||||
|
if (datalen != sizeof c->pid)
|
||||||
|
fatalx("bad MSG_IDENTIFY_CLIENTPID size");
|
||||||
|
memcpy(&c->pid, data, sizeof c->pid);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
25
tmux.1
25
tmux.1
@ -408,14 +408,15 @@ An
|
|||||||
pattern which is matched against the session name.
|
pattern which is matched against the session name.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
If the session name is prefixed with a
|
If the session name is prefixed with an
|
||||||
.Ql = : ,
|
.Ql = ,
|
||||||
only an exact match is accepted (so
|
only an exact match is accepted (so
|
||||||
.Ql =mysess
|
.Ql =mysess
|
||||||
will only match exactly
|
will only match exactly
|
||||||
.Ql mysess ,
|
.Ql mysess ,
|
||||||
not
|
not
|
||||||
.Ql mysession ) .
|
.Ql mysession ) .
|
||||||
|
.Pp
|
||||||
If a single session is found, it is used as the target session; multiple matches
|
If a single session is found, it is used as the target session; multiple matches
|
||||||
produce an error.
|
produce an error.
|
||||||
If a session is omitted, the current session is used if available; if no
|
If a session is omitted, the current session is used if available; if no
|
||||||
@ -1237,12 +1238,14 @@ Commands related to windows and panes are as follows:
|
|||||||
.It Xo Ic break-pane
|
.It Xo Ic break-pane
|
||||||
.Op Fl dP
|
.Op Fl dP
|
||||||
.Op Fl F Ar format
|
.Op Fl F Ar format
|
||||||
.Op Fl t Ar target-pane
|
.Op Fl s Ar src-pane
|
||||||
|
.Op Fl t Ar dst-pane
|
||||||
.Xc
|
.Xc
|
||||||
.D1 (alias: Ic breakp )
|
.D1 (alias: Ic breakp )
|
||||||
Break
|
Break
|
||||||
.Ar target-pane
|
.Ar src-pane
|
||||||
off from its containing window to make it the only pane in a new window.
|
off from its containing window to make it the only pane in
|
||||||
|
.Ar dst-window .
|
||||||
If
|
If
|
||||||
.Fl d
|
.Fl d
|
||||||
is given, the new window does not become the current window.
|
is given, the new window does not become the current window.
|
||||||
@ -1548,7 +1551,7 @@ If no
|
|||||||
.Ar target-session
|
.Ar target-session
|
||||||
is specified, select the last window of the current session.
|
is specified, select the last window of the current session.
|
||||||
.It Xo Ic link-window
|
.It Xo Ic link-window
|
||||||
.Op Fl dk
|
.Op Fl adk
|
||||||
.Op Fl s Ar src-window
|
.Op Fl s Ar src-window
|
||||||
.Op Fl t Ar dst-window
|
.Op Fl t Ar dst-window
|
||||||
.Xc
|
.Xc
|
||||||
@ -1562,6 +1565,10 @@ If
|
|||||||
is specified and no such window exists, the
|
is specified and no such window exists, the
|
||||||
.Ar src-window
|
.Ar src-window
|
||||||
is linked there.
|
is linked there.
|
||||||
|
With
|
||||||
|
.Fl a ,
|
||||||
|
the window is moved to the next index up (following windows
|
||||||
|
are moved if necessary).
|
||||||
If
|
If
|
||||||
.Fl k
|
.Fl k
|
||||||
is given and
|
is given and
|
||||||
@ -1627,7 +1634,7 @@ and
|
|||||||
.Ar dst-pane
|
.Ar dst-pane
|
||||||
may belong to the same window.
|
may belong to the same window.
|
||||||
.It Xo Ic move-window
|
.It Xo Ic move-window
|
||||||
.Op Fl rdk
|
.Op Fl ardk
|
||||||
.Op Fl s Ar src-window
|
.Op Fl s Ar src-window
|
||||||
.Op Fl t Ar dst-window
|
.Op Fl t Ar dst-window
|
||||||
.Xc
|
.Xc
|
||||||
@ -3357,6 +3364,7 @@ The following variables are available, where appropriate:
|
|||||||
.It Li "client_created_string" Ta "" Ta "String time client created"
|
.It Li "client_created_string" Ta "" Ta "String time client created"
|
||||||
.It Li "client_height" Ta "" Ta "Height of client"
|
.It Li "client_height" Ta "" Ta "Height of client"
|
||||||
.It Li "client_last_session" Ta "" Ta "Name of the client's last session"
|
.It Li "client_last_session" Ta "" Ta "Name of the client's last session"
|
||||||
|
.It Li "client_pid" Ta "" Ta "PID of client process"
|
||||||
.It Li "client_prefix" Ta "" Ta "1 if prefix key has been pressed"
|
.It Li "client_prefix" Ta "" Ta "1 if prefix key has been pressed"
|
||||||
.It Li "client_readonly" Ta "" Ta "1 if client is readonly"
|
.It Li "client_readonly" Ta "" Ta "1 if client is readonly"
|
||||||
.It Li "client_session" Ta "" Ta "Name of the client's session"
|
.It Li "client_session" Ta "" Ta "Name of the client's session"
|
||||||
@ -3401,6 +3409,7 @@ The following variables are available, where appropriate:
|
|||||||
.It Li "pane_top" Ta "" Ta "Top of pane"
|
.It Li "pane_top" Ta "" Ta "Top of pane"
|
||||||
.It Li "pane_tty" Ta "" Ta "Pseudo terminal of pane"
|
.It Li "pane_tty" Ta "" Ta "Pseudo terminal of pane"
|
||||||
.It Li "pane_width" Ta "" Ta "Width of pane"
|
.It Li "pane_width" Ta "" Ta "Width of pane"
|
||||||
|
.It Li "pid" Ta "" Ta "Server PID"
|
||||||
.It Li "scroll_region_lower" Ta "" Ta "Bottom of scroll region in pane"
|
.It Li "scroll_region_lower" Ta "" Ta "Bottom of scroll region in pane"
|
||||||
.It Li "scroll_region_upper" Ta "" Ta "Top of scroll region in pane"
|
.It Li "scroll_region_upper" Ta "" Ta "Top of scroll region in pane"
|
||||||
.It Li "session_alerts" Ta "" Ta "List of window indexes with alerts"
|
.It Li "session_alerts" Ta "" Ta "List of window indexes with alerts"
|
||||||
@ -3417,6 +3426,8 @@ The following variables are available, where appropriate:
|
|||||||
.It Li "session_name" Ta "#S" Ta "Name of session"
|
.It Li "session_name" Ta "#S" Ta "Name of session"
|
||||||
.It Li "session_width" Ta "" Ta "Width of session"
|
.It Li "session_width" Ta "" Ta "Width of session"
|
||||||
.It Li "session_windows" Ta "" Ta "Number of windows in session"
|
.It Li "session_windows" Ta "" Ta "Number of windows in session"
|
||||||
|
.It Li "window_activity" Ta "" Ta "Integer time of window last activity"
|
||||||
|
.It Li "window_activity_string" Ta "" Ta "String time of window last activity"
|
||||||
.It Li "window_active" Ta "" Ta "1 if window active"
|
.It Li "window_active" Ta "" Ta "1 if window active"
|
||||||
.It Li "window_activity_flag" Ta "" Ta "1 if window has activity alert"
|
.It Li "window_activity_flag" Ta "" Ta "1 if window has activity alert"
|
||||||
.It Li "window_bell_flag" Ta "" Ta "1 if window has bell"
|
.It Li "window_bell_flag" Ta "" Ta "1 if window has bell"
|
||||||
|
10
tmux.h
10
tmux.h
@ -429,6 +429,7 @@ enum msgtype {
|
|||||||
MSG_IDENTIFY_STDIN,
|
MSG_IDENTIFY_STDIN,
|
||||||
MSG_IDENTIFY_ENVIRON,
|
MSG_IDENTIFY_ENVIRON,
|
||||||
MSG_IDENTIFY_DONE,
|
MSG_IDENTIFY_DONE,
|
||||||
|
MSG_IDENTIFY_CLIENTPID,
|
||||||
|
|
||||||
MSG_COMMAND = 200,
|
MSG_COMMAND = 200,
|
||||||
MSG_DETACH,
|
MSG_DETACH,
|
||||||
@ -717,6 +718,12 @@ struct options {
|
|||||||
|
|
||||||
/* Scheduled job. */
|
/* Scheduled job. */
|
||||||
struct job {
|
struct job {
|
||||||
|
enum {
|
||||||
|
JOB_RUNNING,
|
||||||
|
JOB_DEAD,
|
||||||
|
JOB_CLOSED
|
||||||
|
} state;
|
||||||
|
|
||||||
char *cmd;
|
char *cmd;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int status;
|
int status;
|
||||||
@ -895,6 +902,7 @@ struct window {
|
|||||||
char *name;
|
char *name;
|
||||||
struct event name_timer;
|
struct event name_timer;
|
||||||
struct timeval silence_timer;
|
struct timeval silence_timer;
|
||||||
|
struct timeval activity_time;
|
||||||
|
|
||||||
struct window_pane *active;
|
struct window_pane *active;
|
||||||
struct window_pane *last;
|
struct window_pane *last;
|
||||||
@ -1210,6 +1218,7 @@ RB_HEAD(status_out_tree, status_out);
|
|||||||
struct client {
|
struct client {
|
||||||
struct imsgbuf ibuf;
|
struct imsgbuf ibuf;
|
||||||
|
|
||||||
|
pid_t pid;
|
||||||
int fd;
|
int fd;
|
||||||
struct event event;
|
struct event event;
|
||||||
int retval;
|
int retval;
|
||||||
@ -2161,6 +2170,7 @@ struct window_pane *window_pane_find_right(struct window_pane *);
|
|||||||
void window_set_name(struct window *, const char *);
|
void window_set_name(struct window *, const char *);
|
||||||
void window_remove_ref(struct window *);
|
void window_remove_ref(struct window *);
|
||||||
void winlink_clear_flags(struct winlink *);
|
void winlink_clear_flags(struct winlink *);
|
||||||
|
int winlink_shuffle_up(struct session *, struct winlink *);
|
||||||
|
|
||||||
/* layout.c */
|
/* layout.c */
|
||||||
u_int layout_count_cells(struct layout_cell *);
|
u_int layout_count_cells(struct layout_cell *);
|
||||||
|
28
window.c
28
window.c
@ -294,6 +294,9 @@ window_create1(u_int sx, u_int sy)
|
|||||||
w->sx = sx;
|
w->sx = sx;
|
||||||
w->sy = sy;
|
w->sy = sy;
|
||||||
|
|
||||||
|
if (gettimeofday(&w->activity_time, NULL) != 0)
|
||||||
|
fatal("gettimeofday failed");
|
||||||
|
|
||||||
options_init(&w->options, &global_w_options);
|
options_init(&w->options, &global_w_options);
|
||||||
if (options_get_number(&w->options, "automatic-rename"))
|
if (options_get_number(&w->options, "automatic-rename"))
|
||||||
queue_window_name(w);
|
queue_window_name(w);
|
||||||
@ -1389,3 +1392,28 @@ winlink_clear_flags(struct winlink *wl)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
winlink_shuffle_up(struct session *s, struct winlink *wl)
|
||||||
|
{
|
||||||
|
int idx, last;
|
||||||
|
|
||||||
|
idx = wl->idx + 1;
|
||||||
|
|
||||||
|
/* Find the next free index. */
|
||||||
|
for (last = idx; last < INT_MAX; last++) {
|
||||||
|
if (winlink_find_by_index(&s->windows, last) == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (last == INT_MAX)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
/* Move everything from last - 1 to idx up a bit. */
|
||||||
|
for (; last > idx; last--) {
|
||||||
|
wl = winlink_find_by_index(&s->windows, last - 1);
|
||||||
|
server_link_window(s, wl, s, last, 0, 0, NULL);
|
||||||
|
server_unlink_window(s, wl);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (idx);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user