mirror of
https://github.com/tmux/tmux.git
synced 2024-11-05 02:18:47 +00:00
Merge branch 'master' of ssh://git.code.sf.net/p/tmux/tmux-code
This commit is contained in:
commit
f5de847a0c
1
client.c
1
client.c
@ -524,6 +524,7 @@ client_dispatch_wait(void *data)
|
||||
|
||||
event_del(&client_stdin);
|
||||
client_attached = 1;
|
||||
client_write_server(MSG_RESIZE, NULL, 0);
|
||||
break;
|
||||
case MSG_STDIN:
|
||||
if (datalen != 0)
|
||||
|
@ -70,6 +70,18 @@ cmd_display_message_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
if (args_has(args, 'c')) {
|
||||
c = cmd_find_client(cmdq, args_get(args, 'c'), 0);
|
||||
if (c == NULL)
|
||||
return (CMD_RETURN_ERROR);
|
||||
} else {
|
||||
c = cmd_current_client(cmdq);
|
||||
if (c == NULL && !args_has(self->args, 'p')) {
|
||||
cmdq_error(cmdq, "no client available");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
template = args_get(args, 'F');
|
||||
if (args->argc != 0)
|
||||
template = args->argv[0];
|
||||
@ -77,7 +89,7 @@ cmd_display_message_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
template = DISPLAY_MESSAGE_TEMPLATE;
|
||||
|
||||
ft = format_create();
|
||||
if ((c = cmd_find_client(cmdq, args_get(args, 'c'), 1)) != NULL)
|
||||
if (c != NULL)
|
||||
format_client(ft, c);
|
||||
format_session(ft, s);
|
||||
format_winlink(ft, s, wl);
|
||||
|
21
cmd-queue.c
21
cmd-queue.c
@ -152,19 +152,20 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
|
||||
}
|
||||
|
||||
/* Print a guard line. */
|
||||
void
|
||||
int
|
||||
cmdq_guard(struct cmd_q *cmdq, const char *guard)
|
||||
{
|
||||
struct client *c = cmdq->client;
|
||||
|
||||
if (c == NULL || c->session == NULL)
|
||||
return;
|
||||
return 0;
|
||||
if (!(c->flags & CLIENT_CONTROL))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
evbuffer_add_printf(c->stdout_data, "%%%s %ld %u\n", guard,
|
||||
(long) cmdq->time, cmdq->number);
|
||||
server_push_stdout(c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Add command list to queue and begin processing if needed. */
|
||||
@ -197,7 +198,7 @@ cmdq_continue(struct cmd_q *cmdq)
|
||||
{
|
||||
struct cmd_q_item *next;
|
||||
enum cmd_retval retval;
|
||||
int empty;
|
||||
int empty, guard;
|
||||
char s[1024];
|
||||
|
||||
notify_disable();
|
||||
@ -223,12 +224,14 @@ cmdq_continue(struct cmd_q *cmdq)
|
||||
cmdq->time = time(NULL);
|
||||
cmdq->number++;
|
||||
|
||||
cmdq_guard(cmdq, "begin");
|
||||
guard = cmdq_guard(cmdq, "begin");
|
||||
retval = cmdq->cmd->entry->exec(cmdq->cmd, cmdq);
|
||||
if (retval == CMD_RETURN_ERROR)
|
||||
cmdq_guard(cmdq, "error");
|
||||
else
|
||||
cmdq_guard(cmdq, "end");
|
||||
if (guard) {
|
||||
if (retval == CMD_RETURN_ERROR)
|
||||
cmdq_guard(cmdq, "error");
|
||||
else
|
||||
cmdq_guard(cmdq, "end");
|
||||
}
|
||||
|
||||
if (retval == CMD_RETURN_ERROR)
|
||||
break;
|
||||
|
@ -46,8 +46,12 @@ control_notify_input(struct client *c, struct window_pane *wp,
|
||||
if (winlink_find_by_window(&c->session->windows, wp->window) != NULL) {
|
||||
message = evbuffer_new();
|
||||
evbuffer_add_printf(message, "%%output %%%u ", wp->id);
|
||||
for (i = 0; i < len; i++)
|
||||
evbuffer_add_printf(message, "%02hhx", buf[i]);
|
||||
for (i = 0; i < len; i++) {
|
||||
if (buf[i] < ' ' || buf[i] == '\\')
|
||||
evbuffer_add_printf(message, "\\%03o", buf[i]);
|
||||
else
|
||||
evbuffer_add_printf(message, "%c", buf[i]);
|
||||
}
|
||||
control_write_buffer(c, message);
|
||||
evbuffer_free(message);
|
||||
}
|
||||
@ -104,7 +108,7 @@ control_notify_window_unlinked(unused struct session *s, struct window *w)
|
||||
continue;
|
||||
cs = c->session;
|
||||
|
||||
control_write(c, "%%window-close %u", w->id);
|
||||
control_write(c, "%%window-close @%u", w->id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,9 +126,9 @@ control_notify_window_linked(unused struct session *s, struct window *w)
|
||||
cs = c->session;
|
||||
|
||||
if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
|
||||
control_write(c, "%%window-add %u", w->id);
|
||||
control_write(c, "%%window-add @%u", w->id);
|
||||
else
|
||||
control_write(c, "%%unlinked-window-add %u", w->id);
|
||||
control_write(c, "%%unlinked-window-add @%u", w->id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,7 +145,7 @@ control_notify_window_renamed(struct window *w)
|
||||
continue;
|
||||
s = c->session;
|
||||
|
||||
control_write(c, "%%window-renamed %u %s", w->id, w->name);
|
||||
control_write(c, "%%window-renamed @%u %s", w->id, w->name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,7 +158,7 @@ control_notify_attached_session_changed(struct client *c)
|
||||
return;
|
||||
s = c->session;
|
||||
|
||||
control_write(c, "%%session-changed %d %s", s->id, s->name);
|
||||
control_write(c, "%%session-changed $%u %s", s->id, s->name);
|
||||
}
|
||||
|
||||
void
|
||||
@ -165,10 +169,10 @@ control_notify_session_renamed(struct session *s)
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||
c = ARRAY_ITEM(&clients, i);
|
||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session != s)
|
||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||
continue;
|
||||
|
||||
control_write(c, "%%session-renamed %s", s->name);
|
||||
control_write(c, "%%session-renamed $%u %s", s->id, s->name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,7 +184,7 @@ control_notify_session_created(unused struct session *s)
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||
c = ARRAY_ITEM(&clients, i);
|
||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
|
||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||
continue;
|
||||
|
||||
control_write(c, "%%sessions-changed");
|
||||
@ -195,7 +199,7 @@ control_notify_session_close(unused struct session *s)
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||
c = ARRAY_ITEM(&clients, i);
|
||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
|
||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||
continue;
|
||||
|
||||
control_write(c, "%%sessions-changed");
|
||||
|
2
format.c
2
format.c
@ -280,7 +280,7 @@ format_session(struct format_tree *ft, struct session *s)
|
||||
format_add(ft, "session_windows", "%u", winlink_count(&s->windows));
|
||||
format_add(ft, "session_width", "%u", s->sx);
|
||||
format_add(ft, "session_height", "%u", s->sy);
|
||||
format_add(ft, "session_id", "%u", s->id);
|
||||
format_add(ft, "session_id", "$%u", s->id);
|
||||
|
||||
sg = session_group_find(s);
|
||||
format_add(ft, "session_grouped", "%d", sg != NULL);
|
||||
|
@ -24,7 +24,11 @@
|
||||
|
||||
int screen_redraw_cell_border1(struct window_pane *, u_int, u_int);
|
||||
int screen_redraw_cell_border(struct client *, u_int, u_int);
|
||||
int screen_redraw_check_cell(struct client *, u_int, u_int);
|
||||
int screen_redraw_check_cell(struct client *, u_int, u_int,
|
||||
struct window_pane **);
|
||||
int screen_redraw_check_active(u_int, u_int, int, struct window *,
|
||||
struct window_pane *);
|
||||
|
||||
void screen_redraw_draw_number(struct client *, struct window_pane *);
|
||||
|
||||
#define CELL_INSIDE 0
|
||||
@ -93,7 +97,8 @@ screen_redraw_cell_border(struct client *c, u_int px, u_int py)
|
||||
|
||||
/* Check if cell inside a pane. */
|
||||
int
|
||||
screen_redraw_check_cell(struct client *c, u_int px, u_int py)
|
||||
screen_redraw_check_cell(struct client *c, u_int px, u_int py,
|
||||
struct window_pane **wpp)
|
||||
{
|
||||
struct window *w = c->session->curw->window;
|
||||
struct window_pane *wp;
|
||||
@ -105,6 +110,7 @@ screen_redraw_check_cell(struct client *c, u_int px, u_int py)
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if (!window_pane_visible(wp))
|
||||
continue;
|
||||
*wpp = wp;
|
||||
|
||||
/* If outside the pane and its border, skip it. */
|
||||
if ((wp->xoff != 0 && px < wp->xoff - 1) ||
|
||||
@ -162,9 +168,52 @@ screen_redraw_check_cell(struct client *c, u_int px, u_int py)
|
||||
}
|
||||
}
|
||||
|
||||
*wpp = NULL;
|
||||
return (CELL_OUTSIDE);
|
||||
}
|
||||
|
||||
/* Check active pane indicator. */
|
||||
int
|
||||
screen_redraw_check_active(u_int px, u_int py, int type, struct window *w,
|
||||
struct window_pane *wp)
|
||||
{
|
||||
/* Is this off the active pane border? */
|
||||
if (screen_redraw_cell_border1(w->active, px, py) != 1)
|
||||
return (0);
|
||||
|
||||
/* If there are more than two panes, that's enough. */
|
||||
if (window_count_panes(w) != 2)
|
||||
return (1);
|
||||
|
||||
/* Else if the cell is not a border cell, forget it. */
|
||||
if (wp == NULL || (type == CELL_OUTSIDE || type == CELL_INSIDE))
|
||||
return (1);
|
||||
|
||||
/* Check if the pane covers the whole width. */
|
||||
if (wp->xoff == 0 && wp->sx == w->sx) {
|
||||
/* This can either be the top pane or the bottom pane. */
|
||||
if (wp->yoff == 0) { /* top pane */
|
||||
if (wp == w->active)
|
||||
return (px <= wp->sx / 2);
|
||||
return (px > wp->sx / 2);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Check if the pane covers the whole height. */
|
||||
if (wp->yoff == 0 && wp->sy == w->sy) {
|
||||
/* This can either be the left pane or the right pane. */
|
||||
if (wp->xoff == 0) { /* left pane */
|
||||
if (wp == w->active)
|
||||
return (py <= wp->sy / 2);
|
||||
return (py > wp->sy / 2);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (type);
|
||||
}
|
||||
|
||||
/* Redraw entire screen. */
|
||||
void
|
||||
screen_redraw_screen(struct client *c, int status_only, int borders_only)
|
||||
@ -223,10 +272,10 @@ screen_redraw_screen(struct client *c, int status_only, int borders_only)
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < tty->sx; i++) {
|
||||
type = screen_redraw_check_cell(c, i, j);
|
||||
type = screen_redraw_check_cell(c, i, j, &wp);
|
||||
if (type == CELL_INSIDE)
|
||||
continue;
|
||||
if (screen_redraw_cell_border1(w->active, i, j) == 1)
|
||||
if (screen_redraw_check_active(i, j, type, w, wp))
|
||||
tty_attributes(tty, &active_gc);
|
||||
else
|
||||
tty_attributes(tty, &other_gc);
|
||||
|
98
tmux.1
98
tmux.1
@ -23,7 +23,7 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm tmux
|
||||
.Bk -words
|
||||
.Op Fl 28lquvV
|
||||
.Op Fl 28lCquvV
|
||||
.Op Fl c Ar shell-command
|
||||
.Op Fl f Ar file
|
||||
.Op Fl L Ar socket-name
|
||||
@ -102,6 +102,11 @@ to assume the terminal supports 256 colours.
|
||||
Like
|
||||
.Fl 2 ,
|
||||
but indicates that the terminal supports 88 colours.
|
||||
.It Fl C
|
||||
Start in control mode.
|
||||
Given twice
|
||||
.Xo ( Fl CC ) Xc
|
||||
disables echo.
|
||||
.It Fl c Ar shell-command
|
||||
Execute
|
||||
.Ar shell-command
|
||||
@ -1622,8 +1627,8 @@ is given in lines or cells (the default is 1).
|
||||
.Pp
|
||||
With
|
||||
.Fl Z ,
|
||||
the active pane is toggled between occupying the whole of the window and its
|
||||
normal position in the layout.
|
||||
the active pane is toggled between zoomed (occupying the whole of the window)
|
||||
and unzoomed (its normal position in the layout).
|
||||
.It Xo Ic respawn-pane
|
||||
.Op Fl k
|
||||
.Op Fl t Ar target-pane
|
||||
@ -3255,6 +3260,7 @@ The flag is one of the following symbols appended to the window name:
|
||||
.It Li "!" Ta "A bell has occurred in the window."
|
||||
.It Li "+" Ta "Window is monitored for content and it has appeared."
|
||||
.It Li "~" Ta "The window has been silent for the monitor-silence interval."
|
||||
.It Li "Z" Ta "The window's active pane is zoomed."
|
||||
.El
|
||||
.Pp
|
||||
The # symbol relates to the
|
||||
@ -3613,6 +3619,92 @@ option above and the
|
||||
.Xr xterm 1
|
||||
man page.
|
||||
.El
|
||||
.Sh CONTROL MODE
|
||||
.Nm
|
||||
offers a textual interface called
|
||||
.Em control mode .
|
||||
This allows applications to communicate with
|
||||
.Nm
|
||||
using a simple text-only protocol.
|
||||
.Pp
|
||||
In control mode, a client sends
|
||||
.Nm
|
||||
commands or command sequences terminated by newlines on standard input.
|
||||
Each command will produce one block of output on standard output.
|
||||
An output block consists of a
|
||||
.Em %begin
|
||||
line followed by the output (which may be empty).
|
||||
The output block ends with a
|
||||
.Em %end
|
||||
or
|
||||
.Em %error .
|
||||
.Em %begin
|
||||
and matching
|
||||
.Em %end
|
||||
or
|
||||
.Em %error
|
||||
have two arguments: an integer time (as seconds from epoch) and command number.
|
||||
For example:
|
||||
.Bd -literal -offset indent
|
||||
%begin 1363006971 2
|
||||
0: ksh* (1 panes) [80x24] [layout b25f,80x24,0,0,2] @2 (active)
|
||||
%end 1363006971 2
|
||||
.Ed
|
||||
.Pp
|
||||
In control mode,
|
||||
.Nm
|
||||
outputs notifications.
|
||||
A notification will never occur inside an output block.
|
||||
.Pp
|
||||
The following notifications are defined:
|
||||
.Pp
|
||||
.Bl -tag -width Ds
|
||||
.It Ic %exit Op Ar reason
|
||||
The
|
||||
.Nm
|
||||
client is exiting immediately, either because it is not attached to any session
|
||||
or an error occurred.
|
||||
If present,
|
||||
.Ar reason
|
||||
describes why the client exited.
|
||||
.It Ic %layout-change Ar window-id Ar window-layout
|
||||
The layout of a window with ID
|
||||
.Ar window-id
|
||||
changed.
|
||||
The new layout is
|
||||
.Ar window-layout .
|
||||
.It Ic %output Ar pane-id Ar value
|
||||
A window pane produced output.
|
||||
.Ar value
|
||||
escapes non-printable characters and backslash as octal \\xxx.
|
||||
.It Ic %session-changed Ar session-id Ar name
|
||||
The client is now attached to the session with ID
|
||||
.Ar session-id ,
|
||||
which is named
|
||||
.Ar name .
|
||||
.It Ic %session-renamed Ar name
|
||||
The current session was renamed to
|
||||
.Ar name .
|
||||
.It Ic %sessions-changed
|
||||
A session was created or destroyed.
|
||||
.It Ic %unlinked-window-add Ar window-id
|
||||
The window with ID
|
||||
.Ar window-id
|
||||
was created but is not linked to the current session.
|
||||
.It Ic %window-add Ar window-id
|
||||
The window with ID
|
||||
.Ar window-id
|
||||
was linked to the current session.
|
||||
.It Ic %window-close Ar window-id
|
||||
The window with ID
|
||||
.Ar window-id
|
||||
closed.
|
||||
.It Ic %window-renamed Ar window-id Ar name
|
||||
The window with ID
|
||||
.Ar window-id
|
||||
was renamed to
|
||||
.Ar name .
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width "/etc/tmux.confXXX" -compact
|
||||
.It Pa ~/.tmux.conf
|
||||
|
2
tmux.h
2
tmux.h
@ -1856,7 +1856,7 @@ int cmdq_free(struct cmd_q *);
|
||||
void printflike2 cmdq_print(struct cmd_q *, const char *, ...);
|
||||
void printflike2 cmdq_info(struct cmd_q *, const char *, ...);
|
||||
void printflike2 cmdq_error(struct cmd_q *, const char *, ...);
|
||||
void cmdq_guard(struct cmd_q *, const char *);
|
||||
int cmdq_guard(struct cmd_q *, const char *);
|
||||
void cmdq_run(struct cmd_q *, struct cmd_list *);
|
||||
void cmdq_append(struct cmd_q *, struct cmd_list *);
|
||||
int cmdq_continue(struct cmd_q *);
|
||||
|
Loading…
Reference in New Issue
Block a user