Scrollable win for command output.

This commit is contained in:
Nicholas Marriott 2007-11-21 19:44:05 +00:00
parent 24c39950ff
commit acb3661b66
6 changed files with 320 additions and 54 deletions

View File

@ -1,5 +1,7 @@
21 November 2007 21 November 2007
* Make command output (eg list-keys) go to a scrollable window similar to
scroll mode.
* Redo screen redrawing so it is a) readable b) split into utility functions * Redo screen redrawing so it is a) readable b) split into utility functions
that can be used outside screen.c. Use these to make scroll mode only that can be used outside screen.c. Use these to make scroll mode only
redraw what it has to which gets rid of irritating flickering status box and redraw what it has to which gets rid of irritating flickering status box and
@ -245,4 +247,4 @@
(including mutt, emacs). No status bar yet and no key remapping or other (including mutt, emacs). No status bar yet and no key remapping or other
customisation. customisation.
$Id: CHANGES,v 1.78 2007-11-21 18:24:49 nicm Exp $ $Id: CHANGES,v 1.79 2007-11-21 19:44:04 nicm Exp $

View File

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.45 2007-11-21 13:11:41 nicm Exp $ # $Id: Makefile,v 1.46 2007-11-21 19:44:04 nicm Exp $
.SUFFIXES: .c .o .y .h .SUFFIXES: .c .o .y .h
.PHONY: clean update-index.html upload-index.html .PHONY: clean update-index.html upload-index.html
@ -27,7 +27,7 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
cmd-link-window.c cmd-unlink-window.c cmd-next-window.c \ cmd-link-window.c cmd-unlink-window.c cmd-next-window.c \
cmd-swap-window.c cmd-rename-session.c cmd-kill-session.c \ cmd-swap-window.c cmd-rename-session.c cmd-kill-session.c \
cmd-switch-client.c cmd-has-session.c cmd-scroll-mode.c \ cmd-switch-client.c cmd-has-session.c cmd-scroll-mode.c \
window-scroll.c window-scroll.c window-more.c
CC?= cc CC?= cc
INCDIRS+= -I. -I- -I/usr/local/include INCDIRS+= -I. -I- -I/usr/local/include

View File

@ -1,4 +1,4 @@
/* $Id: key-bindings.c,v 1.18 2007-11-21 13:11:41 nicm Exp $ */ /* $Id: key-bindings.c,v 1.19 2007-11-21 19:44:05 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -160,56 +160,18 @@ key_bindings_error(struct cmd_ctx *ctx, const char *fmt, ...)
void printflike2 void printflike2
key_bindings_print(struct cmd_ctx *ctx, const char *fmt, ...) key_bindings_print(struct cmd_ctx *ctx, const char *fmt, ...)
{ {
static u_int line; struct window *w = ctx->session->curw->window;
struct client *c = ctx->client;
struct screen *s = &c->session->curw->window->screen;
struct hdr hdr;
va_list ap; va_list ap;
char *msg;
size_t size;
u_int i, sx, sy;
sx = screen_size_x(s); if (w->mode == NULL) {
sy = screen_size_y(s); w->mode = &window_more_mode;
w->mode->init(w);
buffer_ensure(c->out, sizeof hdr); } else if (w->mode != &window_more_mode)
buffer_add(c->out, sizeof hdr); return;
size = BUFFER_USED(c->out);
if (line == 2 * sy || !(c->flags & CLIENT_HOLD)) {
input_store_zero(c->out, CODE_CURSOROFF);
for (i = 0; i < sy; i++) {
input_store_two(c->out, CODE_CURSORMOVE, i + 1, 1);
input_store_zero(c->out, CODE_CLEARLINE);
}
input_store_two(c->out, CODE_CURSORMOVE, 1, 1);
input_store_two(c->out, CODE_ATTRIBUTES, 0, 0x88);
line = 0;
c->flags |= CLIENT_HOLD;
}
if (line >= sy) {
input_store_two(c->out, CODE_CURSORMOVE, line - sy + 1, sx / 2);
}
line++;
va_start(ap, fmt); va_start(ap, fmt);
xvasprintf(&msg, fmt, ap); window_more_vadd(w, fmt, ap);
va_end(ap); va_end(ap);
if (strlen(msg) > sx / 2)
msg[sx / 2] = '\0';
buffer_write(c->out, msg, strlen(msg));
if (line != sy && line != 2 * sy) {
input_store8(c->out, '\r');
input_store8(c->out, '\n');
}
xfree(msg);
size = BUFFER_USED(c->out) - size;
hdr.type = MSG_DATA;
hdr.size = size;
memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr);
} }
void void
@ -238,4 +200,7 @@ key_bindings_dispatch(int key, struct client *c)
ctx.flags = CMD_KEY; ctx.flags = CMD_KEY;
cmd_exec(bd->cmd, &ctx); cmd_exec(bd->cmd, &ctx);
if (c->session->curw->window->mode == &window_more_mode)
server_redraw_window_all(c->session->curw->window);
} }

7
tmux.h
View File

@ -1,4 +1,4 @@
/* $Id: tmux.h,v 1.88 2007-11-21 18:24:49 nicm Exp $ */ /* $Id: tmux.h,v 1.89 2007-11-21 19:44:05 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -815,6 +815,11 @@ void window_key(struct window *, int);
/* window-scroll.c */ /* window-scroll.c */
extern const struct window_mode window_scroll_mode; extern const struct window_mode window_scroll_mode;
/* window-more.c */
extern const struct window_mode window_more_mode;
void window_more_vadd(struct window *, const char *, va_list);
void printflike2 window_more_add(struct window *, const char *, ...);
/* session.c */ /* session.c */
extern struct sessions sessions; extern struct sessions sessions;
void session_cancelbell(struct session *, struct winlink *); void session_cancelbell(struct session *, struct winlink *);

294
window-more.c Normal file
View File

@ -0,0 +1,294 @@
/* $Id: window-more.c,v 1.1 2007-11-21 19:44:05 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <string.h>
#include "tmux.h"
void window_more_init(struct window *);
void window_more_resize(struct window *, u_int, u_int);
void window_more_draw(struct window *, struct buffer *, u_int, u_int);
void window_more_key(struct window *, int);
void window_more_draw_position(struct window *, struct screen_draw_ctx *);
void window_more_draw_line(struct window *, struct screen_draw_ctx *, u_int);
void window_more_up_1(struct window *);
void window_more_down_1(struct window *);
const struct window_mode window_more_mode = {
window_more_init,
window_more_resize,
window_more_draw,
window_more_key
};
struct window_more_mode_data {
ARRAY_DECL(, char *) list;
u_int top;
};
void
window_more_vadd(struct window *w, const char *fmt, va_list ap)
{
struct window_more_mode_data *data = w->modedata;
char *s;
xvasprintf(&s, fmt, ap);
ARRAY_ADD(&data->list, s);
}
void
window_more_add(struct window *w, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
window_more_vadd(w, fmt, ap);
va_end(ap);
}
void
window_more_init(struct window *w)
{
struct window_more_mode_data *data;
w->modedata = data = xmalloc(sizeof *data);
ARRAY_INIT(&data->list);
data->top = 0;
}
void
window_more_resize(unused struct window *w, unused u_int sx, unused u_int sy)
{
}
void
window_more_draw_position(struct window *w, struct screen_draw_ctx *ctx)
{
struct window_more_mode_data *data = w->modedata;
char *ptr, buf[32];
size_t len;
char *line;
size_t n;
len = xsnprintf(
buf, sizeof buf, "[%u/%u]", data->top, ARRAY_LENGTH(&data->list));
if (len <= screen_size_x(ctx->s))
ptr = buf;
else {
ptr = buf + len - screen_size_x(ctx->s);
len -= len - screen_size_x(ctx->s);
}
screen_draw_move(ctx, 0, 0);
if (data->top < ARRAY_LENGTH(&data->list)) {
line = ARRAY_ITEM(&data->list, data->top);
n = strlen(line);
if (n > screen_size_x(ctx->s) - len)
n = screen_size_x(ctx->s) - len;
buffer_write(ctx->b, line, n);
} else
n = 0;
for (; n < screen_size_x(ctx->s) - len; n++)
input_store8(ctx->b, SCREEN_DEFDATA);
screen_draw_move(ctx, screen_size_x(ctx->s) - len, 0);
screen_draw_set_attributes(ctx, 0, status_colour);
buffer_write(ctx->b, buf, len);
}
void
window_more_draw_line(struct window *w, struct screen_draw_ctx *ctx, u_int py)
{
struct window_more_mode_data *data = w->modedata;
char *line;
size_t n;
u_int p;
screen_draw_move(ctx, 0, py);
screen_draw_set_attributes(ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR);
p = data->top + py;
if (p >= ARRAY_LENGTH(&data->list)) {
input_store_zero(ctx->b, CODE_CLEARLINE);
return;
}
line = ARRAY_ITEM(&data->list, p);
n = strlen(line);
if (n > screen_size_x(ctx->s))
n = screen_size_x(ctx->s);
buffer_write(ctx->b, line, n);
for (; n < screen_size_x(ctx->s); n++)
input_store8(ctx->b, SCREEN_DEFDATA);
}
void
window_more_draw(struct window *w, struct buffer *b, u_int py, u_int ny)
{
struct screen *s = &w->screen;
struct screen_draw_ctx ctx;
u_int i;
screen_draw_start(&ctx, s, b, 0, 0);
for (i = py; i < py + ny; i++) {
if (i == 0)
continue;
window_more_draw_line(w, &ctx, i);
}
if (py == 0)
window_more_draw_position(w, &ctx);
screen_draw_stop(&ctx);
input_store_zero(b, CODE_CURSOROFF);
}
void
window_more_key(struct window *w, int key)
{
struct window_more_mode_data *data = w->modedata;
u_int top, sy;
sy = screen_size_y(&w->screen);
top = data->top;
switch (key) {
case 'Q':
case 'q':
w->mode = NULL;
xfree(w->modedata);
recalculate_sizes();
server_redraw_window_all(w);
return;
case 'k':
case 'K':
case KEYC_UP:
window_more_up_1(w);
return;
case 'j':
case 'J':
case KEYC_DOWN:
window_more_down_1(w);
return;
case '\025': /* C-u */
case KEYC_PPAGE:
if (data->top < sy)
data->top = 0;
else
data->top -= sy;
break;
case '\006': /* C-f */
case KEYC_NPAGE:
if (data->top + sy > ARRAY_LENGTH(&data->list))
data->top = ARRAY_LENGTH(&data->list);
else
data->top += sy;
break;
}
if (top != data->top)
server_redraw_window_all(w);
}
void
window_more_up_1(struct window *w)
{
struct window_more_mode_data *data = w->modedata;
struct screen *s = &w->screen;
struct screen_draw_ctx ctx;
struct client *c;
u_int i;
struct hdr hdr;
size_t size;
if (data->top == 0)
return;
data->top--;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session == NULL)
continue;
if (!session_has(c->session, w))
continue;
buffer_ensure(c->out, sizeof hdr);
buffer_add(c->out, sizeof hdr);
size = BUFFER_USED(c->out);
screen_draw_start(&ctx, s, c->out, 0, 0);
screen_draw_move(&ctx, 0, 0);
input_store_one(c->out, CODE_INSERTLINE, 1);
window_more_draw_position(w, &ctx);
window_more_draw_line(w, &ctx, 1);
screen_draw_stop(&ctx);
input_store_zero(c->out, CODE_CURSOROFF);
size = BUFFER_USED(c->out) - size;
hdr.type = MSG_DATA;
hdr.size = size;
memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr);
}
}
void
window_more_down_1(struct window *w)
{
struct window_more_mode_data *data = w->modedata;
struct screen *s = &w->screen;
struct screen_draw_ctx ctx;
struct client *c;
u_int i;
struct hdr hdr;
size_t size;
if (data->top >= ARRAY_LENGTH(&data->list))
return;
data->top++;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session == NULL)
continue;
if (!session_has(c->session, w))
continue;
buffer_ensure(c->out, sizeof hdr);
buffer_add(c->out, sizeof hdr);
size = BUFFER_USED(c->out);
screen_draw_start(&ctx, s, c->out, 0, 0);
screen_draw_move(&ctx, 0, 0);
input_store_one(c->out, CODE_DELETELINE, 1);
window_more_draw_line(w, &ctx, screen_last_y(s));
window_more_draw_position(w, &ctx);
screen_draw_stop(&ctx);
input_store_zero(c->out, CODE_CURSOROFF);
size = BUFFER_USED(c->out) - size;
hdr.type = MSG_DATA;
hdr.size = size;
memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr);
}
}

View File

@ -1,4 +1,4 @@
/* $Id: window-scroll.c,v 1.7 2007-11-21 18:24:49 nicm Exp $ */ /* $Id: window-scroll.c,v 1.8 2007-11-21 19:44:05 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -149,14 +149,14 @@ window_scroll_key(struct window *w, int key)
case KEYC_DOWN: case KEYC_DOWN:
window_scroll_down_1(w); window_scroll_down_1(w);
return; return;
case '\025': case '\025': /* C-u */
case KEYC_PPAGE: case KEYC_PPAGE:
if (data->oy + sy > data->size) if (data->oy + sy > data->size)
data->oy = data->size; data->oy = data->size;
else else
data->oy += sy; data->oy += sy;
break; break;
case '\006': case '\006': /* C-f */
case KEYC_NPAGE: case KEYC_NPAGE:
if (data->oy < sy) if (data->oy < sy)
data->oy = 0; data->oy = 0;
@ -198,7 +198,7 @@ window_scroll_up_1(struct window *w)
screen_draw_move(&ctx, 0, 0); screen_draw_move(&ctx, 0, 0);
input_store_one(c->out, CODE_INSERTLINE, 1); input_store_one(c->out, CODE_INSERTLINE, 1);
window_scroll_draw_position(w, &ctx); window_scroll_draw_position(w, &ctx);
screen_draw_line(&ctx, 1); /* nuke old position */ screen_draw_line(&ctx, 1); /* nuke old position display */
screen_draw_stop(&ctx); screen_draw_stop(&ctx);
input_store_zero(c->out, CODE_CURSOROFF); input_store_zero(c->out, CODE_CURSOROFF);