NeoMutt  2025-12-11-276-g10b23b
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
dump.c File Reference

Dump key bindings. More...

#include "config.h"
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "dump.h"
#include "menu/lib.h"
#include "pager/lib.h"
#include "get.h"
#include "init.h"
#include "keymap.h"
#include "menu.h"
+ Include dependency graph for dump.c:

Go to the source code of this file.

Functions

int print_bind (enum MenuType menu, FILE *fp)
 Display the bindings for one menu.
 
void colon_bind (enum MenuType menu, FILE *fp)
 Dump the key bindings.
 
int print_macro (enum MenuType menu, FILE *fp)
 Display the macros for one menu.
 
void colon_macro (enum MenuType menu, FILE *fp)
 Dump the macros.
 
void dump_bind_macro (const struct Command *cmd, int mtype, struct Buffer *buf, struct Buffer *err)
 Dump a Menu's binds or macros to the Pager.
 
int binding_sort (const void *a, const void *b, void *sdata)
 Compare two BindingInfo by their keybinding - Implements sort_t -.
 
void escape_macro (const char *macro, struct Buffer *buf)
 Escape any special characters in a macro.
 
const char * help_lookup_function (const struct MenuDefinition *md, int op)
 Find a keybinding for an operation.
 
void gather_menu (enum MenuType menu, struct BindingInfoArray *bia_bind, struct BindingInfoArray *bia_macro, bool one_submenu)
 Gather info about one menu.
 
int measure_column (struct BindingInfoArray *bia, int col)
 Measure one column of a table.
 
int gather_unbound (enum MenuType mtype, struct BindingInfoArray *bia_unbound)
 Gather info about unbound functions for one menu.
 
struct StringArray km_get_func_array (enum MenuType mtype)
 Get array of function names for a Menu.
 

Detailed Description

Dump key bindings.

Authors
  • Richard Russon
  • Dennis Schön

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 dump.c.

Function Documentation

◆ print_bind()

int print_bind ( enum MenuType menu,
FILE * fp )

Display the bindings for one menu.

Parameters
menuMenu type
fpFile to write to
Return values
numNumber of bindings

Definition at line 54 of file dump.c.

55{
56 struct BindingInfoArray bia_bind = ARRAY_HEAD_INITIALIZER;
57
58 gather_menu(menu, &bia_bind, NULL, true);
59 if (ARRAY_EMPTY(&bia_bind))
60 return 0;
61
62 ARRAY_SORT(&bia_bind, binding_sort, NULL);
63 const int wb0 = measure_column(&bia_bind, 0);
64 const int wb1 = measure_column(&bia_bind, 1);
65
66 const char *menu_name = km_get_menu_name(menu);
67
68 struct BindingInfo *bi = NULL;
69 ARRAY_FOREACH(bi, &bia_bind)
70 {
71 if (!bi->a[0])
72 continue;
73
74 fprintf(fp, "bind %s %*s %*s # %s\n", menu_name, -wb0, bi->a[0], -wb1,
75 bi->a[1], bi->a[2]);
76 }
77
78 const int count = ARRAY_SIZE(&bia_bind);
79 ARRAY_FOREACH(bi, &bia_bind)
80 {
81 // we only need to free the keybinding
82 FREE(&bi->a[0]);
83 }
84
85 ARRAY_FREE(&bia_bind);
86 return count - 1;
87}
#define ARRAY_SORT(head, fn, sdata)
Sort an array.
Definition array.h:373
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition array.h:74
#define ARRAY_SIZE(head)
The number of elements stored.
Definition array.h:87
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:209
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
int binding_sort(const void *a, const void *b, void *sdata)
Compare two BindingInfo by their keybinding - Implements sort_t -.
Definition dump.c:237
int measure_column(struct BindingInfoArray *bia, int col)
Measure one column of a table.
Definition dump.c:423
void gather_menu(enum MenuType menu, struct BindingInfoArray *bia_bind, struct BindingInfoArray *bia_macro, bool one_submenu)
Gather info about one menu.
Definition dump.c:342
const char * km_get_menu_name(int mtype)
Get the name of a Menu.
Definition menu.c:195
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
Info about one keybinding.
Definition dump.h:41
const char * a[3]
Array of info.
Definition dump.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ colon_bind()

void colon_bind ( enum MenuType menu,
FILE * fp )

Dump the key bindings.

Parameters
menuMenu type
fpFile to write to

Definition at line 94 of file dump.c.

95{
96 if (menu == MENU_MAX)
97 {
98 for (enum MenuType i = 1; i < MENU_MAX; i++)
99 {
100 if (print_bind(i, fp) > 0)
101 fprintf(fp, "\n");
102 }
103 }
104 else
105 {
106 print_bind(menu, fp);
107 }
108}
int print_bind(enum MenuType menu, FILE *fp)
Display the bindings for one menu.
Definition dump.c:54
MenuType
Types of GUI selections.
Definition type.h:33
@ MENU_MAX
Definition type.h:51
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_macro()

int print_macro ( enum MenuType menu,
FILE * fp )

Display the macros for one menu.

Parameters
menuMenu type
fpFile to write to
Return values
numNumber of macros

Definition at line 116 of file dump.c.

117{
118 struct BindingInfoArray bia_macro = ARRAY_HEAD_INITIALIZER;
119
120 gather_menu(menu, NULL, &bia_macro, true);
121 if (ARRAY_EMPTY(&bia_macro))
122 return 0;
123
124 ARRAY_SORT(&bia_macro, binding_sort, NULL);
125 const int wm0 = measure_column(&bia_macro, 0);
126
127 const char *menu_name = km_get_menu_name(menu);
128
129 struct BindingInfo *bi = NULL;
130 ARRAY_FOREACH(bi, &bia_macro)
131 {
132 if (!bi->a[0])
133 continue;
134
135 if (bi->a[2]) // description
136 {
137 fprintf(fp, "macro %s %*s \"%s\" \"%s\"\n", menu_name, -wm0, bi->a[0],
138 bi->a[1], bi->a[2]);
139 }
140 else
141 {
142 fprintf(fp, "macro %s %*s \"%s\"\n", menu_name, -wm0, bi->a[0], bi->a[1]);
143 }
144 }
145
146 const int count = ARRAY_SIZE(&bia_macro);
147 ARRAY_FOREACH(bi, &bia_macro)
148 {
149 // free the keybinding and the macro text
150 FREE(&bi->a[0]);
151 FREE(&bi->a[1]);
152 }
153
154 ARRAY_FREE(&bia_macro);
155 return count - 1;
156}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ colon_macro()

void colon_macro ( enum MenuType menu,
FILE * fp )

Dump the macros.

Parameters
menuMenu type
fpFile to write to

Definition at line 163 of file dump.c.

164{
165 if (menu == MENU_MAX)
166 {
167 for (enum MenuType i = 1; i < MENU_MAX; i++)
168 {
169 if (print_macro(i, fp) > 0)
170 {
171 fprintf(fp, "\n");
172 }
173 }
174 }
175 else
176 {
177 print_macro(menu, fp);
178 }
179}
int print_macro(enum MenuType menu, FILE *fp)
Display the macros for one menu.
Definition dump.c:116
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dump_bind_macro()

void dump_bind_macro ( const struct Command * cmd,
int mtype,
struct Buffer * buf,
struct Buffer * err )

Dump a Menu's binds or macros to the Pager.

Parameters
cmdCommand
mtypeMenu Type
bufMenu name, e.g. "index"
errBuffer for errors

Definition at line 188 of file dump.c.

190{
191 bool dump_all = (mtype == MENU_MAX);
192
193 struct Buffer *tempfile = buf_pool_get();
194 buf_mktemp(tempfile);
195 FILE *fp = mutt_file_fopen(buf_string(tempfile), "w");
196 if (!fp)
197 {
198 // L10N: '%s' is the file name of the temporary file
199 buf_printf(err, _("Could not create temporary file %s"), buf_string(tempfile));
200 goto done;
201 }
202
203 if (cmd->id == CMD_BIND)
204 colon_bind(mtype, fp);
205 else
206 colon_macro(mtype, fp);
207
208 if (ftello(fp) == 0)
209 {
210 // L10N: '%s' is the name of the menu, e.g. 'index' or 'pager',
211 // it might also be 'all' when all menus are affected.
212 buf_printf(err, (cmd->id == CMD_BIND) ? _("%s: no binds for this menu") : _("%s: no macros for this menu"),
213 dump_all ? "all" : buf_string(buf));
214 goto done;
215 }
216 mutt_file_fclose(&fp);
217
218 struct PagerData pdata = { 0 };
219 struct PagerView pview = { &pdata };
220
221 pdata.fname = buf_string(tempfile);
222
223 pview.banner = cmd->name;
225 pview.mode = PAGER_MODE_OTHER;
226
227 mutt_do_pager(&pview, NULL);
228
229done:
230 mutt_file_fclose(&fp);
231 buf_pool_release(&tempfile);
232}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
@ CMD_BIND
:bind
Definition command.h:67
int mutt_do_pager(struct PagerView *pview, struct Email *e)
Display some page-able text to the user (help or attachment)
Definition do_pager.c:122
#define mutt_file_fclose(FP)
Definition file.h:139
#define mutt_file_fopen(PATH, MODE)
Definition file.h:138
void colon_macro(enum MenuType menu, FILE *fp)
Dump the macros.
Definition dump.c:163
void colon_bind(enum MenuType menu, FILE *fp)
Dump the key bindings.
Definition dump.c:94
#define _(a)
Definition message.h:28
#define MUTT_PAGER_NO_FLAGS
No flags are set.
Definition lib.h:61
@ PAGER_MODE_OTHER
Pager is invoked via 3rd path. Non-email content is likely to be shown.
Definition lib.h:141
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
String manipulation buffer.
Definition buffer.h:36
const char * name
Name of the Command.
Definition command.h:159
enum CommandId id
ID of the Command.
Definition command.h:160
Data to be displayed by PagerView.
Definition lib.h:160
const char * fname
Name of the file to read.
Definition lib.h:164
Paged view into some data.
Definition lib.h:171
struct PagerData * pdata
Data that pager displays. NOTNULL.
Definition lib.h:172
enum PagerMode mode
Pager mode.
Definition lib.h:173
PagerFlags flags
Additional settings to tweak pager's function.
Definition lib.h:174
const char * banner
Title to display in status bar.
Definition lib.h:175
#define buf_mktemp(buf)
Definition tmp.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ escape_macro()

void escape_macro ( const char * macro,
struct Buffer * buf )

Escape any special characters in a macro.

Parameters
[in]macroMacro string
[out]bufBuffer for the result

Replace characters, such as <Enter> with the literal "\n"

Definition at line 262 of file dump.c.

263{
264 wchar_t wc = 0;
265 size_t k;
266 size_t len = mutt_str_len(macro);
267 mbstate_t mbstate1 = { 0 };
268 mbstate_t mbstate2 = { 0 };
269
270 for (; (len > 0) && (k = mbrtowc(&wc, macro, MB_LEN_MAX, &mbstate1)); macro += k, len -= k)
271 {
272 if ((k == ICONV_ILLEGAL_SEQ) || (k == ICONV_BUF_TOO_SMALL))
273 {
274 if (k == ICONV_ILLEGAL_SEQ)
275 memset(&mbstate1, 0, sizeof(mbstate1));
276 k = (k == ICONV_ILLEGAL_SEQ) ? 1 : len;
277 wc = ReplacementChar;
278 }
279
280 const int w = wcwidth(wc);
281 if (IsWPrint(wc) && (w >= 0))
282 {
283 char tmp[MB_LEN_MAX * 2] = { 0 };
284 if (wcrtomb(tmp, wc, &mbstate2) != ICONV_ILLEGAL_SEQ)
285 {
286 buf_addstr(buf, tmp);
287 }
288 }
289 else if ((wc < 0x20) || (wc == 0x7f))
290 {
291 if (wc == '\033') // Escape
292 buf_addstr(buf, "\\e");
293 else if (wc == '\n')
294 buf_addstr(buf, "\\n");
295 else if (wc == '\r')
296 buf_addstr(buf, "\\r");
297 else if (wc == '\t')
298 buf_addstr(buf, "\\t");
299 else
300 buf_add_printf(buf, "^%c", (char) ((wc + '@') & 0x7f));
301 }
302 else
303 {
304 buf_addch(buf, '?');
305 }
306 }
307}
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition buffer.c:204
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:241
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:226
#define IsWPrint(wc)
Definition mbyte.h:40
wchar_t ReplacementChar
When a Unicode character can't be displayed, use this instead.
Definition charset.c:61
#define ICONV_BUF_TOO_SMALL
Error value for iconv() - Buffer too small.
Definition charset.h:116
#define ICONV_ILLEGAL_SEQ
Error value for iconv() - Illegal sequence.
Definition charset.h:114
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:500
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ help_lookup_function()

const char * help_lookup_function ( const struct MenuDefinition * md,
int op )

Find a keybinding for an operation.

Parameters
mdMenu Definition
opOperation, e.g. OP_DELETE
Return values
strKey binding
NULLNo key binding found

Definition at line 316 of file dump.c.

317{
318 struct SubMenu **smp = NULL;
319
320 ARRAY_FOREACH(smp, &md->submenus)
321 {
322 struct SubMenu *sm = *smp;
323
324 for (int i = 0; sm->functions[i].name; i++)
325 {
326 const struct MenuFuncOp *mfo = &sm->functions[i];
327 if (mfo->op == op)
328 return mfo->name;
329 }
330 }
331
332 return "UNKNOWN";
333}
struct SubMenuPArray submenus
Parts making up the Menu.
Definition menu.h:84
Mapping between a function and an operation.
Definition menu.h:39
const char * name
Name of the function.
Definition menu.h:40
int op
Operation, e.g. OP_DELETE.
Definition menu.h:41
Collection of related functions.
Definition menu.h:69
const struct MenuFuncOp * functions
All available functions.
Definition menu.h:71
+ Here is the caller graph for this function:

◆ gather_menu()

void gather_menu ( enum MenuType menu,
struct BindingInfoArray * bia_bind,
struct BindingInfoArray * bia_macro,
bool one_submenu )

Gather info about one menu.

Parameters
[in]menuMenu type
[out]bia_bindArray for bind results (may be NULL)
[out]bia_macroArray for macro results (may be NULL)
[in]one_submenuOnly parse the first SubMenu

Definition at line 342 of file dump.c.

344{
345 struct Buffer *key_binding = buf_pool_get();
346 struct Buffer *macro = buf_pool_get();
347
348 struct MenuDefinition *md = NULL;
350 {
351 if (md->id == menu)
352 break;
353 }
354
355 struct SubMenu **smp = NULL;
356
357 ARRAY_FOREACH(smp, &md->submenus)
358 {
359 struct SubMenu *sm = *smp;
360 const char *name = sm->parent->name;
361
362 struct BindingInfo bi_label = { ARRAY_FOREACH_IDX_smp, { NULL, NULL, name } };
363
364 if (bia_bind)
365 ARRAY_ADD(bia_bind, bi_label);
366 if (bia_macro)
367 ARRAY_ADD(bia_macro, bi_label);
368
369 struct Keymap *map = NULL;
370 STAILQ_FOREACH(map, &sm->keymaps, entries)
371 {
372 struct BindingInfo bi = { ARRAY_FOREACH_IDX_smp, { NULL, NULL, NULL } };
373
374 buf_reset(key_binding);
375 keymap_expand_key(map, key_binding);
376
377 if (map->op == OP_MACRO)
378 {
379 if (!bia_macro || (map->op == OP_NULL))
380 continue;
381
382 buf_reset(macro);
383 escape_macro(map->macro, macro);
384 bi.a[0] = buf_strdup(key_binding);
385 bi.a[1] = buf_strdup(macro);
386 bi.a[2] = map->desc;
387 ARRAY_ADD(bia_macro, bi);
388 }
389 else
390 {
391 if (!bia_bind)
392 continue;
393
394 if (map->op == OP_NULL)
395 {
396 bi.a[0] = buf_strdup(key_binding);
397 bi.a[1] = "noop";
398 ARRAY_ADD(bia_bind, bi);
399 continue;
400 }
401
402 bi.a[0] = buf_strdup(key_binding);
403 bi.a[1] = help_lookup_function(md, map->op);
404 bi.a[2] = _(opcodes_get_description(map->op));
405 ARRAY_ADD(bia_bind, bi);
406 }
407 }
408
409 if (one_submenu)
410 break;
411 }
412
413 buf_pool_release(&key_binding);
414 buf_pool_release(&macro);
415}
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition array.h:157
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:571
struct MenuDefinitionArray MenuDefs
All the registered Menus.
Definition init.c:42
void escape_macro(const char *macro, struct Buffer *buf)
Escape any special characters in a macro.
Definition dump.c:262
const char * help_lookup_function(const struct MenuDefinition *md, int op)
Find a keybinding for an operation.
Definition dump.c:316
bool keymap_expand_key(struct Keymap *km, struct Buffer *buf)
Get the key string bound to a Keymap.
Definition keymap.c:229
const char * opcodes_get_description(int op)
Get the description of an opcode.
Definition opcodes.c:68
#define STAILQ_FOREACH(var, head, field)
Definition queue.h:390
A keyboard mapping.
Definition keymap.h:43
char * macro
Macro expansion (op == OP_MACRO)
Definition keymap.h:44
char * desc
Description of a macro for the help menu.
Definition keymap.h:45
short op
Operation to perform.
Definition keymap.h:46
Functions for a Dialog or Window.
Definition menu.h:81
const char * name
Menu name, e.g. "alias".
Definition menu.h:83
int id
Menu ID, e.g. MENU_ALIAS.
Definition menu.h:82
struct KeymapList keymaps
All keybindings.
Definition menu.h:72
struct MenuDefinition * parent
Primary parent.
Definition menu.h:70
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ measure_column()

int measure_column ( struct BindingInfoArray * bia,
int col )

Measure one column of a table.

Parameters
biaArray of binding info
colColumn to measure
Return values
numWidth of widest column

Definition at line 423 of file dump.c.

424{
425 int max_width = 0;
426
427 struct BindingInfo *bi = NULL;
428 ARRAY_FOREACH(bi, bia)
429 {
430 const int col_width = mutt_strwidth(bi->a[col]);
431 max_width = MAX(max_width, col_width);
432 }
433
434 return max_width;
435}
size_t mutt_strwidth(const char *s)
Measure a string's width in screen cells.
Definition curs_lib.c:444
#define MAX(a, b)
Return the maximum of two values.
Definition memory.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ gather_unbound()

int gather_unbound ( enum MenuType mtype,
struct BindingInfoArray * bia_unbound )

Gather info about unbound functions for one menu.

Parameters
[in]mtypeMenu Type, e.g. MENU_INDEX
[out]bia_unboundUnbound functions
Return values
numNumber of unbound functions

Definition at line 443 of file dump.c.

444{
445 if (!bia_unbound)
446 return 0;
447
448 struct MenuDefinition *md = NULL;
450 {
451 if (md->id == mtype)
452 break;
453 }
454
455 struct SubMenu **smp = NULL;
456
457 ARRAY_FOREACH(smp, &md->submenus)
458 {
459 struct SubMenu *sm = *smp;
460
461 for (int i = 0; sm->functions[i].name; i++)
462 {
463 const struct MenuFuncOp *mfo = &sm->functions[i];
464
465 if (mfo->flags & MFF_DEPRECATED)
466 continue;
467
468 if (is_bound(md, mfo->op))
469 continue;
470
471 struct BindingInfo bi = { 0 };
472 bi.a[0] = NULL;
473 bi.a[1] = mfo->name;
474 bi.a[2] = _(opcodes_get_description(mfo->op));
475 ARRAY_ADD(bia_unbound, bi);
476 }
477 }
478
479 return ARRAY_SIZE(bia_unbound);
480}
#define MFF_DEPRECATED
Redraw the pager.
Definition get.h:44
bool is_bound(const struct MenuDefinition *md, int op)
Does a function have a keybinding?
Definition menu.c:305
MenuFuncFlags flags
Flags, e.g. MFF_DEPRECATED.
Definition menu.h:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ km_get_func_array()

struct StringArray km_get_func_array ( enum MenuType mtype)

Get array of function names for a Menu.

Parameters
mtypeMenu type

Definition at line 486 of file dump.c.

487{
488 struct StringArray fna = ARRAY_HEAD_INITIALIZER;
489
490 struct MenuDefinition *md = NULL;
492 {
493 if (md->id != mtype)
494 continue;
495
496 struct SubMenu **smp = NULL;
497
498 ARRAY_FOREACH(smp, &md->submenus)
499 {
500 struct SubMenu *sm = *smp;
501
502 for (int i = 0; sm->functions[i].name; i++)
503 {
504 ARRAY_ADD(&fna, sm->functions[i].name);
505 }
506 }
507 break;
508 }
509
510 return fna;
511}
+ Here is the call graph for this function:
+ Here is the caller graph for this function: