summaryrefslogtreecommitdiff
path: root/src/dged/binding.h
blob: 79f8c479f7dd878366073b50f512dbb44a606d87 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include "hash.h"
#include "keyboard.h"

/**
 * Directory of keyboard mappings.
 */
struct keymap {
  /** Keymap name */
  const char *name;

  /** The bindings in this keymap */
  struct binding *bindings;

  /** The number of bindings in this keymap */
  uint32_t nbindings;

  /** The number of bindings this keymap can currently hold */
  uint32_t capacity;
};

/**
 * Type of a keyboard binding
 */
enum binding_type {
  /** This binding is to a command */
  BindingType_Command,

  /** This binding is to another keymap */
  BindingType_Keymap,

  /** This binding is to an already resolved command,
   * a.k.a. anonymous binding.
   */
  BindingType_DirectCommand
};

#define BINDING_INNER(mod_, c_, command_)                                      \
  (struct binding) {                                                           \
    .key = {.mod = mod_, .key = c_}, .type = BindingType_Command,              \
    .command = hash_name(command_)                                             \
  }

#define ANONYMOUS_BINDING_INNER(mod_, c_, command_)                            \
  (struct binding) {                                                           \
    .key = {.mod = mod_, .key = c_}, .type = BindingType_DirectCommand,        \
    .direct_command = command_                                                 \
  }

#define PREFIX_INNER(mod_, c_, keymap_)                                        \
  (struct binding) {                                                           \
    .key = {.mod = mod_, .key = c_}, .type = BindingType_Keymap,               \
    .keymap = keymap_                                                          \
  }

/**
 * Define a key binding.
 *
 * Used like BINDING((mod), key, "<command-name>") where
 * the key modifier is optional.
 */
#define BINDING(...) BINDING_INNER(__VA_ARGS__)

/**
 * Define a prefix (a keybinding for a keymap).
 *
 * Used like PREFIX((mod), key, <ptr-to-keymap>) where
 * the key modifier is optional.
 */
#define PREFIX(...) PREFIX_INNER(__VA_ARGS__)

/**
 * Define an anonymous binding, i.e. a binding directly to a function.
 *
 * Note the function that this key binds to cannot usually be
 * executed dynamically (with M-x).
 *
 * Used like ANONYMOUS_BINDING((mod), key, <ptr-to-command>) where
 * the key modifier is optional.
 */
#define ANONYMOUS_BINDING(...) ANONYMOUS_BINDING_INNER(__VA_ARGS__)

/**
 * A keyboard key bound to an action
 */
struct binding {
  /** The keyboard key that triggers the action in this binding */
  struct key key;

  /** Type of this binding, see @ref binding_type */
  uint8_t type;

  union {
    /** A hash of a command name */
    uint32_t command;
    /** A command */
    struct command *direct_command;
    /** A keymap */
    struct keymap *keymap;
  };
};

/**
 * Result of a binding lookup
 */
struct lookup_result {
  /** True if a binding was found */
  bool found;

  /** Type of binding in the result */
  uint8_t type;

  union {
    /** A command */
    struct command *command;
    /** A keymap */
    struct keymap *keymap;
  };
};

struct commands;

/**
 * Create a new keymap
 *
 * @param name Name of the keymap
 * @param capacity Initial capacity of the keymap.
 * @returns The created keymap
 */
struct keymap keymap_create(const char *name, uint32_t capacity);

/**
 * Bind keys in a keymap.
 *
 * @param keymap The keymap to bind keys in.
 * @param bindings Bindings to add.
 * @param nbindings Number of bindings in @p bindings.
 */
void keymap_bind_keys(struct keymap *keymap, struct binding *bindings,
                      uint32_t nbindings);

/**
 * Destroy a keymap.
 *
 * This clears all keybindings associated with the keymap.
 * @param keymap Keymap to destroy.
 */
void keymap_destroy(struct keymap *keymap);

/**
 * Lookup the binding for a key in a set of keymaps.
 *
 * @param keymaps The keymaps to look in.
 * @param nkeymaps The number of keymaps in @p keymaps.
 * @param key The keystroke to look up bindings for.
 * @param commands Available commands for lookup.
 * @returns A @ref lookup_result with the result of the lookup.
 */
struct lookup_result lookup_key(struct keymap *keymaps, uint32_t nkeymaps,
                                struct key *key, struct commands *commands);