NeoMutt  2025-01-09-81-g753ae0
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
parse.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <stdbool.h>
31#include <stdint.h>
32#include <stdio.h>
33#include <string.h>
34#include "mutt/lib.h"
35#include "core/lib.h"
36#include "gui/lib.h"
37#include "mutt.h"
38#include "key/lib.h"
39#include "menu/lib.h"
40#include "parse/lib.h"
41
43#define MAX_SEQ 8
44
58static enum CommandResult km_bind_err(const char *s, enum MenuType mtype, int op,
59 char *macro, char *desc, struct Buffer *err)
60{
62 struct Keymap *last = NULL, *np = NULL, *compare = NULL;
63 keycode_t buf[MAX_SEQ];
64 size_t pos = 0, lastpos = 0;
65
66 size_t len = parsekeys(s, buf, MAX_SEQ);
67
68 struct Keymap *map = alloc_keys(len, buf);
69 map->op = op;
70 map->macro = mutt_str_dup(macro);
71 map->desc = mutt_str_dup(desc);
72
73 /* find position to place new keymap */
74 STAILQ_FOREACH(np, &Keymaps[mtype], entries)
75 {
76 compare = km_compare_keys(map, np, &pos);
77
78 if (compare == map) /* map's keycode is bigger */
79 {
80 last = np;
81 lastpos = pos;
82 if (pos > np->eq)
83 pos = np->eq;
84 }
85 else if (compare == np) /* np's keycode is bigger, found insert location */
86 {
87 map->eq = pos;
88 break;
89 }
90 else /* equal keycodes */
91 {
92 /* Don't warn on overwriting a 'noop' binding */
93 if ((np->len != len) && (np->op != OP_NULL))
94 {
95 static const char *guide_link = "https://neomutt.org/guide/configuration.html#bind-warnings";
96 /* Overwrite with the different lengths, warn */
97 struct Buffer *old_binding = buf_pool_get();
98 struct Buffer *new_binding = buf_pool_get();
99
100 km_expand_key(map, old_binding);
101 km_expand_key(np, new_binding);
102
103 char *err_msg = _("Binding '%s' will alias '%s' Before, try: 'bind %s %s noop'");
104 if (err)
105 {
106 /* err was passed, put the string there */
107 buf_printf(err, err_msg, buf_string(old_binding), buf_string(new_binding),
108 mutt_map_get_name(mtype, MenuNames), buf_string(new_binding));
109 buf_add_printf(err, " %s", guide_link);
110 }
111 else
112 {
113 struct Buffer *tmp = buf_pool_get();
114 buf_printf(tmp, err_msg, buf_string(old_binding), buf_string(new_binding),
115 mutt_map_get_name(mtype, MenuNames), buf_string(new_binding));
116 buf_add_printf(tmp, " %s", guide_link);
117 mutt_error("%s", buf_string(tmp));
118 buf_pool_release(&tmp);
119 }
120 rc = MUTT_CMD_WARNING;
121
122 buf_pool_release(&old_binding);
123 buf_pool_release(&new_binding);
124 }
125
126 map->eq = np->eq;
127 STAILQ_REMOVE(&Keymaps[mtype], np, Keymap, entries);
128 mutt_keymap_free(&np);
129 break;
130 }
131 }
132
133 if (map->op == OP_NULL)
134 {
135 mutt_keymap_free(&map);
136 }
137 else
138 {
139 if (last) /* if queue has at least one entry */
140 {
141 if (STAILQ_NEXT(last, entries))
142 STAILQ_INSERT_AFTER(&Keymaps[mtype], last, map, entries);
143 else /* last entry in the queue */
144 STAILQ_INSERT_TAIL(&Keymaps[mtype], map, entries);
145 last->eq = lastpos;
146 }
147 else /* queue is empty, so insert from head */
148 {
149 STAILQ_INSERT_HEAD(&Keymaps[mtype], map, entries);
150 }
151 }
152
153 return rc;
154}
155
165enum CommandResult km_bind(char *s, enum MenuType mtype, int op, char *macro, char *desc)
166{
167 return km_bind_err(s, mtype, op, macro, desc, NULL);
168}
169
178static enum CommandResult km_bindkey_err(const char *s, enum MenuType mtype,
179 int op, struct Buffer *err)
180{
181 return km_bind_err(s, mtype, op, NULL, NULL, err);
182}
183
191enum CommandResult km_bindkey(const char *s, enum MenuType mtype, int op)
192{
193 return km_bindkey_err(s, mtype, op, NULL);
194}
195
203static void km_unbind_all(struct KeymapList *km_list, unsigned long mode)
204{
205 struct Keymap *np = NULL, *tmp = NULL;
206
207 STAILQ_FOREACH_SAFE(np, km_list, entries, tmp)
208 {
209 if (((mode & MUTT_UNBIND) && !np->macro) || ((mode & MUTT_UNMACRO) && np->macro))
210 {
211 STAILQ_REMOVE(km_list, np, Keymap, entries);
212 mutt_keymap_free(&np);
213 }
214 }
215}
216
231static char *parse_keymap(enum MenuType *mtypes, struct Buffer *s, int max_menus,
232 int *num_menus, struct Buffer *err, bool bind)
233{
234 struct Buffer *buf = buf_pool_get();
235 int i = 0;
236 char *q = NULL;
237 char *result = NULL;
238
239 /* menu name */
241 char *p = buf->data;
242 if (MoreArgs(s))
243 {
244 while (i < max_menus)
245 {
246 q = strchr(p, ',');
247 if (q)
248 *q = '\0';
249
250 int val = mutt_map_get_value(p, MenuNames);
251 if (val == -1)
252 {
253 buf_printf(err, _("%s: no such menu"), p);
254 goto done;
255 }
256 mtypes[i] = val;
257 i++;
258 if (q)
259 p = q + 1;
260 else
261 break;
262 }
263 *num_menus = i;
264 /* key sequence */
266
267 if (buf_at(buf, 0) == '\0')
268 {
269 buf_printf(err, _("%s: null key sequence"), bind ? "bind" : "macro");
270 }
271 else if (MoreArgs(s))
272 {
273 result = buf_strdup(buf);
274 goto done;
275 }
276 }
277 else
278 {
279 buf_printf(err, _("%s: too few arguments"), bind ? "bind" : "macro");
280 }
281done:
282 buf_pool_release(&buf);
283 return result;
284}
285
295static void *parse_menu(bool *menus, char *s, struct Buffer *err)
296{
297 char *menu_names_dup = mutt_str_dup(s);
298 char *marker = menu_names_dup;
299 char *menu_name = NULL;
300
301 while ((menu_name = mutt_str_sep(&marker, ",")))
302 {
303 int value = mutt_map_get_value(menu_name, MenuNames);
304 if (value == -1)
305 {
306 buf_printf(err, _("%s: no such menu"), menu_name);
307 break;
308 }
309 else
310 {
311 menus[value] = true;
312 }
313 }
314
315 FREE(&menu_names_dup);
316 return NULL;
317}
318
328static enum CommandResult try_bind(char *key, enum MenuType mtype, char *func,
329 const struct MenuFuncOp *funcs, struct Buffer *err)
330{
331 for (int i = 0; funcs[i].name; i++)
332 {
333 if (mutt_str_equal(func, funcs[i].name))
334 {
335 return km_bindkey_err(key, mtype, funcs[i].op, err);
336 }
337 }
338 if (err)
339 {
340 buf_printf(err, _("Function '%s' not available for menu '%s'"), func,
342 }
343 return MUTT_CMD_ERROR; /* Couldn't find an existing function with this name */
344}
345
349enum CommandResult mutt_parse_push(struct Buffer *buf, struct Buffer *s,
350 intptr_t data, struct Buffer *err)
351{
353 if (MoreArgs(s))
354 {
355 buf_printf(err, _("%s: too many arguments"), "push");
356 return MUTT_CMD_ERROR;
357 }
358
360 return MUTT_CMD_SUCCESS;
361}
362
368enum CommandResult mutt_parse_bind(struct Buffer *buf, struct Buffer *s,
369 intptr_t data, struct Buffer *err)
370{
371 if (StartupComplete)
372 {
373 // Save and restore the offset in `s` because dump_bind_macro() might change it
374 char *dptr = s->dptr;
375 if (dump_bind_macro(buf, s, data, err) == MUTT_CMD_SUCCESS)
376 return MUTT_CMD_SUCCESS;
377 if (!buf_is_empty(err))
378 return MUTT_CMD_ERROR;
379 s->dptr = dptr;
380 }
381
382 const struct MenuFuncOp *funcs = NULL;
383 enum MenuType mtypes[MenuNamesLen];
384 int num_menus = 0;
386
387 char *key = parse_keymap(mtypes, s, mutt_array_size(mtypes), &num_menus, err, true);
388 if (!key)
389 return MUTT_CMD_ERROR;
390
391 /* function to execute */
393 if (MoreArgs(s))
394 {
395 buf_printf(err, _("%s: too many arguments"), "bind");
396 rc = MUTT_CMD_ERROR;
397 }
398 else if (mutt_istr_equal("noop", buf->data))
399 {
400 struct Buffer *keystr = buf_pool_get();
401 for (int i = 0; i < num_menus; i++)
402 {
403 km_bindkey(key, mtypes[i], OP_NULL); /* the 'unbind' command */
404 funcs = km_get_table(mtypes[i]);
405 if (funcs)
406 {
407 buf_reset(keystr);
408 km_expand_key_string(key, keystr);
409 const char *mname = mutt_map_get_name(mtypes[i], MenuNames);
410 mutt_debug(LL_NOTIFY, "NT_BINDING_DELETE: %s %s\n", mname, buf_string(keystr));
411
412 int op = get_op(OpGeneric, buf->data, mutt_str_len(buf->data));
413 struct EventBinding ev_b = { mtypes[i], key, op };
415 }
416 }
417 buf_pool_release(&keystr);
418 }
419 else
420 {
421 struct Buffer *keystr = buf_pool_get();
422 for (int i = 0; i < num_menus; i++)
423 {
424 /* The pager and editor menus don't use the generic map,
425 * however for other menus try generic first. */
426 if ((mtypes[i] != MENU_PAGER) && (mtypes[i] != MENU_EDITOR) && (mtypes[i] != MENU_GENERIC))
427 {
428 rc = try_bind(key, mtypes[i], buf->data, OpGeneric, err);
429 if (rc == MUTT_CMD_SUCCESS)
430 {
431 buf_reset(keystr);
432 km_expand_key_string(key, keystr);
433 const char *mname = mutt_map_get_name(mtypes[i], MenuNames);
434 mutt_debug(LL_NOTIFY, "NT_BINDING_NEW: %s %s\n", mname, buf_string(keystr));
435
436 int op = get_op(OpGeneric, buf->data, mutt_str_len(buf->data));
437 struct EventBinding ev_b = { mtypes[i], key, op };
439 continue;
440 }
441 if (rc == MUTT_CMD_WARNING)
442 break;
443 }
444
445 /* Clear any error message, we're going to try again */
446 err->data[0] = '\0';
447 funcs = km_get_table(mtypes[i]);
448 if (funcs)
449 {
450 rc = try_bind(key, mtypes[i], buf->data, funcs, err);
451 if (rc == MUTT_CMD_SUCCESS)
452 {
453 buf_reset(keystr);
454 km_expand_key_string(key, keystr);
455 const char *mname = mutt_map_get_name(mtypes[i], MenuNames);
456 mutt_debug(LL_NOTIFY, "NT_BINDING_NEW: %s %s\n", mname, buf_string(keystr));
457
458 int op = get_op(funcs, buf->data, mutt_str_len(buf->data));
459 struct EventBinding ev_b = { mtypes[i], key, op };
461 continue;
462 }
463 }
464 }
465 buf_pool_release(&keystr);
466 }
467 FREE(&key);
468 return rc;
469}
470
481enum CommandResult mutt_parse_unbind(struct Buffer *buf, struct Buffer *s,
482 intptr_t data, struct Buffer *err)
483{
484 bool menu_matches[MENU_MAX] = { 0 };
485 bool all_keys = false;
486 char *key = NULL;
487
489 if (mutt_str_equal(buf->data, "*"))
490 {
491 for (enum MenuType i = 1; i < MENU_MAX; i++)
492 menu_matches[i] = true;
493 }
494 else
495 {
496 parse_menu(menu_matches, buf->data, err);
497 }
498
499 if (MoreArgs(s))
500 {
502 key = buf->data;
503 }
504 else
505 {
506 all_keys = true;
507 }
508
509 if (MoreArgs(s))
510 {
511 const char *cmd = (data & MUTT_UNMACRO) ? "unmacro" : "unbind";
512
513 buf_printf(err, _("%s: too many arguments"), cmd);
514 return MUTT_CMD_ERROR;
515 }
516
517 for (enum MenuType i = 1; i < MENU_MAX; i++)
518 {
519 if (!menu_matches[i])
520 continue;
521 if (all_keys)
522 {
523 km_unbind_all(&Keymaps[i], data);
524 km_bindkey("<enter>", MENU_GENERIC, OP_GENERIC_SELECT_ENTRY);
525 km_bindkey("<return>", MENU_GENERIC, OP_GENERIC_SELECT_ENTRY);
526 km_bindkey("<enter>", MENU_INDEX, OP_DISPLAY_MESSAGE);
527 km_bindkey("<return>", MENU_INDEX, OP_DISPLAY_MESSAGE);
528 km_bindkey("<backspace>", MENU_EDITOR, OP_EDITOR_BACKSPACE);
529 km_bindkey("\177", MENU_EDITOR, OP_EDITOR_BACKSPACE);
530 km_bindkey(":", MENU_GENERIC, OP_ENTER_COMMAND);
531 km_bindkey(":", MENU_PAGER, OP_ENTER_COMMAND);
532 if (i != MENU_EDITOR)
533 {
534 km_bindkey("?", i, OP_HELP);
535 km_bindkey("q", i, OP_EXIT);
536 }
537
538 const char *mname = mutt_map_get_name(i, MenuNames);
539 mutt_debug(LL_NOTIFY, "NT_MACRO_DELETE_ALL: %s\n", mname);
540
541 struct EventBinding ev_b = { i, NULL, OP_NULL };
544 &ev_b);
545 }
546 else
547 {
548 struct Buffer *keystr = buf_pool_get();
549 km_expand_key_string(key, keystr);
550 const char *mname = mutt_map_get_name(i, MenuNames);
551 mutt_debug(LL_NOTIFY, "NT_MACRO_DELETE: %s %s\n", mname, buf_string(keystr));
552 buf_pool_release(&keystr);
553
554 km_bindkey(key, i, OP_NULL);
555 struct EventBinding ev_b = { i, key, OP_NULL };
558 }
559 }
560
561 return MUTT_CMD_SUCCESS;
562}
563
569enum CommandResult mutt_parse_macro(struct Buffer *buf, struct Buffer *s,
570 intptr_t data, struct Buffer *err)
571{
572 if (StartupComplete)
573 {
574 // Save and restore the offset in `s` because dump_bind_macro() might change it
575 char *dptr = s->dptr;
576 if (dump_bind_macro(buf, s, data, err) == MUTT_CMD_SUCCESS)
577 return MUTT_CMD_SUCCESS;
578 if (!buf_is_empty(err))
579 return MUTT_CMD_ERROR;
580 s->dptr = dptr;
581 }
582
583 enum MenuType mtypes[MenuNamesLen];
584 int num_menus = 0;
586
587 char *key = parse_keymap(mtypes, s, mutt_array_size(mtypes), &num_menus, err, false);
588 if (!key)
589 return MUTT_CMD_ERROR;
590
592 /* make sure the macro sequence is not an empty string */
593 if (buf->data[0] == '\0')
594 {
595 buf_strcpy(err, _("macro: empty key sequence"));
596 }
597 else
598 {
599 if (MoreArgs(s))
600 {
601 char *seq = mutt_str_dup(buf->data);
603
604 if (MoreArgs(s))
605 {
606 buf_printf(err, _("%s: too many arguments"), "macro");
607 }
608 else
609 {
610 struct Buffer *keystr = buf_pool_get();
611 for (int i = 0; i < num_menus; i++)
612 {
613 rc = km_bind(key, mtypes[i], OP_MACRO, seq, buf->data);
614 if (rc == MUTT_CMD_SUCCESS)
615 {
616 buf_reset(keystr);
617 km_expand_key_string(key, keystr);
618 const char *mname = mutt_map_get_name(mtypes[i], MenuNames);
619 mutt_debug(LL_NOTIFY, "NT_MACRO_NEW: %s %s\n", mname, buf_string(keystr));
620
621 struct EventBinding ev_b = { mtypes[i], key, OP_MACRO };
623 continue;
624 }
625 }
626 buf_pool_release(&keystr);
627 }
628
629 FREE(&seq);
630 }
631 else
632 {
633 struct Buffer *keystr = buf_pool_get();
634 for (int i = 0; i < num_menus; i++)
635 {
636 rc = km_bind(key, mtypes[i], OP_MACRO, buf->data, NULL);
637 if (rc == MUTT_CMD_SUCCESS)
638 {
639 buf_reset(keystr);
640 km_expand_key_string(key, keystr);
641 const char *mname = mutt_map_get_name(mtypes[i], MenuNames);
642 mutt_debug(LL_NOTIFY, "NT_MACRO_NEW: %s %s\n", mname, buf_string(keystr));
643
644 struct EventBinding ev_b = { mtypes[i], key, OP_MACRO };
646 continue;
647 }
648 }
649 buf_pool_release(&keystr);
650 }
651 }
652 FREE(&key);
653 return rc;
654}
655
659enum CommandResult mutt_parse_exec(struct Buffer *buf, struct Buffer *s,
660 intptr_t data, struct Buffer *err)
661{
662 int ops[128];
663 int nops = 0;
664 const struct MenuFuncOp *funcs = NULL;
665 char *function = NULL;
666
667 if (!MoreArgs(s))
668 {
669 buf_strcpy(err, _("exec: no arguments"));
670 return MUTT_CMD_ERROR;
671 }
672
673 do
674 {
676 function = buf->data;
677
678 const enum MenuType mtype = menu_get_current_type();
679 funcs = km_get_table(mtype);
680 if (!funcs && (mtype != MENU_PAGER))
681 funcs = OpGeneric;
682
683 ops[nops] = get_op(funcs, function, mutt_str_len(function));
684 if ((ops[nops] == OP_NULL) && (mtype != MENU_PAGER) && (mtype != MENU_GENERIC))
685 {
686 ops[nops] = get_op(OpGeneric, function, mutt_str_len(function));
687 }
688
689 if (ops[nops] == OP_NULL)
690 {
692 mutt_error(_("%s: no such function"), function);
693 return MUTT_CMD_ERROR;
694 }
695 nops++;
696 } while (MoreArgs(s) && nops < mutt_array_size(ops));
697
698 while (nops)
699 mutt_push_macro_event(0, ops[--nops]);
700
701 return MUTT_CMD_SUCCESS;
702}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:161
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:204
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:76
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:291
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition: buffer.c:668
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:395
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:571
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
CommandResult
Error codes for command_t parse functions.
Definition: command.h:36
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition: command.h:39
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition: command.h:37
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition: command.h:38
bool StartupComplete
When the config has been read.
Definition: main.c:198
Convenience wrapper for the core headers.
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: get.c:58
void mutt_push_macro_event(int ch, int op)
Add the character/operation to the macro buffer.
Definition: get.c:155
int parse_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: extract.c:50
#define TOKEN_CONDENSE
^(char) to control chars (macros)
Definition: extract.h:48
#define MoreArgs(buf)
Definition: extract.h:32
#define TOKEN_NO_FLAGS
No flags are set.
Definition: extract.h:46
enum CommandResult mutt_parse_bind(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'bind' command - Implements Command::parse() -.
Definition: parse.c:368
enum CommandResult mutt_parse_unbind(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'unbind' command - Implements Command::parse() -.
Definition: parse.c:481
enum CommandResult mutt_parse_macro(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'macro' command - Implements Command::parse() -.
Definition: parse.c:569
enum CommandResult mutt_parse_push(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'push' command - Implements Command::parse() -.
Definition: parse.c:349
enum CommandResult mutt_parse_exec(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'exec' command - Implements Command::parse() -.
Definition: parse.c:659
enum CommandResult dump_bind_macro(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse 'bind' and 'macro' commands - Implements Command::parse() -.
Definition: dump.c:179
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
const struct MenuFuncOp OpGeneric[]
Functions for the Generic Menu.
Definition: functions.c:68
Convenience wrapper for the gui headers.
void generic_tokenize_push_string(char *s)
Parse and queue a 'push' command.
Definition: lib.c:337
struct Keymap * km_compare_keys(struct Keymap *k1, struct Keymap *k2, size_t *pos)
Compare two keymaps' keyscodes and return the bigger one.
Definition: lib.c:274
struct Keymap * alloc_keys(size_t len, keycode_t *keys)
Allocate space for a sequence of keys.
Definition: lib.c:149
void mutt_keymap_free(struct Keymap **ptr)
Free a Keymap.
Definition: lib.c:130
struct KeymapList Keymaps[MENU_MAX]
Array of key mappings, one for each MenuType.
Definition: lib.c:124
size_t parsekeys(const char *str, keycode_t *d, size_t max)
Parse a key string into key codes.
Definition: lib.c:215
const struct MenuFuncOp * km_get_table(enum MenuType mtype)
Lookup a Menu's functions.
Definition: lib.c:499
int get_op(const struct MenuFuncOp *funcs, const char *start, size_t len)
Get the function by its name.
Definition: lib.c:298
bool km_expand_key(struct Keymap *map, struct Buffer *buf)
Get the key string bound to a Keymap.
Definition: lib.c:451
void km_expand_key_string(char *str, struct Buffer *buf)
Get a human-readable key string.
Definition: lib.c:469
Manage keymappings.
@ NT_MACRO_ADD
Key macro has been added.
Definition: lib.h:139
@ NT_MACRO_DELETE
Key macro has been deleted.
Definition: lib.h:140
@ NT_MACRO_DELETE_ALL
All key macros have been deleted.
Definition: lib.h:141
@ NT_BINDING_DELETE
Key binding has been deleted.
Definition: lib.h:136
@ NT_BINDING_ADD
Key binding has been added.
Definition: lib.h:135
@ NT_BINDING_DELETE_ALL
All key bindings have been deleted.
Definition: lib.h:137
#define MUTT_UNBIND
Parse 'unbind' command.
Definition: lib.h:48
#define MUTT_UNMACRO
Parse 'unmacro' command.
Definition: lib.h:49
short keycode_t
Type for key storage, the rest of neomutt works fine with int type.
Definition: lib.h:56
static void * parse_menu(bool *menus, char *s, struct Buffer *err)
Parse menu-names into an array.
Definition: parse.c:295
enum CommandResult km_bind(char *s, enum MenuType mtype, int op, char *macro, char *desc)
Bind a key to a macro.
Definition: parse.c:165
static enum CommandResult km_bind_err(const char *s, enum MenuType mtype, int op, char *macro, char *desc, struct Buffer *err)
Set up a key binding.
Definition: parse.c:58
static enum CommandResult km_bindkey_err(const char *s, enum MenuType mtype, int op, struct Buffer *err)
Bind a key in a Menu to an operation (with error message)
Definition: parse.c:178
static void km_unbind_all(struct KeymapList *km_list, unsigned long mode)
Free all the keys in the supplied Keymap.
Definition: parse.c:203
enum CommandResult km_bindkey(const char *s, enum MenuType mtype, int op)
Bind a key in a Menu to an operation.
Definition: parse.c:191
static char * parse_keymap(enum MenuType *mtypes, struct Buffer *s, int max_menus, int *num_menus, struct Buffer *err, bool bind)
Parse a user-config key binding.
Definition: parse.c:231
static enum CommandResult try_bind(char *key, enum MenuType mtype, char *func, const struct MenuFuncOp *funcs, struct Buffer *err)
Try to make a key binding.
Definition: parse.c:328
#define MAX_SEQ
Maximum length of a key binding sequence used for buffer in km_bindkey.
Definition: parse.c:43
@ LL_NOTIFY
Log of notifications.
Definition: logging2.h:48
int mutt_map_get_value(const char *name, const struct Mapping *map)
Lookup the constant for a string.
Definition: mapping.c:85
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition: mapping.c:42
#define FREE(x)
Definition: memory.h:55
#define mutt_array_size(x)
Definition: memory.h:38
GUI present the user with a selectable list.
enum MenuType menu_get_current_type(void)
Get the type of the current Window.
Definition: menu.c:89
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:173
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:673
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:254
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:661
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:497
char * mutt_str_sep(char **stringp, const char *delim)
Find first occurrence of any of delim characters in *stringp.
Definition: string.c:187
Many unsorted constants and some structs.
@ NT_BINDING
Key binding has changed, NotifyBinding, EventBinding.
Definition: notify_type.h:40
Text parsing functions.
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:96
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:441
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:390
#define STAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:427
#define STAILQ_INSERT_HEAD(head, elm, field)
Definition: queue.h:421
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:400
#define STAILQ_NEXT(elm, field)
Definition: queue.h:439
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field)
Definition: queue.h:415
String manipulation buffer.
Definition: buffer.h:36
char * dptr
Current read/write position.
Definition: buffer.h:38
char * data
Pointer to data.
Definition: buffer.h:37
A key binding Event.
Definition: lib.h:120
const char * key
Key string being bound (for new bind/macro)
Definition: lib.h:122
int op
Operation the key's bound to (for bind), e.g. OP_DELETE.
Definition: lib.h:123
A keyboard mapping.
Definition: lib.h:66
char * macro
Macro expansion (op == OP_MACRO)
Definition: lib.h:67
short eq
Number of leading keys equal to next entry.
Definition: lib.h:70
char * desc
Description of a macro for the help menu.
Definition: lib.h:68
short len
Length of key sequence (unit: sizeof (keycode_t))
Definition: lib.h:71
short op
Operation to perform.
Definition: lib.h:69
Mapping between a function and an operation.
Definition: lib.h:102
const char * name
Name of the function.
Definition: lib.h:103
int op
Operation, e.g. OP_DELETE.
Definition: lib.h:104
Container for Accounts, Notifications.
Definition: neomutt.h:42
struct Notify * notify
Notifications handler.
Definition: neomutt.h:43
const int MenuNamesLen
Number of entries in the MenuNames array.
Definition: type.c:64
const struct Mapping MenuNames[]
Menu name lookup table.
Definition: type.c:37
MenuType
Types of GUI selections.
Definition: type.h:36
@ MENU_INDEX
Index panel (list of emails)
Definition: type.h:51
@ MENU_GENERIC
Generic selection list.
Definition: type.h:46
@ MENU_PAGER
Pager pager (email viewer)
Definition: type.h:52
@ MENU_MAX
Definition: type.h:57
@ MENU_EDITOR
Text entry area.
Definition: type.h:44