NeoMutt  2022-04-29-249-gaae397
Teaching an old dog new tricks
DOXYGEN
lib.h File Reference

Read/write command history from/to a file. More...

#include <stdbool.h>
#include <stdlib.h>
+ Include dependency graph for lib.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Enumerations

enum  HistoryClass {
  HC_CMD , HC_ALIAS , HC_COMMAND , HC_FILE ,
  HC_PATTERN , HC_OTHER , HC_MBOX , HC_MAX
}
 Type to differentiate different histories. More...
 

Functions

void mutt_hist_add (enum HistoryClass hclass, const char *str, bool save)
 Add a string to a history. More...
 
bool mutt_hist_at_scratch (enum HistoryClass hclass)
 Is the current History position at the 'scratch' place? More...
 
void mutt_hist_free (void)
 Free all the history lists. More...
 
void mutt_hist_init (void)
 Create a set of empty History ring buffers. More...
 
char * mutt_hist_next (enum HistoryClass hclass)
 Get the next string in a History. More...
 
char * mutt_hist_prev (enum HistoryClass hclass)
 Get the previous string in a History. More...
 
void mutt_hist_read_file (void)
 Read the History from a file. More...
 
void mutt_hist_reset_state (enum HistoryClass hclass)
 Move the 'current' position to the end of the History. More...
 
void mutt_hist_save_scratch (enum HistoryClass hclass, const char *str)
 Save a temporary string to the History. More...
 
int mutt_hist_search (const char *search_buf, enum HistoryClass hclass, char **matches)
 Find matches in a history list. More...
 
void dlg_select_history (char *buf, size_t buflen, char **matches, int match_count)
 Select an item from a history list. More...
 

Detailed Description

Read/write command history from/to a file.

Authors
  • Michael R. Elkins

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 lib.h.

Enumeration Type Documentation

◆ HistoryClass

Type to differentiate different histories.

Saved lists of recently-used:

Enumerator
HC_CMD 

External commands.

HC_ALIAS 

Aliases.

HC_COMMAND 

NeoMutt commands.

HC_FILE 

Files.

HC_PATTERN 

Patterns.

HC_OTHER 

Miscellaneous strings.

HC_MBOX 

Mailboxes.

HC_MAX 

Definition at line 47 of file lib.h.

48{
49 HC_CMD,
50 HC_ALIAS,
52 HC_FILE,
54 HC_OTHER,
55 HC_MBOX,
56 HC_MAX,
57};
@ HC_MBOX
Mailboxes.
Definition: lib.h:55
@ HC_FILE
Files.
Definition: lib.h:52
@ HC_COMMAND
NeoMutt commands.
Definition: lib.h:51
@ HC_ALIAS
Aliases.
Definition: lib.h:50
@ HC_MAX
Definition: lib.h:56
@ HC_PATTERN
Patterns.
Definition: lib.h:53
@ HC_OTHER
Miscellaneous strings.
Definition: lib.h:54
@ HC_CMD
External commands.
Definition: lib.h:49

Function Documentation

◆ mutt_hist_add()

void mutt_hist_add ( enum HistoryClass  hclass,
const char *  str,
bool  save 
)

Add a string to a history.

Parameters
hclassHistory to add to
strString to add
saveShould the changes be saved to file immediately?

Definition at line 483 of file history.c.

484{
485 struct History *h = get_history(hclass);
486 if (!h)
487 return; /* disabled */
488
489 if (*str)
490 {
491 int prev = h->last - 1;
492 const short c_history = cs_subset_number(NeoMutt->sub, "history");
493 if (prev < 0)
494 prev = c_history;
495
496 /* don't add to prompt history:
497 * - lines beginning by a space
498 * - repeated lines */
499 if ((*str != ' ') && (!h->hist[prev] || !mutt_str_equal(h->hist[prev], str)))
500 {
501 const bool c_history_remove_dups = cs_subset_bool(NeoMutt->sub, "history_remove_dups");
502 if (c_history_remove_dups)
503 remove_history_dups(hclass, str);
504 const short c_save_history = cs_subset_number(NeoMutt->sub, "save_history");
505 const char *const c_history_file = cs_subset_path(NeoMutt->sub, "history_file");
506 if (save && (c_save_history != 0) && c_history_file)
507 save_history(hclass, str);
508 mutt_str_replace(&h->hist[h->last++], str);
509 if (h->last > c_history)
510 h->last = 0;
511 }
512 }
513 h->cur = h->last; /* reset to the last entry */
514}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
static void remove_history_dups(enum HistoryClass hclass, const char *str)
De-dupe the history.
Definition: history.c:359
static struct History * get_history(enum HistoryClass hclass)
Get a particular history.
Definition: history.c:105
static void save_history(enum HistoryClass hclass, const char *str)
Save one history string to a file.
Definition: history.c:308
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:807
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
Saved list of user-entered commands/searches.
Definition: history.c:89
short cur
Current history item.
Definition: history.c:91
short last
Last history item.
Definition: history.c:92
char ** hist
Array of history items.
Definition: history.c:90
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_at_scratch()

bool mutt_hist_at_scratch ( enum HistoryClass  hclass)

Is the current History position at the 'scratch' place?

Parameters
hclassHistory to use
Return values
trueHistory is at 'scratch' place

The last entry in the history is used as a 'scratch' area. It can be overwritten as the user types and edits.

To get (back) to the scratch area, call mutt_hist_next(), mutt_hist_prev() or mutt_hist_reset_state().

Definition at line 645 of file history.c.

646{
647 struct History *h = get_history(hclass);
648 if (!h)
649 return false; /* disabled */
650
651 return h->cur == h->last;
652}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_free()

void mutt_hist_free ( void  )

Free all the history lists.

Definition at line 438 of file history.c.

439{
440 if (!NeoMutt)
441 return;
442
443 const short c_history = cs_subset_number(NeoMutt->sub, "history");
444 for (enum HistoryClass hclass = HC_FIRST; hclass < HC_MAX; hclass++)
445 {
446 struct History *h = &Histories[hclass];
447 if (!h->hist)
448 continue;
449
450 /* The array has (`$history`+1) elements */
451 for (int i = 0; i <= c_history; i++)
452 {
453 FREE(&h->hist[i]);
454 }
455 FREE(&h->hist);
456 }
457}
HistoryClass
Type to differentiate different histories.
Definition: lib.h:48
static struct History Histories[HC_MAX]
Definition: history.c:97
#define HC_FIRST
Definition: history.c:81
#define FREE(x)
Definition: memory.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_init()

void mutt_hist_init ( void  )

Create a set of empty History ring buffers.

This just creates empty histories. To fill them, call mutt_hist_read_file().

Definition at line 465 of file history.c.

466{
467 const short c_history = cs_subset_number(NeoMutt->sub, "history");
468 if (c_history == OldSize)
469 return;
470
471 for (enum HistoryClass hclass = HC_FIRST; hclass < HC_MAX; hclass++)
472 init_history(&Histories[hclass]);
473
474 OldSize = c_history;
475}
static int OldSize
Definition: history.c:98
static void init_history(struct History *h)
Set up a new History ring buffer.
Definition: history.c:121
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_next()

char * mutt_hist_next ( enum HistoryClass  hclass)

Get the next string in a History.

Parameters
hclassHistory to choose
Return values
ptrNext string

If there is no next string, and empty string will be returned.

Definition at line 523 of file history.c.

524{
525 struct History *h = get_history(hclass);
526 if (!h)
527 return ""; /* disabled */
528
529 int next = h->cur;
530 do
531 {
532 next++;
533 const short c_history = cs_subset_number(NeoMutt->sub, "history");
534 if (next > c_history)
535 next = 0;
536 if (next == h->last)
537 break;
538 } while (!h->hist[next]);
539
540 h->cur = next;
541 return NONULL(h->hist[h->cur]);
542}
#define NONULL(x)
Definition: string2.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_prev()

char * mutt_hist_prev ( enum HistoryClass  hclass)

Get the previous string in a History.

Parameters
hclassHistory to choose
Return values
ptrPrevious string

If there is no previous string, and empty string will be returned.

Definition at line 551 of file history.c.

552{
553 struct History *h = get_history(hclass);
554 if (!h)
555 return ""; /* disabled */
556
557 int prev = h->cur;
558 do
559 {
560 prev--;
561 const short c_history = cs_subset_number(NeoMutt->sub, "history");
562 if (prev < 0)
563 prev = c_history;
564 if (prev == h->last)
565 break;
566 } while (!h->hist[prev]);
567
568 h->cur = prev;
569 return NONULL(h->hist[h->cur]);
570}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_read_file()

void mutt_hist_read_file ( void  )

Read the History from a file.

The file $history_file is read and parsed into separate History ring buffers.

Definition at line 593 of file history.c.

594{
595 int line = 0, hclass, read;
596 char *linebuf = NULL, *p = NULL;
597 size_t buflen;
598
599 const char *const c_history_file = cs_subset_path(NeoMutt->sub, "history_file");
600 if (!c_history_file)
601 return;
602
603 FILE *fp = mutt_file_fopen(c_history_file, "r");
604 if (!fp)
605 return;
606
607 while ((linebuf = mutt_file_read_line(linebuf, &buflen, fp, &line, MUTT_RL_NO_FLAGS)))
608 {
609 read = 0;
610 if ((sscanf(linebuf, "%d:%n", &hclass, &read) < 1) || (read == 0) ||
611 (*(p = linebuf + strlen(linebuf) - 1) != '|') || (hclass < 0))
612 {
613 mutt_error(_("Bad history file format (line %d)"), line);
614 break;
615 }
616 /* silently ignore too high class (probably newer neomutt) */
617 if (hclass >= HC_MAX)
618 continue;
619 *p = '\0';
620 p = mutt_str_dup(linebuf + read);
621 if (p)
622 {
623 const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
624 mutt_ch_convert_string(&p, "utf-8", c_charset, MUTT_ICONV_NO_FLAGS);
625 mutt_hist_add(hclass, p, false);
626 FREE(&p);
627 }
628 }
629
630 mutt_file_fclose(&fp);
631 FREE(&linebuf);
632}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition: file.c:720
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:618
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:38
#define mutt_error(...)
Definition: logging.h:87
void mutt_hist_add(enum HistoryClass hclass, const char *str, bool save)
Add a string to a history.
Definition: history.c:483
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:752
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:71
#define _(a)
Definition: message.h:28
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_reset_state()

void mutt_hist_reset_state ( enum HistoryClass  hclass)

Move the 'current' position to the end of the History.

Parameters
hclassHistory to reset

After calling mutt_hist_next() and mutt_hist_prev(), this function resets the current position ('cur' pointer).

Definition at line 579 of file history.c.

580{
581 struct History *h = get_history(hclass);
582 if (!h)
583 return; /* disabled */
584
585 h->cur = h->last;
586}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_save_scratch()

void mutt_hist_save_scratch ( enum HistoryClass  hclass,
const char *  str 
)

Save a temporary string to the History.

Parameters
hclassHistory to alter
strString to set

Write a 'scratch' string into the History's current position. This is useful to preserver a user's edits.

Definition at line 662 of file history.c.

663{
664 struct History *h = get_history(hclass);
665 if (!h)
666 return; /* disabled */
667
668 /* Don't check if str has a value because the scratch buffer may contain
669 * an old garbage value that should be overwritten */
670 mutt_str_replace(&h->hist[h->last], str);
671}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_search()

int mutt_hist_search ( const char *  search_buf,
enum HistoryClass  hclass,
char **  matches 
)

Find matches in a history list.

Parameters
[in]search_bufString to find
[in]hclassHistory list
[out]matchesAll the matching lines
Return values
numMatches found

Definition at line 409 of file history.c.

410{
411 if (!search_buf || !matches)
412 return 0;
413
414 struct History *h = get_history(hclass);
415 if (!h)
416 return 0;
417
418 int match_count = 0;
419 int cur = h->last;
420 const short c_history = cs_subset_number(NeoMutt->sub, "history");
421 do
422 {
423 cur--;
424 if (cur < 0)
425 cur = c_history;
426 if (cur == h->last)
427 break;
428 if (mutt_istr_find(h->hist[cur], search_buf))
429 matches[match_count++] = h->hist[cur];
430 } while (match_count < c_history);
431
432 return match_count;
433}
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition: string.c:592
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dlg_select_history()

void dlg_select_history ( char *  buf,
size_t  buflen,
char **  matches,
int  match_count 
)

Select an item from a history list.

Parameters
[in]bufBuffer in which to save string
[in]buflenBuffer length
[out]matchesItems to choose from
[in]match_countNumber of items

Definition at line 129 of file dlg_history.c.

130{
132
133 struct MuttWindow *sbar = window_find_child(dlg, WT_STATUS_BAR);
134 char title[256] = { 0 };
135 snprintf(title, sizeof(title), _("History '%s'"), buf);
136 sbar_set_title(sbar, title);
137
138 struct Menu *menu = dlg->wdata;
140 menu->max = match_count;
141 menu->mdata = matches;
142 menu->mdata_free = NULL; // Menu doesn't own the data
143
144 struct HistoryData hd = { false, false, buf, buflen,
146 dlg->wdata = &hd;
147
148 // ---------------------------------------------------------------------------
149 // Event Loop
150 int op = OP_NULL;
151 do
152 {
154 window_redraw(NULL);
155
156 struct KeyEvent event = km_dokey_event(MENU_GENERIC);
157 if (event.ch == 'q')
158 op = OP_EXIT;
159 else
160 op = event.op;
161
162 mutt_debug(LL_DEBUG1, "Got op %s (%d)\n", opcodes_get_name(op), op);
163 if (op < 0)
164 continue;
165 if (op == OP_NULL)
166 {
168 continue;
169 }
171
172 int rc = history_function_dispatcher(dlg, op);
173
174 if (rc == FR_UNKNOWN)
175 rc = menu_function_dispatcher(menu->win, op);
176 if (rc == FR_UNKNOWN)
177 rc = global_function_dispatcher(NULL, op);
178 } while (!hd.done);
179 // ---------------------------------------------------------------------------
180
181 simple_dialog_free(&dlg);
182}
@ FR_UNKNOWN
Unknown function.
Definition: dispatcher.h:33
static const struct Mapping HistoryHelp[]
Help Bar for the History Selection dialog.
Definition: dlg_history.c:75
int menu_tagging_dispatcher(struct MuttWindow *win, int op)
Perform tagging operations on the Menu - Implements function_dispatcher_t -.
Definition: tagging.c:223
int global_function_dispatcher(struct MuttWindow *win, int op)
Perform a Global function - Implements function_dispatcher_t -.
Definition: global.c:164
int menu_function_dispatcher(struct MuttWindow *win, int op)
Perform a Menu function - Implements function_dispatcher_t -.
Definition: functions.c:320
int history_function_dispatcher(struct MuttWindow *win, int op)
Perform a History function - Implements function_dispatcher_t -.
Definition: functions.c:76
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
static void history_make_entry(struct Menu *menu, char *buf, size_t buflen, int line)
Format a menu item for the history list - Implements Menu::make_entry() -.
Definition: dlg_history.c:114
void simple_dialog_free(struct MuttWindow **ptr)
Destroy a simple index Dialog.
Definition: simple.c:166
struct MuttWindow * simple_dialog_new(enum MenuType mtype, enum WindowType wtype, const struct Mapping *help_data)
Create a simple index Dialog.
Definition: simple.c:129
struct KeyEvent km_dokey_event(enum MenuType mtype)
Determine what a keypress should do.
Definition: keymap.c:637
void km_error_key(enum MenuType mtype)
Handle an unbound key sequence.
Definition: keymap.c:1061
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
Definition: mutt_window.c:604
struct MuttWindow * window_find_child(struct MuttWindow *win, enum WindowType type)
Recursively find a child Window of a given type.
Definition: mutt_window.c:522
@ WT_DLG_HISTORY
History Dialog, dlg_select_history()
Definition: mutt_window.h:85
@ WT_STATUS_BAR
Status Bar containing extra info about the Index/Pager/etc.
Definition: mutt_window.h:102
const char * opcodes_get_name(int op)
Get the name of an opcode.
Definition: opcodes.c:46
void sbar_set_title(struct MuttWindow *win, const char *title)
Set the title for the Simple Bar.
Definition: sbar.c:224
Data to pass to the History Functions.
Definition: functions.h:35
size_t buflen
Length of the results buffer.
Definition: functions.h:39
struct Menu * menu
History Menu.
Definition: functions.h:40
char ** matches
History entries.
Definition: functions.h:41
bool done
Should we close the Dialog?
Definition: functions.h:36
char * buf
Buffer for the results.
Definition: functions.h:38
int match_count
Number of history entries.
Definition: functions.h:42
An event such as a keypress.
Definition: keymap.h:65
int op
Function opcode, e.g. OP_HELP.
Definition: keymap.h:67
int ch
Raw key pressed.
Definition: keymap.h:66
Definition: lib.h:69
struct MuttWindow * win
Window holding the Menu.
Definition: lib.h:76
void(* make_entry)(struct Menu *menu, char *buf, size_t buflen, int line)
Definition: lib.h:96
void(* mdata_free)(struct Menu *menu, void **ptr)
Definition: lib.h:152
void * mdata
Private data.
Definition: lib.h:137
int max
Number of entries in the menu.
Definition: lib.h:71
void * wdata
Private data.
Definition: mutt_window.h:145
@ MENU_GENERIC
Generic selection list.
Definition: type.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function: