NeoMutt  2021-10-22-8-g9cb437
Teaching an old dog new tricks
DOXYGEN
icommands.c File Reference

Information commands. More...

#include "config.h"
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "core/lib.h"
#include "mutt.h"
#include "icommands.h"
#include "menu/lib.h"
#include "pager/lib.h"
#include "functions.h"
#include "init.h"
#include "keymap.h"
#include "muttlib.h"
#include "opcodes.h"
#include "version.h"
+ Include dependency graph for icommands.c:

Go to the source code of this file.

Functions

static enum CommandResult icmd_bind (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse 'bind' and 'macro' commands - Implements ICommand::parse() More...
 
static enum CommandResult icmd_set (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse 'set' command to display config - Implements ICommand::parse() More...
 
static enum CommandResult icmd_version (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse 'version' command - Implements ICommand::parse() More...
 
enum CommandResult mutt_parse_icommand (char *line, struct Buffer *err)
 Parse an informational command. More...
 
static void dump_bind (struct Buffer *buf, struct Mapping *menu, struct Keymap *map)
 Dump a bind map to a buffer. More...
 
static void dump_macro (struct Buffer *buf, struct Mapping *menu, struct Keymap *map)
 Dump a macro map to a buffer. More...
 
static bool dump_menu (struct Buffer *buf, struct Mapping *menu, bool bind)
 Dumps all the binds or macros maps of a menu into a buffer. More...
 
static void dump_all_menus (struct Buffer *buf, bool bind)
 Dumps all the binds or macros inside every menu. More...
 

Variables

static const struct ICommand ICommandList []
 All available informational commands. More...
 

Detailed Description

Information commands.

Authors
  • Christopher John Czettel
  • Richard Russon
  • Victor Fernandes

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

Function Documentation

◆ icmd_bind()

static enum CommandResult icmd_bind ( struct Buffer buf,
struct Buffer s,
intptr_t  data,
struct Buffer err 
)
static

Parse 'bind' and 'macro' commands - Implements ICommand::parse()

Definition at line 215 of file icommands.c.

235 {
236  FILE *fp_out = NULL;
237  char tempfile[PATH_MAX];
238  bool dump_all = false, bind = (data == 0);
239 
240  if (!MoreArgs(s))
241  dump_all = true;
242  else
244 
245  if (MoreArgs(s))
246  {
247  /* More arguments potentially means the user is using the
248  * ::command_t :bind command thus we delegate the task. */
249  return MUTT_CMD_ERROR;
250  }
251 
252  struct Buffer filebuf = mutt_buffer_make(4096);
253  if (dump_all || mutt_istr_equal(buf->data, "all"))
254  {
255  dump_all_menus(&filebuf, bind);
256  }
257  else
258  {
259  const int menu_index = mutt_map_get_value(buf->data, MenuNames);
260  if (menu_index == -1)
261  {
262  // L10N: '%s' is the (misspelled) name of the menu, e.g. 'index' or 'pager'
263  mutt_buffer_printf(err, _("%s: no such menu"), buf->data);
264  mutt_buffer_dealloc(&filebuf);
265  return MUTT_CMD_ERROR;
266  }
267 
268  struct Mapping menu = { buf->data, menu_index };
269  dump_menu(&filebuf, &menu, bind);
270  }
271 
272  if (mutt_buffer_is_empty(&filebuf))
273  {
274  // L10N: '%s' is the name of the menu, e.g. 'index' or 'pager',
275  // it might also be 'all' when all menus are affected.
276  mutt_buffer_printf(err, bind ? _("%s: no binds for this menu") : _("%s: no macros for this menu"),
277  dump_all ? "all" : buf->data);
278  mutt_buffer_dealloc(&filebuf);
279  return MUTT_CMD_ERROR;
280  }
281 
282  mutt_mktemp(tempfile, sizeof(tempfile));
283  fp_out = mutt_file_fopen(tempfile, "w");
284  if (!fp_out)
285  {
286  // L10N: '%s' is the file name of the temporary file
287  mutt_buffer_printf(err, _("Could not create temporary file %s"), tempfile);
288  mutt_buffer_dealloc(&filebuf);
289  return MUTT_CMD_ERROR;
290  }
291  fputs(filebuf.data, fp_out);
292 
293  mutt_file_fclose(&fp_out);
294  mutt_buffer_dealloc(&filebuf);
295 
296  struct PagerData pdata = { 0 };
297  struct PagerView pview = { &pdata };
298 
299  pdata.fname = tempfile;
300 
301  pview.banner = (bind) ? "bind" : "macro";
302  pview.flags = MUTT_PAGER_NO_FLAGS;
303  pview.mode = PAGER_MODE_OTHER;
304 
305  if (mutt_do_pager(&pview, NULL) == -1)
306  {
307  // L10N: '%s' is the file name of the temporary file
308  mutt_buffer_printf(err, _("Could not create temporary file %s"), tempfile);
309  return MUTT_CMD_ERROR;
310  }
311 
312  return MUTT_CMD_SUCCESS;
313 }
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
#define MoreArgs(buf)
Definition: buffer.h:40
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition: command.h:37
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition: command.h:35
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:120
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:593
static void dump_all_menus(struct Buffer *buf, bool bind)
Dumps all the binds or macros inside every menu.
Definition: icommands.c:215
static bool dump_menu(struct Buffer *buf, struct Mapping *menu, bool bind)
Dumps all the binds or macros maps of a menu into a buffer.
Definition: icommands.c:188
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:398
int mutt_map_get_value(const char *name, const struct Mapping *map)
Lookup the constant for a string.
Definition: mapping.c:85
#define _(a)
Definition: message.h:28
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:66
#define PATH_MAX
Definition: mutt.h:40
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:71
#define MUTT_PAGER_NO_FLAGS
No flags are set.
Definition: lib.h:59
@ PAGER_MODE_OTHER
Pager is invoked via 3rd path. Non-email content is likely to be shown.
Definition: lib.h:140
String manipulation buffer.
Definition: buffer.h:34
char * data
Pointer to data.
Definition: buffer.h:35
Mapping between user-readable string and a constant.
Definition: mapping.h:32
Data to be displayed by PagerView.
Definition: lib.h:149
const char * fname
Name of the file to read.
Definition: lib.h:153
Paged view into some data.
Definition: lib.h:160
struct PagerData * pdata
Data that pager displays. NOTNULL.
Definition: lib.h:161
enum PagerMode mode
Pager mode.
Definition: lib.h:162
PagerFlags flags
Additional settings to tweak pager's function.
Definition: lib.h:163
const char * banner
Title to display in status bar.
Definition: lib.h:164
const struct Mapping MenuNames[]
Menu name lookup table.
Definition: type.c:31

◆ icmd_set()

static enum CommandResult icmd_set ( struct Buffer buf,
struct Buffer s,
intptr_t  data,
struct Buffer err 
)
static

Parse 'set' command to display config - Implements ICommand::parse()

Definition at line 215 of file icommands.c.

320 {
321  const bool set = mutt_str_equal(s->data, "set");
322  const bool set_all = mutt_str_equal(s->data, "set all");
323 
324  if (!set && !set_all)
325  return MUTT_CMD_ERROR;
326 
327  char tempfile[PATH_MAX];
328  mutt_mktemp(tempfile, sizeof(tempfile));
329 
330  FILE *fp_out = mutt_file_fopen(tempfile, "w");
331  if (!fp_out)
332  {
333  // L10N: '%s' is the file name of the temporary file
334  mutt_buffer_printf(err, _("Could not create temporary file %s"), tempfile);
335  return MUTT_CMD_ERROR;
336  }
337 
338  if (set_all)
340  else
342 
343  mutt_file_fclose(&fp_out);
344 
345  struct PagerData pdata = { 0 };
346  struct PagerView pview = { &pdata };
347 
348  pdata.fname = tempfile;
349 
350  pview.banner = "set";
351  pview.flags = MUTT_PAGER_NO_FLAGS;
352  pview.mode = PAGER_MODE_OTHER;
353 
354  mutt_do_pager(&pview, NULL);
355 
356  return MUTT_CMD_SUCCESS;
357 }
bool dump_config(struct ConfigSet *cs, ConfigDumpFlags flags, FILE *fp)
Write all the config to a file.
Definition: dump.c:165
#define CS_DUMP_ONLY_CHANGED
Only show config that the user has changed.
Definition: dump.h:36
#define CS_DUMP_NO_FLAGS
No flags are set.
Definition: dump.h:35
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
struct ConfigSet * cs
Parent ConfigSet.
Definition: subset.h:51
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39

◆ icmd_version()

static enum CommandResult icmd_version ( struct Buffer buf,
struct Buffer s,
intptr_t  data,
struct Buffer err 
)
static

Parse 'version' command - Implements ICommand::parse()

Definition at line 215 of file icommands.c.

364 {
365  char tempfile[PATH_MAX];
366  mutt_mktemp(tempfile, sizeof(tempfile));
367 
368  FILE *fp_out = mutt_file_fopen(tempfile, "w");
369  if (!fp_out)
370  {
371  // L10N: '%s' is the file name of the temporary file
372  mutt_buffer_printf(err, _("Could not create temporary file %s"), tempfile);
373  return MUTT_CMD_ERROR;
374  }
375 
376  print_version(fp_out);
377  mutt_file_fclose(&fp_out);
378 
379  struct PagerData pdata = { 0 };
380  struct PagerView pview = { &pdata };
381 
382  pdata.fname = tempfile;
383 
384  pview.banner = "version";
385  pview.flags = MUTT_PAGER_NO_FLAGS;
386  pview.mode = PAGER_MODE_OTHER;
387 
388  if (mutt_do_pager(&pview, NULL) == -1)
389  {
390  // L10N: '%s' is the file name of the temporary file
391  mutt_buffer_printf(err, _("Could not create temporary file %s"), tempfile);
392  return MUTT_CMD_ERROR;
393  }
394 
395  return MUTT_CMD_SUCCESS;
396 }
bool print_version(FILE *fp)
Print system and compile info to a file.
Definition: version.c:403

◆ mutt_parse_icommand()

enum CommandResult mutt_parse_icommand ( char *  line,
struct Buffer err 
)

Parse an informational command.

Parameters
lineCommand to execute
errBuffer for error messages
Return values
MUTT_CMD_SUCCESSSuccess
MUTT_CMD_WARNINGWarning with message: command failed
MUTT_CMD_ERROR
  • Error (no message): command not found
  • Error with message: command failed

Definition at line 1 of file icommands.c.

81 {
82  if (!line || (*line == '\0') || !err)
83  return MUTT_CMD_ERROR;
84 
85  enum CommandResult rc = MUTT_CMD_ERROR;
86 
87  struct Buffer *token = mutt_buffer_pool_get();
88  struct Buffer expn = mutt_buffer_make(0);
89  mutt_buffer_addstr(&expn, line);
90  mutt_buffer_seek(&expn, 0);
91 
92  mutt_buffer_reset(err);
93 
94  SKIPWS(expn.dptr);
96  for (size_t i = 0; ICommandList[i].name; i++)
97  {
98  if (!mutt_str_equal(token->data, ICommandList[i].name))
99  continue;
100 
101  rc = ICommandList[i].parse(token, &expn, ICommandList[i].data, err);
102  if (rc != 0)
103  goto finish;
104 
105  break; /* Continue with next command */
106  }
107 
108 finish:
109  mutt_buffer_pool_release(&token);
110  mutt_buffer_dealloc(&expn);
111  return rc;
112 }
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
void mutt_buffer_seek(struct Buffer *buf, size_t offset)
Set current read/write position to offset from beginning.
Definition: buffer.c:466
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
CommandResult
Error codes for command_t parse functions.
Definition: command.h:34
static const struct ICommand ICommandList[]
All available informational commands.
Definition: icommands.c:60
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define SKIPWS(ch)
Definition: string2.h:46
char * dptr
Current read/write position.
Definition: buffer.h:36
enum CommandResult(* parse)(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Function to parse information commands.
Definition: icommands.h:47
char * name
Name of the command.
Definition: icommands.h:37
+ Here is the caller graph for this function:

◆ dump_bind()

static void dump_bind ( struct Buffer buf,
struct Mapping menu,
struct Keymap map 
)
static

Dump a bind map to a buffer.

Parameters
bufOutput buffer
menuMap menu
mapBind keymap

Definition at line 120 of file icommands.c.

121 {
122  char key_binding[32];
123  const char *fn_name = NULL;
124 
125  km_expand_key(key_binding, sizeof(key_binding), map);
126  if (map->op == OP_NULL)
127  {
128  mutt_buffer_add_printf(buf, "bind %s %s noop\n", menu->name, key_binding);
129  return;
130  }
131 
132  /* The pager and editor menus don't use the generic map,
133  * however for other menus try generic first. */
134  if ((menu->value != MENU_PAGER) && (menu->value != MENU_EDITOR) && (menu->value != MENU_GENERIC))
135  {
136  fn_name = mutt_get_func(OpGeneric, map->op);
137  }
138 
139  /* if it's one of the menus above or generic doesn't find
140  * the function, try with its own menu. */
141  if (!fn_name)
142  {
143  const struct Binding *bindings = km_get_table(menu->value);
144  if (!bindings)
145  return;
146 
147  fn_name = mutt_get_func(bindings, map->op);
148  }
149 
150  mutt_buffer_add_printf(buf, "bind %s %s %s\n", menu->name, key_binding, fn_name);
151 }
int mutt_buffer_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:203
const struct Binding OpGeneric[]
Key bindings for the generic menu.
Definition: functions.c:53
const struct Binding * km_get_table(enum MenuType mtype)
Lookup a menu's keybindings.
Definition: keymap.c:1301
int km_expand_key(char *s, size_t len, struct Keymap *map)
Get the key string bound to a Keymap.
Definition: keymap.c:910
const char * mutt_get_func(const struct Binding *bindings, int op)
Get the name of a function.
Definition: keymap.c:508
Mapping between a user key and a function.
Definition: keymap.h:92
short op
operation to perform
Definition: keymap.h:52
int value
Integer value.
Definition: mapping.h:34
const char * name
String value.
Definition: mapping.h:33
@ MENU_GENERIC
Generic selection list.
Definition: type.h:45
@ MENU_PAGER
Pager pager (email viewer)
Definition: type.h:54
@ MENU_EDITOR
Text entry area.
Definition: type.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dump_macro()

static void dump_macro ( struct Buffer buf,
struct Mapping menu,
struct Keymap map 
)
static

Dump a macro map to a buffer.

Parameters
bufOutput buffer
menuMap menu
mapMacro keymap

Definition at line 159 of file icommands.c.

160 {
161  char key_binding[MAX_SEQ];
162  km_expand_key(key_binding, MAX_SEQ, map);
163 
164  struct Buffer tmp = mutt_buffer_make(0);
165  escape_string(&tmp, map->macro);
166 
167  if (map->desc)
168  {
169  mutt_buffer_add_printf(buf, "macro %s %s \"%s\" \"%s\"\n", menu->name,
170  key_binding, tmp.data, map->desc);
171  }
172  else
173  {
174  mutt_buffer_add_printf(buf, "macro %s %s \"%s\"\n", menu->name, key_binding, tmp.data);
175  }
176 
177  mutt_buffer_dealloc(&tmp);
178 }
size_t escape_string(struct Buffer *buf, const char *src)
Write a string to a buffer, escaping special characters.
Definition: dump.c:46
#define MAX_SEQ
Definition: keymap.h:36
char * macro
macro expansion (op == OP_MACRO)
Definition: keymap.h:50
char * desc
description of a macro for the help menu
Definition: keymap.h:51
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dump_menu()

static bool dump_menu ( struct Buffer buf,
struct Mapping menu,
bool  bind 
)
static

Dumps all the binds or macros maps of a menu into a buffer.

Parameters
bufOutput buffer
menuMenu to dump
bindIf true it's :bind, else :macro
Return values
trueMenu is empty
falseMenu is not empty

Definition at line 188 of file icommands.c.

189 {
190  bool empty = true;
191  struct Keymap *map = NULL;
192 
193  STAILQ_FOREACH(map, &Keymaps[menu->value], entries)
194  {
195  if (bind && (map->op != OP_MACRO))
196  {
197  empty = false;
198  dump_bind(buf, menu, map);
199  }
200  else if (!bind && (map->op == OP_MACRO))
201  {
202  empty = false;
203  dump_macro(buf, menu, map);
204  }
205  }
206 
207  return empty;
208 }
static void dump_macro(struct Buffer *buf, struct Mapping *menu, struct Keymap *map)
Dump a macro map to a buffer.
Definition: icommands.c:159
static void dump_bind(struct Buffer *buf, struct Mapping *menu, struct Keymap *map)
Dump a bind map to a buffer.
Definition: icommands.c:120
struct KeymapList Keymaps[MENU_MAX]
Array of Keymap keybindings, one for each Menu.
Definition: keymap.c:120
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
A keyboard mapping.
Definition: keymap.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dump_all_menus()

static void dump_all_menus ( struct Buffer buf,
bool  bind 
)
static

Dumps all the binds or macros inside every menu.

Parameters
bufOutput buffer
bindIf true it's :bind, else :macro

Definition at line 215 of file icommands.c.

216 {
217  for (int i = 0; i < MENU_MAX; i++)
218  {
219  const char *menu_name = mutt_map_get_name(i, MenuNames);
220  struct Mapping menu = { menu_name, i };
221 
222  const bool empty = dump_menu(buf, &menu, bind);
223 
224  /* Add a new line for readability between menus. */
225  if (!empty && (i < (MENU_MAX - 1)))
226  mutt_buffer_addch(buf, '\n');
227  }
228 }
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition: mapping.c:42
@ MENU_MAX
Definition: type.h:59
+ Here is the call graph for this function:

Variable Documentation

◆ ICommandList

const struct ICommand ICommandList[]
static
Initial value:
= {
{ "bind", icmd_bind, 0 },
{ "macro", icmd_bind, 1 },
{ "set", icmd_set, 0 },
{ "version", icmd_version, 0 },
{ NULL, NULL, 0 },
}
static enum CommandResult icmd_set(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse 'set' command to display config - Implements ICommand::parse()
Definition: icommands.c:318
static enum CommandResult icmd_bind(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse 'bind' and 'macro' commands - Implements ICommand::parse()
Definition: icommands.c:233
static enum CommandResult icmd_version(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse 'version' command - Implements ICommand::parse()
Definition: icommands.c:362

All available informational commands.

Note
These commands take precedence over conventional NeoMutt rc-lines

Definition at line 1 of file icommands.c.