aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/cmdhist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/cmdhist.c')
-rw-r--r--src/nvim/cmdhist.c292
1 files changed, 159 insertions, 133 deletions
diff --git a/src/nvim/cmdhist.c b/src/nvim/cmdhist.c
index 5a59f09113..2df82d9355 100644
--- a/src/nvim/cmdhist.c
+++ b/src/nvim/cmdhist.c
@@ -3,14 +3,30 @@
// cmdhist.c: Functions for the history of the command-line.
+#include <assert.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
#include "nvim/ascii.h"
#include "nvim/charset.h"
#include "nvim/cmdhist.h"
+#include "nvim/eval/typval.h"
#include "nvim/ex_cmds.h"
+#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_getln.h"
+#include "nvim/gettext.h"
+#include "nvim/globals.h"
+#include "nvim/macros.h"
+#include "nvim/memory.h"
+#include "nvim/message.h"
+#include "nvim/option_defs.h"
+#include "nvim/pos.h"
#include "nvim/regexp.h"
#include "nvim/strings.h"
-#include "nvim/ui.h"
+#include "nvim/types.h"
#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -116,56 +132,58 @@ void init_history(void)
int newlen = (int)p_hi;
int oldlen = hislen;
+ if (newlen == oldlen) { // history length didn't change
+ return;
+ }
+
// If history tables size changed, reallocate them.
// Tables are circular arrays (current position marked by hisidx[type]).
// On copying them to the new arrays, we take the chance to reorder them.
- if (newlen != oldlen) {
- for (int type = 0; type < HIST_COUNT; type++) {
- histentry_T *temp = (newlen
- ? xmalloc((size_t)newlen * sizeof(*temp))
- : NULL);
-
- int j = hisidx[type];
- if (j >= 0) {
- // old array gets partitioned this way:
- // [0 , i1 ) --> newest entries to be deleted
- // [i1 , i1 + l1) --> newest entries to be copied
- // [i1 + l1 , i2 ) --> oldest entries to be deleted
- // [i2 , i2 + l2) --> oldest entries to be copied
- int l1 = MIN(j + 1, newlen); // how many newest to copy
- int l2 = MIN(newlen, oldlen) - l1; // how many oldest to copy
- int i1 = j + 1 - l1; // copy newest from here
- int i2 = MAX(l1, oldlen - newlen + l1); // copy oldest from here
-
- // copy as much entries as they fit to new table, reordering them
- if (newlen) {
- // copy oldest entries
- memcpy(&temp[0], &history[type][i2], (size_t)l2 * sizeof(*temp));
- // copy newest entries
- memcpy(&temp[l2], &history[type][i1], (size_t)l1 * sizeof(*temp));
- }
-
- // delete entries that don't fit in newlen, if any
- for (int i = 0; i < i1; i++) {
- hist_free_entry(history[type] + i);
- }
- for (int i = i1 + l1; i < i2; i++) {
- hist_free_entry(history[type] + i);
- }
+ for (int type = 0; type < HIST_COUNT; type++) {
+ histentry_T *temp = (newlen > 0
+ ? xmalloc((size_t)newlen * sizeof(*temp))
+ : NULL);
+
+ int j = hisidx[type];
+ if (j >= 0) {
+ // old array gets partitioned this way:
+ // [0 , i1 ) --> newest entries to be deleted
+ // [i1 , i1 + l1) --> newest entries to be copied
+ // [i1 + l1 , i2 ) --> oldest entries to be deleted
+ // [i2 , i2 + l2) --> oldest entries to be copied
+ int l1 = MIN(j + 1, newlen); // how many newest to copy
+ int l2 = MIN(newlen, oldlen) - l1; // how many oldest to copy
+ int i1 = j + 1 - l1; // copy newest from here
+ int i2 = MAX(l1, oldlen - newlen + l1); // copy oldest from here
+
+ // copy as much entries as they fit to new table, reordering them
+ if (newlen) {
+ // copy oldest entries
+ memcpy(&temp[0], &history[type][i2], (size_t)l2 * sizeof(*temp));
+ // copy newest entries
+ memcpy(&temp[l2], &history[type][i1], (size_t)l1 * sizeof(*temp));
}
- // clear remaining space, if any
- int l3 = j < 0 ? 0 : MIN(newlen, oldlen); // number of copied entries
- if (newlen) {
- memset(temp + l3, 0, (size_t)(newlen - l3) * sizeof(*temp));
+ // delete entries that don't fit in newlen, if any
+ for (int i = 0; i < i1; i++) {
+ hist_free_entry(history[type] + i);
+ }
+ for (int i = i1 + l1; i < i2; i++) {
+ hist_free_entry(history[type] + i);
}
+ }
- hisidx[type] = l3 - 1;
- xfree(history[type]);
- history[type] = temp;
+ // clear remaining space, if any
+ int l3 = j < 0 ? 0 : MIN(newlen, oldlen); // number of copied entries
+ if (newlen > 0) {
+ memset(temp + l3, 0, (size_t)(newlen - l3) * sizeof(*temp));
}
- hislen = newlen;
+
+ hisidx[type] = l3 - 1;
+ xfree(history[type]);
+ history[type] = temp;
}
+ hislen = newlen;
}
static inline void hist_free_entry(histentry_T *hisptr)
@@ -203,7 +221,7 @@ static int in_history(int type, char *str, int move_to_front, int sep)
// well.
char *p = history[type][i].hisstr;
if (strcmp(str, p) == 0
- && (type != HIST_SEARCH || sep == p[STRLEN(p) + 1])) {
+ && (type != HIST_SEARCH || sep == p[strlen(p) + 1])) {
if (!move_to_front) {
return true;
}
@@ -215,24 +233,25 @@ static int in_history(int type, char *str, int move_to_front, int sep)
}
} while (i != hisidx[type]);
- if (last_i >= 0) {
- list_T *const list = history[type][i].additional_elements;
- str = history[type][i].hisstr;
- while (i != hisidx[type]) {
- if (++i >= hislen) {
- i = 0;
- }
- history[type][last_i] = history[type][i];
- last_i = i;
+ if (last_i < 0) {
+ return false;
+ }
+
+ list_T *const list = history[type][i].additional_elements;
+ str = history[type][i].hisstr;
+ while (i != hisidx[type]) {
+ if (++i >= hislen) {
+ i = 0;
}
- tv_list_unref(list);
- history[type][i].hisnum = ++hisnum[type];
- history[type][i].hisstr = str;
- history[type][i].timestamp = os_time();
- history[type][i].additional_elements = NULL;
- return true;
- }
- return false;
+ history[type][last_i] = history[type][i];
+ last_i = i;
+ }
+ tv_list_unref(list);
+ history[type][i].hisnum = ++hisnum[type];
+ history[type][i].hisstr = str;
+ history[type][i].timestamp = os_time();
+ history[type][i].additional_elements = NULL;
+ return true;
}
/// Convert history name to its HIST_ equivalent
@@ -261,7 +280,7 @@ static HistoryType get_histtype(const char *const name, const size_t len, const
}
}
- if (vim_strchr(":=@>?/", name[0]) != NULL && len == 1) {
+ if (vim_strchr(":=@>?/", (uint8_t)name[0]) != NULL && len == 1) {
return hist_char2type(name[0]);
}
@@ -304,24 +323,27 @@ void add_to_history(int histype, char *new_entry, int in_map, int sep)
}
last_maptick = -1;
}
- if (!in_history(histype, new_entry, true, sep)) {
- if (++hisidx[histype] == hislen) {
- hisidx[histype] = 0;
- }
- hisptr = &history[histype][hisidx[histype]];
- hist_free_entry(hisptr);
-
- // Store the separator after the NUL of the string.
- size_t len = strlen(new_entry);
- hisptr->hisstr = xstrnsave(new_entry, len + 2);
- hisptr->timestamp = os_time();
- hisptr->additional_elements = NULL;
- hisptr->hisstr[len + 1] = (char)sep;
-
- hisptr->hisnum = ++hisnum[histype];
- if (histype == HIST_SEARCH && in_map) {
- last_maptick = maptick;
- }
+
+ if (in_history(histype, new_entry, true, sep)) {
+ return;
+ }
+
+ if (++hisidx[histype] == hislen) {
+ hisidx[histype] = 0;
+ }
+ hisptr = &history[histype][hisidx[histype]];
+ hist_free_entry(hisptr);
+
+ // Store the separator after the NUL of the string.
+ size_t len = strlen(new_entry);
+ hisptr->hisstr = xstrnsave(new_entry, len + 2);
+ hisptr->timestamp = os_time();
+ hisptr->additional_elements = NULL;
+ hisptr->hisstr[len + 1] = (char)sep;
+
+ hisptr->hisnum = ++hisnum[histype];
+ if (histype == HIST_SEARCH && in_map) {
+ last_maptick = maptick;
}
}
@@ -415,49 +437,50 @@ int clr_history(const int histype)
/// Remove all entries matching {str} from a history.
///
/// @param histype may be one of the HIST_ values.
-static int del_history_entry(int histype, char_u *str)
+static int del_history_entry(int histype, char *str)
{
+ if (hislen == 0 || histype < 0 || histype >= HIST_COUNT || *str == NUL
+ || hisidx[histype] < 0) {
+ return false;
+ }
+
+ const int idx = hisidx[histype];
regmatch_T regmatch;
- histentry_T *hisptr;
- int idx;
- int i;
- int last;
- bool found = false;
+ regmatch.regprog = vim_regcomp(str, RE_MAGIC + RE_STRING);
+ if (regmatch.regprog == NULL) {
+ return false;
+ }
- regmatch.regprog = NULL;
regmatch.rm_ic = false; // always match case
- if (hislen != 0
- && histype >= 0
- && histype < HIST_COUNT
- && *str != NUL
- && (idx = hisidx[histype]) >= 0
- && (regmatch.regprog = vim_regcomp((char *)str, RE_MAGIC + RE_STRING)) != NULL) {
- i = last = idx;
- do {
- hisptr = &history[histype][i];
- if (hisptr->hisstr == NULL) {
- break;
- }
- if (vim_regexec(&regmatch, hisptr->hisstr, (colnr_T)0)) {
- found = true;
- hist_free_entry(hisptr);
- } else {
- if (i != last) {
- history[histype][last] = *hisptr;
- clear_hist_entry(hisptr);
- }
- if (--last < 0) {
- last += hislen;
- }
+
+ bool found = false;
+ int i = idx, last = idx;
+ do {
+ histentry_T *hisptr = &history[histype][i];
+ if (hisptr->hisstr == NULL) {
+ break;
+ }
+ if (vim_regexec(&regmatch, hisptr->hisstr, (colnr_T)0)) {
+ found = true;
+ hist_free_entry(hisptr);
+ } else {
+ if (i != last) {
+ history[histype][last] = *hisptr;
+ clear_hist_entry(hisptr);
}
- if (--i < 0) {
- i += hislen;
+ if (--last < 0) {
+ last += hislen;
}
- } while (i != idx);
- if (history[histype][idx].hisstr == NULL) {
- hisidx[histype] = -1;
}
+ if (--i < 0) {
+ i += hislen;
+ }
+ } while (i != idx);
+
+ if (history[histype][idx].hisstr == NULL) {
+ hisidx[histype] = -1;
}
+
vim_regfree(regmatch.regprog);
return found;
}
@@ -504,16 +527,19 @@ void f_histadd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
const char *str = tv_get_string_chk(&argvars[0]); // NULL on type error
histype = str != NULL ? get_histtype(str, strlen(str), false) : HIST_INVALID;
- if (histype != HIST_INVALID) {
- char buf[NUMBUFLEN];
- str = tv_get_string_buf(&argvars[1], buf);
- if (*str != NUL) {
- init_history();
- add_to_history(histype, (char *)str, false, NUL);
- rettv->vval.v_number = true;
- return;
- }
+ if (histype == HIST_INVALID) {
+ return;
+ }
+
+ char buf[NUMBUFLEN];
+ str = tv_get_string_buf(&argvars[1], buf);
+ if (*str == NUL) {
+ return;
}
+
+ init_history();
+ add_to_history(histype, (char *)str, false, NUL);
+ rettv->vval.v_number = true;
}
/// "histdel()" function
@@ -534,7 +560,7 @@ void f_histdel(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
// string given: remove all matching entries
char buf[NUMBUFLEN];
n = del_history_entry(get_histtype(str, strlen(str), false),
- (char_u *)tv_get_string_buf(&argvars[1], buf));
+ (char *)tv_get_string_buf(&argvars[1], buf));
}
rettv->vval.v_number = n;
}
@@ -585,7 +611,7 @@ void ex_history(exarg_T *eap)
int idx;
int i, j, k;
char *end;
- char_u *arg = (char_u *)eap->arg;
+ char *arg = eap->arg;
if (hislen == 0) {
msg(_("'history' option is zero"));
@@ -593,12 +619,12 @@ void ex_history(exarg_T *eap)
}
if (!(ascii_isdigit(*arg) || *arg == '-' || *arg == ',')) {
- end = (char *)arg;
+ end = arg;
while (ASCII_ISALPHA(*end)
- || vim_strchr(":=@>/?", *end) != NULL) {
+ || vim_strchr(":=@>/?", (uint8_t)(*end)) != NULL) {
end++;
}
- histype1 = get_histtype((const char *)arg, (size_t)(end - (char *)arg), false);
+ histype1 = get_histtype(arg, (size_t)(end - arg), false);
if (histype1 == HIST_INVALID) {
if (STRNICMP(arg, "all", end - (char *)arg) == 0) {
histype1 = 0;
@@ -611,7 +637,7 @@ void ex_history(exarg_T *eap)
histype2 = histype1;
}
} else {
- end = (char *)arg;
+ end = arg;
}
if (!get_list_range(&end, &hisidx1, &hisidx2) || *end != NUL) {
semsg(_(e_trailing_arg), end);
@@ -622,7 +648,7 @@ void ex_history(exarg_T *eap)
STRCPY(IObuff, "\n # ");
assert(history_names[histype1] != NULL);
STRCAT(STRCAT(IObuff, history_names[histype1]), " history");
- msg_puts_title((char *)IObuff);
+ msg_puts_title(IObuff);
idx = hisidx[histype1];
hist = history[histype1];
j = hisidx1;
@@ -641,15 +667,15 @@ void ex_history(exarg_T *eap)
if (hist[i].hisstr != NULL
&& hist[i].hisnum >= j && hist[i].hisnum <= k) {
msg_putchar('\n');
- snprintf((char *)IObuff, IOSIZE, "%c%6d ", i == idx ? '>' : ' ',
+ snprintf(IObuff, IOSIZE, "%c%6d ", i == idx ? '>' : ' ',
hist[i].hisnum);
if (vim_strsize(hist[i].hisstr) > Columns - 10) {
- trunc_string(hist[i].hisstr, (char *)IObuff + strlen(IObuff),
+ trunc_string(hist[i].hisstr, IObuff + strlen(IObuff),
Columns - 10, IOSIZE - (int)strlen(IObuff));
} else {
STRCAT(IObuff, hist[i].hisstr);
}
- msg_outtrans((char *)IObuff);
+ msg_outtrans(IObuff);
}
if (i == idx) {
break;