aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/builtin.txt27
-rw-r--r--runtime/doc/usr_41.txt1
-rw-r--r--src/nvim/autocmd.c1
-rw-r--r--src/nvim/buffer_defs.h3
-rw-r--r--src/nvim/change.c4
-rw-r--r--src/nvim/charset.c24
-rw-r--r--src/nvim/cursor.c16
-rw-r--r--src/nvim/drawline.c28
-rw-r--r--src/nvim/edit.c80
-rw-r--r--src/nvim/eval.lua1
-rw-r--r--src/nvim/eval/funcs.c31
-rw-r--r--src/nvim/ex_cmds.c2
-rw-r--r--src/nvim/ex_docmd.c3
-rw-r--r--src/nvim/ex_getln.c38
-rw-r--r--src/nvim/getchar.c19
-rw-r--r--src/nvim/globals.h2
-rw-r--r--src/nvim/indent.c52
-rw-r--r--src/nvim/mouse.c26
-rw-r--r--src/nvim/normal.c5
-rw-r--r--src/nvim/ops.c101
-rw-r--r--src/nvim/plines.c182
-rw-r--r--src/nvim/plines.h14
-rw-r--r--src/nvim/po/zh_CN.UTF-8.po52
-rw-r--r--src/nvim/po/zh_TW.UTF-8.po360
-rw-r--r--src/nvim/quickfix.c10
-rw-r--r--src/nvim/regexp.c2
-rw-r--r--src/nvim/regexp_bt.c1
-rw-r--r--src/nvim/regexp_nfa.c2
-rw-r--r--src/nvim/testdir/test_autocmd.vim33
-rw-r--r--src/nvim/testdir/test_cmdline.vim40
-rw-r--r--src/nvim/testdir/test_quickfix.vim6
-rw-r--r--src/nvim/window.c2
-rw-r--r--test/functional/autocmd/winscrolled_spec.lua14
-rw-r--r--test/functional/editor/K_spec.lua11
34 files changed, 766 insertions, 427 deletions
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 8cb9149529..a2e15142e7 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -400,6 +400,7 @@ setbufvar({buf}, {varname}, {val}) set {varname} in buffer {buf} to {val}
setcellwidths({list}) none set character cell width overrides
setcharpos({expr}, {list}) Number set the {expr} position to {list}
setcharsearch({dict}) Dict set character search from {dict}
+setcmdline({str} [, {pos}]) Number set command-line
setcmdpos({pos}) Number set cursor position in command-line
setcursorcharpos({list}) Number move cursor to position in {list}
setenv({name}, {val}) none set environment variable
@@ -2880,7 +2881,8 @@ getcmdcompltype() *getcmdcompltype()*
Only works when the command line is being edited, thus
requires use of |c_CTRL-\_e| or |c_CTRL-R_=|.
See |:command-completion| for the return string.
- Also see |getcmdtype()|, |setcmdpos()| and |getcmdline()|.
+ Also see |getcmdtype()|, |setcmdpos()|, |getcmdline()| and
+ |setcmdline()|.
Returns an empty string when completion is not defined.
getcmdline() *getcmdline()*
@@ -2889,7 +2891,8 @@ getcmdline() *getcmdline()*
|c_CTRL-R_=|.
Example: >
:cmap <F7> <C-\>eescape(getcmdline(), ' \')<CR>
-< Also see |getcmdtype()|, |getcmdpos()| and |setcmdpos()|.
+< Also see |getcmdtype()|, |getcmdpos()|, |setcmdpos()| and
+ |setcmdline()|.
Returns an empty string when entering a password or using
|inputsecret()|.
@@ -2899,7 +2902,8 @@ getcmdpos() *getcmdpos()*
Only works when editing the command line, thus requires use of
|c_CTRL-\_e| or |c_CTRL-R_=| or an expression mapping.
Returns 0 otherwise.
- Also see |getcmdtype()|, |setcmdpos()| and |getcmdline()|.
+ Also see |getcmdtype()|, |setcmdpos()|, |getcmdline()| and
+ |setcmdline()|.
getcmdscreenpos() *getcmdscreenpos()*
Return the screen position of the cursor in the command line
@@ -2908,7 +2912,8 @@ getcmdscreenpos() *getcmdscreenpos()*
Only works when editing the command line, thus requires use of
|c_CTRL-\_e| or |c_CTRL-R_=| or an expression mapping.
Returns 0 otherwise.
- Also see |getcmdpos()|, |setcmdpos()|.
+ Also see |getcmdpos()|, |setcmdpos()|, |getcmdline()| and
+ |setcmdline()|.
getcmdtype() *getcmdtype()*
Return the current command-line type. Possible return values
@@ -6912,6 +6917,16 @@ setcharsearch({dict}) *setcharsearch()*
Can also be used as a |method|: >
SavedSearch()->setcharsearch()
+setcmdline({str} [, {pos}]) *setcmdline()*
+ Set the command line to {str} and set the cursor position to
+ {pos}.
+ If {pos} is omitted, the cursor is positioned after the text.
+ Returns 0 when successful, 1 when not editing the command
+ line.
+
+ Can also be used as a |method|: >
+ GetText()->setcmdline()
+
setcmdpos({pos}) *setcmdpos()*
Set the cursor position in the command line to byte position
{pos}. The first position is 1.
@@ -6924,8 +6939,8 @@ setcmdpos({pos}) *setcmdpos()*
before inserting the resulting text.
When the number is too big the cursor is put at the end of the
line. A number smaller than one has undefined results.
- Returns FALSE when successful, TRUE when not editing the
- command line.
+ Returns 0 when successful, 1 when not editing the command
+ line.
Can also be used as a |method|: >
GetPos()->setcmdpos()
diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt
index 0c907bfb68..76c2f8454f 100644
--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -872,6 +872,7 @@ Command line: *command-line-functions*
getcmdpos() get position of the cursor in the command line
getcmdscreenpos() get screen position of the cursor in the
command line
+ setcmdline() set the current command line
setcmdpos() set position of the cursor in the command line
getcmdtype() return the current command-line type
getcmdwintype() return the current command-line window type
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 2fe9df2206..1c1de214cd 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -1119,6 +1119,7 @@ int autocmd_register(int64_t id, event_T event, char *pat, int patlen, int group
if (event == EVENT_WINSCROLLED && !has_event(EVENT_WINSCROLLED)) {
curwin->w_last_topline = curwin->w_topline;
curwin->w_last_leftcol = curwin->w_leftcol;
+ curwin->w_last_skipcol = curwin->w_skipcol;
curwin->w_last_width = curwin->w_width;
curwin->w_last_height = curwin->w_height;
}
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 58bdd2c0a8..319c2addba 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -1240,9 +1240,10 @@ struct window_S {
colnr_T w_skipcol; // starting column when a single line
// doesn't fit in the window
- // four fields that are only used when there is a WinScrolled autocommand
+ // five fields that are only used when there is a WinScrolled autocommand
linenr_T w_last_topline; ///< last known value for w_topline
colnr_T w_last_leftcol; ///< last known value for w_leftcol
+ colnr_T w_last_skipcol; ///< last known value for w_skipcol
int w_last_width; ///< last known value for w_width
int w_last_height; ///< last known value for w_height
diff --git a/src/nvim/change.c b/src/nvim/change.c
index 04dfb20a1b..074700f4df 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -653,9 +653,9 @@ void ins_char_bytes(char_u *buf, size_t charlen)
// cells. May result in adding spaces to fill a gap.
colnr_T vcol;
getvcol(curwin, &curwin->w_cursor, NULL, &vcol, NULL);
- colnr_T new_vcol = vcol + win_chartabsize(curwin, buf, vcol);
+ colnr_T new_vcol = vcol + win_chartabsize(curwin, (char *)buf, vcol);
while (oldp[col + oldlen] != NUL && vcol < new_vcol) {
- vcol += win_chartabsize(curwin, oldp + col + oldlen, vcol);
+ vcol += win_chartabsize(curwin, (char *)oldp + col + oldlen, vcol);
// Don't need to remove a TAB that takes us to the right
// position.
if (vcol > new_vcol && oldp[col + oldlen] == TAB) {
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index df951854e0..e0f798121a 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -930,14 +930,18 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
posptr -= utf_head_off(line, posptr);
}
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, wp, pos->lnum, 0, line, line);
+
// This function is used very often, do some speed optimizations.
// When 'list', 'linebreak', 'showbreak' and 'breakindent' are not set
- // use a simple loop.
+ // and there are no virtual text use a simple loop.
// Also use this when 'list' is set but tabs take their normal size.
if ((!wp->w_p_list || (wp->w_p_lcs_chars.tab1 != NUL))
&& !wp->w_p_lbr
&& *get_showbreak_value(wp) == NUL
- && !wp->w_p_bri) {
+ && !wp->w_p_bri
+ && !cts.cts_has_virt_text) {
for (;;) {
head = 0;
int c = *ptr;
@@ -984,25 +988,29 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
} else {
for (;;) {
// A tab gets expanded, depending on the current column
+ // Other things also take up space.
head = 0;
- incr = win_lbr_chartabsize(wp, line, ptr, vcol, &head);
+ incr = win_lbr_chartabsize(&cts, &head);
// make sure we don't go past the end of the line
- if (*ptr == NUL) {
+ if (*cts.cts_ptr == NUL) {
// NUL at end of line only takes one column
incr = 1;
break;
}
- if ((posptr != NULL) && (ptr >= posptr)) {
+ if ((posptr != NULL) && ((char_u *)cts.cts_ptr >= posptr)) {
// character at pos->col
break;
}
- vcol += incr;
- MB_PTR_ADV(ptr);
+ cts.cts_vcol += incr;
+ MB_PTR_ADV(cts.cts_ptr);
}
+ vcol = cts.cts_vcol;
+ ptr = (char_u *)cts.cts_ptr;
}
+ clear_chartabsize_arg(&cts);
if (start != NULL) {
*start = vcol + head;
@@ -1013,6 +1021,8 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
}
if (cursor != NULL) {
+ // cursor is after inserted text
+ vcol += cts.cts_cur_text_width;
if ((*ptr == TAB)
&& (State & MODE_NORMAL)
&& !wp->w_p_list
diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c
index 14ebc11cbf..ed0488cf76 100644
--- a/src/nvim/cursor.c
+++ b/src/nvim/cursor.c
@@ -137,14 +137,18 @@ static int coladvance2(pos_T *pos, bool addspaces, bool finetune, colnr_T wcol_a
}
}
- char_u *ptr = line;
- while (col <= wcol && *ptr != NUL) {
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, pos->lnum, 0, line, line);
+ while (cts.cts_vcol <= wcol && *cts.cts_ptr != NUL) {
// Count a tab for what it's worth (if list mode not on)
- csize = win_lbr_chartabsize(curwin, line, ptr, col, &head);
- MB_PTR_ADV(ptr);
- col += csize;
+ csize = win_lbr_chartabsize(&cts, &head);
+ MB_PTR_ADV(cts.cts_ptr);
+ cts.cts_vcol += csize;
}
- idx = (int)(ptr - line);
+ col = cts.cts_vcol;
+ idx = (int)(cts.cts_ptr - (char *)line);
+ clear_chartabsize_arg(&cts);
+
// Handle all the special cases. The virtual_active() check
// is needed to ensure that a virtual position off the end of
// a line has the correct indexing. The one_more comparison
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index 9132d6666e..4b5f6c6c06 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -940,12 +940,19 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
if (v > 0 && !number_only) {
char_u *prev_ptr = ptr;
- while (vcol < v && *ptr != NUL) {
- c = win_lbr_chartabsize(wp, line, ptr, (colnr_T)vcol, NULL);
- vcol += c;
- prev_ptr = ptr;
- MB_PTR_ADV(ptr);
+ chartabsize_T cts;
+ int charsize;
+
+ init_chartabsize_arg(&cts, wp, lnum, (colnr_T)vcol, line, ptr);
+ while (cts.cts_vcol < v && *cts.cts_ptr != NUL) {
+ charsize = win_lbr_chartabsize(&cts, NULL);
+ cts.cts_vcol += charsize;
+ prev_ptr = (char_u *)cts.cts_ptr;
+ MB_PTR_ADV(cts.cts_ptr);
}
+ vcol = cts.cts_vcol;
+ ptr = (char_u *)cts.cts_ptr;
+ clear_chartabsize_arg(&cts);
// When:
// - 'cuc' is set, or
@@ -963,11 +970,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// Handle a character that's not completely on the screen: Put ptr at
// that character but skip the first few screen characters.
if (vcol > v) {
- vcol -= c;
+ vcol -= charsize;
ptr = prev_ptr;
// If the character fits on the screen, don't need to skip it.
// Except for a TAB.
- if (utf_ptr2cells((char *)ptr) >= c || *ptr == TAB) {
+ if (utf_ptr2cells((char *)ptr) >= charsize || *ptr == TAB) {
n_skip = (int)(v - vcol);
}
}
@@ -1798,8 +1805,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
&& !vim_isbreak((int)(*ptr))) {
int mb_off = utf_head_off(line, ptr - 1);
char_u *p = ptr - (mb_off + 1);
- // TODO(neovim): is passing p for start of the line OK?
- n_extra = win_lbr_chartabsize(wp, line, p, (colnr_T)vcol, NULL) - 1;
+ chartabsize_T cts;
+
+ init_chartabsize_arg(&cts, wp, lnum, (colnr_T)vcol, line, p);
+ n_extra = win_lbr_chartabsize(&cts, NULL) - 1;
// We have just drawn the showbreak value, no need to add
// space for it again.
@@ -1825,6 +1834,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
c = ' ';
}
}
+ clear_chartabsize_arg(&cts);
}
in_multispace = c == ' ' && ((ptr > line + 1 && ptr[-2] == ' ') || *ptr == ' ');
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index adcf9cd075..b9432ca362 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -1665,28 +1665,28 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
} else if (!(State & MODE_INSERT)) {
new_cursor_col = curwin->w_cursor.col;
} else {
- /*
- * Compute the screen column where the cursor should be.
- */
+ // Compute the screen column where the cursor should be.
vcol = get_indent() - vcol;
curwin->w_virtcol = (colnr_T)((vcol < 0) ? 0 : vcol);
- /*
- * Advance the cursor until we reach the right screen column.
- */
- vcol = last_vcol = 0;
- new_cursor_col = -1;
+ // Advance the cursor until we reach the right screen column.
+ last_vcol = 0;
ptr = get_cursor_line_ptr();
- while (vcol <= (int)curwin->w_virtcol) {
- last_vcol = vcol;
- if (new_cursor_col >= 0) {
- new_cursor_col += utfc_ptr2len((char *)ptr + new_cursor_col);
- } else {
- new_cursor_col++;
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, 0, 0, ptr, ptr);
+ while (cts.cts_vcol <= (int)curwin->w_virtcol) {
+ last_vcol = cts.cts_vcol;
+ if (cts.cts_vcol > 0) {
+ MB_PTR_ADV(cts.cts_ptr);
+ }
+ if (*cts.cts_ptr == NUL) {
+ break;
}
- vcol += lbr_chartabsize(ptr, ptr + new_cursor_col, (colnr_T)vcol);
+ cts.cts_vcol += lbr_chartabsize(&cts);
}
vcol = last_vcol;
+ new_cursor_col = (int)(cts.cts_ptr - cts.cts_line);
+ clear_chartabsize_arg(&cts);
/*
* May need to insert spaces to be able to position the cursor on
@@ -2991,7 +2991,7 @@ static void replace_do_bs(int limit_col)
// Get the number of screen cells used by the character we are
// going to delete.
getvcol(curwin, &curwin->w_cursor, NULL, &start_vcol, NULL);
- orig_vcols = win_chartabsize(curwin, get_cursor_pos_ptr(), start_vcol);
+ orig_vcols = win_chartabsize(curwin, (char *)get_cursor_pos_ptr(), start_vcol);
}
(void)del_char_after_col(limit_col);
if (l_State & VREPLACE_FLAG) {
@@ -3006,7 +3006,7 @@ static void replace_do_bs(int limit_col)
ins_len = (int)STRLEN(p) - orig_len;
vcol = start_vcol;
for (i = 0; i < ins_len; i++) {
- vcol += win_chartabsize(curwin, p + i, vcol);
+ vcol += win_chartabsize(curwin, (char *)p + i, vcol);
i += utfc_ptr2len((char *)p) - 1;
}
vcol -= start_vcol;
@@ -4642,11 +4642,15 @@ static bool ins_tab(void)
getvcol(curwin, &fpos, &vcol, NULL, NULL);
getvcol(curwin, cursor, &want_vcol, NULL, NULL);
+ char_u *tab = (char_u *)"\t";
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, 0, vcol, tab, tab);
+
// Use as many TABs as possible. Beware of 'breakindent', 'showbreak'
// and 'linebreak' adding extra virtual columns.
while (ascii_iswhite(*ptr)) {
- i = lbr_chartabsize(NULL, (char_u *)"\t", vcol);
- if (vcol + i > want_vcol) {
+ i = lbr_chartabsize(&cts);
+ if (cts.cts_vcol + i > want_vcol) {
break;
}
if (*ptr != TAB) {
@@ -4661,19 +4665,24 @@ static bool ins_tab(void)
}
fpos.col++;
ptr++;
- vcol += i;
+ cts.cts_vcol += i;
}
+ vcol = cts.cts_vcol;
+ clear_chartabsize_arg(&cts);
if (change_col >= 0) {
int repl_off = 0;
- char_u *line = ptr;
-
// Skip over the spaces we need.
- while (vcol < want_vcol && *ptr == ' ') {
- vcol += lbr_chartabsize(line, ptr, vcol);
- ptr++;
+ init_chartabsize_arg(&cts, curwin, 0, vcol, ptr, ptr);
+ while (cts.cts_vcol < want_vcol && *cts.cts_ptr == ' ') {
+ cts.cts_vcol += lbr_chartabsize(&cts);
+ cts.cts_ptr++;
repl_off++;
}
+ ptr = (char_u *)cts.cts_ptr;
+ vcol = cts.cts_vcol;
+ clear_chartabsize_arg(&cts);
+
if (vcol > want_vcol) {
// Must have a char with 'showbreak' just before it.
ptr--;
@@ -4853,7 +4862,6 @@ static int ins_digraph(void)
int ins_copychar(linenr_T lnum)
{
int c;
- int temp;
char_u *ptr, *prev_ptr;
char_u *line;
@@ -4863,17 +4871,23 @@ int ins_copychar(linenr_T lnum)
}
// try to advance to the cursor column
- temp = 0;
- line = ptr = ml_get(lnum);
- prev_ptr = ptr;
+ line = ml_get(lnum);
+ prev_ptr = line;
validate_virtcol();
- while ((colnr_T)temp < curwin->w_virtcol && *ptr != NUL) {
- prev_ptr = ptr;
- temp += lbr_chartabsize_adv(line, &ptr, (colnr_T)temp);
+
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, lnum, 0, line, line);
+ while (cts.cts_vcol < curwin->w_virtcol && *cts.cts_ptr != NUL) {
+ prev_ptr = (char_u *)cts.cts_ptr;
+ cts.cts_vcol += lbr_chartabsize_adv(&cts);
}
- if ((colnr_T)temp > curwin->w_virtcol) {
+
+ if (cts.cts_vcol > curwin->w_virtcol) {
ptr = prev_ptr;
+ } else {
+ ptr = (char_u *)cts.cts_ptr;
}
+ clear_chartabsize_arg(&cts);
c = utf_ptr2char((char *)ptr);
if (c == NUL) {
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index 4863d8013d..3e89489459 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -332,6 +332,7 @@ return {
setcharpos={args=2, base=2},
setcharsearch={args=1, base=1},
setcmdpos={args=1, base=1},
+ setcmdline={args={1, 2}, base=1},
setcursorcharpos={args={1, 3}, base=1},
setenv={args=2, base=2},
setfperm={args=2, base=1},
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 22447b933a..0c3d2d6935 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -849,11 +849,11 @@ static void get_col(typval_T *argvars, typval_T *rettv, bool charcol)
// col(".") when the cursor is on the NUL at the end of the line
// because of "coladd" can be seen as an extra column.
if (virtual_active() && fp == &curwin->w_cursor) {
- char_u *p = get_cursor_pos_ptr();
+ char *p = (char *)get_cursor_pos_ptr();
if (curwin->w_cursor.coladd >=
(colnr_T)win_chartabsize(curwin, p, curwin->w_virtcol - curwin->w_cursor.coladd)) {
int l;
- if (*p != NUL && p[(l = utfc_ptr2len((char *)p))] == NUL) {
+ if (*p != NUL && p[(l = utfc_ptr2len(p))] == NUL) {
col += l;
}
}
@@ -7621,6 +7621,31 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, EvalFuncData fpt
}
}
+/// "setcmdline()" function
+static void f_setcmdline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
+{
+ if (argvars[0].v_type != VAR_STRING || argvars[0].vval.v_string == NULL) {
+ emsg(_(e_stringreq));
+ return;
+ }
+
+ int pos = -1;
+ if (argvars[1].v_type != VAR_UNKNOWN) {
+ bool error = false;
+
+ pos = (int)tv_get_number_chk(&argvars[1], &error) - 1;
+ if (error) {
+ return;
+ }
+ if (pos < 0) {
+ emsg(_(e_positive));
+ return;
+ }
+ }
+
+ rettv->vval.v_number = set_cmdline_str(argvars[0].vval.v_string, pos);
+}
+
/// "setcmdpos()" function
static void f_setcmdpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
@@ -8514,7 +8539,7 @@ static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv, EvalFuncData f
col = (int)tv_get_number(&argvars[1]);
}
- rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, (char_u *)s) - col);
+ rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, (char *)s) - col);
}
/// "strwidth()" function
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 4a1cdb0fc5..6886ce0987 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -841,7 +841,7 @@ void ex_retab(exarg_T *eap)
if (ptr[col] == NUL) {
break;
}
- vcol += win_chartabsize(curwin, (char_u *)ptr + col, (colnr_T)vcol);
+ vcol += win_chartabsize(curwin, ptr + col, (colnr_T)vcol);
if (vcol >= MAXCOL) {
emsg(_(e_resulting_text_too_long));
break;
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 8ecc1e266b..5b38118a33 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -3586,6 +3586,9 @@ char *invalid_range(exarg_T *eap)
assert(eap->line2 >= 0);
// No error for value that is too big, will use the last entry.
if (eap->line2 <= 0) {
+ if (eap->addr_count == 0) {
+ return _(e_no_errors);
+ }
return _(e_invrange);
}
break;
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index c509205a6c..3d991996d6 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -2373,9 +2373,9 @@ end:
return cmdpreview_type != 0;
}
-static int command_line_changed(CommandLineState *s)
+/// Trigger CmdlineChanged autocommands.
+static void do_autocmd_cmdlinechanged(int firstc)
{
- // Trigger CmdlineChanged autocommands.
if (has_event(EVENT_CMDLINECHANGED)) {
TryState tstate;
Error err = ERROR_INIT;
@@ -2383,7 +2383,7 @@ static int command_line_changed(CommandLineState *s)
dict_T *dict = get_v_event(&save_v_event);
char firstcbuf[2];
- firstcbuf[0] = (char)(s->firstc > 0 ? s->firstc : '-');
+ firstcbuf[0] = (char)firstc;
firstcbuf[1] = 0;
// set v:event to a dictionary with information about the commandline
@@ -2403,6 +2403,12 @@ static int command_line_changed(CommandLineState *s)
redrawcmd();
}
}
+}
+
+static int command_line_changed(CommandLineState *s)
+{
+ // Trigger CmdlineChanged autocommands.
+ do_autocmd_cmdlinechanged(s->firstc > 0 ? s->firstc : '-');
if (s->firstc == ':'
&& current_sctx.sc_sid == 0 // only if interactive
@@ -3991,6 +3997,32 @@ int get_cmdline_screen_pos(void)
return p->cmdspos;
}
+/// Set the command line str to "str".
+/// @return 1 when failed, 0 when OK.
+int set_cmdline_str(const char *str, int pos)
+{
+ CmdlineInfo *p = get_ccline_ptr();
+
+ if (p == NULL) {
+ return 1;
+ }
+
+ int len = (int)STRLEN(str);
+ realloc_cmdbuff(len + 1);
+ p->cmdlen = len;
+ STRCPY(p->cmdbuff, str);
+
+ p->cmdpos = pos < 0 || pos > p->cmdlen ? p->cmdlen : pos;
+ new_cmdpos = p->cmdpos;
+
+ redrawcmd();
+
+ // Trigger CmdlineChanged autocommands.
+ do_autocmd_cmdlinechanged(ccline.cmdfirstc == NUL ? '-' : ccline.cmdfirstc);
+
+ return 0;
+}
+
/*
* Set the command line byte position to "pos". Zero is the first position.
* Only works when the command line is being edited.
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index ebea4b7a9b..574eba9bdd 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -2547,7 +2547,7 @@ static int vgetorpeek(bool advance)
&& (State & MODE_INSERT)
&& (p_timeout || (keylen == KEYLEN_PART_KEY && p_ttimeout))
&& (c = inchar(typebuf.tb_buf + typebuf.tb_off + typebuf.tb_len, 3, 25L)) == 0) {
- colnr_T col = 0, vcol;
+ colnr_T col = 0;
char_u *ptr;
if (mode_displayed) {
@@ -2565,15 +2565,20 @@ static int vgetorpeek(bool advance)
// We are expecting to truncate the trailing
// white-space, so find the last non-white
// character -- webb
- col = vcol = curwin->w_wcol = 0;
+ curwin->w_wcol = 0;
ptr = get_cursor_line_ptr();
- while (col < curwin->w_cursor.col) {
- if (!ascii_iswhite(ptr[col])) {
- curwin->w_wcol = vcol;
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin,
+ curwin->w_cursor.lnum, 0, ptr, ptr);
+ while ((char_u *)cts.cts_ptr < ptr + curwin->w_cursor.col) {
+ if (!ascii_iswhite(*cts.cts_ptr)) {
+ curwin->w_wcol = cts.cts_vcol;
}
- vcol += lbr_chartabsize(ptr, ptr + col, vcol);
- col += utfc_ptr2len((char *)ptr + col);
+ cts.cts_vcol += lbr_chartabsize(&cts);
+ cts.cts_ptr += utfc_ptr2len(cts.cts_ptr);
}
+ clear_chartabsize_arg(&cts);
+
curwin->w_wrow = curwin->w_cline_row
+ curwin->w_wcol / curwin->w_width_inner;
curwin->w_wcol %= curwin->w_width_inner;
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 8d62674a22..77784defd1 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -920,7 +920,7 @@ EXTERN char e_patnotf2[] INIT(= N_("E486: Pattern not found: %s"));
EXTERN char e_positive[] INIT(= N_("E487: Argument must be positive"));
EXTERN char e_prev_dir[] INIT(= N_("E459: Cannot go back to previous directory"));
-EXTERN char e_quickfix[] INIT(= N_("E42: No Errors"));
+EXTERN char e_no_errors[] INIT(= N_("E42: No Errors"));
EXTERN char e_loclist[] INIT(= N_("E776: No location list"));
EXTERN char e_re_damg[] INIT(= N_("E43: Damaged match string"));
EXTERN char e_re_corr[] INIT(= N_("E44: Corrupted regexp program"));
diff --git a/src/nvim/indent.c b/src/nvim/indent.c
index 7c5f291837..c983de6d5e 100644
--- a/src/nvim/indent.c
+++ b/src/nvim/indent.c
@@ -1035,13 +1035,15 @@ int get_lisp_indent(void)
amount = 2;
} else {
char_u *line = that;
-
- amount = 0;
-
- while (*that && col) {
- amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount);
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, pos->lnum, 0, line, line);
+ while (*cts.cts_ptr != NUL && col > 0) {
+ cts.cts_vcol += lbr_chartabsize_adv(&cts);
col--;
}
+ amount = cts.cts_vcol;
+ that = (char_u *)cts.cts_ptr;
+ clear_chartabsize_arg(&cts);
// Some keywords require "body" indenting rules (the
// non-standard-lisp ones are Scheme special forms):
@@ -1057,10 +1059,15 @@ int get_lisp_indent(void)
}
firsttry = amount;
- while (ascii_iswhite(*that)) {
- amount += lbr_chartabsize(line, that, (colnr_T)amount);
- that++;
+ init_chartabsize_arg(&cts, curwin, (colnr_T)(that - line),
+ amount, line, that);
+ while (ascii_iswhite(*cts.cts_ptr)) {
+ cts.cts_vcol += lbr_chartabsize(&cts);
+ cts.cts_ptr++;
}
+ that = (char_u *)cts.cts_ptr;
+ amount = cts.cts_vcol;
+ clear_chartabsize_arg(&cts);
if (*that && (*that != ';')) {
// Not a comment line.
@@ -1073,33 +1080,38 @@ int get_lisp_indent(void)
parencount = 0;
quotecount = 0;
+ init_chartabsize_arg(&cts, curwin,
+ (colnr_T)(that - line), amount, line, that);
if (vi_lisp || ((*that != '"') && (*that != '\'')
&& (*that != '#') && ((*that < '0') || (*that > '9')))) {
- while (*that
- && (!ascii_iswhite(*that) || quotecount || parencount)
- && (!((*that == '(' || *that == '[')
+ while (*cts.cts_ptr
+ && (!ascii_iswhite(*cts.cts_ptr) || quotecount || parencount)
+ && (!((*cts.cts_ptr == '(' || *cts.cts_ptr == '[')
&& !quotecount && !parencount && vi_lisp))) {
- if (*that == '"') {
+ if (*cts.cts_ptr == '"') {
quotecount = !quotecount;
}
- if (((*that == '(') || (*that == '[')) && !quotecount) {
+ if (((*cts.cts_ptr == '(') || (*cts.cts_ptr == '[')) && !quotecount) {
parencount++;
}
- if (((*that == ')') || (*that == ']')) && !quotecount) {
+ if (((*cts.cts_ptr == ')') || (*cts.cts_ptr == ']')) && !quotecount) {
parencount--;
}
- if ((*that == '\\') && (*(that + 1) != NUL)) {
- amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount);
+ if ((*cts.cts_ptr == '\\') && (*(cts.cts_ptr + 1) != NUL)) {
+ cts.cts_vcol += lbr_chartabsize_adv(&cts);
}
- amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount);
+ cts.cts_vcol += lbr_chartabsize_adv(&cts);
}
}
- while (ascii_iswhite(*that)) {
- amount += lbr_chartabsize(line, that, (colnr_T)amount);
- that++;
+ while (ascii_iswhite(*cts.cts_ptr)) {
+ cts.cts_vcol += lbr_chartabsize(&cts);
+ cts.cts_ptr++;
}
+ that = (char_u *)cts.cts_ptr;
+ amount = cts.cts_vcol;
+ clear_chartabsize_arg(&cts);
if (!*that || (*that == ';')) {
amount = firsttry;
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index 3dfbeec048..5ebe97aa61 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -631,14 +631,16 @@ colnr_T vcol2col(win_T *const wp, const linenr_T lnum, const colnr_T vcol)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
// try to advance to the specified column
- char_u *ptr = ml_get_buf(wp->w_buffer, lnum, false);
- char_u *const line = ptr;
- colnr_T count = 0;
- while (count < vcol && *ptr != NUL) {
- count += win_lbr_chartabsize(wp, line, ptr, count, NULL);
- MB_PTR_ADV(ptr);
- }
- return (colnr_T)(ptr - line);
+ char_u *line = ml_get_buf(wp->w_buffer, lnum, false);
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
+ while (cts.cts_vcol < vcol && *cts.cts_ptr != NUL) {
+ cts.cts_vcol += win_lbr_chartabsize(&cts, NULL);
+ MB_PTR_ADV(cts.cts_ptr);
+ }
+ clear_chartabsize_arg(&cts);
+
+ return (colnr_T)((char_u *)cts.cts_ptr - line);
}
/// Set UI mouse depending on current mode and 'mouse'.
@@ -667,7 +669,7 @@ static colnr_T scroll_line_len(linenr_T lnum)
char_u *line = ml_get(lnum);
if (*line != NUL) {
for (;;) {
- int numchar = win_chartabsize(curwin, line, col);
+ int numchar = win_chartabsize(curwin, (char *)line, col);
MB_PTR_ADV(line);
if (*line == NUL) { // don't count the last character
break;
@@ -790,7 +792,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
// checked for concealed characters.
vcol = 0;
while (vcol < offset && *ptr != NUL) {
- vcol += win_chartabsize(curwin, ptr, vcol);
+ vcol += win_chartabsize(curwin, (char *)ptr, vcol);
ptr += utfc_ptr2len((char *)ptr);
}
@@ -801,7 +803,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
vcol = offset;
ptr_end = ptr_row_offset;
while (vcol < col && *ptr_end != NUL) {
- vcol += win_chartabsize(curwin, ptr_end, vcol);
+ vcol += win_chartabsize(curwin, (char *)ptr_end, vcol);
ptr_end += utfc_ptr2len((char *)ptr_end);
}
@@ -816,7 +818,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
#define DECR() nudge--; ptr_end -= utfc_ptr2len((char *)ptr_end)
while (ptr < ptr_end && *ptr != NUL) {
- cwidth = win_chartabsize(curwin, ptr, vcol);
+ cwidth = win_chartabsize(curwin, (char *)ptr, vcol);
vcol += cwidth;
if (cwidth > 1 && *ptr == '\t' && nudge > 0) {
// A tab will "absorb" any previous adjustments.
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 5dd6742e2f..8c5b1a033c 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -4278,13 +4278,12 @@ static void nv_ident(cmdarg_T *cap)
// double the length of the word. p_kp / curbuf->b_p_kp could be added
// and some numbers.
char_u *kp = *curbuf->b_p_kp == NUL ? p_kp : (char_u *)curbuf->b_p_kp; // 'keywordprg'
- assert(*kp != NUL); // option.c:do_set() should default to ":help" if empty.
- bool kp_ex = (*kp == ':'); // 'keywordprg' is an ex command
- bool kp_help = (STRCMP(kp, ":he") == 0 || STRCMP(kp, ":help") == 0);
+ bool kp_help = (*kp == NUL || STRCMP(kp, ":he") == 0 || STRCMP(kp, ":help") == 0);
if (kp_help && *skipwhite(ptr) == NUL) {
emsg(_(e_noident)); // found white space only
return;
}
+ bool kp_ex = (*kp == ':'); // 'keywordprg' is an ex command
size_t buf_size = n * 2 + 30 + STRLEN(kp);
char *buf = xmalloc(buf_size);
buf[0] = NUL;
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 1bf4c00633..092487fd3e 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -378,12 +378,20 @@ static void shift_block(oparg_T *oap, int amount)
bd.startspaces = 0;
}
}
- for (; ascii_iswhite(*bd.textstart);) {
- // TODO(fmoralesc): is passing bd.textstart for start of the line OK?
- incr = lbr_chartabsize_adv(bd.textstart, &bd.textstart, bd.start_vcol);
+
+ // TODO(vim): is passing bd.textstart for start of the line OK?
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum,
+ bd.start_vcol, bd.textstart, bd.textstart);
+ while (ascii_iswhite(*cts.cts_ptr)) {
+ incr = lbr_chartabsize_adv(&cts);
total += incr;
- bd.start_vcol += incr;
+ cts.cts_vcol += incr;
}
+ bd.textstart = (char_u *)cts.cts_ptr;
+ bd.start_vcol = cts.cts_vcol;
+ clear_chartabsize_arg(&cts);
+
// OK, now total=all the VWS reqd, and textstart points at the 1st
// non-ws char in the block.
if (!curbuf->b_p_et) {
@@ -438,10 +446,16 @@ static void shift_block(oparg_T *oap, int amount)
// The character's column is in "bd.start_vcol".
colnr_T non_white_col = bd.start_vcol;
- while (ascii_iswhite(*non_white)) {
- incr = lbr_chartabsize_adv(bd.textstart, &non_white, non_white_col);
- non_white_col += incr;
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum,
+ non_white_col, bd.textstart, non_white);
+ while (ascii_iswhite(*cts.cts_ptr)) {
+ incr = lbr_chartabsize_adv(&cts);
+ cts.cts_vcol += incr;
}
+ non_white_col = cts.cts_vcol;
+ non_white = (char_u *)cts.cts_ptr;
+ clear_chartabsize_arg(&cts);
const colnr_T block_space_width = non_white_col - oap->start_vcol;
// We will shift by "total" or "block_space_width", whichever is less.
@@ -462,17 +476,19 @@ static void shift_block(oparg_T *oap, int amount)
if (bd.startspaces) {
verbatim_copy_width -= bd.start_char_vcols;
}
- while (verbatim_copy_width < destination_col) {
- char_u *line = verbatim_copy_end;
-
- // TODO: is passing verbatim_copy_end for start of the line OK?
- incr = lbr_chartabsize(line, verbatim_copy_end, verbatim_copy_width);
- if (verbatim_copy_width + incr > destination_col) {
+ init_chartabsize_arg(&cts, curwin, 0, verbatim_copy_width,
+ bd.textstart, verbatim_copy_end);
+ while (cts.cts_vcol < destination_col) {
+ incr = lbr_chartabsize(&cts);
+ if (cts.cts_vcol + incr > destination_col) {
break;
}
- verbatim_copy_width += incr;
- MB_PTR_ADV(verbatim_copy_end);
+ cts.cts_vcol += incr;
+ MB_PTR_ADV(cts.cts_ptr);
}
+ verbatim_copy_width = cts.cts_vcol;
+ verbatim_copy_end = (char_u *)cts.cts_ptr;
+ clear_chartabsize_arg(&cts);
// If "destination_col" is different from the width of the initial
// part of the line that will be copied, it means we encountered a tab
@@ -1550,6 +1566,7 @@ int op_delete(oparg_T *oap)
// Put deleted text into register 1 and shift number registers if the
// delete contains a line break, or when using a specific operator (Vi
// compatible)
+
if (oap->motion_type == kMTLineWise || oap->line_count > 1 || oap->use_reg_one) {
shift_delete_registers(is_append_register(oap->regname));
reg = &y_regs[1];
@@ -3280,12 +3297,19 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
// get the old line and advance to the position to insert at
oldp = get_cursor_line_ptr();
oldlen = STRLEN(oldp);
- for (ptr = oldp; vcol < col && *ptr;) {
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum, 0,
+ oldp, oldp);
+
+ while (cts.cts_vcol < col && *cts.cts_ptr != NUL) {
// Count a tab for what it's worth (if list mode not on)
- incr = lbr_chartabsize_adv(oldp, &ptr, vcol);
- vcol += incr;
+ incr = lbr_chartabsize_adv(&cts);
+ cts.cts_vcol += incr;
}
+ vcol = cts.cts_vcol;
+ ptr = (char_u *)cts.cts_ptr;
bd.textcol = (colnr_T)(ptr - oldp);
+ clear_chartabsize_arg(&cts);
shortline = (vcol < col) || (vcol == col && !*ptr);
@@ -3312,9 +3336,14 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
// calculate number of spaces required to fill right side of
// block
spaces = y_width + 1;
+ init_chartabsize_arg(&cts, curwin, 0, 0,
+ (char_u *)y_array[i], (char_u *)y_array[i]);
for (int j = 0; j < yanklen; j++) {
- spaces -= lbr_chartabsize(NULL, (char_u *)(&y_array[i][j]), 0);
+ spaces -= lbr_chartabsize(&cts);
+ cts.cts_ptr++;
+ cts.cts_vcol = 0;
}
+ clear_chartabsize_arg(&cts);
if (spaces < 0) {
spaces = 0;
}
@@ -4227,22 +4256,28 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bool
bdp->start_char_vcols = 0;
line = ml_get(lnum);
- pstart = line;
prev_pstart = line;
- while (bdp->start_vcol < oap->start_vcol && *pstart) {
+
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, lnum, bdp->start_vcol, line, line);
+ while (cts.cts_vcol < oap->start_vcol && *cts.cts_ptr != NUL) {
// Count a tab for what it's worth (if list mode not on)
- incr = lbr_chartabsize(line, pstart, bdp->start_vcol);
- bdp->start_vcol += incr;
- if (ascii_iswhite(*pstart)) {
+ incr = lbr_chartabsize(&cts);
+ cts.cts_vcol += incr;
+ if (ascii_iswhite(*cts.cts_ptr)) {
bdp->pre_whitesp += incr;
bdp->pre_whitesp_c++;
} else {
bdp->pre_whitesp = 0;
bdp->pre_whitesp_c = 0;
}
- prev_pstart = pstart;
- MB_PTR_ADV(pstart);
+ prev_pstart = (char_u *)cts.cts_ptr;
+ MB_PTR_ADV(cts.cts_ptr);
}
+ bdp->start_vcol = cts.cts_vcol;
+ pstart = (char_u *)cts.cts_ptr;
+ clear_chartabsize_arg(&cts);
+
bdp->start_char_vcols = incr;
if (bdp->start_vcol < oap->start_vcol) { // line too short
bdp->end_vcol = bdp->start_vcol;
@@ -4278,13 +4313,19 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bool
}
}
} else {
+ init_chartabsize_arg(&cts, curwin, lnum, bdp->end_vcol,
+ line, pend);
prev_pend = pend;
- while (bdp->end_vcol <= oap->end_vcol && *pend != NUL) {
+ while (cts.cts_vcol <= oap->end_vcol && *cts.cts_ptr != NUL) {
// Count a tab for what it's worth (if list mode not on)
- prev_pend = pend;
- incr = lbr_chartabsize_adv(line, &pend, bdp->end_vcol);
- bdp->end_vcol += incr;
+ prev_pend = (char_u *)cts.cts_ptr;
+ incr = lbr_chartabsize_adv(&cts);
+ cts.cts_vcol += incr;
}
+ bdp->end_vcol = cts.cts_vcol;
+ pend = (char_u *)cts.cts_ptr;
+ clear_chartabsize_arg(&cts);
+
if (bdp->end_vcol <= oap->end_vcol
&& (!is_del
|| oap->op_type == OP_APPEND
diff --git a/src/nvim/plines.c b/src/nvim/plines.c
index 70bdbd8b1d..f13e83ca9b 100644
--- a/src/nvim/plines.c
+++ b/src/nvim/plines.c
@@ -98,15 +98,15 @@ int plines_win_nofill(win_T *wp, linenr_T lnum, bool winheight)
/// "wp". Does not care about folding, 'wrap' or 'diff'.
int plines_win_nofold(win_T *wp, linenr_T lnum)
{
- char_u *s;
+ char *s;
unsigned int col;
int width;
- s = ml_get_buf(wp->w_buffer, lnum, false);
+ s = (char *)ml_get_buf(wp->w_buffer, lnum, false);
if (*s == NUL) { // empty line
return 1;
}
- col = win_linetabsize(wp, s, MAXCOL);
+ col = win_linetabsize(wp, lnum, (char_u *)s, MAXCOL);
// If list mode is on, then the '$' at the end of the line may take up one
// extra column.
@@ -145,23 +145,27 @@ int plines_win_col(win_T *wp, linenr_T lnum, long column)
}
char_u *line = ml_get_buf(wp->w_buffer, lnum, false);
- char_u *s = line;
colnr_T col = 0;
- while (*s != NUL && --column >= 0) {
- col += win_lbr_chartabsize(wp, line, s, col, NULL);
- MB_PTR_ADV(s);
+ chartabsize_T cts;
+
+ init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
+ while (*cts.cts_ptr != NUL && --column >= 0) {
+ cts.cts_vcol += win_lbr_chartabsize(&cts, NULL);
+ MB_PTR_ADV(cts.cts_ptr);
}
- // If *s is a TAB, and the TAB is not displayed as ^I, and we're not in
- // MODE_INSERT state, then col must be adjusted so that it represents the
+ // If *cts.cts_ptr is a TAB, and the TAB is not displayed as ^I, and we're not
+ // in MODE_INSERT state, then col must be adjusted so that it represents the
// last screen position of the TAB. This only fixes an error when the TAB
// wraps from one screen line to the next (when 'columns' is not a multiple
// of 'ts') -- webb.
- if (*s == TAB && (State & MODE_NORMAL)
+ col = cts.cts_vcol;
+ if (*cts.cts_ptr == TAB && (State & MODE_NORMAL)
&& (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) {
- col += win_lbr_chartabsize(wp, line, s, col, NULL) - 1;
+ col += win_lbr_chartabsize(&cts, NULL) - 1;
}
+ clear_chartabsize_arg(&cts);
// Add column offset for 'number', 'relativenumber', 'foldcolumn', etc.
int width = wp->w_width_inner - win_col_off(wp);
@@ -223,7 +227,7 @@ int plines_m_win(win_T *wp, linenr_T first, linenr_T last)
/// @param col
///
/// @return Number of characters.
-int win_chartabsize(win_T *wp, char_u *p, colnr_T col)
+int win_chartabsize(win_T *wp, char *p, colnr_T col)
{
buf_T *buf = wp->w_buffer;
if (*p == TAB && (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) {
@@ -241,24 +245,24 @@ int win_chartabsize(win_T *wp, char_u *p, colnr_T col)
/// @return Number of characters the string will take on the screen.
int linetabsize(char_u *s)
{
- return linetabsize_col(0, s);
+ return linetabsize_col(0, (char *)s);
}
-/// Like linetabsize(), but starting at column "startcol".
+/// Like linetabsize(), but "s" starts at column "startcol".
///
/// @param startcol
/// @param s
///
/// @return Number of characters the string will take on the screen.
-int linetabsize_col(int startcol, char_u *s)
+int linetabsize_col(int startcol, char *s)
{
- colnr_T col = startcol;
- char_u *line = s; // pointer to start of line, for breakindent
-
- while (*s != NUL) {
- col += lbr_chartabsize_adv(line, &s, col);
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, 0, startcol, (char_u *)s, (char_u *)s);
+ while (*cts.cts_ptr != NUL) {
+ cts.cts_vcol += lbr_chartabsize_adv(&cts);
}
- return (int)col;
+ clear_chartabsize_arg(&cts);
+ return (int)cts.cts_vcol;
}
/// Like linetabsize(), but for a given window instead of the current one.
@@ -268,19 +272,39 @@ int linetabsize_col(int startcol, char_u *s)
/// @param len
///
/// @return Number of characters the string will take on the screen.
-unsigned int win_linetabsize(win_T *wp, char_u *line, colnr_T len)
+unsigned int win_linetabsize(win_T *wp, linenr_T lnum, char_u *line, colnr_T len)
{
- colnr_T col = 0;
-
- for (char_u *s = line;
- *s != NUL && (len == MAXCOL || s < line + len);
- MB_PTR_ADV(s)) {
- col += win_lbr_chartabsize(wp, line, s, col, NULL);
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
+ for (; *cts.cts_ptr != NUL && (len == MAXCOL || cts.cts_ptr < (char *)line + len);
+ MB_PTR_ADV(cts.cts_ptr)) {
+ cts.cts_vcol += win_lbr_chartabsize(&cts, NULL);
}
+ clear_chartabsize_arg(&cts);
+ return (unsigned int)cts.cts_vcol;
+}
- return (unsigned int)col;
+/// Prepare the structure passed to chartabsize functions.
+///
+/// "line" is the start of the line, "ptr" is the first relevant character.
+/// When "lnum" is zero do not use text properties that insert text.
+void init_chartabsize_arg(chartabsize_T *cts, win_T *wp, linenr_T lnum, colnr_T col, char_u *line,
+ char_u *ptr)
+{
+ cts->cts_win = wp;
+ cts->cts_lnum = lnum;
+ cts->cts_vcol = col;
+ cts->cts_line = (char *)line;
+ cts->cts_ptr = (char *)ptr;
+ cts->cts_cur_text_width = 0;
+ // TODO(bfredl): actually lookup inline virtual text here
+ cts->cts_has_virt_text = false;
}
+/// Free any allocated item in "cts".
+void clear_chartabsize_arg(chartabsize_T *cts)
+{}
+
/// like win_chartabsize(), but also check for line breaks on the screen
///
/// @param line
@@ -288,16 +312,16 @@ unsigned int win_linetabsize(win_T *wp, char_u *line, colnr_T len)
/// @param col
///
/// @return The number of characters taken up on the screen.
-int lbr_chartabsize(char_u *line, unsigned char *s, colnr_T col)
+int lbr_chartabsize(chartabsize_T *cts)
{
if (!curwin->w_p_lbr && *get_showbreak_value(curwin) == NUL
- && !curwin->w_p_bri) {
+ && !curwin->w_p_bri && !cts->cts_has_virt_text) {
if (curwin->w_p_wrap) {
- return win_nolbr_chartabsize(curwin, s, col, NULL);
+ return win_nolbr_chartabsize(cts, NULL);
}
- return win_chartabsize(curwin, s, col);
+ return win_chartabsize(curwin, cts->cts_ptr, cts->cts_vcol);
}
- return win_lbr_chartabsize(curwin, line == NULL ? s: line, s, col, NULL);
+ return win_lbr_chartabsize(cts, NULL);
}
/// Call lbr_chartabsize() and advance the pointer.
@@ -307,12 +331,12 @@ int lbr_chartabsize(char_u *line, unsigned char *s, colnr_T col)
/// @param col
///
/// @return The number of characters take up on the screen.
-int lbr_chartabsize_adv(char_u *line, char_u **s, colnr_T col)
+int lbr_chartabsize_adv(chartabsize_T *cts)
{
int retval;
- retval = lbr_chartabsize(line, *s, col);
- MB_PTR_ADV(*s);
+ retval = lbr_chartabsize(cts);
+ MB_PTR_ADV(cts->cts_ptr);
return retval;
}
@@ -322,17 +346,19 @@ int lbr_chartabsize_adv(char_u *line, char_u **s, colnr_T col)
/// string at start of line. Warning: *headp is only set if it's a non-zero
/// value, init to 0 before calling.
///
-/// @param wp
-/// @param line
-/// @param s
-/// @param col
+/// @param cts
/// @param headp
///
/// @return The number of characters taken up on the screen.
-int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *headp)
+int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
{
+ win_T *wp = cts->cts_win;
+ char *line = cts->cts_line; // start of the line
+ char_u *s = (char_u *)cts->cts_ptr;
+ colnr_T vcol = cts->cts_vcol;
+
colnr_T col2;
- colnr_T col_adj = 0; // col + screen size of tab
+ colnr_T col_adj = 0; // vcol + screen size of tab
colnr_T colmax;
int added;
int mb_added = 0;
@@ -340,16 +366,23 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
char_u *ps;
int n;
+ cts->cts_cur_text_width = 0;
+
// No 'linebreak', 'showbreak' and 'breakindent': return quickly.
- if (!wp->w_p_lbr && !wp->w_p_bri && *get_showbreak_value(wp) == NUL) {
+ if (!wp->w_p_lbr && !wp->w_p_bri && *get_showbreak_value(wp) == NUL
+ && !cts->cts_has_virt_text) {
if (wp->w_p_wrap) {
- return win_nolbr_chartabsize(wp, s, col, headp);
+ return win_nolbr_chartabsize(cts, headp);
}
- return win_chartabsize(wp, s, col);
+ return win_chartabsize(wp, (char *)s, vcol);
+ }
+
+ // First get normal size, without 'linebreak' or virtual text
+ int size = win_chartabsize(wp, (char *)s, vcol);
+ if (cts->cts_has_virt_text) {
+ // TODO(bfredl): inline virtual text
}
- // First get normal size, without 'linebreak'
- int size = win_chartabsize(wp, s, col);
int c = *s;
if (*s == TAB) {
col_adj = size - 1;
@@ -365,15 +398,15 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
// Count all characters from first non-blank after a blank up to next
// non-blank after a blank.
numberextra = win_col_off(wp);
- col2 = col;
+ col2 = vcol;
colmax = (colnr_T)(wp->w_width_inner - numberextra - col_adj);
- if (col >= colmax) {
+ if (vcol >= colmax) {
colmax += col_adj;
n = colmax + win_col_off2(wp);
if (n > 0) {
- colmax += (((col - colmax) / n) + 1) * n - col_adj;
+ colmax += (((vcol - colmax) / n) + 1) * n - col_adj;
}
}
@@ -383,21 +416,21 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
c = *s;
if (!(c != NUL
- && (vim_isbreak(c) || col2 == col || !vim_isbreak((int)(*ps))))) {
+ && (vim_isbreak(c) || col2 == vcol || !vim_isbreak((int)(*ps))))) {
break;
}
- col2 += win_chartabsize(wp, s, col2);
+ col2 += win_chartabsize(wp, (char *)s, col2);
if (col2 >= colmax) { // doesn't fit
- size = colmax - col + col_adj;
+ size = colmax - vcol + col_adj;
break;
}
}
} else if ((size == 2)
&& (MB_BYTE2LEN(*s) > 1)
&& wp->w_p_wrap
- && in_win_border(wp, col)) {
+ && in_win_border(wp, vcol)) {
// Count the ">" in the last column.
size++;
mb_added = 1;
@@ -409,40 +442,40 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
added = 0;
char *const sbr = (char *)get_showbreak_value(wp);
- if ((*sbr != NUL || wp->w_p_bri) && wp->w_p_wrap && col != 0) {
+ if ((*sbr != NUL || wp->w_p_bri) && wp->w_p_wrap && vcol != 0) {
colnr_T sbrlen = 0;
int numberwidth = win_col_off(wp);
numberextra = numberwidth;
- col += numberextra + mb_added;
+ vcol += numberextra + mb_added;
- if (col >= (colnr_T)wp->w_width_inner) {
- col -= wp->w_width_inner;
+ if (vcol >= (colnr_T)wp->w_width_inner) {
+ vcol -= wp->w_width_inner;
numberextra = wp->w_width_inner - (numberextra - win_col_off2(wp));
- if (col >= numberextra && numberextra > 0) {
- col %= numberextra;
+ if (vcol >= numberextra && numberextra > 0) {
+ vcol %= numberextra;
}
if (*sbr != NUL) {
sbrlen = (colnr_T)mb_charlen((char_u *)sbr);
- if (col >= sbrlen) {
- col -= sbrlen;
+ if (vcol >= sbrlen) {
+ vcol -= sbrlen;
}
}
- if (col >= numberextra && numberextra > 0) {
- col %= numberextra;
- } else if (col > 0 && numberextra > 0) {
- col += numberwidth - win_col_off2(wp);
+ if (vcol >= numberextra && numberextra > 0) {
+ vcol %= numberextra;
+ } else if (vcol > 0 && numberextra > 0) {
+ vcol += numberwidth - win_col_off2(wp);
}
numberwidth -= win_col_off2(wp);
}
- if (col == 0 || (col + size + sbrlen > (colnr_T)wp->w_width_inner)) {
+ if (vcol == 0 || (vcol + size + sbrlen > (colnr_T)wp->w_width_inner)) {
if (*sbr != NUL) {
if (size + sbrlen + numberwidth > (colnr_T)wp->w_width_inner) {
// Calculate effective window width.
int width = (colnr_T)wp->w_width_inner - sbrlen - numberwidth;
- int prev_width = col ? ((colnr_T)wp->w_width_inner - (sbrlen + col))
+ int prev_width = vcol ? ((colnr_T)wp->w_width_inner - (sbrlen + vcol))
: 0;
if (width <= 0) {
@@ -459,11 +492,11 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
}
if (wp->w_p_bri) {
- added += get_breakindent_win(wp, line);
+ added += get_breakindent_win(wp, (char_u *)line);
}
size += added;
- if (col != 0) {
+ if (vcol != 0) {
added = 0;
}
}
@@ -485,8 +518,11 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
/// @param headp
///
/// @return The number of characters take up on the screen.
-static int win_nolbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp)
+static int win_nolbr_chartabsize(chartabsize_T *cts, int *headp)
{
+ win_T *wp = cts->cts_win;
+ char *s = cts->cts_ptr;
+ colnr_T col = cts->cts_vcol;
int n;
if ((*s == TAB) && (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) {
@@ -498,7 +534,7 @@ static int win_nolbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp)
// Add one cell for a double-width character in the last column of the
// window, displayed with a ">".
- if ((n == 2) && (MB_BYTE2LEN(*s) > 1) && in_win_border(wp, col)) {
+ if ((n == 2) && (MB_BYTE2LEN((uint8_t)(*s)) > 1) && in_win_border(wp, col)) {
if (headp != NULL) {
*headp = 1;
}
diff --git a/src/nvim/plines.h b/src/nvim/plines.h
index 32778b69f1..7b228f3e91 100644
--- a/src/nvim/plines.h
+++ b/src/nvim/plines.h
@@ -3,6 +3,20 @@
#include "nvim/vim.h"
+// Argument for lbr_chartabsize().
+typedef struct {
+ win_T *cts_win;
+ linenr_T cts_lnum; // zero when not using text properties
+ char *cts_line; // start of the line
+ char *cts_ptr; // current position in line
+
+ bool cts_has_virt_text; // true if if a property inserts text
+ int cts_cur_text_width; // width of current inserted text
+ // TODO(bfredl): iterator in to the marktree for scanning virt text
+
+ int cts_vcol; // virtual column at current position
+} chartabsize_T;
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "plines.h.generated.h"
#endif
diff --git a/src/nvim/po/zh_CN.UTF-8.po b/src/nvim/po/zh_CN.UTF-8.po
index 373833fa80..afa2f29029 100644
--- a/src/nvim/po/zh_CN.UTF-8.po
+++ b/src/nvim/po/zh_CN.UTF-8.po
@@ -734,9 +734,9 @@ msgid "E120: Using <SID> not in a script context: %s"
msgstr "E120: <SID> 不能在 script 上下文外使用: %s"
#: ../eval.c:7391
-#, fuzzy, c-format
+#, c-format
msgid "E725: Calling dict function without Dictionary: %s"
-msgstr "E720: Dictionary 中缺少冒号: %s"
+msgstr "E725: 调用字典函数但是没有字典:%s"
#: ../eval.c:7453
#, fuzzy
@@ -766,19 +766,16 @@ msgid "E737: Key already exists: %s"
msgstr "E737: 键已存在: %s"
#: ../eval.c:8692
-#, fuzzy
msgid "extend() argument"
-msgstr "--cmd 参数"
+msgstr "extend() 参数"
#: ../eval.c:8915
-#, fuzzy
msgid "map() argument"
-msgstr "-c 参数"
+msgstr "map() 参数"
#: ../eval.c:8916
-#, fuzzy
msgid "filter() argument"
-msgstr "-c 参数"
+msgstr "filter() 参数"
#: ../eval.c:9229
#, c-format
@@ -849,9 +846,8 @@ msgid "E702: Sort compare function failed"
msgstr "E702: Sort 比较函数失败"
#: ../eval.c:13806
-#, fuzzy
msgid "E882: Uniq compare function failed"
-msgstr "E702: Sort 比较函数失败"
+msgstr "E882: Uniq 比较函数失败"
#: ../eval.c:14085
msgid "(Invalid)"
@@ -864,31 +860,31 @@ msgstr "E677: 写临时文件出错"
#: ../eval.c:16159
#, fuzzy
msgid "E805: Using a Float as a Number"
-msgstr "E745: 将 List 作数字使用"
+msgstr "E805: 将浮点数当做数字使用"
#: ../eval.c:16162
msgid "E703: Using a Funcref as a Number"
-msgstr "E703: 将 Funcref 作数字使用"
+msgstr "E703: 将函数当做数字使用"
#: ../eval.c:16170
msgid "E745: Using a List as a Number"
-msgstr "E745: 将 List 作数字使用"
+msgstr "E745: 将列表当做数字使用"
#: ../eval.c:16173
msgid "E728: Using a Dictionary as a Number"
-msgstr "E728: 将 Dictionary 作数字使用"
+msgstr "E728: 将字典当做数字使用"
#: ../eval.c:16259
msgid "E729: using Funcref as a String"
-msgstr "E729: 将 Funcref 作 String 使用"
+msgstr "E729: 将函数当做字符串使用"
#: ../eval.c:16262
msgid "E730: using List as a String"
-msgstr "E730: 将 List 作 String 使用"
+msgstr "E730: 将列表当做字符串使用"
#: ../eval.c:16265
msgid "E731: using Dictionary as a String"
-msgstr "E731: 将 Dictionary 作 String 使用"
+msgstr "E731: 将字典当做字符串使用"
#: ../eval.c:16619
#, c-format
@@ -3053,11 +3049,11 @@ msgstr "E673: 不兼容的多字节编码和字符集。"
#: ../hardcopy.c:2238
msgid "E674: printmbcharset cannot be empty with multi-byte encoding."
-msgstr "E674: printmbcharset 在多字节编码下不能为空。"
+msgstr "E674: printmbcharset 在多字节编码下不能为空"
#: ../hardcopy.c:2254
msgid "E675: No default font specified for multi-byte printing."
-msgstr "E675: 没有指定多字节打印的默认字体。"
+msgstr "E675: 没有指定多字节打印的默认字体"
#: ../hardcopy.c:2426
msgid "E324: Can't open PostScript output file"
@@ -4204,9 +4200,8 @@ msgstr "E329: 没有菜单 \"%s\""
#. Only a mnemonic or accelerator is not valid.
#: ../menu.c:329
-#, fuzzy
msgid "E792: Empty menu name"
-msgstr "E749: 空的缓冲区"
+msgstr "E792: 空的菜单名称"
#: ../menu.c:340
msgid "E330: Menu path must not lead to a sub-menu"
@@ -4329,9 +4324,8 @@ msgid "E766: Insufficient arguments for printf()"
msgstr "E766: printf() 的参数不足"
#: ../message.c:3119
-#, fuzzy
msgid "E807: Expected Float argument for printf()"
-msgstr "E766: printf() 的参数不足"
+msgstr "E807: 期盼浮点数作为printf()参数"
#: ../message.c:3873
msgid "E767: Too many arguments to printf()"
@@ -5675,9 +5669,9 @@ msgid "E781: .sug file doesn't match .spl file: %s"
msgstr "E781: .sug 文件不能匹配 .spl 文件: %s"
#: ../spell.c:9305
-#, fuzzy, c-format
+#, c-format
msgid "E782: error while reading .sug file: %s"
-msgstr "E47: 读取错误文件失败"
+msgstr "E782: 当读取.sug 文件时错误"
#. This should have been checked when generating the .spl
#. file.
@@ -5867,6 +5861,7 @@ msgstr "E410: 不正确的 :syntax 子命令: %s"
msgid ""
" TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN"
msgstr ""
+" 总 计 计 数 匹 配 最 慢 的 平 均 名 字 模 式"
#: ../syntax.c:6146
msgid "E679: recursive loop loading syncolor.vim"
@@ -6103,14 +6098,13 @@ msgstr "Vim: 读错误,退出中...\n"
#. This happens when the FileChangedRO autocommand changes the
#. * file in a way it becomes shorter.
#: ../undo.c:379
-#, fuzzy
msgid "E881: Line count changed unexpectedly"
-msgstr "E787: 意外地改变了缓冲区"
+msgstr "E881: 行数意外地改变了"
#: ../undo.c:627
-#, fuzzy, c-format
+#, c-format
msgid "E828: Cannot open undo file for writing: %s"
-msgstr "E212: 无法打开并写入文件"
+msgstr "E828: 无法打开撤销文件去写入"
#: ../undo.c:717
#, c-format
diff --git a/src/nvim/po/zh_TW.UTF-8.po b/src/nvim/po/zh_TW.UTF-8.po
index 5da69dfe69..e95b1e2cad 100644
--- a/src/nvim/po/zh_TW.UTF-8.po
+++ b/src/nvim/po/zh_TW.UTF-8.po
@@ -59,19 +59,19 @@ msgstr "無法傳送回應訊息"
#: ../api/private/helpers.c:204
msgid "internal error: unknown option type"
-msgstr ""
+msgstr "內部錯誤: 未知的選項類型"
#: ../buffer.c:92
msgid "[Location List]"
-msgstr ""
+msgstr "[Location 列表]"
#: ../buffer.c:93
msgid "[Quickfix List]"
-msgstr ""
+msgstr "[Quickfix 列表]"
#: ../buffer.c:94
msgid "E855: Autocommands caused command to abort"
-msgstr ""
+msgstr "E855: 自動命令導致命令被停止"
#: ../buffer.c:135
msgid "E82: Cannot allocate any buffer, exiting..."
@@ -349,7 +349,7 @@ msgstr "E103: 緩衝區 \"%s\" 不是在 diff 模式"
#: ../diff.c:2193
msgid "E787: Buffer changed unexpectedly"
-msgstr ""
+msgstr "E787: 意外地改變了緩衝區"
#: ../digraph.c:1598
msgid "E104: Escape not allowed in digraph"
@@ -365,7 +365,7 @@ msgstr "E105: 使用 :loadkeymap "
#: ../digraph.c:1821
msgid "E791: Empty keymap entry"
-msgstr ""
+msgstr "E791: 空的鍵位映射項"
#: ../edit.c:82
msgid " Keyword completion (^N^P)"
@@ -434,11 +434,11 @@ msgstr "已到段落結尾"
#: ../edit.c:101
msgid "E839: Completion function changed window"
-msgstr ""
+msgstr "E839: 補全函式更改了窗口"
#: ../edit.c:102
msgid "E840: Completion function deleted text"
-msgstr ""
+msgstr "E840: 補全函式刪除了文本"
#: ../edit.c:1847
msgid "'dictionary' option is empty"
@@ -556,7 +556,7 @@ msgstr "E118: 函式 %s 的引數過多"
#: ../eval.c:148
#, c-format
msgid "E716: Key not present in Dictionary: %s"
-msgstr ""
+msgstr "E716: 鍵在字典中不存在: %s"
#: ../eval.c:150
#, c-format
@@ -581,7 +581,7 @@ msgstr "E360: 不能用 -f 選項執行 shell"
#: ../eval.c:154
#, c-format
msgid "E734: Wrong variable type for %s="
-msgstr ""
+msgstr "E734: 錯誤的變數類型: %s="
#: ../eval.c:155
#, fuzzy, c-format
@@ -595,19 +595,19 @@ msgstr "E461: 不合法的變數名稱: %s"
#: ../eval.c:157
msgid "E806: using Float as a String"
-msgstr ""
+msgstr "E806: 使用浮點數作為字串"
#: ../eval.c:1830
msgid "E687: Less targets than List items"
-msgstr ""
+msgstr "E687: 目標比列表項數少"
#: ../eval.c:1834
msgid "E688: More targets than List items"
-msgstr ""
+msgstr "E688: 目標比列表項數多"
#: ../eval.c:1906
msgid "Double ; in list of variables"
-msgstr ""
+msgstr "變數列表出現兩個 ;"
#: ../eval.c:2078
#, fuzzy, c-format
@@ -616,23 +616,23 @@ msgstr "E138: 無法寫入 viminfo 檔案 %s !"
#: ../eval.c:2391
msgid "E689: Can only index a List or Dictionary"
-msgstr ""
+msgstr "E689: 只能索引一個列表或者字典"
#: ../eval.c:2396
msgid "E708: [:] must come last"
-msgstr ""
+msgstr "E708: [:] 必須在最後"
#: ../eval.c:2439
msgid "E709: [:] requires a List value"
-msgstr ""
+msgstr "E709: [:] 需要一個列表值"
#: ../eval.c:2674
msgid "E710: List value has more items than target"
-msgstr ""
+msgstr "E710: 列表值的項比目標多"
#: ../eval.c:2678
msgid "E711: List value has not enough items"
-msgstr ""
+msgstr "E711: 列表值沒有足夠多的項"
#: ../eval.c:2867
#, fuzzy
@@ -651,7 +651,7 @@ msgstr "E108: 無此變數: \"%s\""
#: ../eval.c:3333
msgid "E743: variable nested too deep for (un)lock"
-msgstr ""
+msgstr "E743: (un)lock 的變數嵌套過深"
#: ../eval.c:3630
msgid "E109: Missing ':' after '?'"
@@ -659,7 +659,7 @@ msgstr "E109: '?' 後缺少 ':'"
#: ../eval.c:3893
msgid "E691: Can only compare List with List"
-msgstr ""
+msgstr "E691: 只能比較列表和列表"
#: ../eval.c:3895
#, fuzzy
@@ -668,7 +668,7 @@ msgstr "E449: 收到不正確的運算式"
#: ../eval.c:3915
msgid "E735: Can only compare Dictionary with Dictionary"
-msgstr ""
+msgstr "E735: 只能比較字典和字典"
#: ../eval.c:3917
#, fuzzy
@@ -677,7 +677,7 @@ msgstr "E116: 函式 %s 的引數不正確"
#: ../eval.c:3932
msgid "E693: Can only compare Funcref with Funcref"
-msgstr ""
+msgstr "E693: 只能比較Funcref 和 Funcref"
#: ../eval.c:3934
#, fuzzy
@@ -736,7 +736,7 @@ msgstr "E242: 找不到顏色: %s"
#: ../eval.c:6499
#, c-format
msgid "E721: Duplicate key in Dictionary: \"%s\""
-msgstr ""
+msgstr "E721: Dictionary 中出現重複的鍵: \"%s\""
#: ../eval.c:6517
#, fuzzy, c-format
@@ -781,7 +781,7 @@ msgstr "E120: <SID> 不能在 script 本文外使用: %s"
#: ../eval.c:7391
#, c-format
msgid "E725: Calling dict function without Dictionary: %s"
-msgstr ""
+msgstr "E725: 調用字典函式但是沒有字典: %s"
#: ../eval.c:7453
#, fuzzy
@@ -814,16 +814,15 @@ msgstr "E227: %s 的 mapping 已經存在"
#: ../eval.c:8692
msgid "extend() argument"
-msgstr ""
+msgstr "extend() 參數"
#: ../eval.c:8915
-#, fuzzy
msgid "map() argument"
-msgstr "vim [參數] "
+msgstr "map() 參數"
#: ../eval.c:8916
msgid "filter() argument"
-msgstr ""
+msgstr "filter() 參數"
#: ../eval.c:9229
#, c-format
@@ -857,19 +856,19 @@ msgstr "E596: 不正確的字型"
#: ../eval.c:11980
msgid "E726: Stride is zero"
-msgstr ""
+msgstr "E726: 步長為零"
#: ../eval.c:11982
msgid "E727: Start past end"
-msgstr ""
+msgstr "E727: 起始值在終止值後"
#: ../eval.c:12024 ../eval.c:15297
msgid "<empty>"
-msgstr ""
+msgstr "<空>"
#: ../eval.c:12282
msgid "remove() argument"
-msgstr ""
+msgstr "remove() 參數"
#: ../eval.c:12466
msgid "E655: Too many symbolic links (cycle?)"
@@ -877,11 +876,11 @@ msgstr "E655: 太多層的符號鏈結(symlink) (循環?)"
#: ../eval.c:12593
msgid "reverse() argument"
-msgstr ""
+msgstr "reverse() 參數"
#: ../eval.c:13721
msgid "sort() argument"
-msgstr ""
+msgstr "sort() 參數"
#: ../eval.c:13721
#, fuzzy
@@ -895,7 +894,7 @@ msgstr "E237: 無法選擇此印表機"
#: ../eval.c:13806
msgid "E882: Uniq compare function failed"
-msgstr ""
+msgstr "E882: Uniq 比較函式失敗"
#: ../eval.c:14085
msgid "(Invalid)"
@@ -908,32 +907,31 @@ msgstr "E208: 寫入檔案 \"%s\" 錯誤"
#: ../eval.c:16159
msgid "E805: Using a Float as a Number"
-msgstr ""
+msgstr "E805: 將浮點數當做數字使用"
#: ../eval.c:16162
msgid "E703: Using a Funcref as a Number"
-msgstr ""
+msgstr "E703: 將函式當做數字使用"
#: ../eval.c:16170
msgid "E745: Using a List as a Number"
-msgstr ""
+msgstr "E745: 將列表當做數字使用"
#: ../eval.c:16173
msgid "E728: Using a Dictionary as a Number"
-msgstr ""
+msgstr "E728: 將字典當做數字使用"
#: ../eval.c:16259
msgid "E729: using Funcref as a String"
-msgstr ""
+msgstr "E729: 將函式當做字串使用"
#: ../eval.c:16262
-#, fuzzy
msgid "E730: using List as a String"
-msgstr "E374: 格式化字串裡少了 ]"
+msgstr "E730: 將列表當做字串使用"
#: ../eval.c:16265
msgid "E731: using Dictionary as a String"
-msgstr ""
+msgstr "E731: 將字典當做字串使用"
#: ../eval.c:16619
#, fuzzy, c-format
@@ -953,12 +951,12 @@ msgstr "E128: 函式名稱第一個字母必須大寫: %s"
#: ../eval.c:16732
#, c-format
msgid "E705: Variable name conflicts with existing function: %s"
-msgstr ""
+msgstr "E705: 變數名與已有函式名衝突: %s"
#: ../eval.c:16763
#, c-format
msgid "E741: Value is locked: %s"
-msgstr ""
+msgstr "E741: 值已鎖定: %s"
#: ../eval.c:16764 ../eval.c:16769 ../message.c:1839
msgid "Unknown"
@@ -971,7 +969,7 @@ msgstr "E284: 不能設定 IC 數值"
#: ../eval.c:16838
msgid "E698: variable nested too deep for making a copy"
-msgstr ""
+msgstr "E698: 變數嵌套過深無法複製"
#: ../eval.c:17249
#, c-format
@@ -1216,7 +1214,7 @@ msgstr "要覆寫已存在的檔案 \"%.*s\"?"
#: ../ex_cmds.c:2317
#, c-format
msgid "Swap file \"%s\" exists, overwrite anyway?"
-msgstr ""
+msgstr "交換文件 \"%s\" 已存在,確實需要覆蓋嗎?"
#: ../ex_cmds.c:2326
#, fuzzy, c-format
@@ -1456,7 +1454,7 @@ msgstr "%3d %s %s 第 %<PRId64> 行 "
#: ../ex_cmds2.c:942
msgid "E750: First use \":profile start {fname}\""
-msgstr ""
+msgstr "E750: 請先使用 :profile start <fname>"
#: ../ex_cmds2.c:1269
#, fuzzy, c-format
@@ -1555,7 +1553,7 @@ msgstr "vim [參數] "
#: ../ex_cmds2.c:2771
msgid "environment variable"
-msgstr ""
+msgstr "環境變數"
#: ../ex_cmds2.c:2773
#, fuzzy
@@ -2047,7 +2045,7 @@ msgstr "E199: 已刪除掉作用中的視窗或暫存區"
#: ../file_search.c:203
msgid "E854: path too long for completion"
-msgstr ""
+msgstr "E854: 補全用的路徑太長了"
#: ../file_search.c:446
#, c-format
@@ -2099,11 +2097,11 @@ msgstr "[未命名]"
#: ../fileio.c:511
msgid "[New DIRECTORY]"
-msgstr ""
+msgstr "[新目錄]"
#: ../fileio.c:529 ../fileio.c:532
msgid "[File too big]"
-msgstr ""
+msgstr "[文件太大]"
#: ../fileio.c:534
msgid "[Permission Denied]"
@@ -2265,7 +2263,7 @@ msgstr "E513: 無法寫入 -- 轉換失敗"
msgid ""
"E513: write error, conversion failed in line %<PRId64> (make 'fenc' empty to "
"override)"
-msgstr ""
+msgstr "E513: 寫入錯誤,轉換失敗 (請將 'fenc' 置空以強制執行)"
#: ../fileio.c:3448
msgid "E514: write error (file system full?)"
@@ -2720,7 +2718,7 @@ msgstr "E49: 錯誤的捲動大小"
#: ../globals.h:1021
msgid "E901: Job table is full"
-msgstr ""
+msgstr "E901: 任務表已經滿"
#: ../globals.h:1024
#, c-format
@@ -2877,7 +2875,7 @@ msgstr "E42: 沒有錯誤"
#: ../globals.h:1067
msgid "E776: No location list"
-msgstr ""
+msgstr "E776: 沒有位置列表"
#: ../globals.h:1068
msgid "E43: Damaged match string"
@@ -2992,7 +2990,7 @@ msgstr "E473: 內部錯誤"
#: ../globals.h:1104
msgid "E363: pattern uses more memory than 'maxmempattern'"
-msgstr ""
+msgstr "E363: 表達式的內存超出 'maxmempattern'"
#: ../globals.h:1105
#, fuzzy
@@ -3097,15 +3095,15 @@ msgstr "E621: \"%s\" 資源檔版本錯誤"
#: ../hardcopy.c:2225
msgid "E673: Incompatible multi-byte encoding and character set."
-msgstr ""
+msgstr "E673: 不兼容的多字節編碼和字元集"
#: ../hardcopy.c:2238
msgid "E674: printmbcharset cannot be empty with multi-byte encoding."
-msgstr ""
+msgstr "E674: printmbcharset 在多字節編碼下不能為空"
#: ../hardcopy.c:2254
msgid "E675: No default font specified for multi-byte printing."
-msgstr ""
+msgstr "E675: 沒有指定多字節打印的默認字型"
#: ../hardcopy.c:2426
msgid "E324: Can't open PostScript output file"
@@ -3267,6 +3265,7 @@ msgstr "%-5s: %-30s (用法: %s)"
#: ../if_cscope.c:1155
msgid ""
"\n"
+" a: Find assignments to this symbol\n"
" c: Find functions calling this function\n"
" d: Find functions called by this function\n"
" e: Find this egrep pattern\n"
@@ -3276,6 +3275,16 @@ msgid ""
" s: Find this C symbol\n"
" t: Find this text string\n"
msgstr ""
+"\n"
+" a: 搜索對此符號的賦值\n"
+" c: 搜索調用此函式的函式\n"
+" d: 搜索此函式調用的函式\n"
+" e: 搜索此 egrep 模式\n"
+" f: 搜索此文件\n"
+" g: 搜索此定義\n"
+" i: 搜索包含此文件的文件\n"
+" s: 搜索此 C 符号\n"
+" t: 搜索此文本字串\n"
#: ../if_cscope.c:1226
msgid "E568: duplicate cscope database not added"
@@ -3509,7 +3518,7 @@ msgstr "-N\t\t\t'nocompatible' 不完全與傳統 Vi 相容,可使用 Vim 加
#: ../main.c:2215
msgid "-V[N][fname]\t\tBe verbose [level N] [log messages to fname]"
-msgstr ""
+msgstr "-V[N][fname]\t\t詳細 [level N] [log messages to fname]"
#: ../main.c:2216
msgid "-D\t\t\tDebugging mode"
@@ -3602,7 +3611,7 @@ msgstr "-W <scriptout>\t對檔案 <scriptout> 寫入所有輸入的命令"
#: ../main.c:2240
msgid "--startuptime <file>\tWrite startup timing messages to <file>"
-msgstr ""
+msgstr "--startuptime <file>\t將啟動時間寫入到文件 <file>"
#: ../main.c:2242
msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
@@ -3794,7 +3803,7 @@ msgstr ""
#: ../memline.c:945
msgid " has been damaged (page size is smaller than minimum value).\n"
-msgstr ""
+msgstr "已损坏(頁面大小小於最小值)。\n"
#: ../memline.c:974
#, c-format
@@ -4082,7 +4091,7 @@ msgstr "E317: 指標區塊 id 錯 2"
#: ../memline.c:3070
#, c-format
msgid "E773: Symlink loop for \"%s\""
-msgstr ""
+msgstr "E773: \"%s\" 符號鏈接出現循環"
#: ../memline.c:3221
msgid "E325: ATTENTION"
@@ -4231,7 +4240,7 @@ msgstr "E329: 沒有那樣的選單"
#. Only a mnemonic or accelerator is not valid.
#: ../menu.c:329
msgid "E792: Empty menu name"
-msgstr ""
+msgstr "E792: 空的菜單名稱"
#: ../menu.c:340
msgid "E330: Menu path must not lead to a sub-menu"
@@ -4312,7 +4321,7 @@ msgstr "-- 尚有 --"
#: ../message.c:2398
msgid " SPACE/d/j: screen/page/line down, b/u/k: up, q: quit "
-msgstr ""
+msgstr " 空格/d/j: 屏幕/頁/行 下翻,b/u/k: 上翻,q: 退出 "
#: ../message.c:3021 ../message.c:3031
msgid "Question"
@@ -4357,7 +4366,7 @@ msgstr "E116: 函式 %s 的引數不正確"
#: ../message.c:3119
msgid "E807: Expected Float argument for printf()"
-msgstr ""
+msgstr "E807: 期盼浮點數作為printf()參數"
#: ../message.c:3873
#, fuzzy
@@ -4370,11 +4379,11 @@ msgstr "W10: 注意: 你正在修改一個唯讀檔"
#: ../misc1.c:2537
msgid "Type number and <Enter> or click with mouse (empty cancels): "
-msgstr ""
+msgstr "請輸入數字並<Enter>或點擊鼠標(空白取消): "
#: ../misc1.c:2539
msgid "Type number and <Enter> (empty cancels): "
-msgstr ""
+msgstr "請選擇數字並(<Enter> 取消): "
#: ../misc1.c:2585
msgid "1 more line"
@@ -4400,7 +4409,7 @@ msgstr " (已中斷)"
#: ../misc1.c:2635
msgid "Beep!"
-msgstr ""
+msgstr "Beep!"
#: ../misc2.c:738
#, c-format
@@ -4617,7 +4626,7 @@ msgstr "E520: 不能在 Modeline 裡出現"
#: ../option.c:2815
msgid "E846: Key code not set"
-msgstr ""
+msgstr "E846: 未設置鍵位代碼"
#: ../option.c:2924
msgid "E521: Number required after ="
@@ -4642,11 +4651,11 @@ msgstr "E589: 'backupext' 跟 'patchmode' 是一樣的"
#: ../option.c:3964
msgid "E834: Conflicts with value of 'listchars'"
-msgstr ""
+msgstr "E834: 與'listchars'中的值發生衝突"
#: ../option.c:3966
msgid "E835: Conflicts with value of 'fillchars'"
-msgstr ""
+msgstr "E835: 與'fillchars'中的值發生衝突"
#: ../option.c:4163
msgid "E524: Missing colon"
@@ -4884,7 +4893,7 @@ msgstr "E382: 無法寫入,'buftype' 選項已設定"
#: ../quickfix.c:2812
msgid "E683: File name missing or invalid pattern"
-msgstr ""
+msgstr "E683: 缺少文件名或模式無效"
#: ../quickfix.c:2911
#, fuzzy, c-format
@@ -5022,25 +5031,26 @@ msgid ""
"E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be "
"used "
msgstr ""
+"E864: \\%#= 後面只能是0,1,或者2。自動引擎將會被使用"
#: ../regexp_nfa.c:239
msgid "E865: (NFA) Regexp end encountered prematurely"
-msgstr ""
+msgstr "E865: (NFA) 過早的遇到了正則表達式的結尾"
#: ../regexp_nfa.c:240
#, c-format
msgid "E866: (NFA regexp) Misplaced %c"
-msgstr ""
+msgstr "E866: (NFA regexp) %c 放錯了位置"
#: ../regexp_nfa.c:242
#, c-format
msgid "E877: (NFA regexp) Invalid character class: %<PRId64>"
-msgstr ""
+msgstr "E877: (NFA regexp) 不可用的字元類: %<PRId64>"
#: ../regexp_nfa.c:1261
#, c-format
msgid "E867: (NFA) Unknown operator '\\z%c'"
-msgstr ""
+msgstr "E867: (NFA) 未知的操作符 '\\z%c'"
#: ../regexp_nfa.c:1387
#, c-format
@@ -5050,21 +5060,21 @@ msgstr ""
#: ../regexp_nfa.c:1802
#, c-format
msgid "E869: (NFA) Unknown operator '\\@%c'"
-msgstr ""
+msgstr "E869: (NFA) 未知的操作符 '\\%%%c'"
#: ../regexp_nfa.c:1831
msgid "E870: (NFA regexp) Error reading repetition limits"
-msgstr ""
+msgstr "E870: (NFA regexp) 读取重复限制时出错"
#. Can't have a multi follow a multi.
#: ../regexp_nfa.c:1895
msgid "E871: (NFA regexp) Can't have a multi follow a multi !"
-msgstr ""
+msgstr "E871: (NFA regexp) 不能多个跟多个!"
#. Too many `('
#: ../regexp_nfa.c:2037
msgid "E872: (NFA regexp) Too many '('"
-msgstr ""
+msgstr "E872: (NFA regexp) 太多 '('"
#: ../regexp_nfa.c:2042
#, fuzzy
@@ -5073,31 +5083,32 @@ msgstr "E50: 太多 \\z("
#: ../regexp_nfa.c:2066
msgid "E873: (NFA regexp) proper termination error"
-msgstr ""
+msgstr "E873: (NFA regexp) 未適當終止"
#: ../regexp_nfa.c:2599
msgid "E874: (NFA) Could not pop the stack !"
-msgstr ""
+msgstr "E874: (NFA) 無法出棧!"
#: ../regexp_nfa.c:3298
msgid ""
"E875: (NFA regexp) (While converting from postfix to NFA), too many states "
"left on stack"
-msgstr ""
+msgstr "E875: (NFA regexp) (從後綴轉到 NFA 时),棧上遺留了太多狀態"
#: ../regexp_nfa.c:3302
msgid "E876: (NFA regexp) Not enough space to store the whole NFA "
-msgstr ""
+msgstr "E876: (NFA regexp) 沒有足夠的空間存儲NFA "
#: ../regexp_nfa.c:4571 ../regexp_nfa.c:4869
msgid ""
"Could not open temporary log file for writing, displaying on stderr ... "
msgstr ""
+"無法打開臨時日志文件進行寫入,顯示在stderr中..."
#: ../regexp_nfa.c:4840
#, c-format
msgid "(NFA) COULD NOT OPEN %s !"
-msgstr ""
+msgstr "(NFA) 不能打开 %s !"
#: ../regexp_nfa.c:6049
#, fuzzy
@@ -5270,17 +5281,17 @@ msgstr "E297: 暫存檔寫入錯誤"
#: ../spell.c:952
msgid "E758: Truncated spell file"
-msgstr ""
+msgstr "E758: 已截斷的拼寫文件"
#: ../spell.c:953
#, c-format
msgid "Trailing text in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,多餘的後續文本: %s"
#: ../spell.c:954
#, c-format
msgid "Affix name too long in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,附加項名字太長: %s"
#: ../spell.c:955
#, fuzzy
@@ -5289,20 +5300,20 @@ msgstr "E431: Tag 檔 \"%s\" 格式錯誤"
#: ../spell.c:957
msgid "E762: Character in FOL, LOW or UPP is out of range"
-msgstr ""
+msgstr "E762: FOL、LOW 或 UPP 中字元超出範圍"
#: ../spell.c:958
msgid "Compressing word tree..."
-msgstr ""
+msgstr "壓縮單詞樹……"
#: ../spell.c:1951
msgid "E756: Spell checking is not enabled"
-msgstr ""
+msgstr "E756: 拼寫檢查未啟用"
#: ../spell.c:2249
#, c-format
msgid "Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\""
-msgstr ""
+msgstr "警告: 找不到單詞列表 \"%s.%s.spl\" or \"%s.ascii.spl\""
#: ../spell.c:2473
#, fuzzy, c-format
@@ -5316,11 +5327,11 @@ msgstr "E307: %s 看起來不像是 Vim 暫存檔"
#: ../spell.c:2501
msgid "E771: Old spell file, needs to be updated"
-msgstr ""
+msgstr "E771: 舊的拼寫文件,需要更新"
#: ../spell.c:2504
msgid "E772: Spell file is for newer version of Vim"
-msgstr ""
+msgstr "E772: 為更高版本的 Vim 所使用的拼寫文件"
#: ../spell.c:2602
#, fuzzy
@@ -5340,66 +5351,68 @@ msgstr "搜尋 tag 檔案 \"%s\""
#: ../spell.c:4589 ../spell.c:5635 ../spell.c:6140
#, c-format
msgid "Conversion failure for word in %s line %d: %s"
-msgstr ""
+msgstr "單詞 %s 轉換失敗,第 %d 行: %s"
#: ../spell.c:4630 ../spell.c:6170
#, c-format
msgid "Conversion in %s not supported: from %s to %s"
-msgstr ""
+msgstr "不支持 %s 中的轉換: 从 %s 到 %s"
#: ../spell.c:4642
#, c-format
msgid "Invalid value for FLAG in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,FLAG 的值无效: %s"
#: ../spell.c:4655
#, c-format
msgid "FLAG after using flags in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,在使用標志後出現 FLAG: %s"
#: ../spell.c:4723
#, c-format
msgid ""
"Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line "
"%d"
-msgstr ""
+msgstr "在 PFX 項之後定義 COMPOUNDFORBIDFLAG (%s 第%d行)可能會給出的錯誤結果"
+"%d"
#: ../spell.c:4731
#, c-format
msgid ""
"Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line "
"%d"
-msgstr ""
+msgstr "在 PFX 項之後定義 COMPOUNDFORBIDFLAG (%s 第%d行)可能會給出的錯誤結果"
+"%d"
#: ../spell.c:4747
#, c-format
msgid "Wrong COMPOUNDRULES value in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,错误的 COMPOUNDMIN 值: %s"
#: ../spell.c:4771
#, c-format
msgid "Wrong COMPOUNDWORDMAX value in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,错误的 COMPOUNDWORDMAX 值: %s"
#: ../spell.c:4777
#, c-format
msgid "Wrong COMPOUNDMIN value in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,错误的 COMPOUNDMIN 值: %s"
#: ../spell.c:4783
#, c-format
msgid "Wrong COMPOUNDSYLMAX value in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,错误的 COMPOUNDSYLMAX 值: %s"
#: ../spell.c:4795
#, c-format
msgid "Wrong CHECKCOMPOUNDPATTERN value in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,错误的 CHECKCOMPOUNDPATTERN 值: %s"
#: ../spell.c:4847
#, c-format
msgid "Different combining flag in continued affix block in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,在連續的附加塊種出現不同的組合標誌: %s"
#: ../spell.c:4850
#, fuzzy, c-format
@@ -5412,45 +5425,47 @@ msgid ""
"Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST in %s "
"line %d: %s"
msgstr ""
+"%s 第 %d 行,附加項被 BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST 使"
+"用: %s"
#: ../spell.c:4893
#, c-format
msgid "Expected Y or N in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,此處需要 Y 或 N: %s"
#: ../spell.c:4968
#, c-format
msgid "Broken condition in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,錯誤的條件: %s"
#: ../spell.c:5091
#, c-format
msgid "Expected REP(SAL) count in %s line %d"
-msgstr ""
+msgstr "%s 第 %d 行,此處需要 REP(SAL) 計數"
#: ../spell.c:5120
#, c-format
msgid "Expected MAP count in %s line %d"
-msgstr ""
+msgstr "%s 第 %d 行,此處需要 MAP 計數"
#: ../spell.c:5132
#, c-format
msgid "Duplicate character in MAP in %s line %d"
-msgstr ""
+msgstr "%s 第 %d 行,MAP 中存在重複的字元"
#: ../spell.c:5176
#, c-format
msgid "Unrecognized or duplicate item in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,無法識別或重複的項: %s"
#: ../spell.c:5197
#, c-format
msgid "Missing FOL/LOW/UPP line in %s"
-msgstr ""
+msgstr "%s 中缺少 FOL/LOW/UPP 行"
#: ../spell.c:5220
msgid "COMPOUNDSYLMAX used without SYLLABLE"
-msgstr ""
+msgstr "在没有 SYLLABLE 的情況下使用了 COMPOUNDSYLMAX"
#: ../spell.c:5236
#, fuzzy
@@ -5464,32 +5479,32 @@ msgstr "太多編輯參數"
#: ../spell.c:5240
msgid "Too many postponed prefixes and/or compound flags"
-msgstr ""
+msgstr "太多延遲前綴和/或組合標誌"
#: ../spell.c:5250
#, c-format
msgid "Missing SOFO%s line in %s"
-msgstr ""
+msgstr "%s 中缺少 SOFO%s 行"
#: ../spell.c:5253
#, c-format
msgid "Both SAL and SOFO lines in %s"
-msgstr ""
+msgstr "%s 同時出現 SAL 和 SOFO 行"
#: ../spell.c:5331
#, c-format
msgid "Flag is not a number in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,標誌不是數字: %s"
#: ../spell.c:5334
#, c-format
msgid "Illegal flag in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,無效的標誌: %s"
#: ../spell.c:5493 ../spell.c:5501
#, c-format
msgid "%s value differs from what is used in another .aff file"
-msgstr ""
+msgstr "%s 的值與另一個 .aff 文件中使用的值不相同"
#: ../spell.c:5602
#, fuzzy, c-format
@@ -5499,12 +5514,12 @@ msgstr "掃瞄字典: %s"
#: ../spell.c:5611
#, c-format
msgid "E760: No word count in %s"
-msgstr ""
+msgstr "E760: %s 中没有單詞計數"
#: ../spell.c:5669
#, c-format
msgid "line %6d, word %6d - %s"
-msgstr ""
+msgstr "第 %6d 行,第 %6d 个單詞 - %s"
#: ../spell.c:5691
#, fuzzy, c-format
@@ -5514,17 +5529,17 @@ msgstr "每一行都找不到: %s"
#: ../spell.c:5694
#, c-format
msgid "First duplicate word in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,首次出現重複的單詞: %s"
#: ../spell.c:5746
#, c-format
msgid "%d duplicate word(s) in %s"
-msgstr ""
+msgstr "存在 %d 个重複的單詞,在 %s 中"
#: ../spell.c:5748
#, c-format
msgid "Ignored %d word(s) with non-ASCII characters in %s"
-msgstr ""
+msgstr "忽略了含有非 ASCII 字元的 %d 个單詞,在 %s 中"
#: ../spell.c:6115
#, fuzzy, c-format
@@ -5534,42 +5549,42 @@ msgstr "從標準輸入讀取..."
#: ../spell.c:6155
#, c-format
msgid "Duplicate /encoding= line ignored in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %ld 行,重复的 /encoding= 行已被忽略: %s"
#: ../spell.c:6159
#, c-format
msgid "/encoding= line after word ignored in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,单词后的 /encoding= 行已被忽略: %s"
#: ../spell.c:6180
#, c-format
msgid "Duplicate /regions= line ignored in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,重复的 /regions= 行已被忽略: %s"
#: ../spell.c:6185
#, c-format
msgid "Too many regions in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,太多區域: %s"
#: ../spell.c:6198
#, c-format
msgid "/ line ignored in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,/ 行已被忽略: %s"
#: ../spell.c:6224
#, fuzzy, c-format
msgid "Invalid region nr in %s line %d: %s"
-msgstr "E573: 不正確的伺服器 id : %s"
+msgstr "%s 第 %d 行,無效的區域號: %s"
#: ../spell.c:6230
#, c-format
msgid "Unrecognized flags in %s line %d: %s"
-msgstr ""
+msgstr "%s 第 %d 行,不可識別的標誌: %s"
#: ../spell.c:6257
#, c-format
msgid "Ignored %d words with non-ASCII characters"
-msgstr ""
+msgstr "忽略了含有非 ASCII 字元的 %d 个單詞"
#: ../spell.c:6656
#, c-format
@@ -5578,23 +5593,23 @@ msgstr ""
#: ../spell.c:7340
msgid "Reading back spell file..."
-msgstr ""
+msgstr "读取拼寫文件……"
#. Go through the trie of good words, soundfold each word and add it to
#. the soundfold trie.
#: ../spell.c:7357
msgid "Performing soundfolding..."
-msgstr ""
+msgstr "正在 soundfolding……"
#: ../spell.c:7368
#, c-format
msgid "Number of words after soundfolding: %<PRId64>"
-msgstr ""
+msgstr "soundfolding 后的單詞数: %<PRId64>"
#: ../spell.c:7476
#, c-format
msgid "Total number of words: %d"
-msgstr ""
+msgstr "單詞总数: %d"
#: ../spell.c:7655
#, fuzzy, c-format
@@ -5604,11 +5619,11 @@ msgstr "寫入 viminfo 檔案 \"%s\" 中"
#: ../spell.c:7707 ../spell.c:7927
#, c-format
msgid "Estimated runtime memory use: %d bytes"
-msgstr ""
+msgstr "估計運行時的內存用量: %d 位元"
#: ../spell.c:7820
msgid "E751: Output file name must not have region name"
-msgstr ""
+msgstr "E751: 輸出文件不能含有區域名"
#: ../spell.c:7822
#, fuzzy
@@ -5622,7 +5637,7 @@ msgstr "E15: 不正確的運算式: %s"
#: ../spell.c:7907
msgid "Warning: both compounding and NOBREAK specified"
-msgstr ""
+msgstr "警告: 同時指定了 compounding 和 NOBREAK"
#: ../spell.c:7920
#, fuzzy, c-format
@@ -5631,30 +5646,30 @@ msgstr "寫入 viminfo 檔案 \"%s\" 中"
#: ../spell.c:7925
msgid "Done!"
-msgstr ""
+msgstr "完成!"
#: ../spell.c:8034
#, c-format
msgid "E765: 'spellfile' does not have %<PRId64> entries"
-msgstr ""
+msgstr "E765: 'spellfile' 没有 %<PRId64> 項"
#: ../spell.c:8074
#, c-format
msgid "Word '%.*s' removed from %s"
-msgstr ""
+msgstr "从 %s 中删除了單詞"
#: ../spell.c:8117
#, c-format
msgid "Word '%.*s' added to %s"
-msgstr ""
+msgstr "向 %s 中添加了單詞"
#: ../spell.c:8381
msgid "E763: Word characters differ between spell files"
-msgstr ""
+msgstr "E763: 拼寫文件之間的字元不相同"
#: ../spell.c:8684
msgid "Sorry, no suggestions"
-msgstr ""
+msgstr "抱歉,没有建议"
#: ../spell.c:8687
#, fuzzy, c-format
@@ -5671,7 +5686,7 @@ msgstr "將變動存儲至 \"%.*s\"?"
#: ../spell.c:8737
#, c-format
msgid " < \"%.*s\""
-msgstr ""
+msgstr " < \"%.*s\""
#: ../spell.c:8882
#, fuzzy
@@ -5691,28 +5706,28 @@ msgstr "E307: %s 看起來不像是 Vim 暫存檔"
#: ../spell.c:9282
#, c-format
msgid "E779: Old .sug file, needs to be updated: %s"
-msgstr ""
+msgstr "E779: 舊的.sug 文件,需要更新: %s"
#: ../spell.c:9286
#, c-format
msgid "E780: .sug file is for newer version of Vim: %s"
-msgstr ""
+msgstr "E780: .sug 文件適用於較新的 Vim 版本: %s"
#: ../spell.c:9295
#, c-format
msgid "E781: .sug file doesn't match .spl file: %s"
-msgstr ""
+msgstr "E781: .sug 文件不能匹配 .spl 文件: %s"
#: ../spell.c:9305
#, fuzzy, c-format
msgid "E782: error while reading .sug file: %s"
-msgstr "E47: 讀取錯誤檔案失敗"
+msgstr "E782: 當讀取.sug 文件時錯誤"
#. This should have been checked when generating the .spl
#. file.
#: ../spell.c:11575
msgid "E783: duplicate char in MAP entry"
-msgstr ""
+msgstr "E783: MAP 條目中有重複的字元"
#: ../syntax.c:266
msgid "No Syntax items defined for this buffer"
@@ -5894,10 +5909,11 @@ msgstr "E410: 不正確的 :syntax 子命令: %s"
msgid ""
" TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN"
msgstr ""
+" 總 計 計 數 匹 配 最 慢 的 平 均 名 字 模 式"
#: ../syntax.c:6146
msgid "E679: recursive loop loading syncolor.vim"
-msgstr ""
+msgstr "E679: 加載 syncolor.vim 时出現嵌套循環"
#: ../syntax.c:6256
#, c-format
@@ -5975,7 +5991,7 @@ msgstr "E5248: 群組名稱中有不正確的字元"
#: ../syntax.c:7448
msgid "E849: Too many highlight and syntax groups"
-msgstr ""
+msgstr "E849: 高亮和語法組過多"
#: ../tag.c:104
msgid "E555: at bottom of tag stack"
@@ -6083,7 +6099,7 @@ msgstr "E435: 找不到 tag, 用猜的!"
#: ../tag.c:2797
#, c-format
msgid "Duplicate field name: %s"
-msgstr ""
+msgstr "重複的字段名: %s"
#: ../term.c:1442
msgid "' not known. Available builtin terminals are:"
@@ -6131,35 +6147,35 @@ msgstr "Vim: 讀取輸入錯誤,離開中...\n"
#. * file in a way it becomes shorter.
#: ../undo.c:379
msgid "E881: Line count changed unexpectedly"
-msgstr ""
+msgstr "E881: 行數意外地改變了"
#: ../undo.c:627
-#, fuzzy, c-format
+#, c-format
msgid "E828: Cannot open undo file for writing: %s"
-msgstr "E212: 無法以寫入模式開啟"
+msgstr "E828: 無法打開撤銷文件去寫入"
#: ../undo.c:717
#, c-format
msgid "E825: Corrupted undo file (%s): %s"
-msgstr ""
+msgstr "E825: 已損壞的撤銷文件 (%s): %s"
#: ../undo.c:1039
msgid "Cannot write undo file in any directory in 'undodir'"
-msgstr ""
+msgstr "不能寫入撤銷文件到 'undodir' 中的任何文件夾"
#: ../undo.c:1074
#, c-format
msgid "Will not overwrite with undo file, cannot read: %s"
-msgstr ""
+msgstr "不能寫入撤銷文件,不可讀取: %s"
#: ../undo.c:1092
#, c-format
msgid "Will not overwrite, this is not an undo file: %s"
-msgstr ""
+msgstr "不會覆蓋,這不是撤銷文件: %s"
#: ../undo.c:1108
msgid "Skipping undo file write, nothing to undo"
-msgstr ""
+msgstr "跳過撤消文件寫入,沒有可撤消的內容"
#: ../undo.c:1121
#, fuzzy, c-format
@@ -6174,7 +6190,7 @@ msgstr "E297: 暫存檔寫入錯誤"
#: ../undo.c:1280
#, c-format
msgid "Not reading undo file, owner differs: %s"
-msgstr ""
+msgstr "不能讀取撤銷文件,擁有者不同: %s"
#: ../undo.c:1292
#, fuzzy, c-format
@@ -6198,7 +6214,7 @@ msgstr "E484: 無法開啟檔案 %s"
#: ../undo.c:1328
msgid "File contents changed, cannot use undo info"
-msgstr ""
+msgstr "文件內容已經改變,不能使用撤銷信息"
#: ../undo.c:1497
#, fuzzy, c-format
@@ -6207,11 +6223,11 @@ msgstr "結束執行 %s"
#: ../undo.c:1586 ../undo.c:1812
msgid "Already at oldest change"
-msgstr ""
+msgstr "已經在最早的改變"
#: ../undo.c:1597 ../undo.c:1814
msgid "Already at newest change"
-msgstr ""
+msgstr "已經在最新的改變"
#: ../undo.c:1806
#, fuzzy, c-format
@@ -6259,11 +6275,11 @@ msgstr "%<PRId64> 行 %s 過 %d 次"
#: ../undo.c:2228
msgid "before"
-msgstr ""
+msgstr "之前"
#: ../undo.c:2228
msgid "after"
-msgstr ""
+msgstr "之後"
#: ../undo.c:2325
#, fuzzy
@@ -6272,7 +6288,7 @@ msgstr "沒有這個 mapping 對應"
#: ../undo.c:2330
msgid "number changes when saved"
-msgstr ""
+msgstr " 編號 改變 時間 保存"
#: ../undo.c:2360
#, fuzzy, c-format
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 1b548e1f1b..53bb17364e 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -2932,7 +2932,7 @@ static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, boo
}
if (qf_stack_empty(qi) || qf_list_empty(qf_get_curlist(qi))) {
- emsg(_(e_quickfix));
+ emsg(_(e_no_errors));
return;
}
@@ -3111,7 +3111,7 @@ void qf_list(exarg_T *eap)
}
if (qf_stack_empty(qi) || qf_list_empty(qf_get_curlist(qi))) {
- emsg(_(e_quickfix));
+ emsg(_(e_no_errors));
return;
}
@@ -3467,7 +3467,7 @@ void qf_view_result(bool split)
qi = GET_LOC_LIST(curwin);
}
if (qf_list_empty(qf_get_curlist(qi))) {
- emsg(_(e_quickfix));
+ emsg(_(e_no_errors));
return;
}
@@ -4898,7 +4898,7 @@ void ex_cbelow(exarg_T *eap)
|| eap->cmdidx == CMD_cafter) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY;
if (!(curbuf->b_has_qf_entry & buf_has_flag)) {
- emsg(_(e_quickfix));
+ emsg(_(e_no_errors));
return;
}
@@ -4910,7 +4910,7 @@ void ex_cbelow(exarg_T *eap)
qf_list_T *qfl = qf_get_curlist(qi);
// check if the list has valid errors
if (!qf_list_has_valid_entries(qfl)) {
- emsg(_(e_quickfix));
+ emsg(_(e_no_errors));
return;
}
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index b7ec4bf94e..75bd7b4cc1 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -1165,7 +1165,7 @@ static bool reg_match_visual(void)
rex.line = reg_getline(rex.lnum);
rex.input = rex.line + col;
- unsigned int cols_u = win_linetabsize(wp, rex.line, col);
+ unsigned int cols_u = win_linetabsize(wp, rex.reg_firstlnum + rex.lnum, rex.line, col);
assert(cols_u <= MAXCOL);
colnr_T cols = (colnr_T)cols_u;
if (cols < start || cols > end - (*p_sel == 'e')) {
diff --git a/src/nvim/regexp_bt.c b/src/nvim/regexp_bt.c
index d7a4f40ecf..88f0d781af 100644
--- a/src/nvim/regexp_bt.c
+++ b/src/nvim/regexp_bt.c
@@ -3764,6 +3764,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
case RE_VCOL:
if (!re_num_cmp(win_linetabsize(rex.reg_win == NULL
? curwin : rex.reg_win,
+ rex.reg_firstlnum + rex.lnum,
rex.line,
(colnr_T)(rex.input - rex.line)) + 1,
scan)) {
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c
index 554def5b8a..d4db710d93 100644
--- a/src/nvim/regexp_nfa.c
+++ b/src/nvim/regexp_nfa.c
@@ -6910,7 +6910,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
result = col > t->state->val * ts;
}
if (!result) {
- uintmax_t lts = win_linetabsize(wp, rex.line, col);
+ uintmax_t lts = win_linetabsize(wp, rex.reg_firstlnum + rex.lnum, rex.line, col);
assert(t->state->val >= 0);
result = nfa_re_num_cmp((uintmax_t)t->state->val, op, lts + 1);
}
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index a249c2bf50..27bc6303cf 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -341,6 +341,39 @@ func Test_WinScrolled_close_curwin()
call delete('Xtestout')
endfunc
+func Test_WinScrolled_long_wrapped()
+ CheckRunVimInTerminal
+
+ let lines =<< trim END
+ set scrolloff=0
+ let height = winheight(0)
+ let width = winwidth(0)
+ let g:scrolled = 0
+ au WinScrolled * let g:scrolled += 1
+ call setline(1, repeat('foo', height * width))
+ call cursor(1, height * width)
+ END
+ call writefile(lines, 'Xtest_winscrolled_long_wrapped')
+ let buf = RunVimInTerminal('-S Xtest_winscrolled_long_wrapped', {'rows': 6})
+
+ call term_sendkeys(buf, ":echo g:scrolled\<CR>")
+ call WaitForAssert({-> assert_match('^0 ', term_getline(buf, 6))}, 1000)
+
+ call term_sendkeys(buf, 'gj')
+ call term_sendkeys(buf, ":echo g:scrolled\<CR>")
+ call WaitForAssert({-> assert_match('^1 ', term_getline(buf, 6))}, 1000)
+
+ call term_sendkeys(buf, '0')
+ call term_sendkeys(buf, ":echo g:scrolled\<CR>")
+ call WaitForAssert({-> assert_match('^2 ', term_getline(buf, 6))}, 1000)
+
+ call term_sendkeys(buf, '$')
+ call term_sendkeys(buf, ":echo g:scrolled\<CR>")
+ call WaitForAssert({-> assert_match('^3 ', term_getline(buf, 6))}, 1000)
+
+ call delete('Xtest_winscrolled_long_wrapped')
+endfunc
+
func Test_WinClosed()
" Test that the pattern is matched against the closed window's ID, and both
" <amatch> and <afile> are set to it.
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index 517509004a..a5a30b7953 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -2185,4 +2185,44 @@ func Test_wildmenu_pum_disable_while_shown()
set wildoptions& wildmenu&
endfunc
+func Test_setcmdline()
+ func SetText(text, pos)
+ call assert_equal(0, setcmdline(a:text))
+ call assert_equal(a:text, getcmdline())
+ call assert_equal(len(a:text) + 1, getcmdpos())
+
+ call assert_equal(0, setcmdline(a:text, a:pos))
+ call assert_equal(a:text, getcmdline())
+ call assert_equal(a:pos, getcmdpos())
+
+ call assert_fails('call setcmdline("' .. a:text .. '", -1)', 'E487:')
+ call assert_fails('call setcmdline({}, 0)', 'E928:')
+ call assert_fails('call setcmdline("' .. a:text .. '", {})', 'E728:')
+
+ return ''
+ endfunc
+
+ call feedkeys(":\<C-R>=SetText('set rtp?', 2)\<CR>\<CR>", 'xt')
+ call assert_equal('set rtp?', @:)
+
+ " setcmdline() returns 1 when not editing the command line.
+ call assert_equal(1, 'foo'->setcmdline())
+
+ " Called in custom function
+ func CustomComplete(A, L, P)
+ call assert_equal(0, setcmdline("DoCmd "))
+ return "January\nFebruary\nMars\n"
+ endfunc
+
+ com! -nargs=* -complete=custom,CustomComplete DoCmd :
+ call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"DoCmd January February Mars', @:)
+
+ " Called in <expr>
+ cnoremap <expr>a setcmdline('let foo=')
+ call feedkeys(":a\<CR>", 'tx')
+ call assert_equal('let foo=0', @:)
+ cunmap a
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index f6d573d76b..8c9e39570f 100644
--- a/src/nvim/testdir/test_quickfix.vim
+++ b/src/nvim/testdir/test_quickfix.vim
@@ -85,6 +85,12 @@ func s:setup_commands(cchar)
endif
endfunc
+" This must be run before any error lists are created.
+func Test_AA_cc_no_errors()
+ call assert_fails('cc', 'E42:')
+ call assert_fails('ll', 'E42:')
+endfunc
+
" Tests for the :clist and :llist commands
func XlistTests(cchar)
call s:setup_commands(a:cchar)
diff --git a/src/nvim/window.c b/src/nvim/window.c
index ffbb0fa27f..5b8a69f6eb 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -5362,6 +5362,7 @@ void may_trigger_winscrolled(void)
win_T *wp = curwin;
if (wp->w_last_topline != wp->w_topline
|| wp->w_last_leftcol != wp->w_leftcol
+ || wp->w_last_skipcol != wp->w_skipcol
|| wp->w_last_width != wp->w_width
|| wp->w_last_height != wp->w_height) {
char winid[NUMBUFLEN];
@@ -5375,6 +5376,7 @@ void may_trigger_winscrolled(void)
if (win_valid_any_tab(wp)) {
wp->w_last_topline = wp->w_topline;
wp->w_last_leftcol = wp->w_leftcol;
+ wp->w_last_skipcol = wp->w_skipcol;
wp->w_last_width = wp->w_width;
wp->w_last_height = wp->w_height;
}
diff --git a/test/functional/autocmd/winscrolled_spec.lua b/test/functional/autocmd/winscrolled_spec.lua
index 5c1b758961..12b8e7c42d 100644
--- a/test/functional/autocmd/winscrolled_spec.lua
+++ b/test/functional/autocmd/winscrolled_spec.lua
@@ -61,6 +61,20 @@ describe('WinScrolled', function()
eq(3, eval('g:scrolled'))
end)
+ it('is triggered by scrolling on a long wrapped line #19968', function()
+ local height = meths.win_get_height(0)
+ local width = meths.win_get_width(0)
+ meths.buf_set_lines(0, 0, -1, true, {('foo'):rep(height * width)})
+ meths.win_set_cursor(0, {1, height * width - 1})
+ eq(0, eval('g:scrolled'))
+ feed('gj')
+ eq(1, eval('g:scrolled'))
+ feed('0')
+ eq(2, eval('g:scrolled'))
+ feed('$')
+ eq(3, eval('g:scrolled'))
+ end)
+
it('is triggered when the window scrolls in Insert mode', function()
local height = meths.win_get_height(0)
local lines = {}
diff --git a/test/functional/editor/K_spec.lua b/test/functional/editor/K_spec.lua
index 8ad81ac3d6..3b5580540f 100644
--- a/test/functional/editor/K_spec.lua
+++ b/test/functional/editor/K_spec.lua
@@ -1,6 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
-local eq, clear, eval, feed, retry =
- helpers.eq, helpers.clear, helpers.eval, helpers.feed, helpers.retry
+local eq, clear, eval, feed, meths, retry =
+ helpers.eq, helpers.clear, helpers.eval, helpers.feed, helpers.meths, helpers.retry
describe('K', function()
local test_file = 'K_spec_out'
@@ -58,4 +58,11 @@ describe('K', function()
helpers.neq(bufnr, eval('bufnr()'))
end)
+ it('empty string falls back to :help #19298', function()
+ meths.set_option('keywordprg', '')
+ meths.buf_set_lines(0, 0, -1, true, {'doesnotexist'})
+ feed('K')
+ eq('E149: Sorry, no help for doesnotexist', meths.get_vvar('errmsg'))
+ end)
+
end)