String/number arguments..

This commit is contained in:
Nicholas Marriott 2007-10-03 12:34:16 +00:00
parent dadc56d754
commit fe06744d66
9 changed files with 203 additions and 126 deletions

View File

@ -1,5 +1,6 @@
03 October 2007
* (nicm) String number arguments. So you can do: tmux bind ^Q create "blah".
* (nicm) Key binding. tmux bind key command [argument] and tmux unbind key.
Key names are in a table in key-string.c, plus A is A, ^A is ctrl-A.
Possible commands are in cmd.c (look at cmd_bind_table).
@ -98,5 +99,5 @@
(including mutt, emacs). No status bar yet and no key remapping or other
customisation.
$Id: CHANGES,v 1.24 2007-10-03 11:26:33 nicm Exp $
$Id: CHANGES,v 1.25 2007-10-03 12:34:16 nicm Exp $

2
TODO
View File

@ -34,6 +34,7 @@
packet... hrm. already scanning output for \e, could add an extra
byte to it for message
- could use bsearch all over the place
- better errors when creating new windows/sessions (how?)
-- For 0.1 --------------------------------------------------------------------
- man page
@ -49,6 +50,7 @@
set status on/off
set meta
set shell
list-keys (list key bindings)
- fix resize (width problems with multiple clients?)
- handle tmux in tmux (check $TMUX and abort)
- check for some reqd terminfo caps on startup

View File

@ -1,4 +1,4 @@
/* $Id: client-fn.c,v 1.1 2007-10-03 10:18:31 nicm Exp $ */
/* $Id: client-fn.c,v 1.2 2007-10-03 12:34:16 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -62,6 +62,23 @@ client_write_server(
hdr.type = type;
hdr.size = len;
buffer_write(cctx->srv_out, &hdr, sizeof hdr);
if (len > 0)
if (buf != NULL)
buffer_write(cctx->srv_out, buf, len);
}
void
client_write_server2(struct client_ctx *cctx,
enum hdrtype type, void *buf1, size_t len1, void *buf2, size_t len2)
{
struct hdr hdr;
hdr.type = type;
hdr.size = len1 + len2;
buffer_write(cctx->srv_out, &hdr, sizeof hdr);
if (buf1 != NULL)
buffer_write(cctx->srv_out, buf1, len1);
if (buf2 != NULL)
buffer_write(cctx->srv_out, buf2, len2);
}

133
cmd.c
View File

@ -1,4 +1,4 @@
/* $Id: cmd.c,v 1.2 2007-10-03 11:26:34 nicm Exp $ */
/* $Id: cmd.c,v 1.3 2007-10-03 12:34:16 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -25,54 +25,49 @@
int cmd_prefix = META;
void cmd_fn_create(struct client *, int);
void cmd_fn_detach(struct client *, int);
void cmd_fn_last(struct client *, int);
void cmd_fn_meta(struct client *, int);
void cmd_fn_next(struct client *, int);
void cmd_fn_previous(struct client *, int);
void cmd_fn_refresh(struct client *, int);
void cmd_fn_select(struct client *, int);
void cmd_fn_windowinfo(struct client *, int);
void cmd_fn_create(struct client *, struct cmd *);
void cmd_fn_detach(struct client *, struct cmd *);
void cmd_fn_last(struct client *, struct cmd *);
void cmd_fn_meta(struct client *, struct cmd *);
void cmd_fn_next(struct client *, struct cmd *);
void cmd_fn_previous(struct client *, struct cmd *);
void cmd_fn_refresh(struct client *, struct cmd *);
void cmd_fn_select(struct client *, struct cmd *);
void cmd_fn_windowinfo(struct client *, struct cmd *);
struct cmd {
int key;
void (*fn)(struct client *, int);
int arg;
};
const struct cmd cmd_default[] = {
{ '0', cmd_fn_select, 0 },
{ '1', cmd_fn_select, 1 },
{ '2', cmd_fn_select, 2 },
{ '3', cmd_fn_select, 3 },
{ '4', cmd_fn_select, 4 },
{ '5', cmd_fn_select, 5 },
{ '6', cmd_fn_select, 6 },
{ '7', cmd_fn_select, 7 },
{ '8', cmd_fn_select, 8 },
{ '9', cmd_fn_select, 9 },
{ 'C', cmd_fn_create, 0 },
{ 'c', cmd_fn_create, 0 },
{ 'D', cmd_fn_detach, 0 },
{ 'd', cmd_fn_detach, 0 },
{ 'N', cmd_fn_next, 0 },
{ 'n', cmd_fn_next, 0 },
{ 'P', cmd_fn_previous, 0 },
{ 'p', cmd_fn_previous, 0 },
{ 'R', cmd_fn_refresh, 0 },
{ 'r', cmd_fn_refresh, 0 },
{ 'L', cmd_fn_last, 0 },
{ 'l', cmd_fn_last, 0 },
{ 'I', cmd_fn_windowinfo, 0 },
{ 'i', cmd_fn_windowinfo, 0 },
{ META, cmd_fn_meta, 0 },
{ '0', cmd_fn_select, 0, NULL },
{ '1', cmd_fn_select, 1, NULL },
{ '2', cmd_fn_select, 2, NULL },
{ '3', cmd_fn_select, 3, NULL },
{ '4', cmd_fn_select, 4, NULL },
{ '5', cmd_fn_select, 5, NULL },
{ '6', cmd_fn_select, 6, NULL },
{ '7', cmd_fn_select, 7, NULL },
{ '8', cmd_fn_select, 8, NULL },
{ '9', cmd_fn_select, 9, NULL },
{ 'C', cmd_fn_create, 0, NULL },
{ 'c', cmd_fn_create, 0, NULL },
{ 'D', cmd_fn_detach, 0, NULL },
{ 'd', cmd_fn_detach, 0, NULL },
{ 'N', cmd_fn_next, 0, NULL },
{ 'n', cmd_fn_next, 0, NULL },
{ 'P', cmd_fn_previous, 0, NULL },
{ 'p', cmd_fn_previous, 0, NULL },
{ 'R', cmd_fn_refresh, 0, NULL },
{ 'r', cmd_fn_refresh, 0, NULL },
{ 'L', cmd_fn_last, 0, NULL },
{ 'l', cmd_fn_last, 0, NULL },
{ 'I', cmd_fn_windowinfo, 0, NULL },
{ 'i', cmd_fn_windowinfo, 0, NULL },
{ META, cmd_fn_meta, 0, NULL },
};
u_int cmd_count = (sizeof cmd_default / sizeof cmd_default[0]);
struct cmd *cmd_table;
const struct bind cmd_bind_table[] = {
{ "select", cmd_fn_select, -1 },
{ "create", cmd_fn_create, 0 },
{ "select", cmd_fn_select, BIND_NUMBER|BIND_USER },
{ "create", cmd_fn_create, BIND_STRING|BIND_USER },
{ "detach", cmd_fn_detach, 0 },
{ "next", cmd_fn_next, 0 },
{ "previous", cmd_fn_previous, 0 },
@ -98,7 +93,7 @@ cmd_lookup_bind(const char *name)
}
void
cmd_add_bind(int key, int arg, const struct bind *bind)
cmd_add_bind(int key, u_int num, char *str, const struct bind *bind)
{
struct cmd *cmd = NULL;
u_int i;
@ -124,10 +119,12 @@ cmd_add_bind(int key, int arg, const struct bind *bind)
cmd->key = key;
cmd->fn = bind->fn;
if (bind->arg != -1)
cmd->arg = bind->arg;
else
cmd->arg = arg;
if (bind->flags & BIND_USER) {
if (bind->flags & BIND_STRING)
cmd->str = xstrdup(str);
if (bind->flags & BIND_NUMBER)
cmd->num = num;
}
}
void
@ -155,6 +152,7 @@ cmd_init(void)
void
cmd_free(void)
{
/* XXX free strings */
xfree(cmd_table);
}
@ -167,35 +165,32 @@ cmd_dispatch(struct client *c, int key)
for (i = 0; i < cmd_count; i++) {
cmd = cmd_table + i;
if (cmd->key != KEYC_NONE && cmd->key == key)
cmd->fn(c, cmd->arg);
cmd->fn(c, cmd);
}
}
void
cmd_fn_create(struct client *c, unused int arg)
cmd_fn_create(struct client *c, struct cmd *cmd)
{
const char *shell;
char *cmd;
shell = getenv("SHELL");
if (shell == NULL)
shell = "/bin/ksh";
xasprintf(&cmd, "%s -l", shell);
if (session_new(c->session, cmd, c->sx, c->sy) != 0)
fatalx("session_new failed");
xfree(cmd);
char *s;
s = cmd->str;
if (s == NULL)
s = default_command;
if (session_new(c->session, s, c->sx, c->sy) != 0)
server_write_message(c, "%s failed", s); /* XXX */
else
server_draw_client(c, 0, c->sy - 1);
}
void
cmd_fn_detach(struct client *c, unused int arg)
cmd_fn_detach(struct client *c, unused struct cmd *cmd)
{
server_write_client(c, MSG_DETACH, NULL, 0);
}
void
cmd_fn_last(struct client *c, unused int arg)
cmd_fn_last(struct client *c, unused struct cmd *cmd)
{
if (session_last(c->session) == 0)
server_window_changed(c);
@ -204,13 +199,13 @@ cmd_fn_last(struct client *c, unused int arg)
}
void
cmd_fn_meta(struct client *c, unused int arg)
cmd_fn_meta(struct client *c, unused struct cmd *cmd)
{
window_key(c->session->window, cmd_prefix);
}
void
cmd_fn_next(struct client *c, unused int arg)
cmd_fn_next(struct client *c, unused struct cmd *cmd)
{
if (session_next(c->session) == 0)
server_window_changed(c);
@ -219,7 +214,7 @@ cmd_fn_next(struct client *c, unused int arg)
}
void
cmd_fn_previous(struct client *c, unused int arg)
cmd_fn_previous(struct client *c, unused struct cmd *cmd)
{
if (session_previous(c->session) == 0)
server_window_changed(c);
@ -228,22 +223,22 @@ cmd_fn_previous(struct client *c, unused int arg)
}
void
cmd_fn_refresh(struct client *c, unused int arg)
cmd_fn_refresh(struct client *c, unused struct cmd *cmd)
{
server_draw_client(c, 0, c->sy - 1);
}
void
cmd_fn_select(struct client *c, int arg)
cmd_fn_select(struct client *c, struct cmd *cmd)
{
if (session_select(c->session, arg) == 0)
if (session_select(c->session, cmd->num) == 0)
server_window_changed(c);
else
server_write_message(c, "Window %u not present", arg);
server_write_message(c, "Window %u not present", cmd->num);
}
void
cmd_fn_windowinfo(struct client *c, unused int arg)
cmd_fn_windowinfo(struct client *c, unused struct cmd *cmd)
{
struct window *w;
char *buf;

40
op.c
View File

@ -1,4 +1,4 @@
/* $Id: op.c,v 1.10 2007-10-03 11:26:34 nicm Exp $ */
/* $Id: op.c,v 1.11 2007-10-03 12:34:16 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -168,6 +168,9 @@ op_bind_key(char *path, int argc, char **argv)
struct client_ctx cctx;
int opt;
const char *errstr;
char *str;
size_t len;
const struct bind *bind;
optind = 1;
while ((opt = getopt(argc, argv, "?")) != EOF) {
@ -190,19 +193,46 @@ op_bind_key(char *path, int argc, char **argv)
return (1);
}
if (argc == 3) {
data.arg = strtonum(argv[2], 0, INT_MAX, &errstr);
if ((bind = cmd_lookup_bind(data.cmd)) == NULL) {
log_warnx("unknown command: %s", data.cmd);
return (1);
}
str = NULL;
len = 0;
if (bind->flags & BIND_USER) {
if (argc != 3) {
log_warnx("%s requires an argument", data.cmd);
return (1);
}
data.flags |= BIND_USER;
if (bind->flags & BIND_STRING) {
data.flags |= BIND_STRING;
str = argv[2];
len = strlen(str);
} else if (bind->flags & BIND_NUMBER) {
data.flags |= BIND_NUMBER;
data.num = strtonum(argv[2], 0, INT_MAX, &errstr);
if (errstr != NULL) {
log_warnx("argument %s: %s", errstr, argv[2]);
return (1);
}
} else
data.arg = -1;
fatalx("no argument type");
} else {
if (argc != 2) {
log_warnx("%s cannot have an argument", data.cmd);
return (1);
}
data.flags = 0;
}
if (client_init(path, &cctx, 1) != 0)
return (1);
client_write_server(&cctx, MSG_BINDKEY, &data, sizeof data);
client_write_server2(&cctx, MSG_BINDKEY, &data, sizeof data, str, len);
return (client_flush(&cctx));
}

View File

@ -1,4 +1,4 @@
/* $Id: server-fn.c,v 1.12 2007-10-03 10:18:32 nicm Exp $ */
/* $Id: server-fn.c,v 1.13 2007-10-03 12:34:16 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -230,6 +230,8 @@ server_write_message(struct client *c, const char *fmt, ...)
va_start(ap, fmt);
xvasprintf(&msg, fmt, ap);
va_end(ap);
if (strlen(msg) > c->sx - 1)
msg[c->sx - 1] = '\0';
buffer_write(c->out, msg, strlen(msg));
for (i = strlen(msg); i < c->sx; i++)
input_store8(c->out, ' ');

View File

@ -1,4 +1,4 @@
/* $Id: server-msg.c,v 1.17 2007-10-03 11:26:34 nicm Exp $ */
/* $Id: server-msg.c,v 1.18 2007-10-03 12:34:16 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -88,14 +88,13 @@ int
server_msg_fn_new(struct hdr *hdr, struct client *c)
{
struct new_data data;
const char *shell;
char *cmd, *msg;
char *msg;
if (c->session != NULL)
return (0);
if (hdr->size != sizeof data)
fatalx("bad MSG_NEW size");
buffer_read(c->in, &data, hdr->size);
buffer_read(c->in, &data, sizeof data);
c->sx = data.sx;
if (c->sx == 0)
@ -115,14 +114,9 @@ server_msg_fn_new(struct hdr *hdr, struct client *c)
return (0);
}
shell = getenv("SHELL");
if (shell == NULL)
shell = "/bin/ksh";
xasprintf(&cmd, "%s -l", shell);
c->session = session_create(data.name, cmd, c->sx, c->sy);
c->session = session_create(data.name, default_command, c->sx, c->sy);
if (c->session == NULL)
fatalx("session_create failed");
xfree(cmd);
server_write_client(c, MSG_OKAY, NULL, 0);
server_draw_client(c, 0, c->sy - 1);
@ -141,7 +135,7 @@ server_msg_fn_attach(struct hdr *hdr, struct client *c)
return (0);
if (hdr->size != sizeof data)
fatalx("bad MSG_ATTACH size");
buffer_read(c->in, &data, hdr->size);
buffer_read(c->in, &data, sizeof data);
c->sx = data.sx;
if (c->sx == 0)
@ -174,7 +168,7 @@ server_msg_fn_size(struct hdr *hdr, struct client *c)
return (0);
if (hdr->size != sizeof data)
fatalx("bad MSG_SIZE size");
buffer_read(c->in, &data, hdr->size);
buffer_read(c->in, &data, sizeof data);
c->sx = data.sx;
if (c->sx == 0)
@ -206,7 +200,7 @@ server_msg_fn_keys(struct hdr *hdr, struct client *c)
size = hdr->size;
while (size != 0) {
key = input_extract16(c->in);
key = (int16_t) input_extract16(c->in);
size -= 2;
if (c->prefix) {
@ -235,7 +229,7 @@ server_msg_fn_sessions(struct hdr *hdr, struct client *c)
if (hdr->size != sizeof data)
fatalx("bad MSG_SESSIONS size");
buffer_read(c->in, &data, hdr->size);
buffer_read(c->in, &data, sizeof data);
data.sessions = 0;
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
@ -275,7 +269,7 @@ server_msg_fn_windows(struct hdr *hdr, struct client *c)
if (hdr->size != sizeof data)
fatalx("bad MSG_WINDOWS size");
buffer_read(c->in, &data, hdr->size);
buffer_read(c->in, &data, sizeof data);
if ((s = server_find_sessid(&data.sid, &cause)) == NULL) {
server_write_error(c, "%s", cause);
@ -318,8 +312,7 @@ server_msg_fn_rename(struct hdr *hdr, struct client *c)
if (hdr->size != sizeof data)
fatalx("bad MSG_RENAME size");
buffer_read(c->in, &data, hdr->size);
buffer_read(c->in, &data, sizeof data);
data.newname[(sizeof data.newname) - 1] = '\0';
if ((s = server_find_sessid(&data.sid, &cause)) == NULL) {
@ -395,28 +388,40 @@ server_msg_fn_bindkey(struct hdr *hdr, struct client *c)
{
struct bind_data data;
const struct bind *bind;
char *str;
if (hdr->size != sizeof data)
fatalx("bad MSG_BIND size");
if (hdr->size < sizeof data)
fatalx("bad MSG_BINDKEY size");
buffer_read(c->in, &data, sizeof data);
buffer_read(c->in, &data, hdr->size);
str = NULL;
if (data.flags & BIND_STRING) {
hdr->size -= sizeof data;
if (hdr->size != 0) {
str = xmalloc(hdr->size + 1);
buffer_read(c->in, str, hdr->size);
str[hdr->size] = '\0';
}
if (*str == '\0') {
xfree(str);
str = NULL;
}
}
data.cmd[(sizeof data.cmd) - 1] = '\0';
if ((bind = cmd_lookup_bind(data.cmd)) == NULL) {
server_write_error(c, "unknown command: %s", data.cmd);
return (0);
}
if ((bind = cmd_lookup_bind(data.cmd)) == NULL)
fatalx("unknown command");
if (!(bind->flags & BIND_USER) &&
(data.flags & (BIND_NUMBER|BIND_STRING)) != 0)
fatalx("argument missing");
if ((bind->flags & BIND_USER) &&
(data.flags & (BIND_NUMBER|BIND_STRING)) == 0)
fatalx("argument required");
if (bind->arg != -1 && data.arg != -1) {
server_write_error(c, "%s cannot have an argument", data.cmd);
return (0);
}
if (bind->arg == -1 && data.arg == -1) {
server_write_error(c, "%s requires an argument", data.cmd);
return (0);
}
cmd_add_bind(data.key, data.arg, bind);
cmd_add_bind(data.key, data.num, str, bind);
if (str != NULL)
xfree(str);
server_write_client(c, MSG_OKAY, NULL, 0);
@ -430,7 +435,7 @@ server_msg_fn_unbindkey(struct hdr *hdr, struct client *c)
struct bind_data data;
if (hdr->size != sizeof data)
fatalx("bad MSG_UNBIND size");
fatalx("bad MSG_UNBINDKEY size");
buffer_read(c->in, &data, hdr->size);

9
tmux.c
View File

@ -1,4 +1,4 @@
/* $Id: tmux.c,v 1.21 2007-10-03 11:26:34 nicm Exp $ */
/* $Id: tmux.c,v 1.22 2007-10-03 12:34:16 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -36,6 +36,7 @@ volatile sig_atomic_t sigwinch;
volatile sig_atomic_t sigterm;
int debug_level;
u_int status_lines;
char *default_command;
void sighandler(int);
@ -172,6 +173,7 @@ int
main(int argc, char **argv)
{
const struct op *op, *found;
const char *shell;
char *path;
int opt;
u_int i;
@ -199,6 +201,11 @@ main(int argc, char **argv)
status_lines = 1;
shell = getenv("SHELL");
if (shell == NULL)
shell = "/bin/ksh";
xasprintf(&default_command, "%s -l", shell);
found = NULL;
for (i = 0; i < NOP; i++) {
op = op_table + i;

28
tmux.h
View File

@ -1,4 +1,4 @@
/* $Id: tmux.h,v 1.35 2007-10-03 11:26:34 nicm Exp $ */
/* $Id: tmux.h,v 1.36 2007-10-03 12:34:16 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -339,7 +339,10 @@ struct rename_data {
struct bind_data {
int key;
char cmd[MAXNAMELEN];
int arg;
int flags;
u_int num;
};
/* Attributes. */
@ -494,11 +497,23 @@ struct client_ctx {
struct winsize ws;
};
/* Key command. */
struct cmd {
int key;
void (*fn)(struct client *, struct cmd *);
u_int num;
char *str;
};
/* Key binding. */
struct bind {
const char *name;
void (*fn)(struct client *, int);
int arg; /* -1 if user specifies */
void (*fn)(struct client *, struct cmd *);
#define BIND_USER 0x1
#define BIND_NUMBER 0x2
#define BIND_STRING 0x4
int flags;
};
/* tmux.c */
@ -506,6 +521,7 @@ extern volatile sig_atomic_t sigwinch;
extern volatile sig_atomic_t sigterm;
extern int debug_level;
extern u_int status_lines;
extern char *default_command;
int usage(const char *, ...);
void logfile(const char *);
void siginit(void);
@ -532,12 +548,14 @@ int client_msg_dispatch(struct client_ctx *, char **);
/* client-fn.c */
void client_write_server(struct client_ctx *, enum hdrtype, void *, size_t);
void client_write_server2(
struct client_ctx *, enum hdrtype, void *, size_t, void *, size_t);
void client_fill_sessid(struct sessid *, char [MAXNAMELEN]);
/* cmd.c */
extern int cmd_prefix;
const struct bind *cmd_lookup_bind(const char *);
void cmd_add_bind(int, int, const struct bind *);
void cmd_add_bind(int, u_int, char *, const struct bind *);
void cmd_remove_bind(int);
void cmd_init(void);
void cmd_free(void);