[BACK]Return to cmd-bind-key.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Annotation of src/usr.bin/tmux/cmd-bind-key.c, Revision 1.6

1.6     ! nicm        1: /* $OpenBSD: cmd-bind-key.c,v 1.5 2009/07/28 17:05:10 nicm Exp $ */
1.1       nicm        2:
                      3: /*
                      4:  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
                     15:  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                     16:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18:
                     19: #include <sys/types.h>
                     20:
1.5       nicm       21: #include <string.h>
                     22:
1.1       nicm       23: #include "tmux.h"
                     24:
                     25: /*
                     26:  * Bind a key to a command, this recurses through cmd_*.
                     27:  */
                     28:
                     29: int    cmd_bind_key_parse(struct cmd *, int, char **, char **);
                     30: int    cmd_bind_key_exec(struct cmd *, struct cmd_ctx *);
                     31: void   cmd_bind_key_free(struct cmd *);
                     32: size_t cmd_bind_key_print(struct cmd *, char *, size_t);
                     33:
1.5       nicm       34: int    cmd_bind_key_table(struct cmd *, struct cmd_ctx *);
                     35:
1.1       nicm       36: struct cmd_bind_key_data {
                     37:        int              key;
                     38:        int              can_repeat;
                     39:        struct cmd_list *cmdlist;
1.5       nicm       40:
                     41:        int              command_key;
                     42:        char            *tablename;
                     43:        char            *modecmd;
1.1       nicm       44: };
                     45:
                     46: const struct cmd_entry cmd_bind_key_entry = {
                     47:        "bind-key", "bind",
1.5       nicm       48:        "[-cnr] [-t key-table] key command [arguments]",
1.6     ! nicm       49:        0, "",
1.1       nicm       50:        NULL,
                     51:        cmd_bind_key_parse,
                     52:        cmd_bind_key_exec,
                     53:        cmd_bind_key_free,
                     54:        cmd_bind_key_print
                     55: };
                     56:
                     57: int
                     58: cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
                     59: {
                     60:        struct cmd_bind_key_data        *data;
1.3       nicm       61:        int                              opt, no_prefix = 0;
1.1       nicm       62:
                     63:        self->data = data = xmalloc(sizeof *data);
                     64:        data->can_repeat = 0;
                     65:        data->cmdlist = NULL;
1.5       nicm       66:        data->command_key = 0;
                     67:        data->tablename = NULL;
                     68:        data->modecmd = NULL;
1.1       nicm       69:
1.5       nicm       70:        while ((opt = getopt(argc, argv, "cnrt:")) != -1) {
1.1       nicm       71:                switch (opt) {
1.5       nicm       72:                case 'c':
                     73:                        data->command_key = 1;
                     74:                        break;
1.3       nicm       75:                case 'n':
                     76:                        no_prefix = 1;
                     77:                        break;
1.1       nicm       78:                case 'r':
                     79:                        data->can_repeat = 1;
                     80:                        break;
1.5       nicm       81:                case 't':
                     82:                        data->tablename = xstrdup(optarg);
                     83:                        break;
1.1       nicm       84:                default:
                     85:                        goto usage;
                     86:                }
                     87:        }
                     88:        argc -= optind;
                     89:        argv += optind;
                     90:        if (argc < 1)
                     91:                goto usage;
                     92:
                     93:        if ((data->key = key_string_lookup_string(argv[0])) == KEYC_NONE) {
                     94:                xasprintf(cause, "unknown key: %s", argv[0]);
                     95:                goto error;
                     96:        }
1.3       nicm       97:        if (!no_prefix)
                     98:                data->key |= KEYC_PREFIX;
1.1       nicm       99:
                    100:        argc--;
                    101:        argv++;
1.5       nicm      102:        if (data->tablename != NULL) {
                    103:                if (argc != 1)
                    104:                        goto usage;
                    105:                data->modecmd = xstrdup(argv[0]);
                    106:        } else {
                    107:                if ((data->cmdlist = cmd_list_parse(argc, argv, cause)) == NULL)
                    108:                        goto error;
                    109:        }
1.1       nicm      110:
                    111:        return (0);
                    112:
                    113: usage:
                    114:        xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
                    115:
                    116: error:
                    117:        self->entry->free(self);
                    118:        return (-1);
                    119: }
                    120:
                    121: int
                    122: cmd_bind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
                    123: {
                    124:        struct cmd_bind_key_data        *data = self->data;
                    125:
                    126:        if (data == NULL)
                    127:                return (0);
1.5       nicm      128:        if (data->tablename != NULL)
                    129:                return (cmd_bind_key_table(self, ctx));
1.1       nicm      130:
                    131:        key_bindings_add(data->key, data->can_repeat, data->cmdlist);
                    132:        data->cmdlist = NULL;   /* avoid free */
                    133:
                    134:        return (0);
                    135: }
                    136:
1.5       nicm      137: int
                    138: cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx)
                    139: {
                    140:        struct cmd_bind_key_data        *data = self->data;
                    141:        const struct mode_key_table     *mtab;
                    142:        struct mode_key_binding         *mbind, mtmp;
                    143:        enum mode_key_cmd                cmd;
                    144:
                    145:        if ((mtab = mode_key_findtable(data->tablename)) == NULL) {
                    146:                ctx->error(ctx, "unknown key table: %s", data->tablename);
                    147:                return (-1);
                    148:        }
                    149:
                    150:        cmd = mode_key_fromstring(mtab->cmdstr, data->modecmd);
                    151:        if (cmd == MODEKEY_NONE) {
                    152:                ctx->error(ctx, "unknown command: %s", data->modecmd);
                    153:                return (-1);
                    154:        }
                    155:
                    156:        mtmp.key = data->key & ~KEYC_PREFIX;
                    157:        mtmp.mode = data->command_key ? 1 : 0;
                    158:        if ((mbind = SPLAY_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
                    159:                mbind->cmd = cmd;
                    160:                return (0);
                    161:        }
                    162:        mbind = xmalloc(sizeof *mbind);
                    163:        mbind->key = mtmp.key;
                    164:        mbind->mode = mtmp.mode;
                    165:        mbind->cmd = cmd;
                    166:        SPLAY_INSERT(mode_key_tree, mtab->tree, mbind);
                    167:        return (0);
                    168: }
                    169:
1.1       nicm      170: void
                    171: cmd_bind_key_free(struct cmd *self)
                    172: {
                    173:        struct cmd_bind_key_data        *data = self->data;
                    174:
                    175:        if (data->cmdlist != NULL)
                    176:                cmd_list_free(data->cmdlist);
1.5       nicm      177:        if (data->tablename != NULL)
                    178:                xfree(data->tablename);
                    179:        if (data->modecmd != NULL)
                    180:                xfree(data->modecmd);
1.1       nicm      181:        xfree(data);
                    182: }
                    183:
                    184: size_t
                    185: cmd_bind_key_print(struct cmd *self, char *buf, size_t len)
                    186: {
                    187:        struct cmd_bind_key_data        *data = self->data;
                    188:        size_t                           off = 0;
                    189:        const char                      *skey;
                    190:
                    191:        off += xsnprintf(buf, len, "%s", self->entry->name);
                    192:        if (data == NULL)
                    193:                return (off);
                    194:        if (off < len) {
                    195:                skey = key_string_lookup_key(data->key);
                    196:                off += xsnprintf(buf + off, len - off, " %s ", skey);
                    197:        }
                    198:        if (off < len)
                    199:                off += cmd_list_print(data->cmdlist, buf + off, len - off);
                    200:        return (off);
                    201: }