mirror of
https://github.com/tmate-io/tmate.git
synced 2025-01-18 11:58:24 +01:00
Show status messages without blocking the server.
This commit is contained in:
parent
99df48d70f
commit
9ef5bdc7c0
6
TODO
6
TODO
@ -37,8 +37,6 @@
|
|||||||
- function groups, bind-key ^W { select-window 0; send-key ^W } etc ***
|
- function groups, bind-key ^W { select-window 0; send-key ^W } etc ***
|
||||||
- allow fnmatch for -c, so that you can, eg, detach all clients
|
- allow fnmatch for -c, so that you can, eg, detach all clients
|
||||||
- bind non prefix keys
|
- bind non prefix keys
|
||||||
- stuff like rename would be nice to be able to do in-client like screen, if
|
|
||||||
it could be implemented in a non-icky way
|
|
||||||
- there is too much redrawing. use flags?
|
- there is too much redrawing. use flags?
|
||||||
- command mode (! + type tmux command)
|
- command mode (! + type tmux command)
|
||||||
- garbage collect window history (100 lines at a time?) if it hasn't been used
|
- garbage collect window history (100 lines at a time?) if it hasn't been used
|
||||||
@ -86,3 +84,7 @@ option to pass through to xterm window when switching window
|
|||||||
session not being watched?
|
session not being watched?
|
||||||
- document status-left/status-right/status-interval/set-titles
|
- document status-left/status-right/status-interval/set-titles
|
||||||
- enhance paste buffers. per-session buffers, lots of command love
|
- enhance paste buffers. per-session buffers, lots of command love
|
||||||
|
- stuff like rename would be nice to be able to do in-client like screen, if
|
||||||
|
it could be implemented in a non-icky way (we have control over the tty fd
|
||||||
|
now in the server so should be easier...)
|
||||||
|
- tidy up window modes
|
||||||
|
66
server-fn.c
66
server-fn.c
@ -1,4 +1,4 @@
|
|||||||
/* $Id: server-fn.c,v 1.42 2008-06-16 17:35:40 nicm Exp $ */
|
/* $Id: server-fn.c,v 1.43 2008-06-19 18:27:55 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -23,6 +23,31 @@
|
|||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
server_set_client_message(struct client *c, const char *msg)
|
||||||
|
{
|
||||||
|
struct timespec ts = { 0, 750000000L };
|
||||||
|
|
||||||
|
c->message_string = xstrdup(msg);
|
||||||
|
if (clock_gettime(CLOCK_REALTIME, &c->message_timer) != 0)
|
||||||
|
fatal("clock_gettime");
|
||||||
|
timespecadd(&c->message_timer, &ts, &c->message_timer);
|
||||||
|
|
||||||
|
c->flags |= CLIENT_STATUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
server_clear_client_message(struct client *c)
|
||||||
|
{
|
||||||
|
if (c->message_string == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
xfree(c->message_string);
|
||||||
|
c->message_string = NULL;
|
||||||
|
|
||||||
|
c->flags |= CLIENT_STATUS;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
server_write_client(
|
server_write_client(
|
||||||
struct client *c, enum hdrtype type, const void *buf, size_t len)
|
struct client *c, enum hdrtype type, const void *buf, size_t len)
|
||||||
@ -150,47 +175,14 @@ server_status_window(struct window *w)
|
|||||||
void printflike2
|
void printflike2
|
||||||
server_write_message(struct client *c, const char *fmt, ...)
|
server_write_message(struct client *c, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
struct screen_redraw_ctx ctx;
|
va_list ap;
|
||||||
va_list ap;
|
char *msg;
|
||||||
char *msg;
|
|
||||||
size_t size;
|
|
||||||
u_int slines;
|
|
||||||
|
|
||||||
slines = options_get_number(&c->session->options, "status-lines");
|
|
||||||
|
|
||||||
screen_redraw_start_client(&ctx, c);
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
xvasprintf(&msg, fmt, ap);
|
xvasprintf(&msg, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
msg = xrealloc(msg, 1, c->sx + 1);
|
server_set_client_message(c, msg);
|
||||||
msg[c->sx] = '\0';
|
|
||||||
|
|
||||||
size = strlen(msg);
|
|
||||||
if (size < c->sx)
|
|
||||||
memset(msg + size, ' ', c->sx - size);
|
|
||||||
|
|
||||||
screen_redraw_move_cursor(&ctx, 0, c->sy - 1);
|
|
||||||
screen_redraw_set_attributes(&ctx, ATTR_REVERSE, 0x88);
|
|
||||||
screen_redraw_write_string(&ctx, "%s", msg);
|
|
||||||
|
|
||||||
buffer_flush(c->tty.fd, c->tty.in, c->tty.out);
|
|
||||||
usleep(750000);
|
|
||||||
|
|
||||||
memset(msg, ' ', c->sx);
|
|
||||||
|
|
||||||
screen_redraw_move_cursor(&ctx, 0, c->sy - 1);
|
|
||||||
screen_redraw_set_attributes(&ctx, 0, 0x88);
|
|
||||||
screen_redraw_write_string(&ctx, "%s", msg);
|
|
||||||
|
|
||||||
xfree(msg);
|
xfree(msg);
|
||||||
|
|
||||||
if (slines == 0) {
|
|
||||||
screen_redraw_lines(&ctx, c->sy - 1, 1);
|
|
||||||
screen_redraw_stop(&ctx);
|
|
||||||
} else {
|
|
||||||
screen_redraw_stop(&ctx);
|
|
||||||
server_status_client(c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
57
server.c
57
server.c
@ -1,4 +1,4 @@
|
|||||||
/* $Id: server.c,v 1.68 2008-06-18 22:21:51 nicm Exp $ */
|
/* $Id: server.c,v 1.69 2008-06-19 18:27:55 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -54,7 +54,7 @@ void server_handle_window(struct window *);
|
|||||||
void server_lost_client(struct client *);
|
void server_lost_client(struct client *);
|
||||||
void server_lost_window(struct window *);
|
void server_lost_window(struct window *);
|
||||||
void server_check_redraw(struct client *);
|
void server_check_redraw(struct client *);
|
||||||
void server_check_status(struct client *);
|
void server_check_timers(struct client *);
|
||||||
void server_update_socket(const char *);
|
void server_update_socket(const char *);
|
||||||
|
|
||||||
/* Fork new server. */
|
/* Fork new server. */
|
||||||
@ -322,7 +322,7 @@ server_check_redraw(struct client *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
xx = c->sx;
|
xx = c->sx;
|
||||||
yy = c->sy - options_get_number(&s->options, "status-lines");
|
yy = c->sy - 1; //options_get_number(&s->options, "status-lines");
|
||||||
if (c->flags & CLIENT_REDRAW) {
|
if (c->flags & CLIENT_REDRAW) {
|
||||||
sx = screen_size_x(s->curw->window->screen);
|
sx = screen_size_x(s->curw->window->screen);
|
||||||
sy = screen_size_y(s->curw->window->screen);
|
sy = screen_size_y(s->curw->window->screen);
|
||||||
@ -351,33 +351,47 @@ server_check_redraw(struct client *c)
|
|||||||
screen_redraw_lines(&ctx, 0, screen_size_y(ctx.s));
|
screen_redraw_lines(&ctx, 0, screen_size_y(ctx.s));
|
||||||
screen_redraw_stop(&ctx);
|
screen_redraw_stop(&ctx);
|
||||||
|
|
||||||
status_redraw(c);
|
c->flags |= CLIENT_STATUS;
|
||||||
} else if (c->flags & CLIENT_STATUS)
|
}
|
||||||
status_redraw(c);
|
|
||||||
|
|
||||||
c->flags &= ~(CLIENT_CLEAR|CLIENT_REDRAW|CLIENT_STATUS);
|
if (c->flags & CLIENT_STATUS) {
|
||||||
|
if (c->message_string != NULL)
|
||||||
|
status_message_redraw(c);
|
||||||
|
else
|
||||||
|
status_redraw(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
c->flags &= ~(CLIENT_REDRAW|CLIENT_STATUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for status line redraw on client. */
|
/* Check for timers on client. */
|
||||||
void
|
void
|
||||||
server_check_status(struct client *c)
|
server_check_timers(struct client *c)
|
||||||
{
|
{
|
||||||
struct timespec ts;
|
struct session *s;
|
||||||
|
struct timespec ts, ts2;
|
||||||
u_int nlines, interval;
|
u_int nlines, interval;
|
||||||
|
|
||||||
if (c == NULL || c->session == NULL)
|
if (c == NULL || c->session == NULL)
|
||||||
return;
|
return;
|
||||||
|
s = c->session;
|
||||||
nlines = options_get_number(&c->session->options, "status-lines");
|
|
||||||
interval = options_get_number(&c->session->options, "status-interval");
|
|
||||||
if (nlines == 0 || interval == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
|
if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
|
||||||
fatal("clock_gettime");
|
fatal("clock_gettime");
|
||||||
ts.tv_sec -= interval;
|
|
||||||
|
if (c->message_string != NULL && timespeccmp(&ts, &c->message_timer, >))
|
||||||
|
server_clear_client_message(c);
|
||||||
|
|
||||||
if (timespeccmp(&c->status_ts, &ts, <))
|
nlines = options_get_number(&s->options, "status-lines");
|
||||||
|
if (nlines == 0)
|
||||||
|
return;
|
||||||
|
interval = options_get_number(&s->options, "status-interval");
|
||||||
|
if (interval == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memcpy(&ts2, &ts, sizeof ts2);
|
||||||
|
ts2.tv_sec -= interval;
|
||||||
|
if (timespeccmp(&c->status_timer, &ts2, <))
|
||||||
c->flags |= CLIENT_STATUS;
|
c->flags |= CLIENT_STATUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,8 +405,8 @@ server_fill_clients(struct pollfd **pfd)
|
|||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||||
c = ARRAY_ITEM(&clients, i);
|
c = ARRAY_ITEM(&clients, i);
|
||||||
|
|
||||||
|
server_check_timers(c);
|
||||||
server_check_redraw(c);
|
server_check_redraw(c);
|
||||||
server_check_status(c);
|
|
||||||
|
|
||||||
if (c == NULL)
|
if (c == NULL)
|
||||||
(*pfd)->fd = -1;
|
(*pfd)->fd = -1;
|
||||||
@ -483,6 +497,12 @@ server_accept_client(int srv_fd)
|
|||||||
c->sx = 80;
|
c->sx = 80;
|
||||||
c->sy = 25;
|
c->sy = 25;
|
||||||
|
|
||||||
|
c->message_string = NULL;
|
||||||
|
|
||||||
|
c->prompt_string = NULL;
|
||||||
|
c->prompt_buffer = NULL;
|
||||||
|
c->prompt_size = 0;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||||
if (ARRAY_ITEM(&clients, i) == NULL) {
|
if (ARRAY_ITEM(&clients, i) == NULL) {
|
||||||
ARRAY_SET(&clients, i, c);
|
ARRAY_SET(&clients, i, c);
|
||||||
@ -502,6 +522,7 @@ server_handle_client(struct client *c)
|
|||||||
|
|
||||||
prefix = options_get_key(&c->session->options, "prefix-key");
|
prefix = options_get_key(&c->session->options, "prefix-key");
|
||||||
while (tty_keys_next(&c->tty, &key) == 0) {
|
while (tty_keys_next(&c->tty, &key) == 0) {
|
||||||
|
server_clear_client_message(c);
|
||||||
if (c->flags & CLIENT_PREFIX) {
|
if (c->flags & CLIENT_PREFIX) {
|
||||||
key_bindings_dispatch(key, c);
|
key_bindings_dispatch(key, c);
|
||||||
c->flags &= ~CLIENT_PREFIX;
|
c->flags &= ~CLIENT_PREFIX;
|
||||||
|
60
status.c
60
status.c
@ -1,4 +1,4 @@
|
|||||||
/* $Id: status.c,v 1.30 2008-06-18 22:21:51 nicm Exp $ */
|
/* $Id: status.c,v 1.31 2008-06-19 18:27:55 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -39,14 +39,15 @@ status_redraw(struct client *c)
|
|||||||
size_t llen, rlen, offset, xx, yy;
|
size_t llen, rlen, offset, xx, yy;
|
||||||
size_t size, start, width;
|
size_t size, start, width;
|
||||||
u_char attr, colr;
|
u_char attr, colr;
|
||||||
|
struct tm *tm;
|
||||||
int larrow, rarrow;
|
int larrow, rarrow;
|
||||||
|
|
||||||
yy = options_get_number(&s->options, "status-lines");
|
yy = options_get_number(&s->options, "status-lines");
|
||||||
if (c->sy == 0 || yy == 0)
|
if (c->sy == 0 || yy == 0)
|
||||||
return;
|
goto off;
|
||||||
larrow = rarrow = 0;
|
larrow = rarrow = 0;
|
||||||
|
|
||||||
if (clock_gettime(CLOCK_REALTIME, &c->status_ts) != 0)
|
if (clock_gettime(CLOCK_REALTIME, &c->status_timer) != 0)
|
||||||
fatal("clock_gettime failed");
|
fatal("clock_gettime failed");
|
||||||
colr = options_get_colours(&s->options, "status-colour");
|
colr = options_get_colours(&s->options, "status-colour");
|
||||||
|
|
||||||
@ -54,11 +55,12 @@ status_redraw(struct client *c)
|
|||||||
if (yy == 0)
|
if (yy == 0)
|
||||||
goto blank;
|
goto blank;
|
||||||
|
|
||||||
|
tm = localtime(&(c->status_timer.tv_sec));
|
||||||
left = options_get_string(&s->options, "status-left");
|
left = options_get_string(&s->options, "status-left");
|
||||||
strftime(lbuf, sizeof lbuf, left, localtime(&(c->status_ts.tv_sec)));
|
strftime(lbuf, sizeof lbuf, left, tm);
|
||||||
llen = strlen(lbuf);
|
llen = strlen(lbuf);
|
||||||
right = options_get_string(&s->options, "status-right");
|
right = options_get_string(&s->options, "status-right");
|
||||||
strftime(rbuf, sizeof rbuf, right, localtime(&(c->status_ts.tv_sec)));
|
strftime(rbuf, sizeof rbuf, right, tm);
|
||||||
rlen = strlen(rbuf);
|
rlen = strlen(rbuf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -229,6 +231,26 @@ blank:
|
|||||||
for (offset = 0; offset < c->sx; offset++)
|
for (offset = 0; offset < c->sx; offset++)
|
||||||
ctx.write(ctx.data, TTY_CHARACTER, ' ');
|
ctx.write(ctx.data, TTY_CHARACTER, ' ');
|
||||||
screen_redraw_stop(&ctx);
|
screen_redraw_stop(&ctx);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
off:
|
||||||
|
/*
|
||||||
|
* Draw the real window last line. Necessary to wipe over message if
|
||||||
|
* status is off. Not sure this is the right place for this.
|
||||||
|
*/
|
||||||
|
screen_redraw_start_client(&ctx, c);
|
||||||
|
/* If the screen is too small, use blank. */
|
||||||
|
if (screen_size_y(c->session->curw->window->screen) < c->sy) {
|
||||||
|
screen_redraw_move_cursor(&ctx, 0, c->sy - 1);
|
||||||
|
screen_redraw_set_attributes(&ctx, 0, 0x88);
|
||||||
|
for (offset = 0; offset < c->sx; offset++)
|
||||||
|
ctx.write(ctx.data, TTY_CHARACTER, ' ');
|
||||||
|
} else
|
||||||
|
screen_redraw_lines(&ctx, c->sy - 1, 1);
|
||||||
|
screen_redraw_stop(&ctx);
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
@ -261,3 +283,31 @@ status_print(struct session *s, struct winlink *wl, u_char *attr)
|
|||||||
xasprintf(&text, "%d:%s%c", wl->idx, wl->window->name, flag);
|
xasprintf(&text, "%d:%s%c", wl->idx, wl->window->name, flag);
|
||||||
return (text);
|
return (text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Draw client message on status line of present else on last line. */
|
||||||
|
void
|
||||||
|
status_message_redraw(struct client *c)
|
||||||
|
{
|
||||||
|
struct screen_redraw_ctx ctx;
|
||||||
|
size_t xx, yy;
|
||||||
|
|
||||||
|
if (c->sx == 0 || c->sy == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
xx = strlen(c->message_string);
|
||||||
|
if (xx > c->sx)
|
||||||
|
xx = c->sx;
|
||||||
|
yy = c->sy - 1;
|
||||||
|
|
||||||
|
screen_redraw_start_client(&ctx, c);
|
||||||
|
screen_redraw_set_attributes(&ctx, ATTR_REVERSE, 0x88);
|
||||||
|
|
||||||
|
screen_redraw_move_cursor(&ctx, 0, yy);
|
||||||
|
screen_redraw_write_string(&ctx, "%.*s", (int) xx, c->message_string);
|
||||||
|
for (; xx < c->sx; xx++)
|
||||||
|
ctx.write(ctx.data, TTY_CHARACTER, ' ');
|
||||||
|
screen_redraw_stop(&ctx);
|
||||||
|
|
||||||
|
/* Force cursor off. */
|
||||||
|
tty_write_client(c, TTY_CURSOROFF);
|
||||||
|
}
|
||||||
|
15
tmux.h
15
tmux.h
@ -1,4 +1,4 @@
|
|||||||
/* $Id: tmux.h,v 1.151 2008-06-18 20:58:03 nicm Exp $ */
|
/* $Id: tmux.h,v 1.152 2008-06-19 18:27:55 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -664,7 +664,7 @@ struct client {
|
|||||||
char *title;
|
char *title;
|
||||||
|
|
||||||
struct tty tty;
|
struct tty tty;
|
||||||
struct timespec status_ts;
|
struct timespec status_timer;
|
||||||
|
|
||||||
u_int sx;
|
u_int sx;
|
||||||
u_int sy;
|
u_int sy;
|
||||||
@ -674,9 +674,15 @@ struct client {
|
|||||||
#define CLIENT_MOUSE 0x4
|
#define CLIENT_MOUSE 0x4
|
||||||
#define CLIENT_REDRAW 0x8
|
#define CLIENT_REDRAW 0x8
|
||||||
#define CLIENT_STATUS 0x10
|
#define CLIENT_STATUS 0x10
|
||||||
#define CLIENT_CLEAR 0x20
|
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
|
char *message_string;
|
||||||
|
struct timespec message_timer;
|
||||||
|
|
||||||
|
char *prompt_string;
|
||||||
|
char *prompt_buffer;
|
||||||
|
size_t prompt_size;
|
||||||
|
|
||||||
struct session *session;
|
struct session *session;
|
||||||
};
|
};
|
||||||
ARRAY_DECL(clients, struct client *);
|
ARRAY_DECL(clients, struct client *);
|
||||||
@ -949,6 +955,8 @@ int server_start(const char *);
|
|||||||
int server_msg_dispatch(struct client *);
|
int server_msg_dispatch(struct client *);
|
||||||
|
|
||||||
/* server-fn.c */
|
/* server-fn.c */
|
||||||
|
void server_set_client_message(struct client *, const char *);
|
||||||
|
void server_clear_client_message(struct client *);
|
||||||
struct session *server_extract_session(
|
struct session *server_extract_session(
|
||||||
struct msg_command_data *, char *, char **);
|
struct msg_command_data *, char *, char **);
|
||||||
void server_write_client(
|
void server_write_client(
|
||||||
@ -967,6 +975,7 @@ void printflike2 server_write_message(struct client *, const char *, ...);
|
|||||||
|
|
||||||
/* status.c */
|
/* status.c */
|
||||||
void status_redraw(struct client *c);
|
void status_redraw(struct client *c);
|
||||||
|
void status_message_redraw(struct client *c);
|
||||||
|
|
||||||
/* resize.c */
|
/* resize.c */
|
||||||
void recalculate_sizes(void);
|
void recalculate_sizes(void);
|
||||||
|
Loading…
Reference in New Issue
Block a user