aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Marriott <nicholas.marriott@gmail.com>2015-06-20 08:45:19 +0100
committerNicholas Marriott <nicholas.marriott@gmail.com>2015-06-20 08:45:19 +0100
commit8b8a007e8e1faa6af20acdeac728c4fddfeb2f6b (patch)
tree10612c9842dbdb0749e0840cf057ca4a08a84948
parent8abcea18a24dea24d6049fefa31c877133489092 (diff)
parent0ef3e28609ba89f53bedf40f5facc990cc57e60d (diff)
downloadrtmux-8b8a007e8e1faa6af20acdeac728c4fddfeb2f6b.tar.gz
rtmux-8b8a007e8e1faa6af20acdeac728c4fddfeb2f6b.tar.bz2
rtmux-8b8a007e8e1faa6af20acdeac728c4fddfeb2f6b.zip
Merge branch 'master' of github.com:tmux/tmux
-rw-r--r--client.c8
-rw-r--r--cmd-break-pane.c19
-rw-r--r--cmd-join-pane.c4
-rw-r--r--cmd-move-window.c13
-rw-r--r--cmd-new-window.c18
-rw-r--r--cmd-queue.c50
-rw-r--r--format.c14
-rw-r--r--input.c4
-rw-r--r--job.c13
-rw-r--r--server-client.c6
-rw-r--r--tmux.125
-rw-r--r--tmux.h10
-rw-r--r--window.c28
13 files changed, 148 insertions, 64 deletions
diff --git a/client.c b/client.c
index 7d997a7e..9c493dfa 100644
--- a/client.c
+++ b/client.c
@@ -352,9 +352,10 @@ client_main(int argc, char **argv, int flags)
void
client_send_identify(int flags)
{
- const char *s;
+ const char *s;
char **ss;
- int fd;
+ int fd;
+ pid_t pid;
client_write_one(MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags);
@@ -374,6 +375,9 @@ client_send_identify(int flags)
fatal("dup failed");
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++)
client_write_one(MSG_IDENTIFY_ENVIRON, -1, *ss, strlen(*ss) + 1);
diff --git a/cmd-break-pane.c b/cmd-break-pane.c
index a1da0a3a..c7af7865 100644
--- a/cmd-break-pane.c
+++ b/cmd-break-pane.c
@@ -32,8 +32,8 @@ enum cmd_retval cmd_break_pane_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_break_pane_entry = {
"break-pane", "breakp",
- "dPF:t:", 0, 0,
- "[-dP] [-F format] " CMD_TARGET_PANE_USAGE,
+ "dPF:s:t:", 0, 0,
+ "[-dP] [-F format] " CMD_SRCDST_PANE_USAGE,
0,
cmd_break_pane_exec
};
@@ -48,13 +48,19 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq)
struct window *w;
char *name;
char *cause;
- int base_idx;
+ int idx;
struct format_tree *ft;
const char *template;
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);
+ 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) {
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);
layout_init(w, wp);
- base_idx = options_get_number(&s->options, "base-index");
- wl = session_attach(s, w, -1 - base_idx, &cause); /* can't fail */
+ if (idx == -1)
+ 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'))
session_select(s, wl->idx);
diff --git a/cmd-join-pane.c b/cmd-join-pane.c
index 3d2a04b2..c384631c 100644
--- a/cmd-join-pane.c
+++ b/cmd-join-pane.c
@@ -35,7 +35,7 @@ enum cmd_retval join_pane(struct cmd *, struct cmd_q *, int);
const struct cmd_entry cmd_join_pane_entry = {
"join-pane", "joinp",
"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,
cmd_join_pane_exec
};
@@ -43,7 +43,7 @@ const struct cmd_entry cmd_join_pane_entry = {
const struct cmd_entry cmd_move_pane_entry = {
"move-pane", "movep",
"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,
cmd_join_pane_exec
};
diff --git a/cmd-move-window.c b/cmd-move-window.c
index e765b625..b15df4f6 100644
--- a/cmd-move-window.c
+++ b/cmd-move-window.c
@@ -30,7 +30,7 @@ enum cmd_retval cmd_move_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_move_window_entry = {
"move-window", "movew",
- "dkrs:t:", 0, 0,
+ "adkrs:t:", 0, 0,
"[-dkr] " CMD_SRCDST_WINDOW_USAGE,
0,
cmd_move_window_exec
@@ -38,7 +38,7 @@ const struct cmd_entry cmd_move_window_entry = {
const struct cmd_entry cmd_link_window_entry = {
"link-window", "linkw",
- "dks:t:", 0, 0,
+ "adks:t:", 0, 0,
"[-dk] " CMD_SRCDST_WINDOW_USAGE,
0,
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');
dflag = args_has(self->args, 'd');
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,
&cause) != 0) {
cmdq_error(cmdq, "can't link window: %s", cause);
diff --git a/cmd-new-window.c b/cmd-new-window.c
index c05a0ce8..9cead449 100644
--- a/cmd-new-window.c
+++ b/cmd-new-window.c
@@ -51,7 +51,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
struct winlink *wl;
const char *cmd, *path, *template;
char **argv, *cause, *cp;
- int argc, idx, last, detached, cwd, fd = -1;
+ int argc, idx, detached, cwd, fd = -1;
struct format_tree *ft;
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);
if (wl == NULL)
return (CMD_RETURN_ERROR);
- 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) {
+ if ((idx = winlink_shuffle_up(s, wl)) == -1) {
cmdq_error(cmdq, "no free window indexes");
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 {
idx = cmd_find_index(cmdq, args_get(args, 't'), &s);
if (idx == -2)
diff --git a/cmd-queue.c b/cmd-queue.c
index 61b14147..af987f59 100644
--- a/cmd-queue.c
+++ b/cmd-queue.c
@@ -25,6 +25,8 @@
#include "tmux.h"
+enum cmd_retval cmdq_continue_one(struct cmd_q *);
+
/* Create new command queue. */
struct cmd_q *
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;
}
+/* 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. */
int
cmdq_continue(struct cmd_q *cmdq)
{
struct cmd_q_item *next;
enum cmd_retval retval;
- int empty, flags;
- char s[1024];
+ int empty;
cmdq->references++;
notify_disable();
@@ -184,23 +211,7 @@ cmdq_continue(struct cmd_q *cmdq)
do {
while (cmdq->cmd != NULL) {
- cmd_print(cmdq->cmd, s, sizeof s);
- 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);
-
+ retval = cmdq_continue_one(cmdq);
if (retval == CMD_RETURN_ERROR)
break;
if (retval == CMD_RETURN_WAIT)
@@ -209,7 +220,6 @@ cmdq_continue(struct cmd_q *cmdq)
cmdq_flush(cmdq);
goto empty;
}
-
cmdq->cmd = TAILQ_NEXT(cmdq->cmd, qentry);
}
next = TAILQ_NEXT(cmdq->item, qentry);
diff --git a/format.c b/format.c
index 6eeb028e..59ef598c 100644
--- a/format.c
+++ b/format.c
@@ -272,6 +272,7 @@ format_create_status(int status)
*ptr = '\0';
format_add(ft, "host_short", "%s", host);
}
+ format_add(ft, "pid", "%ld", (long) getpid());
return (ft);
}
@@ -338,7 +339,7 @@ format_find(struct format_tree *ft, const char *key)
case OPTIONS_STRING:
return (o->str);
case OPTIONS_NUMBER:
- snprintf(s, sizeof s, "%lld", o->num);
+ xsnprintf(s, sizeof s, "%lld", o->num);
return (s);
case OPTIONS_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) {
if ((wl->flags & WINLINK_ALERTFLAGS) == 0)
continue;
- snprintf(tmp, sizeof tmp, "%u", wl->idx);
+ xsnprintf(tmp, sizeof tmp, "%u", wl->idx);
if (*alerts != '\0')
strlcat(alerts, ",", sizeof alerts);
@@ -704,6 +705,7 @@ format_defaults_client(struct format_tree *ft, struct client *c)
if (ft->s == NULL)
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_width", "%u", c->tty.sx);
if (c->tty.path != NULL)
@@ -748,6 +750,7 @@ void
format_defaults_window(struct format_tree *ft, struct window *w)
{
char *layout;
+ time_t t;
ft->w = w;
@@ -756,6 +759,10 @@ format_defaults_window(struct format_tree *ft, struct window *w)
else
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_name", "%s", w->name);
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",
!!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);
if ((cwd = osdep_get_cwd(wp->fd)) != NULL)
format_add(ft, "pane_current_path", "%s", cwd);
diff --git a/input.c b/input.c
index 7a371c62..d1ff17fe 100644
--- a/input.c
+++ b/input.c
@@ -20,6 +20,7 @@
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include "tmux.h"
@@ -849,6 +850,9 @@ input_parse(struct window_pane *wp)
wp->window->flags |= WINDOW_ACTIVITY;
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
* update the tty.
diff --git a/job.c b/job.c
index 74b316ed..ff21b3b6 100644
--- a/job.c
+++ b/job.c
@@ -99,6 +99,8 @@ job_run(const char *cmd, struct session *s, int cwd,
close(out[1]);
job = xmalloc(sizeof *job);
+ job->state = JOB_RUNNING;
+
job->cmd = xstrdup(cmd);
job->pid = pid;
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);
- if (job->pid == -1) {
+ if (job->state == JOB_DEAD) {
if (job->callbackfn != NULL)
job->callbackfn(job);
job_free(job);
} else {
bufferevent_disable(job->event, EV_READ);
- close(job->fd);
- job->fd = -1;
+ job->state = JOB_CLOSED;
}
}
@@ -185,10 +186,12 @@ job_died(struct job *job, int status)
job->status = status;
- if (job->fd == -1) {
+ if (job->state == JOB_CLOSED) {
if (job->callbackfn != NULL)
job->callbackfn(job);
job_free(job);
- } else
+ } else {
job->pid = -1;
+ job->state = JOB_DEAD;
+ }
}
diff --git a/server-client.c b/server-client.c
index 27efc57d..c9c0c3ef 100644
--- a/server-client.c
+++ b/server-client.c
@@ -1053,6 +1053,7 @@ server_client_msg_dispatch(struct client *c)
case MSG_IDENTIFY_CWD:
case MSG_IDENTIFY_STDIN:
case MSG_IDENTIFY_ENVIRON:
+ case MSG_IDENTIFY_CLIENTPID:
case MSG_IDENTIFY_DONE:
server_client_msg_identify(c, &imsg);
break;
@@ -1227,6 +1228,11 @@ server_client_msg_identify(struct client *c, struct imsg *imsg)
if (strchr(data, '=') != NULL)
environ_put(&c->environ, data);
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:
break;
}
diff --git a/tmux.1 b/tmux.1
index f3eeabcc..20754551 100644
--- a/tmux.1
+++ b/tmux.1
@@ -408,14 +408,15 @@ An
pattern which is matched against the session name.
.El
.Pp
-If the session name is prefixed with a
-.Ql = : ,
+If the session name is prefixed with an
+.Ql = ,
only an exact match is accepted (so
.Ql =mysess
will only match exactly
.Ql mysess ,
not
.Ql mysession ) .
+.Pp
If a single session is found, it is used as the target session; multiple matches
produce an error.
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
.Op Fl dP
.Op Fl F Ar format
-.Op Fl t Ar target-pane
+.Op Fl s Ar src-pane
+.Op Fl t Ar dst-pane
.Xc
.D1 (alias: Ic breakp )
Break
-.Ar target-pane
-off from its containing window to make it the only pane in a new window.
+.Ar src-pane
+off from its containing window to make it the only pane in
+.Ar dst-window .
If
.Fl d
is given, the new window does not become the current window.
@@ -1548,7 +1551,7 @@ If no
.Ar target-session
is specified, select the last window of the current session.
.It Xo Ic link-window
-.Op Fl dk
+.Op Fl adk
.Op Fl s Ar src-window
.Op Fl t Ar dst-window
.Xc
@@ -1562,6 +1565,10 @@ If
is specified and no such window exists, the
.Ar src-window
is linked there.
+With
+.Fl a ,
+the window is moved to the next index up (following windows
+are moved if necessary).
If
.Fl k
is given and
@@ -1627,7 +1634,7 @@ and
.Ar dst-pane
may belong to the same window.
.It Xo Ic move-window
-.Op Fl rdk
+.Op Fl ardk
.Op Fl s Ar src-window
.Op Fl t Ar dst-window
.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_height" Ta "" Ta "Height of client"
.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_readonly" Ta "" Ta "1 if client is readonly"
.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_tty" Ta "" Ta "Pseudo terminal 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_upper" Ta "" Ta "Top of scroll region in pane"
.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_width" Ta "" Ta "Width of 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_activity_flag" Ta "" Ta "1 if window has activity alert"
.It Li "window_bell_flag" Ta "" Ta "1 if window has bell"
diff --git a/tmux.h b/tmux.h
index 210826ad..f0fef0d5 100644
--- a/tmux.h
+++ b/tmux.h
@@ -429,6 +429,7 @@ enum msgtype {
MSG_IDENTIFY_STDIN,
MSG_IDENTIFY_ENVIRON,
MSG_IDENTIFY_DONE,
+ MSG_IDENTIFY_CLIENTPID,
MSG_COMMAND = 200,
MSG_DETACH,
@@ -717,6 +718,12 @@ struct options {
/* Scheduled job. */
struct job {
+ enum {
+ JOB_RUNNING,
+ JOB_DEAD,
+ JOB_CLOSED
+ } state;
+
char *cmd;
pid_t pid;
int status;
@@ -895,6 +902,7 @@ struct window {
char *name;
struct event name_timer;
struct timeval silence_timer;
+ struct timeval activity_time;
struct window_pane *active;
struct window_pane *last;
@@ -1210,6 +1218,7 @@ RB_HEAD(status_out_tree, status_out);
struct client {
struct imsgbuf ibuf;
+ pid_t pid;
int fd;
struct event event;
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_remove_ref(struct window *);
void winlink_clear_flags(struct winlink *);
+int winlink_shuffle_up(struct session *, struct winlink *);
/* layout.c */
u_int layout_count_cells(struct layout_cell *);
diff --git a/window.c b/window.c
index 721d0213..fab9949e 100644
--- a/window.c
+++ b/window.c
@@ -294,6 +294,9 @@ window_create1(u_int sx, u_int sy)
w->sx = sx;
w->sy = sy;
+ if (gettimeofday(&w->activity_time, NULL) != 0)
+ fatal("gettimeofday failed");
+
options_init(&w->options, &global_w_options);
if (options_get_number(&w->options, "automatic-rename"))
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);
+}