NeoMutt  2025-01-09-117-gace867
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
parse.c File Reference

Parse key bindings. More...

#include "config.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "mutt/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "lib.h"
#include "menu/lib.h"
#include "parse/lib.h"
+ Include dependency graph for parse.c:

Go to the source code of this file.

Macros

#define MAX_SEQ   8
 Maximum length of a key binding sequence used for buffer in km_bindkey.
 

Functions

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.
 
enum CommandResult km_bind (char *s, enum MenuType mtype, int op, char *macro, char *desc)
 Bind a key to a macro.
 
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)
 
enum CommandResult km_bindkey (const char *s, enum MenuType mtype, int op)
 Bind a key in a Menu to an operation.
 
static void km_unbind_all (struct KeymapList *km_list, unsigned long mode)
 Free all the keys in the supplied Keymap.
 
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.
 
static void * parse_menu (bool *menus, char *s, struct Buffer *err)
 Parse menu-names into an array.
 
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.
 
enum CommandResult parse_push (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse the 'push' command - Implements Command::parse() -.
 
enum CommandResult parse_bind (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse the 'bind' command - Implements Command::parse() -.
 
enum CommandResult parse_unbind (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse the 'unbind' command - Implements Command::parse() -.
 
enum CommandResult parse_macro (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse the 'macro' command - Implements Command::parse() -.
 
enum CommandResult parse_exec (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse the 'exec' command - Implements Command::parse() -.
 

Detailed Description

Parse key bindings.

Authors
  • Richard Russon

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file parse.c.

Macro Definition Documentation

◆ MAX_SEQ

#define MAX_SEQ   8

Maximum length of a key binding sequence used for buffer in km_bindkey.

Definition at line 43 of file parse.c.

Function Documentation

◆ km_bind_err()

static enum CommandResult km_bind_err ( const char *  s,
enum MenuType  mtype,
int  op,
char *  macro,
char *  desc,
struct Buffer err 
)
static

Set up a key binding.

Parameters
sKey string
mtypeMenu type, e.g. MENU_EDITOR
opOperation, e.g. OP_DELETE
macroMacro string
descDescription of macro (OPTIONAL)
errBuffer for error message
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS

Insert a key sequence into the specified map. The map is sorted by ASCII value (lowest to highest)

Definition at line 58 of file parse.c.

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}
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
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:35
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition: command.h:38
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition: command.h:37
#define mutt_error(...)
Definition: logging2.h:93
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
bool km_expand_key(struct Keymap *map, struct Buffer *buf)
Get the key string bound to a Keymap.
Definition: lib.c:509
short keycode_t
Type for key storage, the rest of neomutt works fine with int type.
Definition: lib.h:56
#define MAX_SEQ
Maximum length of a key binding sequence used for buffer in km_bindkey.
Definition: parse.c:43
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition: mapping.c:42
#define _(a)
Definition: message.h:28
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:254
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_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
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
const struct Mapping MenuNames[]
Menu name lookup table.
Definition: type.c:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ km_bind()

enum CommandResult km_bind ( char *  s,
enum MenuType  mtype,
int  op,
char *  macro,
char *  desc 
)

Bind a key to a macro.

Parameters
sKey string
mtypeMenu type, e.g. MENU_EDITOR
opOperation, e.g. OP_DELETE
macroMacro string
descDescription of macro (OPTIONAL)
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS

Definition at line 165 of file parse.c.

166{
167 return km_bind_err(s, mtype, op, macro, desc, NULL);
168}
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
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ km_bindkey_err()

static enum CommandResult km_bindkey_err ( const char *  s,
enum MenuType  mtype,
int  op,
struct Buffer err 
)
static

Bind a key in a Menu to an operation (with error message)

Parameters
sKey string
mtypeMenu type, e.g. MENU_PAGER
opOperation, e.g. OP_DELETE
errBuffer for error message
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS

Definition at line 178 of file parse.c.

180{
181 return km_bind_err(s, mtype, op, NULL, NULL, err);
182}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ km_bindkey()

enum CommandResult km_bindkey ( const char *  s,
enum MenuType  mtype,
int  op 
)

Bind a key in a Menu to an operation.

Parameters
sKey string
mtypeMenu type, e.g. MENU_PAGER
opOperation, e.g. OP_DELETE
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS

Definition at line 191 of file parse.c.

192{
193 return km_bindkey_err(s, mtype, op, NULL);
194}
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
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ km_unbind_all()

static void km_unbind_all ( struct KeymapList *  km_list,
unsigned long  mode 
)
static

Free all the keys in the supplied Keymap.

Parameters
km_listKeymap mapping
modeUndo bind or macro, e.g. MUTT_UNBIND, MUTT_UNMACRO

Iterate through Keymap and free keys defined either by "macro" or "bind".

Definition at line 203 of file parse.c.

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}
#define MUTT_UNBIND
Parse 'unbind' command.
Definition: lib.h:48
#define MUTT_UNMACRO
Parse 'unmacro' command.
Definition: lib.h:49
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:400
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_keymap()

static char * parse_keymap ( enum MenuType mtypes,
struct Buffer s,
int  max_menus,
int *  num_menus,
struct Buffer err,
bool  bind 
)
static

Parse a user-config key binding.

Parameters
mtypesArray for results
sBuffer containing config string
max_menusTotal number of menus
num_menusNumber of menus this config applies to
errBuffer for error messages
bindIf true 'bind', otherwise 'macro'
Return values
ptrKey string for the binding

Expects to see: <menu-string>,<menu-string>,... <key-string>

Note
Caller needs to free the returned string

Definition at line 231 of file parse.c.

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}
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition: buffer.c:668
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:571
int parse_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: extract.c:49
#define MoreArgs(buf)
Definition: extract.h:32
#define TOKEN_NO_FLAGS
No flags are set.
Definition: extract.h:46
int mutt_map_get_value(const char *name, const struct Mapping *map)
Lookup the constant for a string.
Definition: mapping.c:85
char * data
Pointer to data.
Definition: buffer.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_menu()

static void * parse_menu ( bool *  menus,
char *  s,
struct Buffer err 
)
static

Parse menu-names into an array.

Parameters
menusArray for results
sString containing menu-names
errBuffer for error messages
Return values
NULLAlways

Expects to see: <menu-string>[,<menu-string>]

Definition at line 295 of file parse.c.

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}
#define FREE(x)
Definition: memory.h:55
char * mutt_str_sep(char **stringp, const char *delim)
Find first occurrence of any of delim characters in *stringp.
Definition: string.c:187
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ try_bind()

static enum CommandResult try_bind ( char *  key,
enum MenuType  mtype,
char *  func,
const struct MenuFuncOp funcs,
struct Buffer err 
)
static

Try to make a key binding.

Parameters
keyKey name
mtypeMenu type, e.g. MENU_PAGER
funcFunction name
funcsFunctions table
errBuffer for error message
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS

Definition at line 328 of file parse.c.

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}
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition: command.h:36
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:661
const char * name
Name of the function.
Definition: lib.h:113
+ Here is the call graph for this function:
+ Here is the caller graph for this function: