NeoMutt  2024-03-23-23-gec7045
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
history.c File Reference

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

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

Go to the source code of this file.

Data Structures

struct  History
 Saved list of user-entered commands/searches. More...
 

Macros

#define HC_FIRST   HC_EXT_COMMAND
 

Functions

static struct Historyget_history (enum HistoryClass hclass)
 Get a particular history.
 
static void init_history (struct History *h)
 Set up a new History ring buffer.
 
static int dup_hash_dec (struct HashTable *dup_hash, char *str)
 Decrease the refcount of a history string.
 
static int dup_hash_inc (struct HashTable *dup_hash, char *str)
 Increase the refcount of a history string.
 
static void shrink_histfile (void)
 Read, de-dupe and write the history file.
 
static void save_history (enum HistoryClass hclass, const char *str)
 Save one history string to a file.
 
static void remove_history_dups (enum HistoryClass hclass, const char *str)
 De-dupe the history.
 
int mutt_hist_search (const char *search_buf, enum HistoryClass hclass, char **matches)
 Find matches in a history list.
 
void mutt_hist_cleanup (void)
 Free all the history lists.
 
void mutt_hist_init (void)
 Create a set of empty History ring buffers.
 
void mutt_hist_add (enum HistoryClass hclass, const char *str, bool save)
 Add a string to a history.
 
char * mutt_hist_next (enum HistoryClass hclass)
 Get the next string in a History.
 
char * mutt_hist_prev (enum HistoryClass hclass)
 Get the previous string in a History.
 
void mutt_hist_reset_state (enum HistoryClass hclass)
 Move the 'current' position to the end of the History.
 
void mutt_hist_read_file (void)
 Read the History from a file.
 
bool mutt_hist_at_scratch (enum HistoryClass hclass)
 Is the current History position at the 'scratch' place?
 
void mutt_hist_save_scratch (enum HistoryClass hclass, const char *str)
 Save a temporary string to the History.
 
void mutt_hist_complete (char *buf, size_t buflen, enum HistoryClass hclass)
 Complete a string from a history list.
 
int main_hist_observer (struct NotifyCallback *nc)
 Notification that a Config Variable has change - Implements observer_t -.
 

Variables

static struct History Histories [HC_MAX]
 Command histories, one for each HistoryClass.
 
static int OldSize = 0
 The previous number of history entries to save.
 

Detailed Description

Read/write command history from/to a file.

Authors
  • Richard Russon
  • Pietro Cerutti
  • 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 history.c.

Macro Definition Documentation

◆ HC_FIRST

#define HC_FIRST   HC_EXT_COMMAND

Definition at line 83 of file history.c.

Function Documentation

◆ get_history()

static struct History * get_history ( enum HistoryClass  hclass)
static

Get a particular history.

Parameters
hclassType of history to find
Return values
ptrHistory ring buffer

Definition at line 110 of file history.c.

111{
112 const short c_history = cs_subset_number(NeoMutt->sub, "history");
113 if ((hclass >= HC_MAX) || (c_history == 0))
114 return NULL;
115
116 struct History *hist = &Histories[hclass];
117 return hist->hist ? hist : NULL;
118}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:144
@ HC_MAX
Definition: lib.h:58
static struct History Histories[HC_MAX]
Command histories, one for each HistoryClass.
Definition: history.c:100
Saved list of user-entered commands/searches.
Definition: history.c:91
char ** hist
Array of history items.
Definition: history.c:92
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ init_history()

static void init_history ( struct History h)
static

Set up a new History ring buffer.

Parameters
hHistory to populate

If the History already has entries, they will be freed.

Definition at line 126 of file history.c.

127{
128 if (OldSize != 0)
129 {
130 if (h->hist)
131 {
132 for (int i = 0; i <= OldSize; i++)
133 FREE(&h->hist[i]);
134 FREE(&h->hist);
135 }
136 }
137
138 const short c_history = cs_subset_number(NeoMutt->sub, "history");
139 if (c_history != 0)
140 h->hist = mutt_mem_calloc(c_history + 1, sizeof(char *));
141
142 h->cur = 0;
143 h->last = 0;
144}
static int OldSize
The previous number of history entries to save.
Definition: history.c:103
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define FREE(x)
Definition: memory.h:45
short cur
Current history item.
Definition: history.c:93
short last
Last history item.
Definition: history.c:94
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dup_hash_dec()

static int dup_hash_dec ( struct HashTable dup_hash,
char *  str 
)
static

Decrease the refcount of a history string.

Parameters
dup_hashHash Table containing unique history strings
strString to find
Return values
0String was deleted from the Hash Table
>0Refcount of string
-1Error, string not found

If the string's refcount is 1, then the string will be deleted.

Definition at line 156 of file history.c.

157{
158 struct HashElem *he = mutt_hash_find_elem(dup_hash, str);
159 if (!he)
160 return -1;
161
162 uintptr_t count = (uintptr_t) he->data;
163 if (count <= 1)
164 {
165 mutt_hash_delete(dup_hash, str, NULL);
166 return 0;
167 }
168
169 count--;
170 he->data = (void *) count;
171 return count;
172}
void mutt_hash_delete(struct HashTable *table, const char *strkey, const void *data)
Remove an element from a Hash Table.
Definition: hash.c:427
struct HashElem * mutt_hash_find_elem(const struct HashTable *table, const char *strkey)
Find the HashElem in a Hash Table element using a key.
Definition: hash.c:377
The item stored in a Hash Table.
Definition: hash.h:43
void * data
User-supplied data.
Definition: hash.h:46
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dup_hash_inc()

static int dup_hash_inc ( struct HashTable dup_hash,
char *  str 
)
static

Increase the refcount of a history string.

Parameters
dup_hashHash Table containing unique history strings
strString to find
Return values
numRefcount of string

If the string isn't found it will be added to the Hash Table.

Definition at line 182 of file history.c.

183{
184 uintptr_t count;
185
186 struct HashElem *he = mutt_hash_find_elem(dup_hash, str);
187 if (!he)
188 {
189 count = 1;
190 mutt_hash_insert(dup_hash, str, (void *) count);
191 return count;
192 }
193
194 count = (uintptr_t) he->data;
195 count++;
196 he->data = (void *) count;
197 return count;
198}
struct HashElem * mutt_hash_insert(struct HashTable *table, const char *strkey, void *data)
Add a new element to the Hash Table (with string keys)
Definition: hash.c:335
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ shrink_histfile()

static void shrink_histfile ( void  )
static

Read, de-dupe and write the history file.

Definition at line 203 of file history.c.

204{
205 FILE *fp_tmp = NULL;
206 int n[HC_MAX] = { 0 };
207 int line, hclass, read;
208 char *linebuf = NULL, *p = NULL;
209 size_t buflen;
210 bool regen_file = false;
211 struct HashTable *dup_hashes[HC_MAX] = { 0 };
212
213 const char *const c_history_file = cs_subset_path(NeoMutt->sub, "history_file");
214 FILE *fp = mutt_file_fopen(c_history_file, "r");
215 if (!fp)
216 return;
217
218 const bool c_history_remove_dups = cs_subset_bool(NeoMutt->sub, "history_remove_dups");
219 const short c_save_history = cs_subset_number(NeoMutt->sub, "save_history");
220 if (c_history_remove_dups)
221 {
222 for (hclass = 0; hclass < HC_MAX; hclass++)
223 dup_hashes[hclass] = mutt_hash_new(MAX(10, c_save_history * 2), MUTT_HASH_STRDUP_KEYS);
224 }
225
226 line = 0;
227 while ((linebuf = mutt_file_read_line(linebuf, &buflen, fp, &line, MUTT_RL_NO_FLAGS)))
228 {
229 if ((sscanf(linebuf, "%d:%n", &hclass, &read) < 1) || (read == 0) ||
230 (*(p = linebuf + strlen(linebuf) - 1) != '|') || (hclass < 0))
231 {
232 mutt_error(_("%s:%d: Bad history file format"), c_history_file, line);
233 regen_file = true;
234 continue;
235 }
236 /* silently ignore too high class (probably newer neomutt) */
237 if (hclass >= HC_MAX)
238 continue;
239 *p = '\0';
240 if (c_history_remove_dups && (dup_hash_inc(dup_hashes[hclass], linebuf + read) > 1))
241 {
242 regen_file = true;
243 continue;
244 }
245 n[hclass]++;
246 }
247
248 if (!regen_file)
249 {
250 for (hclass = HC_FIRST; hclass < HC_MAX; hclass++)
251 {
252 if (n[hclass] > c_save_history)
253 {
254 regen_file = true;
255 break;
256 }
257 }
258 }
259
260 if (regen_file)
261 {
262 fp_tmp = mutt_file_mkstemp();
263 if (!fp_tmp)
264 {
265 mutt_perror(_("Can't create temporary file"));
266 goto cleanup;
267 }
268 rewind(fp);
269 line = 0;
270 while ((linebuf = mutt_file_read_line(linebuf, &buflen, fp, &line, MUTT_RL_NO_FLAGS)))
271 {
272 if ((sscanf(linebuf, "%d:%n", &hclass, &read) < 1) || (read == 0) ||
273 (*(p = linebuf + strlen(linebuf) - 1) != '|') || (hclass < 0))
274 {
275 continue;
276 }
277 if (hclass >= HC_MAX)
278 continue;
279 *p = '\0';
280 if (c_history_remove_dups && (dup_hash_dec(dup_hashes[hclass], linebuf + read) > 0))
281 {
282 continue;
283 }
284 *p = '|';
285 if (n[hclass]-- <= c_save_history)
286 fprintf(fp_tmp, "%s\n", linebuf);
287 }
288 }
289
290cleanup:
291 mutt_file_fclose(&fp);
292 FREE(&linebuf);
293 if (fp_tmp)
294 {
295 if ((fflush(fp_tmp) == 0) && (fp = mutt_file_fopen(NONULL(c_history_file), "w")))
296 {
297 rewind(fp_tmp);
298 mutt_file_copy_stream(fp_tmp, fp);
299 mutt_file_fclose(&fp);
300 }
301 mutt_file_fclose(&fp_tmp);
302 }
303 if (c_history_remove_dups)
304 for (hclass = 0; hclass < HC_MAX; hclass++)
305 mutt_hash_free(&dup_hashes[hclass]);
306}
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:169
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:282
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:801
#define mutt_file_fclose(FP)
Definition: file.h:148
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:147
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:40
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_perror(...)
Definition: logging2.h:93
struct HashTable * mutt_hash_new(size_t num_elems, HashFlags flags)
Create a new Hash Table (with string keys)
Definition: hash.c:259
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:457
#define MUTT_HASH_STRDUP_KEYS
make a copy of the keys
Definition: hash.h:111
static int dup_hash_inc(struct HashTable *dup_hash, char *str)
Increase the refcount of a history string.
Definition: history.c:182
#define HC_FIRST
Definition: history.c:83
static int dup_hash_dec(struct HashTable *dup_hash, char *str)
Decrease the refcount of a history string.
Definition: history.c:156
#define MAX(a, b)
Definition: memory.h:31
#define _(a)
Definition: message.h:28
#define NONULL(x)
Definition: string2.h:37
A Hash Table.
Definition: hash.h:97
#define mutt_file_mkstemp()
Definition: tmp.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ save_history()

static void save_history ( enum HistoryClass  hclass,
const char *  str 
)
static

Save one history string to a file.

Parameters
hclassHistory type
strString to save

Definition at line 313 of file history.c.

314{
315 static int n = 0;
316
317 if (!str || (*str == '\0')) // This shouldn't happen, but it's safer
318 return;
319
320 const char *const c_history_file = cs_subset_path(NeoMutt->sub, "history_file");
321 FILE *fp = mutt_file_fopen(c_history_file, "a");
322 if (!fp)
323 return;
324
325 char *tmp = mutt_str_dup(str);
327
328 // If tmp contains '\n' terminate it there.
329 char *nl = strchr(tmp, '\n');
330 if (nl)
331 *nl = '\0';
332
333 /* Format of a history item (1 line): "<histclass>:<string>|".
334 * We add a '|' in order to avoid lines ending with '\'. */
335 fprintf(fp, "%d:%s|\n", (int) hclass, tmp);
336
337 mutt_file_fclose(&fp);
338 FREE(&tmp);
339
340 if (--n < 0)
341 {
342 const short c_save_history = cs_subset_number(NeoMutt->sub, "save_history");
343 n = c_save_history;
345 }
346}
const char * cc_charset(void)
Get the cached value of $charset.
Definition: config_cache.c:116
static void shrink_histfile(void)
Read, de-dupe and write the history file.
Definition: history.c:203
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:830
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:72
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:253
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remove_history_dups()

static void remove_history_dups ( enum HistoryClass  hclass,
const char *  str 
)
static

De-dupe the history.

Parameters
hclassHistory to de-dupe
strString to find

If the string is found, it is removed from the history.

When removing dups, we want the created "blanks" to be right below the resulting h->last position. See the comment section above 'struct History'.

Definition at line 358 of file history.c.

359{
360 struct History *h = get_history(hclass);
361 if (!h)
362 return; /* disabled */
363
364 /* Remove dups from 0..last-1 compacting up. */
365 int source = 0;
366 int dest = 0;
367 while (source < h->last)
368 {
369 if (mutt_str_equal(h->hist[source], str))
370 FREE(&h->hist[source++]);
371 else
372 h->hist[dest++] = h->hist[source++];
373 }
374
375 /* Move 'last' entry up. */
376 h->hist[dest] = h->hist[source];
377 int old_last = h->last;
378 h->last = dest;
379
380 /* Fill in moved entries with NULL */
381 while (source > h->last)
382 h->hist[source--] = NULL;
383
384 /* Remove dups from last+1 .. `$history` compacting down. */
385 const short c_history = cs_subset_number(NeoMutt->sub, "history");
386 source = c_history;
387 dest = c_history;
388 while (source > old_last)
389 {
390 if (mutt_str_equal(h->hist[source], str))
391 FREE(&h->hist[source--]);
392 else
393 h->hist[dest--] = h->hist[source--];
394 }
395
396 /* Fill in moved entries with NULL */
397 while (dest > old_last)
398 h->hist[dest--] = NULL;
399}
static struct History * get_history(enum HistoryClass hclass)
Get a particular history.
Definition: history.c:110
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:709
+ 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 408 of file history.c.

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

◆ mutt_hist_cleanup()

void mutt_hist_cleanup ( void  )

Free all the history lists.

Definition at line 437 of file history.c.

438{
439 if (!NeoMutt)
440 return;
441
442 const short c_history = cs_subset_number(NeoMutt->sub, "history");
443 for (enum HistoryClass hclass = HC_FIRST; hclass < HC_MAX; hclass++)
444 {
445 struct History *h = &Histories[hclass];
446 if (!h->hist)
447 continue;
448
449 /* The array has (`$history`+1) elements */
450 for (int i = 0; i <= c_history; i++)
451 {
452 FREE(&h->hist[i]);
453 }
454 FREE(&h->hist);
455 }
456}
HistoryClass
Type to differentiate different histories.
Definition: lib.h:50
+ 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 464 of file history.c.

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

◆ 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 482 of file history.c.

483{
484 struct History *h = get_history(hclass);
485 if (!h)
486 return; /* disabled */
487
488 if (*str)
489 {
490 int prev = h->last - 1;
491 const short c_history = cs_subset_number(NeoMutt->sub, "history");
492 if (prev < 0)
493 prev = c_history;
494
495 /* don't add to prompt history:
496 * - lines beginning by a space
497 * - repeated lines */
498 if ((*str != ' ') && (!h->hist[prev] || !mutt_str_equal(h->hist[prev], str)))
499 {
500 const bool c_history_remove_dups = cs_subset_bool(NeoMutt->sub, "history_remove_dups");
501 if (c_history_remove_dups)
502 remove_history_dups(hclass, str);
503 const short c_save_history = cs_subset_number(NeoMutt->sub, "save_history");
504 const char *const c_history_file = cs_subset_path(NeoMutt->sub, "history_file");
505 if (save && (c_save_history != 0) && c_history_file)
506 save_history(hclass, str);
507 mutt_str_replace(&h->hist[h->last++], str);
508 if (h->last > c_history)
509 h->last = 0;
510 }
511 }
512 h->cur = h->last; /* reset to the last entry */
513}
static void remove_history_dups(enum HistoryClass hclass, const char *str)
De-dupe the history.
Definition: history.c:358
static void save_history(enum HistoryClass hclass, const char *str)
Save one history string to a file.
Definition: history.c:313
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:329
+ 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 522 of file history.c.

523{
524 struct History *h = get_history(hclass);
525 if (!h)
526 return ""; /* disabled */
527
528 int next = h->cur;
529 const short c_history = cs_subset_number(NeoMutt->sub, "history");
530 do
531 {
532 next++;
533 if (next > c_history)
534 next = 0;
535 if (next == h->last)
536 break;
537 } while (!h->hist[next]);
538
539 h->cur = next;
540 return NONULL(h->hist[h->cur]);
541}
+ 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 550 of file history.c.

551{
552 struct History *h = get_history(hclass);
553 if (!h)
554 return ""; /* disabled */
555
556 int prev = h->cur;
557 const short c_history = cs_subset_number(NeoMutt->sub, "history");
558 do
559 {
560 prev--;
561 if (prev < 0)
562 prev = c_history;
563 if (prev == h->last)
564 break;
565 } while (!h->hist[prev]);
566
567 h->cur = prev;
568 return NONULL(h->hist[h->cur]);
569}
+ 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 578 of file history.c.

579{
580 struct History *h = get_history(hclass);
581 if (!h)
582 return; /* disabled */
583
584 h->cur = h->last;
585}
+ 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 592 of file history.c.

593{
594 const char *const c_history_file = cs_subset_path(NeoMutt->sub, "history_file");
595 if (!c_history_file)
596 return;
597
598 FILE *fp = mutt_file_fopen(c_history_file, "r");
599 if (!fp)
600 return;
601
602 int line = 0, hclass, read;
603 char *linebuf = NULL, *p = NULL;
604 size_t buflen;
605
606 const char *const c_charset = cc_charset();
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(_("%s:%d: Bad history file format"), c_history_file, line);
614 continue;
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 mutt_ch_convert_string(&p, "utf-8", c_charset, MUTT_ICONV_NO_FLAGS);
624 mutt_hist_add(hclass, p, false);
625 FREE(&p);
626 }
627 }
628
629 mutt_file_fclose(&fp);
630 FREE(&linebuf);
631}
void mutt_hist_add(enum HistoryClass hclass, const char *str, bool save)
Add a string to a history.
Definition: history.c:482
+ 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 644 of file history.c.

645{
646 struct History *h = get_history(hclass);
647 if (!h)
648 return false; /* disabled */
649
650 return h->cur == h->last;
651}
+ 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 661 of file history.c.

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

◆ mutt_hist_complete()

void mutt_hist_complete ( char *  buf,
size_t  buflen,
enum HistoryClass  hclass 
)

Complete a string from a history list.

Parameters
bufBuffer in which to save string
buflenBuffer length
hclassHistory list to use

Definition at line 678 of file history.c.

679{
680 const short c_history = cs_subset_number(NeoMutt->sub, "history");
681 char **matches = mutt_mem_calloc(c_history, sizeof(char *));
682 int match_count = mutt_hist_search(buf, hclass, matches);
683 if (match_count)
684 {
685 if (match_count == 1)
686 mutt_str_copy(buf, matches[0], buflen);
687 else
688 dlg_history(buf, buflen, matches, match_count);
689 }
690 FREE(&matches);
691}
void dlg_history(char *buf, size_t buflen, char **matches, int match_count)
Select an item from a history list -.
Definition: dlg_history.c:139
int mutt_hist_search(const char *search_buf, enum HistoryClass hclass, char **matches)
Find matches in a history list.
Definition: history.c:408
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:630
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ Histories

struct History Histories[HC_MAX]
static

Command histories, one for each HistoryClass.

Definition at line 100 of file history.c.

◆ OldSize

int OldSize = 0
static

The previous number of history entries to save.

See also
$history

Definition at line 103 of file history.c.