Per-session configuration options.

This commit is contained in:
Nicholas Marriott 2008-06-03 21:42:37 +00:00
parent 85d520c41e
commit 9e6090a7a2
20 changed files with 343 additions and 102 deletions

View File

@ -1,5 +1,8 @@
03 June 2008 03 June 2008
* Per session options. Setting options without specifying a session sets the
global options as normal (global options are inherited by all sessions);
passing -c or -s will set the option only for that session.
* Because a client has a session attached, any command needing a session can * Because a client has a session attached, any command needing a session can
take a client and use its session. So, anything that used to accept -s now take a client and use its session. So, anything that used to accept -s now
accepts -c as well. accepts -c as well.
@ -379,4 +382,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.102 2008-06-03 16:55:09 nicm Exp $ $Id: CHANGES,v 1.103 2008-06-03 21:42:36 nicm Exp $

View File

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.56 2008-06-03 05:10:38 nicm Exp $ # $Id: Makefile,v 1.57 2008-06-03 21:42:37 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
@ -29,7 +29,7 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
cmd-switch-client.c cmd-has-session.c cmd-scroll-mode.c cmd-copy-mode.c \ cmd-switch-client.c cmd-has-session.c cmd-scroll-mode.c cmd-copy-mode.c \
cmd-paste-buffer.c cmd-new-session.c cmd-start-server.c \ cmd-paste-buffer.c cmd-new-session.c cmd-start-server.c \
cmd-kill-server.c \ cmd-kill-server.c \
window-scroll.c window-more.c window-copy.c \ window-scroll.c window-more.c window-copy.c options.c \
tty.c tty-keys.c tty-write.c screen-write.c screen-redraw.c tty.c tty-keys.c tty-write.c screen-write.c screen-redraw.c
CC?= cc CC?= cc

5
TODO
View File

@ -65,6 +65,11 @@
- different screen model? layers perhaps? hmm - different screen model? layers perhaps? hmm
- cfg file improvements - cfg file improvements
- select-window can become windowonly (what about default?) - select-window can become windowonly (what about default?)
- monitor for activity in windows as well as bell
- status bar customisation variables, date/time, show-activity, show-last-window
string-left, string-right - pass through strptime and print...
- per-window options (per-session list of window ranges?)
- show-options
--- ---
[18:20] *priteau* i found something in tmux that could be tweaked to be better [18:20] *priteau* i found something in tmux that could be tweaked to be better

View File

@ -1,4 +1,4 @@
/* $Id: cmd-new-session.c,v 1.23 2008-06-03 05:35:51 nicm Exp $ */ /* $Id: cmd-new-session.c,v 1.24 2008-06-03 21:42:37 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -113,7 +113,7 @@ cmd_new_session_exec(void *ptr, struct cmd_ctx *ctx)
struct client *c = ctx->cmdclient; struct client *c = ctx->cmdclient;
struct session *s; struct session *s;
char *cmd, *cause; char *cmd, *cause;
u_int sx, sy; u_int sx, sy, slines;
if (ctx->flags & CMD_KEY) if (ctx->flags & CMD_KEY)
return; return;
@ -136,7 +136,7 @@ cmd_new_session_exec(void *ptr, struct cmd_ctx *ctx)
cmd = data->cmd; cmd = data->cmd;
if (cmd == NULL) if (cmd == NULL)
cmd = default_command; cmd = options_get_string(&global_options, "default-command");
sx = 80; sx = 80;
sy = 25; sy = 25;
@ -144,9 +144,11 @@ cmd_new_session_exec(void *ptr, struct cmd_ctx *ctx)
sx = c->sx; sx = c->sx;
sy = c->sy; sy = c->sy;
} }
if (sy < status_lines)
sy = status_lines + 1; slines = options_get_number(&global_options, "status-lines");
sy -= status_lines; if (sy < slines)
sy = slines + 1;
sy -= slines;
if (!data->flag_detached && tty_open(&c->tty, &cause) != 0) { if (!data->flag_detached && tty_open(&c->tty, &cause) != 0) {
ctx->error(ctx, "%s", cause); ctx->error(ctx, "%s", cause);

View File

@ -1,4 +1,4 @@
/* $Id: cmd-new-window.c,v 1.19 2008-06-03 16:55:09 nicm Exp $ */ /* $Id: cmd-new-window.c,v 1.20 2008-06-03 21:42:37 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -138,13 +138,13 @@ cmd_new_window_exec(void *ptr, struct cmd_ctx *ctx)
struct winlink *wl; struct winlink *wl;
char *cmd; char *cmd;
cmd = data->cmd;
if (cmd == NULL)
cmd = default_command;
if ((s = cmd_find_session(ctx, data->cname, data->sname)) == NULL) if ((s = cmd_find_session(ctx, data->cname, data->sname)) == NULL)
return; return;
cmd = data->cmd;
if (cmd == NULL)
cmd = options_get_string(&s->options, "default-command");
if (data->idx < 0) if (data->idx < 0)
data->idx = -1; data->idx = -1;
wl = session_new(s, data->name, cmd, data->idx); wl = session_new(s, data->name, cmd, data->idx);

View File

@ -1,4 +1,4 @@
/* $Id: cmd-send-prefix.c,v 1.11 2008-06-03 16:55:09 nicm Exp $ */ /* $Id: cmd-send-prefix.c,v 1.12 2008-06-03 21:42:37 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -41,12 +41,13 @@ const struct cmd_entry cmd_send_prefix_entry = {
void void
cmd_send_prefix_exec(void *ptr, struct cmd_ctx *ctx) cmd_send_prefix_exec(void *ptr, struct cmd_ctx *ctx)
{ {
struct session *s;
struct winlink *wl; struct winlink *wl;
if ((wl = cmd_windowonly_get(ptr, ctx, NULL)) == NULL) if ((wl = cmd_windowonly_get(ptr, ctx, &s)) == NULL)
return; return;
window_key(wl->window, prefix_key); window_key(wl->window, options_get_number(&s->options, "prefix-key"));
if (ctx->cmdclient != NULL) if (ctx->cmdclient != NULL)
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);

View File

@ -1,4 +1,4 @@
/* $Id: cmd-set-option.c,v 1.18 2008-06-03 05:35:51 nicm Exp $ */ /* $Id: cmd-set-option.c,v 1.19 2008-06-03 21:42:37 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -35,13 +35,16 @@ void cmd_set_option_recv(void **, struct buffer *);
void cmd_set_option_free(void *); void cmd_set_option_free(void *);
struct cmd_set_option_data { struct cmd_set_option_data {
char *cname;
char *sname;
int flag_global;
char *option; char *option;
char *value; char *value;
}; };
const struct cmd_entry cmd_set_option_entry = { const struct cmd_entry cmd_set_option_entry = {
"set-option", "set", "set-option", "set",
"option value", "[-c client-tty|-s session-name] option value",
0, 0,
cmd_set_option_parse, cmd_set_option_parse,
cmd_set_option_exec, cmd_set_option_exec,
@ -59,11 +62,28 @@ cmd_set_option_parse(
int opt; int opt;
*ptr = data = xmalloc(sizeof *data); *ptr = data = xmalloc(sizeof *data);
data->cname = NULL;
data->sname = NULL;
data->flag_global = 1;
data->option = NULL; data->option = NULL;
data->value = NULL; data->value = NULL;
while ((opt = getopt(argc, argv, "")) != EOF) { while ((opt = getopt(argc, argv, "c:s:")) != EOF) {
switch (opt) { switch (opt) {
case 'c':
if (data->sname != NULL)
goto usage;
if (data->cname == NULL)
data->cname = xstrdup(optarg);
data->flag_global = 0;
break;
case 's':
if (data->cname != NULL)
goto usage;
if (data->sname == NULL)
data->sname = xstrdup(optarg);
data->flag_global = 0;
break;
default: default:
goto usage; goto usage;
} }
@ -91,13 +111,22 @@ cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx)
{ {
struct cmd_set_option_data *data = ptr; struct cmd_set_option_data *data = ptr;
struct client *c; struct client *c;
struct session *s;
struct options *oo;
const char *errstr; const char *errstr;
u_int i; u_int i;
int number, bool, key; int number, bool, key;
u_char colour;
if (data == NULL) if (data == NULL)
return; return;
if (data->flag_global ||
((s = cmd_find_session(ctx, data->cname, data->sname))) == NULL)
oo = &global_options;
else
oo = &s->options;
if (*data->option == '\0') { if (*data->option == '\0') {
ctx->error(ctx, "invalid option"); ctx->error(ctx, "invalid option");
return; return;
@ -127,13 +156,13 @@ cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx)
ctx->error(ctx, "unknown key: %s", data->value); ctx->error(ctx, "unknown key: %s", data->value);
return; return;
} }
prefix_key = key; options_set_number(oo, "prefix-key", key);
} else if (strcmp(data->option, "status") == 0) { } else if (strcmp(data->option, "status") == 0) {
if (bool == -1) { if (bool == -1) {
ctx->error(ctx, "bad value: %s", data->value); ctx->error(ctx, "bad value: %s", data->value);
return; return;
} }
status_lines = bool; options_set_number(oo, "status-lines", bool);
recalculate_sizes(); recalculate_sizes();
} else if (strcmp(data->option, "status-fg") == 0) { } else if (strcmp(data->option, "status-fg") == 0) {
if (data->value == NULL) { if (data->value == NULL) {
@ -145,9 +174,13 @@ cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx)
ctx->error(ctx, "bad colour: %s", data->value); ctx->error(ctx, "bad colour: %s", data->value);
return; return;
} }
status_colour &= 0x0f;
status_colour |= number << 4; colour = options_get_number(oo, "status-colour");
if (status_lines > 0) { colour &= 0x0f;
colour |= number << 4;
options_set_number(oo, "status-colour", colour);
if (options_get_number(oo, "status-lines") > 0) {
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);
if (c != NULL && c->session != NULL) if (c != NULL && c->session != NULL)
@ -164,9 +197,13 @@ cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx)
ctx->error(ctx, "bad colour: %s", data->value); ctx->error(ctx, "bad colour: %s", data->value);
return; return;
} }
status_colour &= 0xf0;
status_colour |= number; colour = options_get_number(oo, "status-colour");
if (status_lines > 0) { colour &= 0xf0;
colour |= number;
options_set_number(oo, "status-colour", colour);
if (options_get_number(oo, "status-lines") > 0) {
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);
if (c != NULL && c->session != NULL) if (c != NULL && c->session != NULL)
@ -179,22 +216,22 @@ cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx)
return; return;
} }
if (strcmp(data->value, "any") == 0) if (strcmp(data->value, "any") == 0)
bell_action = BELL_ANY; number = BELL_ANY;
else if (strcmp(data->value, "none") == 0) else if (strcmp(data->value, "none") == 0)
bell_action = BELL_NONE; number = BELL_NONE;
else if (strcmp(data->value, "current") == 0) else if (strcmp(data->value, "current") == 0)
bell_action = BELL_CURRENT; number = BELL_CURRENT;
else { else {
ctx->error(ctx, "unknown bell-action: %s", data->value); ctx->error(ctx, "unknown bell-action: %s", data->value);
return; return;
} }
options_set_number(oo, "bell-action", number);
} else if (strcmp(data->option, "default-command") == 0) { } else if (strcmp(data->option, "default-command") == 0) {
if (data->value == NULL) { if (data->value == NULL) {
ctx->error(ctx, "invalid value"); ctx->error(ctx, "invalid value");
return; return;
} }
xfree(default_command); options_set_string(oo, "default-command", "%s", data->value);
default_command = xstrdup(data->value);
} else if (strcmp(data->option, "history-limit") == 0) { } else if (strcmp(data->option, "history-limit") == 0) {
if (data->value == NULL) { if (data->value == NULL) {
ctx->error(ctx, "invalid value"); ctx->error(ctx, "invalid value");
@ -204,7 +241,7 @@ cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx)
ctx->error(ctx, "history-limit too big: %u", number); ctx->error(ctx, "history-limit too big: %u", number);
return; return;
} }
history_limit = number; options_set_number(oo, "history-limit", number);
} else { } else {
ctx->error(ctx, "unknown option: %s", data->option); ctx->error(ctx, "unknown option: %s", data->option);
return; return;
@ -219,6 +256,9 @@ cmd_set_option_send(void *ptr, struct buffer *b)
{ {
struct cmd_set_option_data *data = ptr; struct cmd_set_option_data *data = ptr;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->cname);
cmd_send_string(b, data->sname);
cmd_send_string(b, data->option); cmd_send_string(b, data->option);
cmd_send_string(b, data->value); cmd_send_string(b, data->value);
} }
@ -229,6 +269,9 @@ cmd_set_option_recv(void **ptr, struct buffer *b)
struct cmd_set_option_data *data; struct cmd_set_option_data *data;
*ptr = data = xmalloc(sizeof *data); *ptr = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->cname = cmd_recv_string(b);
data->sname = cmd_recv_string(b);
data->option = cmd_recv_string(b); data->option = cmd_recv_string(b);
data->value = cmd_recv_string(b); data->value = cmd_recv_string(b);
} }
@ -238,6 +281,10 @@ cmd_set_option_free(void *ptr)
{ {
struct cmd_set_option_data *data = ptr; struct cmd_set_option_data *data = ptr;
if (data->cname != NULL)
xfree(data->cname);
if (data->sname != NULL)
xfree(data->sname);
if (data->option != NULL) if (data->option != NULL)
xfree(data->option); xfree(data->option);
if (data->value != NULL) if (data->value != NULL)

139
options.c Normal file
View File

@ -0,0 +1,139 @@
/* $Id: options.c,v 1.1 2008-06-03 21:42:37 nicm Exp $ */
/*
* Copyright (c) 2008 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 <stdarg.h>
#include <string.h>
#include "tmux.h"
/*
* Option handling; each option has a name, type and value and is stored in
* a splay tree.
*/
SPLAY_GENERATE(options_tree, options_entry, entry, options_cmp);
int
options_cmp(struct options_entry *o1, struct options_entry *o2)
{
return (strcmp(o1->name, o2->name));
}
void
options_init(struct options *oo, struct options *parent)
{
SPLAY_INIT(&oo->tree);
oo->parent = parent;
}
void
options_free(struct options *oo)
{
struct options_entry *o;
while (!SPLAY_EMPTY(&oo->tree)) {
o = SPLAY_ROOT(&oo->tree);
SPLAY_REMOVE(options_tree, &oo->tree, o);
xfree(o->name);
if (o->type == OPTIONS_STRING)
xfree(o->value.string);
xfree(o);
}
}
void printflike3
options_set_string(struct options *oo, const char *name, const char *fmt, ...)
{
struct options_entry *o, p;
va_list ap;
p.name = name;
o = SPLAY_FIND(options_tree, &oo->tree, &p);
if (o == NULL) {
o = xmalloc(sizeof *o);
o->name = xstrdup(name);
SPLAY_INSERT(options_tree, &oo->tree, o);
} else if (o->type == OPTIONS_STRING)
xfree(o->value.string);
va_start(ap, fmt);
o->type = OPTIONS_STRING;
xvasprintf(&o->value.string, fmt, ap);
va_end(ap);
}
char *
options_get_string(struct options *oo, const char *name)
{
struct options_entry *o, p;
p.name = name;
o = SPLAY_FIND(options_tree, &oo->tree, &p);
while (o == NULL) {
oo = oo->parent;
o = SPLAY_FIND(options_tree, &oo->tree, &p);
if (o != NULL)
break;
}
if (o == NULL)
fatalx("missing option");
if (o->type != OPTIONS_STRING)
fatalx("option not a string");
return (o->value.string);
}
void
options_set_number(struct options *oo, const char *name, long long value)
{
struct options_entry *o, p;
p.name = name;
o = SPLAY_FIND(options_tree, &oo->tree, &p);
if (o == NULL) {
o = xmalloc(sizeof *o);
o->name = xstrdup(name);
SPLAY_INSERT(options_tree, &oo->tree, o);
} else if (o->type == OPTIONS_STRING)
xfree(o->value.string);
o->type = OPTIONS_NUMBER;
o->value.number = value;
}
int
options_get_number(struct options *oo, const char *name)
{
struct options_entry *o, p;
p.name = name;
o = SPLAY_FIND(options_tree, &oo->tree, &p);
while (o == NULL) {
oo = oo->parent;
o = SPLAY_FIND(options_tree, &oo->tree, &p);
if (o != NULL)
break;
}
if (o == NULL)
fatalx("missing option");
if (o->type != OPTIONS_NUMBER)
fatalx("option not a number");
return (o->value.number);
}

View File

@ -1,4 +1,4 @@
/* $Id: resize.c,v 1.10 2008-06-01 20:32:41 nicm Exp $ */ /* $Id: resize.c,v 1.11 2008-06-03 21:42:37 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -48,7 +48,7 @@ recalculate_sizes(void)
struct session *s; struct session *s;
struct client *c; struct client *c;
struct window *w; struct window *w;
u_int i, j, ssx, ssy; u_int i, j, ssx, ssy, slines;
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
s = ARRAY_ITEM(&sessions, i); s = ARRAY_ITEM(&sessions, i);
@ -73,9 +73,10 @@ recalculate_sizes(void)
} }
s->flags &= ~SESSION_UNATTACHED; s->flags &= ~SESSION_UNATTACHED;
if (ssy < status_lines) slines = options_get_number(&s->options, "status-lines");
ssy = status_lines + 1; if (ssy < slines)
ssy -= status_lines; ssy = slines + 1;
ssy -= slines;
if (s->sx == ssx && s->sy == ssy) if (s->sx == ssx && s->sy == ssy)
continue; continue;

View File

@ -1,4 +1,4 @@
/* $Id: screen.c,v 1.59 2008-01-03 21:32:11 nicm Exp $ */ /* $Id: screen.c,v 1.60 2008-06-03 21:42:37 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -128,7 +128,7 @@ screen_stringcolour(const char *s)
/* Create a new screen. */ /* Create a new screen. */
void void
screen_create(struct screen *s, u_int dx, u_int dy) screen_create(struct screen *s, u_int dx, u_int dy, u_int hlimit)
{ {
s->dx = dx; s->dx = dx;
s->dy = dy; s->dy = dy;
@ -139,7 +139,7 @@ screen_create(struct screen *s, u_int dx, u_int dy)
s->rlower = s->dy - 1; s->rlower = s->dy - 1;
s->hsize = 0; s->hsize = 0;
s->hlimit = history_limit; s->hlimit = hlimit;
s->attr = SCREEN_DEFATTR; s->attr = SCREEN_DEFATTR;
s->colr = SCREEN_DEFCOLR; s->colr = SCREEN_DEFCOLR;

View File

@ -1,4 +1,4 @@
/* $Id: server-fn.c,v 1.37 2008-06-02 18:08:17 nicm Exp $ */ /* $Id: server-fn.c,v 1.38 2008-06-03 21:42:37 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -182,6 +182,9 @@ server_write_message(struct client *c, const char *fmt, ...)
va_list ap; va_list ap;
char *msg; char *msg;
size_t size; size_t size;
u_int slines;
slines = options_get_number(&c->session->options, "status-lines");
screen_redraw_start_client(&ctx, c); screen_redraw_start_client(&ctx, c);
screen_redraw_move_cursor(&ctx, 0, c->sy - 1); screen_redraw_move_cursor(&ctx, 0, c->sy - 1);
@ -203,7 +206,7 @@ server_write_message(struct client *c, const char *fmt, ...)
buffer_flush(c->tty.fd, c->tty.in, c->tty.out); buffer_flush(c->tty.fd, c->tty.in, c->tty.out);
usleep(750000); usleep(750000);
if (status_lines == 0) { if (slines == 0) {
screen_redraw_lines(&ctx, c->sy - 1, 1); screen_redraw_lines(&ctx, c->sy - 1, 1);
screen_redraw_stop(&ctx); screen_redraw_stop(&ctx);
} else { } else {

View File

@ -1,4 +1,4 @@
/* $Id: server.c,v 1.48 2008-06-02 21:16:21 nicm Exp $ */ /* $Id: server.c,v 1.49 2008-06-03 21:42:37 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -364,14 +364,15 @@ void
server_handle_client(struct client *c) server_handle_client(struct client *c)
{ {
struct window *w = c->session->curw->window; struct window *w = c->session->curw->window;
int key; int key, prefix;
prefix = options_get_number(&c->session->options, "prefix-key");
while (tty_keys_next(&c->tty, &key) == 0) { while (tty_keys_next(&c->tty, &key) == 0) {
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;
continue; continue;
} else if (key == prefix_key) } else if (key == prefix)
c->flags |= CLIENT_PREFIX; c->flags |= CLIENT_PREFIX;
else else
window_key(w, key); window_key(w, key);
@ -413,21 +414,19 @@ server_handle_window(struct window *w)
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
s = ARRAY_ITEM(&sessions, i); s = ARRAY_ITEM(&sessions, i);
if (s != NULL) if (s == NULL || !session_has(s, w))
session_addbell(s, w); continue;
} session_addbell(s, w);
switch (bell_action) { switch (options_get_number(&s->options, "bell-action")) {
case BELL_ANY: case BELL_ANY:
tty_write_window(w, TTY_CHARACTER, '\007'); tty_write_session(s, TTY_CHARACTER, '\007');
break; break;
case BELL_CURRENT: case BELL_CURRENT:
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { if (s->curw->window == w)
s = ARRAY_ITEM(&sessions, i);
if (s != NULL && s->curw->window == w)
tty_write_session(s, TTY_CHARACTER, '\007'); tty_write_session(s, TTY_CHARACTER, '\007');
break;
} }
break;
} }
server_status_window(w); server_status_window(w);

View File

@ -1,4 +1,4 @@
/* $Id: session.c,v 1.32 2008-06-03 18:13:54 nicm Exp $ */ /* $Id: session.c,v 1.33 2008-06-03 21:42:37 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -95,7 +95,8 @@ session_create(const char *name, const char *cmd, u_int sx, u_int sy)
s->curw = s->lastw = NULL; s->curw = s->lastw = NULL;
RB_INIT(&s->windows); RB_INIT(&s->windows);
ARRAY_INIT(&s->bells); ARRAY_INIT(&s->bells);
options_init(&s->options, &global_options);
s->sx = sx; s->sx = sx;
s->sy = sy; s->sy = sy;
@ -137,6 +138,8 @@ session_destroy(struct session *s)
while (!ARRAY_EMPTY(&sessions) && ARRAY_LAST(&sessions) == NULL) while (!ARRAY_EMPTY(&sessions) && ARRAY_LAST(&sessions) == NULL)
ARRAY_TRUNC(&sessions, 1); ARRAY_TRUNC(&sessions, 1);
options_free(&s->options);
while (!RB_EMPTY(&s->windows)) while (!RB_EMPTY(&s->windows))
winlink_remove(&s->windows, RB_ROOT(&s->windows)); winlink_remove(&s->windows, RB_ROOT(&s->windows));
@ -162,14 +165,15 @@ session_new(struct session *s, const char *name, const char *cmd, int idx)
struct window *w; struct window *w;
const char *env[] = { NULL, "TERM=screen", NULL }; const char *env[] = { NULL, "TERM=screen", NULL };
char buf[256]; char buf[256];
u_int i; u_int i, hlimit;
if (session_index(s, &i) != 0) if (session_index(s, &i) != 0)
fatalx("session not found"); fatalx("session not found");
xsnprintf(buf, sizeof buf, "TMUX=%ld,%u", (long) getpid(), i); xsnprintf(buf, sizeof buf, "TMUX=%ld,%u", (long) getpid(), i);
env[0] = buf; env[0] = buf;
if ((w = window_create(name, cmd, env, s->sx, s->sy)) == NULL) hlimit = options_get_number(&s->options, "history-limit");
if ((w = window_create(name, cmd, env, s->sx, s->sy, hlimit)) == NULL)
return (NULL); return (NULL);
return (session_attach(s, w, idx)); return (session_attach(s, w, idx));
} }

View File

@ -1,4 +1,4 @@
/* $Id: status.c,v 1.18 2008-01-03 21:32:11 nicm Exp $ */ /* $Id: status.c,v 1.19 2008-06-03 21:42:37 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -30,13 +30,17 @@ status_write_client(struct client *c)
struct screen_redraw_ctx ctx; struct screen_redraw_ctx ctx;
struct winlink *wl; struct winlink *wl;
char flag; char flag;
u_char scolour;
u_int slines;
if (status_lines == 0 || c->sy <= status_lines) scolour = options_get_number(&c->session->options, "status-colour");
slines = options_get_number(&c->session->options, "status-lines");
if (slines == 0 || c->sy <= slines)
return; return;
screen_redraw_start_client(&ctx, c); screen_redraw_start_client(&ctx, c);
screen_redraw_move_cursor(&ctx, 0, c->sy - status_lines); screen_redraw_move_cursor(&ctx, 0, c->sy - slines);
screen_redraw_set_attributes(&ctx, 0, status_colour); screen_redraw_set_attributes(&ctx, 0, scolour);
RB_FOREACH(wl, winlinks, &c->session->windows) { RB_FOREACH(wl, winlinks, &c->session->windows) {
flag = ' '; flag = ' ';

28
tmux.c
View File

@ -1,4 +1,4 @@
/* $Id: tmux.c,v 1.50 2008-06-03 18:13:54 nicm Exp $ */ /* $Id: tmux.c,v 1.51 2008-06-03 21:42:37 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -42,15 +42,12 @@ const char *_malloc_options = "AJX";
volatile sig_atomic_t sigwinch; volatile sig_atomic_t sigwinch;
volatile sig_atomic_t sigterm; volatile sig_atomic_t sigterm;
char *cfg_file; char *cfg_file;
char *default_command; struct options global_options;
char *paste_buffer; char *paste_buffer;
int bell_action;
int debug_level; int debug_level;
int prefix_key = META;
u_char status_colour;
u_int history_limit;
u_int status_lines;
void sighandler(int); void sighandler(int);
__dead void usage(void); __dead void usage(void);
@ -201,12 +198,12 @@ main(int argc, char **argv)
log_open(stderr, LOG_USER, debug_level); log_open(stderr, LOG_USER, debug_level);
siginit(); siginit();
status_lines = 1; options_init(&global_options, NULL);
status_colour = 0x02; options_set_number(&global_options, "status-lines", 1);
options_set_number(&global_options, "status-colour", 0x02);
bell_action = BELL_ANY; options_set_number(&global_options, "bell-action", BELL_ANY);
options_set_number(&global_options, "history-limit", 2000);
history_limit = 2000; options_set_number(&global_options, "prefix-key", META);
paste_buffer = NULL; paste_buffer = NULL;
@ -260,7 +257,8 @@ main(int argc, char **argv)
if (shell == NULL || *shell == '\0') if (shell == NULL || *shell == '\0')
shell = _PATH_BSHELL; shell = _PATH_BSHELL;
} }
xasprintf(&default_command, "exec %s", shell); options_set_string(
&global_options, "default-command", "exec %s", shell);
if (argc == 0) { if (argc == 0) {
cmd = xmalloc(sizeof *cmd); cmd = xmalloc(sizeof *cmd);
@ -334,7 +332,7 @@ main(int argc, char **argv)
} }
out: out:
xfree(default_command); options_free(&global_options);
close(cctx.srv_fd); close(cctx.srv_fd);
buffer_destroy(cctx.srv_in); buffer_destroy(cctx.srv_in);

46
tmux.h
View File

@ -1,4 +1,4 @@
/* $Id: tmux.h,v 1.124 2008-06-03 18:13:54 nicm Exp $ */ /* $Id: tmux.h,v 1.125 2008-06-03 21:42:37 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -533,6 +533,27 @@ struct winlink {
}; };
RB_HEAD(winlinks, winlink); RB_HEAD(winlinks, winlink);
/* Option data structures. */
struct options_entry {
char *name;
enum {
OPTIONS_STRING,
OPTIONS_NUMBER
} type;
union {
char *string;
long long number;
} value;
SPLAY_ENTRY(options_entry) entry;
};
struct options {
SPLAY_HEAD(options_tree, options_entry) tree;
struct options *parent;
};
/* Client session. */ /* Client session. */
struct session { struct session {
char *name; char *name;
@ -545,6 +566,8 @@ struct session {
struct winlink *lastw; struct winlink *lastw;
struct winlinks windows; struct winlinks windows;
struct options options;
ARRAY_DECL(, struct winlink *) bells; /* windows with bells */ ARRAY_DECL(, struct winlink *) bells; /* windows with bells */
#define SESSION_UNATTACHED 0x1 /* not attached to any clients */ #define SESSION_UNATTACHED 0x1 /* not attached to any clients */
@ -685,15 +708,13 @@ extern volatile sig_atomic_t sigterm;
#define BELL_NONE 0 #define BELL_NONE 0
#define BELL_ANY 1 #define BELL_ANY 1
#define BELL_CURRENT 2 #define BELL_CURRENT 2
extern struct options global_options;
extern char *default_command; extern char *default_command;
extern char *cfg_file; extern char *cfg_file;
extern char *paste_buffer; extern char *paste_buffer;
extern int bell_action; extern int bell_action;
extern int debug_level; extern int debug_level;
extern int prefix_key;
extern u_char status_colour;
extern u_int history_limit; extern u_int history_limit;
extern u_int status_lines;
void logfile(const char *); void logfile(const char *);
void siginit(void); void siginit(void);
void sigreset(void); void sigreset(void);
@ -701,6 +722,17 @@ void sigreset(void);
/* cfg.c */ /* cfg.c */
int load_cfg(const char *, char **x); int load_cfg(const char *, char **x);
/* options.c */
int options_cmp(struct options_entry *, struct options_entry *);
SPLAY_PROTOTYPE(options_tree, options_entry, entry, options_cmp);
void options_init(struct options *, struct options *);
void options_free(struct options *);
void printflike3 options_set_string(
struct options *, const char *, const char *, ...);
char *options_get_string(struct options *, const char *);
void options_set_number(struct options *, const char *, long long);
int options_get_number(struct options *, const char *);
/* tty.c */ /* tty.c */
void tty_init(struct tty *, char *, char *); void tty_init(struct tty *, char *, char *);
int tty_open(struct tty *, char **); int tty_open(struct tty *, char **);
@ -937,7 +969,7 @@ void screen_redraw_lines(struct screen_redraw_ctx *, u_int, u_int);
/* screen.c */ /* screen.c */
const char *screen_colourstring(u_char); const char *screen_colourstring(u_char);
u_char screen_stringcolour(const char *); u_char screen_stringcolour(const char *);
void screen_create(struct screen *, u_int, u_int); void screen_create(struct screen *, u_int, u_int, u_int);
void screen_destroy(struct screen *); void screen_destroy(struct screen *);
void screen_resize(struct screen *, u_int, u_int); void screen_resize(struct screen *, u_int, u_int);
void screen_expand_line(struct screen *, u_int, u_int); void screen_expand_line(struct screen *, u_int, u_int);
@ -967,8 +999,8 @@ struct winlink *winlink_add(struct winlinks *, struct window *, int);
void winlink_remove(struct winlinks *, struct winlink *); void winlink_remove(struct winlinks *, struct winlink *);
struct winlink *winlink_next(struct winlinks *, struct winlink *); struct winlink *winlink_next(struct winlinks *, struct winlink *);
struct winlink *winlink_previous(struct winlinks *, struct winlink *); struct winlink *winlink_previous(struct winlinks *, struct winlink *);
struct window *window_create( struct window *window_create(const char *,
const char *, const char *, const char **, u_int, u_int); const char *, const char **, u_int, u_int, u_int);
void window_destroy(struct window *); void window_destroy(struct window *);
int window_resize(struct window *, u_int, u_int); int window_resize(struct window *, u_int, u_int);
int window_set_mode(struct window *, const struct window_mode *); int window_set_mode(struct window *, const struct window_mode *);

View File

@ -1,4 +1,4 @@
/* $Id: window-copy.c,v 1.15 2007-12-07 09:49:18 nicm Exp $ */ /* $Id: window-copy.c,v 1.16 2008-06-03 21:42:37 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -91,7 +91,7 @@ window_copy_init(struct window *w)
data->cy = w->base.cy; data->cy = w->base.cy;
s = &data->screen; s = &data->screen;
screen_create(s, screen_size_x(&w->base), screen_size_y(&w->base)); screen_create(s, screen_size_x(&w->base), screen_size_y(&w->base), 0);
s->cx = data->cx; s->cx = data->cx;
s->cy = data->cy; s->cy = data->cy;
@ -202,7 +202,8 @@ window_copy_write_line(
size_t size; size_t size;
if (py == 0) { if (py == 0) {
screen_write_set_attributes(ctx, 0, status_colour); screen_write_set_attributes(
ctx, ATTR_BRIGHT|ATTR_REVERSE, 0x70);
screen_write_move_cursor(ctx, 0, 0); screen_write_move_cursor(ctx, 0, 0);
size = screen_write_put_string_rjust( size = screen_write_put_string_rjust(
ctx, "[%u,%u/%u]", data->ox, data->oy, w->base.hsize); ctx, "[%u,%u/%u]", data->ox, data->oy, w->base.hsize);

View File

@ -1,4 +1,4 @@
/* $Id: window-more.c,v 1.10 2008-01-03 21:32:11 nicm Exp $ */ /* $Id: window-more.c,v 1.11 2008-06-03 21:42:37 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -92,7 +92,7 @@ window_more_init(struct window *w)
data->top = 0; data->top = 0;
s = &data->screen; s = &data->screen;
screen_create(s, screen_size_x(&w->base), screen_size_y(&w->base)); screen_create(s, screen_size_x(&w->base), screen_size_y(&w->base), 0);
s->mode &= ~MODE_CURSOR; s->mode &= ~MODE_CURSOR;
return (s); return (s);
@ -171,7 +171,8 @@ window_more_write_line(struct window *w, struct screen_write_ctx *ctx, u_int py)
size_t size; size_t size;
if (py == 0) { if (py == 0) {
screen_write_set_attributes(ctx, 0, status_colour); screen_write_set_attributes(
ctx, ATTR_BRIGHT|ATTR_REVERSE, 0x70);
screen_write_move_cursor(ctx, 0, 0); screen_write_move_cursor(ctx, 0, 0);
size = screen_write_put_string_rjust( size = screen_write_put_string_rjust(
ctx, "[%u/%u]", data->top, ARRAY_LENGTH(&data->list)); ctx, "[%u/%u]", data->top, ARRAY_LENGTH(&data->list));

View File

@ -1,4 +1,4 @@
/* $Id: window-scroll.c,v 1.17 2008-01-03 21:32:11 nicm Exp $ */ /* $Id: window-scroll.c,v 1.18 2008-06-03 21:42:37 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -65,7 +65,7 @@ window_scroll_init(struct window *w)
data->oy = 0; data->oy = 0;
s = &data->screen; s = &data->screen;
screen_create(s, screen_size_x(&w->base), screen_size_y(&w->base)); screen_create(s, screen_size_x(&w->base), screen_size_y(&w->base), 0);
s->mode &= ~MODE_CURSOR; s->mode &= ~MODE_CURSOR;
screen_write_start(&ctx, s, NULL, NULL); screen_write_start(&ctx, s, NULL, NULL);
@ -153,7 +153,8 @@ window_scroll_write_line(
size_t size; size_t size;
if (py == 0) { if (py == 0) {
screen_write_set_attributes(ctx, 0, status_colour); screen_write_set_attributes(
ctx, ATTR_BRIGHT|ATTR_REVERSE, 0x70);
screen_write_move_cursor(ctx, 0, 0); screen_write_move_cursor(ctx, 0, 0);
size = screen_write_put_string_rjust( size = screen_write_put_string_rjust(
ctx, "[%u,%u/%u]", data->ox, data->oy, w->base.hsize); ctx, "[%u,%u/%u]", data->ox, data->oy, w->base.hsize);

View File

@ -1,4 +1,4 @@
/* $Id: window.c,v 1.37 2008-06-03 18:38:51 nicm Exp $ */ /* $Id: window.c,v 1.38 2008-06-03 21:42:37 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -145,8 +145,8 @@ winlink_previous(unused struct winlinks *wwl, struct winlink *wl)
} }
struct window * struct window *
window_create( window_create(const char *name,
const char *name, const char *cmd, const char **env, u_int sx, u_int sy) const char *cmd, const char **env, u_int sx, u_int sy, u_int hlimit)
{ {
struct window *w; struct window *w;
struct winsize ws; struct winsize ws;
@ -186,7 +186,7 @@ window_create(
w->in = buffer_create(BUFSIZ); w->in = buffer_create(BUFSIZ);
w->out = buffer_create(BUFSIZ); w->out = buffer_create(BUFSIZ);
w->mode = NULL; w->mode = NULL;
screen_create(&w->base, sx, sy); screen_create(&w->base, sx, sy, hlimit);
w->screen = &w->base; w->screen = &w->base;
input_init(w); input_init(w);