From dadc56d754f2e86dec96bcf3bed54090538ce336 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Wed, 3 Oct 2007 11:26:34 +0000 Subject: [PATCH] Key binding, unbinding. --- CHANGES | 5 +- Makefile | 5 +- TODO | 2 +- cmd.c | 101 +++++++++++++++++++++-- key-string.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++++ op.c | 80 +++++++++++++++++- server-msg.c | 60 +++++++++++++- server.c | 6 +- tmux.c | 23 ++++-- tmux.h | 40 ++++++--- 10 files changed, 514 insertions(+), 31 deletions(-) create mode 100644 key-string.c diff --git a/CHANGES b/CHANGES index dedf3859..92dcfca6 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,8 @@ 03 October 2007 +* (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). * (nicm) Move command parsing into the client. Also rename some messages and tidy up a few bits. Lots more tidying up needed :-/. @@ -95,5 +98,5 @@ (including mutt, emacs). No status bar yet and no key remapping or other customisation. -$Id: CHANGES,v 1.23 2007-10-03 10:18:31 nicm Exp $ +$Id: CHANGES,v 1.24 2007-10-03 11:26:33 nicm Exp $ diff --git a/Makefile b/Makefile index d421d88e..5da175b0 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.11 2007-10-03 10:18:31 nicm Exp $ +# $Id: Makefile,v 1.12 2007-10-03 11:26:34 nicm Exp $ .SUFFIXES: .c .o .y .h .PHONY: clean @@ -18,7 +18,8 @@ META?= \002 # C-b SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ xmalloc.c xmalloc-debug.c cmd.c input.c input-keys.c screen.c window.c \ - session.c local.c log.c client.c client-msg.c client-fn.c op.c op-list.c + session.c local.c log.c client.c client-msg.c client-fn.c op.c op-list.c \ + key-string.c YACC= yacc -d diff --git a/TODO b/TODO index 5e47d696..9b05a0b4 100644 --- a/TODO +++ b/TODO @@ -33,6 +33,7 @@ IPC is arse-about-face: too much overhead. 8-byte header for each packet... hrm. already scanning output for \e, could add an extra byte to it for message +- could use bsearch all over the place -- For 0.1 -------------------------------------------------------------------- - man page @@ -48,7 +49,6 @@ set status on/off set meta set shell - bind key?? - fix resize (width problems with multiple clients?) - handle tmux in tmux (check $TMUX and abort) - check for some reqd terminfo caps on startup diff --git a/cmd.c b/cmd.c index 5132f0e1..d7ae5c3d 100644 --- a/cmd.c +++ b/cmd.c @@ -1,4 +1,4 @@ -/* $Id: cmd.c,v 1.1 2007-10-03 10:18:32 nicm Exp $ */ +/* $Id: cmd.c,v 1.2 2007-10-03 11:26:34 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -19,6 +19,7 @@ #include #include +#include #include "tmux.h" @@ -39,8 +40,7 @@ struct cmd { void (*fn)(struct client *, int); int arg; }; - -struct cmd cmd_table[] = { +const struct cmd cmd_default[] = { { '0', cmd_fn_select, 0 }, { '1', cmd_fn_select, 1 }, { '2', cmd_fn_select, 2 }, @@ -67,7 +67,96 @@ struct cmd cmd_table[] = { { 'i', cmd_fn_windowinfo, 0 }, { META, cmd_fn_meta, 0 }, }; -#define NCMD (sizeof cmd_table / sizeof cmd_table[0]) +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 }, + { "detach", cmd_fn_detach, 0 }, + { "next", cmd_fn_next, 0 }, + { "previous", cmd_fn_previous, 0 }, + { "refresh", cmd_fn_refresh, 0 }, + { "last", cmd_fn_last, 0 }, + { "window-info",cmd_fn_windowinfo, 0 }, + { "meta", cmd_fn_meta, 0 } +}; +#define NCMDBIND (sizeof cmd_bind_table / sizeof cmd_bind_table[0]) + +const struct bind * +cmd_lookup_bind(const char *name) +{ + const struct bind *bind; + u_int i; + + for (i = 0; i < NCMDBIND; i++) { + bind = cmd_bind_table + i; + if (strcmp(bind->name, name) == 0) + return (bind); + } + return (NULL); +} + +void +cmd_add_bind(int key, int arg, const struct bind *bind) +{ + struct cmd *cmd = NULL; + u_int i; + + for (i = 0; i < cmd_count; i++) { + cmd = cmd_table + i; + if (cmd->key == key) + break; + } + if (i == cmd_count) { + for (i = 0; i < cmd_count; i++) { + cmd = cmd_table + i; + if (cmd->key == KEYC_NONE) + break; + } + if (i == cmd_count) { + cmd_count++; + cmd_table = xrealloc(cmd_table, + cmd_count, sizeof cmd_table[0]); + cmd = cmd_table + cmd_count - 1; + } + } + + cmd->key = key; + cmd->fn = bind->fn; + if (bind->arg != -1) + cmd->arg = bind->arg; + else + cmd->arg = arg; +} + +void +cmd_remove_bind(int key) +{ + struct cmd *cmd; + u_int i; + + for (i = 0; i < cmd_count; i++) { + cmd = cmd_table + i; + if (cmd->key == key) { + cmd->key = KEYC_NONE; + break; + } + } +} + +void +cmd_init(void) +{ + cmd_table = xmalloc(sizeof cmd_default); + memcpy(cmd_table, cmd_default, sizeof cmd_default); +} + +void +cmd_free(void) +{ + xfree(cmd_table); +} void cmd_dispatch(struct client *c, int key) @@ -75,9 +164,9 @@ cmd_dispatch(struct client *c, int key) struct cmd *cmd; u_int i; - for (i = 0; i < NCMD; i++) { + for (i = 0; i < cmd_count; i++) { cmd = cmd_table + i; - if (cmd->key == key) + if (cmd->key != KEYC_NONE && cmd->key == key) cmd->fn(c, cmd->arg); } } diff --git a/key-string.c b/key-string.c new file mode 100644 index 00000000..5740ef6b --- /dev/null +++ b/key-string.c @@ -0,0 +1,223 @@ +/* $Id: key-string.c,v 1.1 2007-10-03 11:26:34 nicm Exp $ */ + +/* + * Copyright (c) 2007 Nicholas Marriott + * + * 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 + +#include + +#include "tmux.h" + +struct { + const char *string; + int key; +} key_string_table[] = { + { "A1", KEYC_A1 }, + { "A3", KEYC_A3 }, + { "B2", KEYC_B2 }, + { "BACKSPACE", KEYC_BACKSPACE }, + { "BEG", KEYC_BEG }, + { "BTAB", KEYC_BTAB }, + { "C1", KEYC_C1 }, + { "C3", KEYC_C3 }, + { "CANCEL", KEYC_CANCEL }, + { "CATAB", KEYC_CATAB }, + { "CLEAR", KEYC_CLEAR }, + { "CLOSE", KEYC_CLOSE }, + { "COMMAND", KEYC_COMMAND }, + { "COPY", KEYC_COPY }, + { "CREATE", KEYC_CREATE }, + { "CTAB", KEYC_CTAB }, + { "DC", KEYC_DC }, + { "DL", KEYC_DL }, + { "DOWN", KEYC_DOWN}, + { "EIC", KEYC_EIC }, + { "END", KEYC_END }, + { "ENTER", KEYC_ENTER }, + { "EOL", KEYC_EOL }, + { "EOS", KEYC_EOS }, + { "EXIT", KEYC_EXIT }, + { "F0", KEYC_F0 }, + { "F1", KEYC_F1 }, + { "F10", KEYC_F10 }, + { "F11", KEYC_F11 }, + { "F12", KEYC_F12 }, + { "F13", KEYC_F13 }, + { "F14", KEYC_F14 }, + { "F15", KEYC_F15 }, + { "F16", KEYC_F16 }, + { "F17", KEYC_F17 }, + { "F18", KEYC_F18 }, + { "F19", KEYC_F19 }, + { "F2", KEYC_F2 }, + { "F20", KEYC_F20 }, + { "F21", KEYC_F21 }, + { "F22", KEYC_F22 }, + { "F23", KEYC_F23 }, + { "F24", KEYC_F24 }, + { "F25", KEYC_F25 }, + { "F26", KEYC_F26 }, + { "F27", KEYC_F27 }, + { "F28", KEYC_F28 }, + { "F29", KEYC_F29 }, + { "F3", KEYC_F3 }, + { "F30", KEYC_F30 }, + { "F31", KEYC_F31 }, + { "F32", KEYC_F32 }, + { "F33", KEYC_F33 }, + { "F34", KEYC_F34 }, + { "F35", KEYC_F35 }, + { "F36", KEYC_F36 }, + { "F37", KEYC_F37 }, + { "F38", KEYC_F38 }, + { "F39", KEYC_F39 }, + { "F4", KEYC_F4 }, + { "F40", KEYC_F40 }, + { "F41", KEYC_F41 }, + { "F42", KEYC_F42 }, + { "F43", KEYC_F43 }, + { "F44", KEYC_F44 }, + { "F45", KEYC_F45 }, + { "F46", KEYC_F46 }, + { "F47", KEYC_F47 }, + { "F48", KEYC_F48 }, + { "F49", KEYC_F49 }, + { "F5", KEYC_F5 }, + { "F50", KEYC_F50 }, + { "F51", KEYC_F51 }, + { "F52", KEYC_F52 }, + { "F53", KEYC_F53 }, + { "F54", KEYC_F54 }, + { "F55", KEYC_F55 }, + { "F56", KEYC_F56 }, + { "F57", KEYC_F57 }, + { "F58", KEYC_F58 }, + { "F59", KEYC_F59 }, + { "F6", KEYC_F6 }, + { "F60", KEYC_F60 }, + { "F61", KEYC_F61 }, + { "F62", KEYC_F62 }, + { "F63", KEYC_F63 }, + { "F7", KEYC_F7 }, + { "F8", KEYC_F8 }, + { "F9", KEYC_F9 }, + { "FIND", KEYC_FIND }, + { "HELP", KEYC_HELP }, + { "HOME", KEYC_HOME }, + { "IC", KEYC_IC }, + { "IL", KEYC_IL }, + { "LEFT", KEYC_LEFT }, + { "LL", KEYC_LL }, + { "MARK", KEYC_MARK }, + { "MESSAGE", KEYC_MESSAGE }, + { "MOVE", KEYC_MOVE }, + { "NEXT", KEYC_NEXT }, + { "NPAGE", KEYC_NPAGE }, + { "OPEN", KEYC_OPEN }, + { "OPTIONS", KEYC_OPTIONS }, + { "PPAGE", KEYC_PPAGE }, + { "PREVIOUS", KEYC_PREVIOUS }, + { "PRINT", KEYC_PRINT }, + { "REDO", KEYC_REDO }, + { "REFERENCE", KEYC_REFERENCE }, + { "REFRESH", KEYC_REFRESH }, + { "REPLACE", KEYC_REPLACE }, + { "RESTART", KEYC_RESTART }, + { "RESUME", KEYC_RESUME }, + { "RIGHT", KEYC_RIGHT }, + { "SAVE", KEYC_SAVE }, + { "SBEG", KEYC_SBEG }, + { "SCANCEL", KEYC_SCANCEL }, + { "SCOMMAND", KEYC_SCOMMAND }, + { "SCOPY", KEYC_SCOPY }, + { "SCREATE", KEYC_SCREATE }, + { "SDC", KEYC_SDC }, + { "SDL", KEYC_SDL }, + { "SELECT", KEYC_SELECT }, + { "SEND", KEYC_SEND }, + { "SEOL", KEYC_SEOL }, + { "SEXIT", KEYC_SEXIT }, + { "SF", KEYC_SF }, + { "SFIND", KEYC_SFIND }, + { "SHELP", KEYC_SHELP }, + { "SHOME", KEYC_SHOME }, + { "SIC", KEYC_SIC }, + { "SLEFT", KEYC_SLEFT }, + { "SMESSAGE", KEYC_SMESSAGE }, + { "SMOVE", KEYC_SMOVE }, + { "SNEXT", KEYC_SNEXT }, + { "SOPTIONS", KEYC_SOPTIONS }, + { "SPREVIOUS", KEYC_SPREVIOUS }, + { "SPRINT", KEYC_SPRINT }, + { "SR", KEYC_SR }, + { "SREDO", KEYC_SREDO }, + { "SREPLACE", KEYC_SREPLACE }, + { "SRIGHT", KEYC_SRIGHT }, + { "SRSUME", KEYC_SRSUME }, + { "SSAVE", KEYC_SSAVE }, + { "SSUSPEND", KEYC_SSUSPEND }, + { "STAB", KEYC_STAB }, + { "SUNDO", KEYC_SUNDO }, + { "SUSPEND", KEYC_SUSPEND }, + { "UNDO", KEYC_UNDO }, + { "UP", KEYC_UP }, + { "^@", 0 }, + { "^A", 1 }, + { "^B", 2 }, + { "^C", 3 }, + { "^D", 4 }, + { "^E", 5 }, + { "^F", 6 }, + { "^G", 7 }, + { "^H", 8 }, + { "^I", 9 }, + { "^J", 10 }, + { "^K", 11 }, + { "^L", 12 }, + { "^M", 13 }, + { "^N", 14 }, + { "^O", 15 }, + { "^P", 16 }, + { "^Q", 17 }, + { "^R", 18 }, + { "^S", 19 }, + { "^T", 20 }, + { "^U", 21 }, + { "^V", 22 }, + { "^W", 23 }, + { "^X", 24 }, + { "^Y", 25 }, + { "^Z", 26 }, +}; +#define NKEYSTRINGS (sizeof key_string_table / sizeof key_string_table[0]) + +int +key_string_lookup(const char *string) +{ + u_int i; + + if (string[0] == '\0') + return (KEYC_NONE); + if (string[1] == '\0') + return (string[0]); + + for (i = 0; i < NKEYSTRINGS; i++) { + if (strcasecmp(string, key_string_table[i].string) == 0) + return (key_string_table[i].key); + } + return (KEYC_NONE); +} diff --git a/op.c b/op.c index 3b8aaaea..ef2a4de6 100644 --- a/op.c +++ b/op.c @@ -1,4 +1,4 @@ -/* $Id: op.c,v 1.9 2007-09-29 14:57:07 nicm Exp $ */ +/* $Id: op.c,v 1.10 2007-10-03 11:26:34 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -160,3 +160,81 @@ op_rename(char *path, int argc, char **argv) return (client_flush(&cctx)); } + +int +op_bind_key(char *path, int argc, char **argv) +{ + struct bind_data data; + struct client_ctx cctx; + int opt; + const char *errstr; + + optind = 1; + while ((opt = getopt(argc, argv, "?")) != EOF) { + switch (opt) { + default: + return (usage("bind-key key command [argument]")); + } + } + argc -= optind; + argv += optind; + if (argc != 2 && argc != 3) + return (usage("bind-key key command [argument]")); + + if ((data.key = key_string_lookup(argv[0])) == KEYC_NONE) { + log_warnx("unknown key: %s", argv[0]); + return (1); + } + if (strlcpy(data.cmd, argv[1], sizeof data.cmd) >= sizeof data.cmd) { + log_warnx("command too long: %s", argv[1]); + return (1); + } + + if (argc == 3) { + data.arg = strtonum(argv[2], 0, INT_MAX, &errstr); + if (errstr != NULL) { + log_warnx("argument %s: %s", errstr, argv[2]); + return (1); + } + } else + data.arg = -1; + + if (client_init(path, &cctx, 1) != 0) + return (1); + + client_write_server(&cctx, MSG_BINDKEY, &data, sizeof data); + + return (client_flush(&cctx)); +} + +int +op_unbind_key(char *path, int argc, char **argv) +{ + struct bind_data data; + struct client_ctx cctx; + int opt; + + optind = 1; + while ((opt = getopt(argc, argv, "?")) != EOF) { + switch (opt) { + default: + return (usage("unbind-key key")); + } + } + argc -= optind; + argv += optind; + if (argc != 1) + return (usage("unbind-key key")); + + if ((data.key = key_string_lookup(argv[0])) == KEYC_NONE) { + log_warnx("unknown key: %s", argv[0]); + return (1); + } + + if (client_init(path, &cctx, 1) != 0) + return (1); + + client_write_server(&cctx, MSG_UNBINDKEY, &data, sizeof data); + + return (client_flush(&cctx)); +} diff --git a/server-msg.c b/server-msg.c index 5f2a421b..7c22d682 100644 --- a/server-msg.c +++ b/server-msg.c @@ -1,4 +1,4 @@ -/* $Id: server-msg.c,v 1.16 2007-10-03 10:18:32 nicm Exp $ */ +/* $Id: server-msg.c,v 1.17 2007-10-03 11:26:34 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -25,11 +25,13 @@ #include "tmux.h" int server_msg_fn_attach(struct hdr *, struct client *); +int server_msg_fn_bindkey(struct hdr *, struct client *); int server_msg_fn_keys(struct hdr *, struct client *); int server_msg_fn_new(struct hdr *, struct client *); int server_msg_fn_rename(struct hdr *, struct client *); int server_msg_fn_sessions(struct hdr *, struct client *); int server_msg_fn_size(struct hdr *, struct client *); +int server_msg_fn_unbindkey(struct hdr *, struct client *); int server_msg_fn_windowlist(struct hdr *, struct client *); int server_msg_fn_windows(struct hdr *, struct client *); @@ -40,11 +42,13 @@ struct server_msg { }; const struct server_msg server_msg_table[] = { { MSG_ATTACH, server_msg_fn_attach }, + { MSG_BINDKEY, server_msg_fn_bindkey }, { MSG_KEYS, server_msg_fn_keys }, { MSG_NEW, server_msg_fn_new }, { MSG_RENAME, server_msg_fn_rename }, { MSG_SESSIONS, server_msg_fn_sessions }, { MSG_SIZE, server_msg_fn_size }, + { MSG_UNBINDKEY, server_msg_fn_unbindkey }, { MSG_WINDOWLIST, server_msg_fn_windowlist }, { MSG_WINDOWS, server_msg_fn_windows }, }; @@ -317,7 +321,7 @@ server_msg_fn_rename(struct hdr *hdr, struct client *c) buffer_read(c->in, &data, hdr->size); - data.newname[(sizeof data.newname) - 1] = '\0'; + data.newname[(sizeof data.newname) - 1] = '\0'; if ((s = server_find_sessid(&data.sid, &cause)) == NULL) { server_write_error(c, "%s", cause); xfree(cause); @@ -384,3 +388,55 @@ server_msg_fn_windowlist(struct hdr *hdr, struct client *c) return (0); } + +/* Bind key message from client */ +int +server_msg_fn_bindkey(struct hdr *hdr, struct client *c) +{ + struct bind_data data; + const struct bind *bind; + + if (hdr->size != sizeof data) + fatalx("bad MSG_BIND size"); + + buffer_read(c->in, &data, hdr->size); + + 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->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); + + server_write_client(c, MSG_OKAY, NULL, 0); + + return (0); +} + +/* Unbind key message from client */ +int +server_msg_fn_unbindkey(struct hdr *hdr, struct client *c) +{ + struct bind_data data; + + if (hdr->size != sizeof data) + fatalx("bad MSG_UNBIND size"); + + buffer_read(c->in, &data, hdr->size); + + cmd_remove_bind(data.key); + + server_write_client(c, MSG_OKAY, NULL, 0); + + return (0); +} diff --git a/server.c b/server.c index 55765c93..8cdbd793 100644 --- a/server.c +++ b/server.c @@ -1,4 +1,4 @@ -/* $Id: server.c,v 1.18 2007-10-03 10:20:33 nicm Exp $ */ +/* $Id: server.c,v 1.19 2007-10-03 11:26:34 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -127,6 +127,8 @@ server_main(char *srv_path, int srv_fd) ARRAY_INIT(&clients); ARRAY_INIT(&sessions); + cmd_init(); + pfds = NULL; while (!sigterm) { /* Initialise pollfd array. */ @@ -169,6 +171,8 @@ server_main(char *srv_path, int srv_fd) server_handle_clients(&pfd); } + cmd_free(); + close(srv_fd); unlink(srv_path); diff --git a/tmux.c b/tmux.c index 7219a298..ca65489d 100644 --- a/tmux.c +++ b/tmux.c @@ -1,4 +1,4 @@ -/* $Id: tmux.c,v 1.20 2007-10-03 09:17:00 nicm Exp $ */ +/* $Id: tmux.c,v 1.21 2007-10-03 11:26:34 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -50,15 +50,28 @@ const struct op op_table[] = { { "list-windows", "lsw", op_list_windows }, { "new-session", "new", op_new/*_session*/ }, { "rename-window", "renw", op_rename }, + { "bind-key", "bind", op_bind_key }, + { "unbind-key", "unbind", op_unbind_key }, }; #define NOP (sizeof op_table / sizeof op_table[0]) int -usage(const char *s) +usage(const char *fmt, ...) { - if (s == NULL) - s = "command [flags]"; - fprintf(stderr, "usage: %s [-v] [-S path] %s\n", __progname, s); + char *msg; + va_list ap; + + if (fmt == NULL) { + fprintf(stderr, + "usage: %s [-v] [-S path] command [flags]\n", __progname); + return (1); + } + + va_start(ap, fmt); + xvasprintf(&msg, fmt, ap); + va_end(ap); + fprintf(stderr, "usage: %s [-v] [-S path] %s\n", __progname, msg); + xfree(msg); return (1); } diff --git a/tmux.h b/tmux.h index f41f9975..d86e39c8 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.34 2007-10-03 10:18:32 nicm Exp $ */ +/* $Id: tmux.h,v 1.35 2007-10-03 11:26:34 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -31,7 +31,7 @@ #include "array.h" extern cc_t ttydefchars[]; -extern char *__progname; +extern char *__progname; #define MAXNAMELEN 32 #define MAXTITLELEN 192 @@ -273,6 +273,8 @@ enum hdrtype { MSG_SIZE, MSG_WINDOWLIST, MSG_WINDOWS, + MSG_BINDKEY, + MSG_UNBINDKEY, }; /* Message header structure. */ @@ -328,21 +330,18 @@ struct size_data { u_int sy; }; -struct select_data { - u_int idx; -}; - -struct refresh_data { - u_int py_upper; - u_int py_lower; -}; - struct rename_data { int idx; struct sessid sid; char newname[MAXNAMELEN]; }; +struct bind_data { + int key; + char cmd[MAXNAMELEN]; + int arg; +}; + /* Attributes. */ #define ATTR_BRIGHT 0x1 #define ATTR_DIM 0x2 @@ -495,12 +494,19 @@ struct client_ctx { struct winsize ws; }; +/* Key binding. */ +struct bind { + const char *name; + void (*fn)(struct client *, int); + int arg; /* -1 if user specifies */ +}; + /* tmux.c */ extern volatile sig_atomic_t sigwinch; extern volatile sig_atomic_t sigterm; extern int debug_level; extern u_int status_lines; -int usage(const char *); +int usage(const char *, ...); void logfile(const char *); void siginit(void); void sigreset(void); @@ -509,6 +515,8 @@ void sigreset(void); int op_new(char *, int, char **); int op_attach(char *, int, char **); int op_rename(char *, int, char **); +int op_bind_key(char *, int, char **); +int op_unbind_key(char *, int, char **); /* op-list.c */ int op_list_sessions(char *, int, char **); @@ -528,8 +536,16 @@ 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_remove_bind(int); +void cmd_init(void); +void cmd_free(void); void cmd_dispatch(struct client *, int); +/* key-string.c */ +int key_string_lookup(const char *); + /* server.c */ extern struct clients clients; int server_start(char *);