NeoMutt  2024-03-23-142-g2b2e76
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 <unistd.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 84 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 111 of file history.c.

112{
113 const short c_history = cs_subset_number(NeoMutt->sub, "history");
114 if ((hclass >= HC_MAX) || (c_history == 0))
115 return NULL;
116
117 struct History *hist = &Histories[hclass];
118 return hist->hist ? hist : NULL;
119}
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:101
Saved list of user-entered commands/searches.
Definition: history.c:92
char ** hist
Array of history items.
Definition: history.c:93
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 127 of file history.c.

128{
129 if (OldSize != 0)
130 {
131 if (h->hist)
132 {
133 for (int i = 0; i <= OldSize; i++)
134 FREE(&h->hist[i]);
135 FREE(&h->hist);
136 }
137 }
138
139 const short c_history = cs_subset_number(NeoMutt->sub, "history");
140 if (c_history != 0)
141 h->hist = mutt_mem_calloc(c_history + 1, sizeof(char *));
142
143 h->cur = 0;
144 h->last = 0;
145}
static int OldSize
The previous number of history entries to save.
Definition: history.c:104
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:94
short last
Last history item.
Definition: history.c:95
+ 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 157 of file history.c.

158{
159 struct HashElem *he = mutt_hash_find_elem(dup_hash, str);
160 if (!he)
161 return -1;
162
163 uintptr_t count = (uintptr_t) he->data;
164 if (count <= 1)
165 {
166 mutt_hash_delete(dup_hash, str, NULL);
167 return 0;
168 }
169
170 count--;
171 he->data = (void *) count;
172 return count;
173}
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 183 of file history.c.

184{
185 uintptr_t count;
186
187 struct HashElem *he = mutt_hash_find_elem(dup_hash, str);
188 if (!he)
189 {
190 count = 1;
191 mutt_hash_insert(dup_hash, str, (void *) count);
192 return count;
193 }
194
195 count = (uintptr_t) he->data;
196 count++;
197 he->data = (void *) count;
198 return count;
199}
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 204 of file history.c.

205{
206 FILE *fp_tmp = NULL;
207 int n[HC_MAX] = { 0 };
208 int line, hclass, read;
209 char *linebuf = NULL, *p = NULL;
210 size_t buflen;
211 bool regen_file = false;
212 struct HashTable *dup_hashes[HC_MAX] = { 0 };
213
214 const char *const c_history_file = cs_subset_path(NeoMutt->sub, "history_file");
215 FILE *fp = mutt_file_fopen(c_history_file, "r");
216 if (!fp)
217 return;
218
219 const bool c_history_remove_dups = cs_subset_bool(NeoMutt->sub, "history_remove_dups");
220 const short c_save_history = cs_subset_number(NeoMutt->sub, "save_history");
221 if (c_history_remove_dups)
222 {
223 for (hclass = 0; hclass < HC_MAX; hclass++)
224 dup_hashes[hclass] = mutt_hash_new(MAX(10, c_save_history * 2), MUTT_HASH_STRDUP_KEYS);
225 }
226
227 line = 0;
228 while ((linebuf = mutt_file_read_line(linebuf, &buflen, fp, &line, MUTT_RL_NO_FLAGS)))
229 {
230 if ((sscanf(linebuf, "%d:%n", &hclass, &read) < 1) || (read == 0) ||
231 (*(p = linebuf + strlen(linebuf) - 1) != '|') || (hclass < 0))
232 {
233 mutt_error(_("%s:%d: Bad history file format"), c_history_file, line);
234 regen_file = true;
235 continue;
236 }
237 /* silently ignore too high class (probably newer neomutt) */
238 if (hclass >= HC_MAX)
239 continue;
240 *p = '\0';
241 if (c_history_remove_dups && (dup_hash_inc(dup_hashes[hclass], linebuf + read) > 1))
242 {
243 regen_file = true;
244 continue;
245 }
246 n[hclass]++;
247 }
248
249 if (!regen_file)
250 {
251 for (hclass = HC_FIRST; hclass < HC_MAX; hclass++)
252 {
253 if (n[hclass] > c_save_history)
254 {
255 regen_file = true;
256 break;
257 }
258 }
259 }
260
261 if (regen_file)
262 {
263 fp_tmp = mutt_file_mkstemp();
264 if (!fp_tmp)
265 {
266 mutt_perror(_("Can't create temporary file"));
267 goto cleanup;
268 }
269 rewind(fp);
270 line = 0;
271 while ((linebuf = mutt_file_read_line(linebuf, &buflen, fp, &line, MUTT_RL_NO_FLAGS)))
272 {
273 if ((sscanf(linebuf, "%d:%n", &hclass, &read) < 1) || (read == 0) ||
274 (*(p = linebuf + strlen(linebuf) - 1) != '|') || (hclass < 0))
275 {
276 continue;
277 }
278 if (hclass >= HC_MAX)
279 continue;
280 *p = '\0';
281 if (c_history_remove_dups && (dup_hash_dec(dup_hashes[hclass], linebuf + read) > 0))
282 {
283 continue;
284 }
285 *p = '|';
286 if (n[hclass]-- <= c_save_history)
287 fprintf(fp_tmp, "%s\n", linebuf);
288 }
289 }
290
291cleanup:
292 mutt_file_fclose(&fp);
293 FREE(&linebuf);
294 if (fp_tmp)
295 {
296 if (fflush(fp_tmp) == 0)
297 {
298 truncate(c_history_file, 0);
299 fp = mutt_file_fopen(c_history_file, "w");
300 if (fp)
301 {
302 rewind(fp_tmp);
303 mutt_file_copy_stream(fp_tmp, fp);
304 mutt_file_fclose(&fp);
305 }
306 }
307 mutt_file_fclose(&fp_tmp);
308 }
309 if (c_history_remove_dups)
310 for (hclass = 0; hclass < HC_MAX; hclass++)
311 mutt_hash_free(&dup_hashes[hclass]);
312}
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:286
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:805
#define mutt_file_fclose(FP)
Definition: file.h:147
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:146
#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:183
#define HC_FIRST
Definition: history.c:84
static int dup_hash_dec(struct HashTable *dup_hash, char *str)
Decrease the refcount of a history string.
Definition: history.c:157
#define MAX(a, b)
Definition: memory.h:31
#define _(a)
Definition: message.h:28
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 319 of file history.c.

320{
321 static int n = 0;
322
323 if (!str || (*str == '\0')) // This shouldn't happen, but it's safer
324 return;
325
326 const char *const c_history_file = cs_subset_path(NeoMutt->sub, "history_file");
327 FILE *fp = mutt_file_fopen(c_history_file, "a");
328 if (!fp)
329 return;
330
331 char *tmp = mutt_str_dup(str);
333
334 // If tmp contains '\n' terminate it there.
335 char *nl = strchr(tmp, '\n');
336 if (nl)
337 *nl = '\0';
338
339 /* Format of a history item (1 line): "<histclass>:<string>|".
340 * We add a '|' in order to avoid lines ending with '\'. */
341 fprintf(fp, "%d:%s|\n", (int) hclass, tmp);
342
343 mutt_file_fclose(&fp);
344 FREE(&tmp);
345
346 if (--n < 0)
347 {
348 const short c_save_history = cs_subset_number(NeoMutt->sub, "save_history");
349 n = c_save_history;
351 }
352}
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:204
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 364 of file history.c.

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

415{
416 if (!search_buf || !matches)
417 return 0;
418
419 struct History *h = get_history(hclass);
420 if (!h)
421 return 0;
422
423 int match_count = 0;
424 int cur = h->last;
425 const short c_history = cs_subset_number(NeoMutt->sub, "history");
426 do
427 {
428 cur--;
429 if (cur < 0)
430 cur = c_history;
431 if (cur == h->last)
432 break;
433 if (mutt_istr_find(h->hist[cur], search_buf))
434 matches[match_count++] = h->hist[cur];
435 } while (match_count < c_history);
436
437 return match_count;
438}
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 443 of file history.c.

444{
445 if (!NeoMutt)
446 return;
447
448 const short c_history = cs_subset_number(NeoMutt->sub, "history");
449 for (enum HistoryClass hclass = HC_FIRST; hclass < HC_MAX; hclass++)
450 {
451 struct History *h = &Histories[hclass];
452 if (!h->hist)
453 continue;
454
455 /* The array has (`$history`+1) elements */
456 for (int i = 0; i <= c_history; i++)
457 {
458 FREE(&h->hist[i]);
459 }
460 FREE(&h->hist);
461 }
462}
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 470 of file history.c.

471{
472 const short c_history = cs_subset_number(NeoMutt->sub, "history");
473 if (c_history == OldSize)
474 return;
475
476 for (enum HistoryClass hclass = HC_FIRST; hclass < HC_MAX; hclass++)
477 init_history(&Histories[hclass]);
478
479 OldSize = c_history;
480}
static void init_history(struct History *h)
Set up a new History ring buffer.
Definition: history.c:127
+ 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 488 of file history.c.

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

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

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

585{
586 struct History *h = get_history(hclass);
587 if (!h)
588 return; /* disabled */
589
590 h->cur = h->last;
591}
+ 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 598 of file history.c.

599{
600 const char *const c_history_file = cs_subset_path(NeoMutt->sub, "history_file");
601 if (!c_history_file)
602 return;
603
604 FILE *fp = mutt_file_fopen(c_history_file, "r");
605 if (!fp)
606 return;
607
608 int line = 0, hclass, read;
609 char *linebuf = NULL, *p = NULL;
610 size_t buflen;
611
612 const char *const c_charset = cc_charset();
613 while ((linebuf = mutt_file_read_line(linebuf, &buflen, fp, &line, MUTT_RL_NO_FLAGS)))
614 {
615 read = 0;
616 if ((sscanf(linebuf, "%d:%n", &hclass, &read) < 1) || (read == 0) ||
617 (*(p = linebuf + strlen(linebuf) - 1) != '|') || (hclass < 0))
618 {
619 mutt_error(_("%s:%d: Bad history file format"), c_history_file, line);
620 continue;
621 }
622 /* silently ignore too high class (probably newer neomutt) */
623 if (hclass >= HC_MAX)
624 continue;
625 *p = '\0';
626 p = mutt_str_dup(linebuf + read);
627 if (p)
628 {
629 mutt_ch_convert_string(&p, "utf-8", c_charset, MUTT_ICONV_NO_FLAGS);
630 mutt_hist_add(hclass, p, false);
631 FREE(&p);
632 }
633 }
634
635 mutt_file_fclose(&fp);
636 FREE(&linebuf);
637}
void mutt_hist_add(enum HistoryClass hclass, const char *str, bool save)
Add a string to a history.
Definition: history.c:488
+ 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 650 of file history.c.

651{
652 struct History *h = get_history(hclass);
653 if (!h)
654 return false; /* disabled */
655
656 return h->cur == h->last;
657}
+ 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 667 of file history.c.

668{
669 struct History *h = get_history(hclass);
670 if (!h)
671 return; /* disabled */
672
673 /* Don't check if str has a value because the scratch buffer may contain
674 * an old garbage value that should be overwritten */
675 mutt_str_replace(&h->hist[h->last], str);
676}
+ 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 684 of file history.c.

685{
686 const short c_history = cs_subset_number(NeoMutt->sub, "history");
687 char **matches = mutt_mem_calloc(c_history, sizeof(char *));
688 int match_count = mutt_hist_search(buf, hclass, matches);
689 if (match_count)
690 {
691 if (match_count == 1)
692 mutt_str_copy(buf, matches[0], buflen);
693 else
694 dlg_history(buf, buflen, matches, match_count);
695 }
696 FREE(&matches);
697}
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:414
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 101 of file history.c.

◆ OldSize

int OldSize = 0
static

The previous number of history entries to save.

See also
$history

Definition at line 104 of file history.c.