forked from aniani/vim
patch 8.2.2324: not easy to get mark en cursor posotion by character count
Problem: Not easy to get mark en cursor posotion by character count.
Solution: Add functions that use character index. (Yegappan Lakshmanan,
closes #7648)
This commit is contained in:
100
src/eval.c
100
src/eval.c
@@ -5053,6 +5053,61 @@ string2float(
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Convert the specified byte index of line 'lnum' in buffer 'buf' to a
|
||||
* character index. Works only for loaded buffers. Returns -1 on failure.
|
||||
* The index of the first character is one.
|
||||
*/
|
||||
int
|
||||
buf_byteidx_to_charidx(buf_T *buf, int lnum, int byteidx)
|
||||
{
|
||||
char_u *str;
|
||||
|
||||
if (buf == NULL || buf->b_ml.ml_mfp == NULL)
|
||||
return -1;
|
||||
|
||||
if (lnum > buf->b_ml.ml_line_count)
|
||||
lnum = buf->b_ml.ml_line_count;
|
||||
|
||||
str = ml_get_buf(buf, lnum, FALSE);
|
||||
if (str == NULL)
|
||||
return -1;
|
||||
|
||||
if (*str == NUL)
|
||||
return 1;
|
||||
|
||||
return mb_charlen_len(str, byteidx + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the specified character index of line 'lnum' in buffer 'buf' to a
|
||||
* byte index. Works only for loaded buffers. Returns -1 on failure. The index
|
||||
* of the first byte and the first character is one.
|
||||
*/
|
||||
int
|
||||
buf_charidx_to_byteidx(buf_T *buf, int lnum, int charidx)
|
||||
{
|
||||
char_u *str;
|
||||
char_u *t;
|
||||
|
||||
if (buf == NULL || buf->b_ml.ml_mfp == NULL)
|
||||
return -1;
|
||||
|
||||
if (lnum > buf->b_ml.ml_line_count)
|
||||
lnum = buf->b_ml.ml_line_count;
|
||||
|
||||
str = ml_get_buf(buf, lnum, FALSE);
|
||||
if (str == NULL)
|
||||
return -1;
|
||||
|
||||
// Convert the character offset to a byte offset
|
||||
t = str;
|
||||
while (*t != NUL && --charidx > 0)
|
||||
t += mb_ptr2len(t);
|
||||
|
||||
return t - str + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate a String variable into a position.
|
||||
* Returns NULL when there is an error.
|
||||
@@ -5061,7 +5116,8 @@ string2float(
|
||||
var2fpos(
|
||||
typval_T *varp,
|
||||
int dollar_lnum, // TRUE when $ is last line
|
||||
int *fnum) // set to fnum for '0, 'A, etc.
|
||||
int *fnum, // set to fnum for '0, 'A, etc.
|
||||
int charcol) // return character column
|
||||
{
|
||||
char_u *name;
|
||||
static pos_T pos;
|
||||
@@ -5083,7 +5139,10 @@ var2fpos(
|
||||
pos.lnum = list_find_nr(l, 0L, &error);
|
||||
if (error || pos.lnum <= 0 || pos.lnum > curbuf->b_ml.ml_line_count)
|
||||
return NULL; // invalid line number
|
||||
len = (long)STRLEN(ml_get(pos.lnum));
|
||||
if (charcol)
|
||||
len = (long)mb_charlen(ml_get(pos.lnum));
|
||||
else
|
||||
len = (long)STRLEN(ml_get(pos.lnum));
|
||||
|
||||
// Get the column number
|
||||
// We accept "$" for the column number: last column.
|
||||
@@ -5118,18 +5177,29 @@ var2fpos(
|
||||
if (name == NULL)
|
||||
return NULL;
|
||||
if (name[0] == '.') // cursor
|
||||
return &curwin->w_cursor;
|
||||
{
|
||||
pos = curwin->w_cursor;
|
||||
if (charcol)
|
||||
pos.col = buf_byteidx_to_charidx(curbuf, pos.lnum, pos.col) - 1;
|
||||
return &pos;
|
||||
}
|
||||
if (name[0] == 'v' && name[1] == NUL) // Visual start
|
||||
{
|
||||
if (VIsual_active)
|
||||
return &VIsual;
|
||||
return &curwin->w_cursor;
|
||||
pos = VIsual;
|
||||
else
|
||||
pos = curwin->w_cursor;
|
||||
if (charcol)
|
||||
pos.col = buf_byteidx_to_charidx(curbuf, pos.lnum, pos.col) - 1;
|
||||
return &pos;
|
||||
}
|
||||
if (name[0] == '\'') // mark
|
||||
{
|
||||
pp = getmark_buf_fnum(curbuf, name[1], FALSE, fnum);
|
||||
if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
|
||||
return NULL;
|
||||
if (charcol)
|
||||
pp->col = buf_byteidx_to_charidx(curbuf, pp->lnum, pp->col) - 1;
|
||||
return pp;
|
||||
}
|
||||
|
||||
@@ -5164,7 +5234,10 @@ var2fpos(
|
||||
else
|
||||
{
|
||||
pos.lnum = curwin->w_cursor.lnum;
|
||||
pos.col = (colnr_T)STRLEN(ml_get_curline());
|
||||
if (charcol)
|
||||
pos.col = (colnr_T)mb_charlen(ml_get_curline());
|
||||
else
|
||||
pos.col = (colnr_T)STRLEN(ml_get_curline());
|
||||
}
|
||||
return &pos;
|
||||
}
|
||||
@@ -5184,7 +5257,8 @@ list2fpos(
|
||||
typval_T *arg,
|
||||
pos_T *posp,
|
||||
int *fnump,
|
||||
colnr_T *curswantp)
|
||||
colnr_T *curswantp,
|
||||
int charcol)
|
||||
{
|
||||
list_T *l = arg->vval.v_list;
|
||||
long i = 0;
|
||||
@@ -5216,6 +5290,18 @@ list2fpos(
|
||||
n = list_find_nr(l, i++, NULL); // col
|
||||
if (n < 0)
|
||||
return FAIL;
|
||||
// If character position is specified, then convert to byte position
|
||||
if (charcol)
|
||||
{
|
||||
buf_T *buf;
|
||||
|
||||
// Get the text for the specified line in a loaded buffer
|
||||
buf = buflist_findnr(fnump == NULL ? curbuf->b_fnum : *fnump);
|
||||
if (buf == NULL || buf->b_ml.ml_mfp == NULL)
|
||||
return FAIL;
|
||||
|
||||
n = buf_charidx_to_byteidx(buf, posp->lnum, n);
|
||||
}
|
||||
posp->col = n;
|
||||
|
||||
n = list_find_nr(l, i, NULL); // off
|
||||
|
||||
406
src/evalfunc.c
406
src/evalfunc.c
@@ -47,6 +47,7 @@ static void f_ceil(typval_T *argvars, typval_T *rettv);
|
||||
#endif
|
||||
static void f_changenr(typval_T *argvars, typval_T *rettv);
|
||||
static void f_char2nr(typval_T *argvars, typval_T *rettv);
|
||||
static void f_charcol(typval_T *argvars, typval_T *rettv);
|
||||
static void f_charidx(typval_T *argvars, typval_T *rettv);
|
||||
static void f_col(typval_T *argvars, typval_T *rettv);
|
||||
static void f_confirm(typval_T *argvars, typval_T *rettv);
|
||||
@@ -87,12 +88,14 @@ static void f_function(typval_T *argvars, typval_T *rettv);
|
||||
static void f_garbagecollect(typval_T *argvars, typval_T *rettv);
|
||||
static void f_get(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getchangelist(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getcharpos(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getcharsearch(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getenv(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getfontname(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getjumplist(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getpid(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getcurpos(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getcursorcharpos(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getpos(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getreg(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getreginfo(typval_T *argvars, typval_T *rettv);
|
||||
@@ -190,7 +193,9 @@ static void f_searchdecl(typval_T *argvars, typval_T *rettv);
|
||||
static void f_searchpair(typval_T *argvars, typval_T *rettv);
|
||||
static void f_searchpairpos(typval_T *argvars, typval_T *rettv);
|
||||
static void f_searchpos(typval_T *argvars, typval_T *rettv);
|
||||
static void f_setcharpos(typval_T *argvars, typval_T *rettv);
|
||||
static void f_setcharsearch(typval_T *argvars, typval_T *rettv);
|
||||
static void f_setcursorcharpos(typval_T *argvars, typval_T *rettv);
|
||||
static void f_setenv(typval_T *argvars, typval_T *rettv);
|
||||
static void f_setfperm(typval_T *argvars, typval_T *rettv);
|
||||
static void f_setpos(typval_T *argvars, typval_T *rettv);
|
||||
@@ -790,6 +795,8 @@ static funcentry_T global_functions[] =
|
||||
ret_number, f_char2nr},
|
||||
{"charclass", 1, 1, FEARG_1, NULL,
|
||||
ret_number, f_charclass},
|
||||
{"charcol", 1, 1, FEARG_1, NULL,
|
||||
ret_number, f_charcol},
|
||||
{"charidx", 2, 3, FEARG_1, NULL,
|
||||
ret_number, f_charidx},
|
||||
{"chdir", 1, 1, FEARG_1, NULL,
|
||||
@@ -928,6 +935,8 @@ static funcentry_T global_functions[] =
|
||||
ret_number, f_getchar},
|
||||
{"getcharmod", 0, 0, 0, NULL,
|
||||
ret_number, f_getcharmod},
|
||||
{"getcharpos", 1, 1, FEARG_1, NULL,
|
||||
ret_list_number, f_getcharpos},
|
||||
{"getcharsearch", 0, 0, 0, NULL,
|
||||
ret_dict_any, f_getcharsearch},
|
||||
{"getcmdline", 0, 0, 0, NULL,
|
||||
@@ -942,6 +951,8 @@ static funcentry_T global_functions[] =
|
||||
ret_list_string, f_getcompletion},
|
||||
{"getcurpos", 0, 1, FEARG_1, NULL,
|
||||
ret_list_number, f_getcurpos},
|
||||
{"getcursorcharpos", 0, 1, FEARG_1, NULL,
|
||||
ret_list_number, f_getcursorcharpos},
|
||||
{"getcwd", 0, 2, FEARG_1, NULL,
|
||||
ret_string, f_getcwd},
|
||||
{"getenv", 1, 1, FEARG_1, NULL,
|
||||
@@ -1394,10 +1405,14 @@ static funcentry_T global_functions[] =
|
||||
ret_void, f_setbufvar},
|
||||
{"setcellwidths", 1, 1, FEARG_1, NULL,
|
||||
ret_void, f_setcellwidths},
|
||||
{"setcharpos", 2, 2, FEARG_2, NULL,
|
||||
ret_number, f_setcharpos},
|
||||
{"setcharsearch", 1, 1, FEARG_1, NULL,
|
||||
ret_void, f_setcharsearch},
|
||||
{"setcmdpos", 1, 1, FEARG_1, NULL,
|
||||
ret_number, f_setcmdpos},
|
||||
{"setcursorcharpos", 1, 3, FEARG_1, NULL,
|
||||
ret_number, f_setcursorcharpos},
|
||||
{"setenv", 2, 2, FEARG_2, NULL,
|
||||
ret_void, f_setenv},
|
||||
{"setfperm", 2, 2, FEARG_1, NULL,
|
||||
@@ -2423,6 +2438,61 @@ f_char2nr(typval_T *argvars, typval_T *rettv)
|
||||
rettv->vval.v_number = tv_get_string(&argvars[0])[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current cursor column and store it in 'rettv'. If 'charcol' is TRUE,
|
||||
* returns the character index of the column. Otherwise, returns the byte index
|
||||
* of the column.
|
||||
*/
|
||||
static void
|
||||
get_col(typval_T *argvars, typval_T *rettv, int charcol)
|
||||
{
|
||||
colnr_T col = 0;
|
||||
pos_T *fp;
|
||||
int fnum = curbuf->b_fnum;
|
||||
|
||||
fp = var2fpos(&argvars[0], FALSE, &fnum, charcol);
|
||||
if (fp != NULL && fnum == curbuf->b_fnum)
|
||||
{
|
||||
if (fp->col == MAXCOL)
|
||||
{
|
||||
// '> can be MAXCOL, get the length of the line then
|
||||
if (fp->lnum <= curbuf->b_ml.ml_line_count)
|
||||
col = (colnr_T)STRLEN(ml_get(fp->lnum)) + 1;
|
||||
else
|
||||
col = MAXCOL;
|
||||
}
|
||||
else
|
||||
{
|
||||
col = fp->col + 1;
|
||||
// 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 = ml_get_cursor();
|
||||
|
||||
if (curwin->w_cursor.coladd >= (colnr_T)chartabsize(p,
|
||||
curwin->w_virtcol - curwin->w_cursor.coladd))
|
||||
{
|
||||
int l;
|
||||
|
||||
if (*p != NUL && p[(l = (*mb_ptr2len)(p))] == NUL)
|
||||
col += l;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rettv->vval.v_number = col;
|
||||
}
|
||||
|
||||
/*
|
||||
* "charcol()" function
|
||||
*/
|
||||
static void
|
||||
f_charcol(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
get_col(argvars, rettv, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* "charidx()" function
|
||||
*/
|
||||
@@ -2497,42 +2567,7 @@ get_optional_window(typval_T *argvars, int idx)
|
||||
static void
|
||||
f_col(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
colnr_T col = 0;
|
||||
pos_T *fp;
|
||||
int fnum = curbuf->b_fnum;
|
||||
|
||||
fp = var2fpos(&argvars[0], FALSE, &fnum);
|
||||
if (fp != NULL && fnum == curbuf->b_fnum)
|
||||
{
|
||||
if (fp->col == MAXCOL)
|
||||
{
|
||||
// '> can be MAXCOL, get the length of the line then
|
||||
if (fp->lnum <= curbuf->b_ml.ml_line_count)
|
||||
col = (colnr_T)STRLEN(ml_get(fp->lnum)) + 1;
|
||||
else
|
||||
col = MAXCOL;
|
||||
}
|
||||
else
|
||||
{
|
||||
col = fp->col + 1;
|
||||
// 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 = ml_get_cursor();
|
||||
|
||||
if (curwin->w_cursor.coladd >= (colnr_T)chartabsize(p,
|
||||
curwin->w_virtcol - curwin->w_cursor.coladd))
|
||||
{
|
||||
int l;
|
||||
|
||||
if (*p != NUL && p[(l = (*mb_ptr2len)(p))] == NUL)
|
||||
col += l;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rettv->vval.v_number = col;
|
||||
get_col(argvars, rettv, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2633,26 +2668,24 @@ f_cosh(typval_T *argvars, typval_T *rettv)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* "cursor(lnum, col)" function, or
|
||||
* "cursor(list)"
|
||||
*
|
||||
* Moves the cursor to the specified line and column.
|
||||
* Returns 0 when the position could be set, -1 otherwise.
|
||||
* Set the cursor position.
|
||||
* If 'charcol' is TRUE, then use the column number as a character offet.
|
||||
* Otherwise use the column number as a byte offset.
|
||||
*/
|
||||
static void
|
||||
f_cursor(typval_T *argvars, typval_T *rettv)
|
||||
set_cursorpos(typval_T *argvars, typval_T *rettv, int charcol)
|
||||
{
|
||||
long line, col;
|
||||
long coladd = 0;
|
||||
int set_curswant = TRUE;
|
||||
|
||||
rettv->vval.v_number = -1;
|
||||
if (argvars[1].v_type == VAR_UNKNOWN)
|
||||
if (argvars[0].v_type == VAR_LIST)
|
||||
{
|
||||
pos_T pos;
|
||||
colnr_T curswant = -1;
|
||||
|
||||
if (list2fpos(argvars, &pos, NULL, &curswant) == FAIL)
|
||||
if (list2fpos(argvars, &pos, NULL, &curswant, charcol) == FAIL)
|
||||
{
|
||||
emsg(_(e_invarg));
|
||||
return;
|
||||
@@ -2666,15 +2699,24 @@ f_cursor(typval_T *argvars, typval_T *rettv)
|
||||
set_curswant = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if ((argvars[0].v_type == VAR_NUMBER ||
|
||||
argvars[0].v_type == VAR_STRING)
|
||||
&& argvars[1].v_type == VAR_NUMBER)
|
||||
{
|
||||
line = tv_get_lnum(argvars);
|
||||
if (line < 0)
|
||||
semsg(_(e_invarg2), tv_get_string(&argvars[0]));
|
||||
col = (long)tv_get_number_chk(&argvars[1], NULL);
|
||||
if (charcol)
|
||||
col = buf_charidx_to_byteidx(curbuf, line, col);
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
coladd = (long)tv_get_number_chk(&argvars[2], NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
emsg(_(e_invarg));
|
||||
return;
|
||||
}
|
||||
if (line < 0 || col < 0 || coladd < 0)
|
||||
return; // type error; errmsg already given
|
||||
if (line > 0)
|
||||
@@ -2693,6 +2735,19 @@ f_cursor(typval_T *argvars, typval_T *rettv)
|
||||
rettv->vval.v_number = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* "cursor(lnum, col)" function, or
|
||||
* "cursor(list)"
|
||||
*
|
||||
* Moves the cursor to the specified line and column.
|
||||
* Returns 0 when the position could be set, -1 otherwise.
|
||||
*/
|
||||
static void
|
||||
f_cursor(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
set_cursorpos(argvars, rettv, FALSE);
|
||||
}
|
||||
|
||||
#ifdef MSWIN
|
||||
/*
|
||||
* "debugbreak()" function
|
||||
@@ -3887,6 +3942,88 @@ f_getchangelist(typval_T *argvars, typval_T *rettv)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
getpos_both(
|
||||
typval_T *argvars,
|
||||
typval_T *rettv,
|
||||
int getcurpos,
|
||||
int charcol)
|
||||
{
|
||||
pos_T *fp = NULL;
|
||||
pos_T pos;
|
||||
win_T *wp = curwin;
|
||||
list_T *l;
|
||||
int fnum = -1;
|
||||
|
||||
if (rettv_list_alloc(rettv) == OK)
|
||||
{
|
||||
l = rettv->vval.v_list;
|
||||
if (getcurpos)
|
||||
{
|
||||
if (argvars[0].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
wp = find_win_by_nr_or_id(&argvars[0]);
|
||||
if (wp != NULL)
|
||||
fp = &wp->w_cursor;
|
||||
}
|
||||
else
|
||||
fp = &curwin->w_cursor;
|
||||
if (fp != NULL && charcol)
|
||||
{
|
||||
pos = *fp;
|
||||
pos.col = buf_byteidx_to_charidx(wp->w_buffer, pos.lnum,
|
||||
pos.col) - 1;
|
||||
fp = &pos;
|
||||
}
|
||||
}
|
||||
else
|
||||
fp = var2fpos(&argvars[0], TRUE, &fnum, charcol);
|
||||
if (fnum != -1)
|
||||
list_append_number(l, (varnumber_T)fnum);
|
||||
else
|
||||
list_append_number(l, (varnumber_T)0);
|
||||
list_append_number(l, (fp != NULL) ? (varnumber_T)fp->lnum
|
||||
: (varnumber_T)0);
|
||||
list_append_number(l, (fp != NULL)
|
||||
? (varnumber_T)(fp->col == MAXCOL ? MAXCOL : fp->col + 1)
|
||||
: (varnumber_T)0);
|
||||
list_append_number(l, (fp != NULL) ? (varnumber_T)fp->coladd :
|
||||
(varnumber_T)0);
|
||||
if (getcurpos)
|
||||
{
|
||||
int save_set_curswant = curwin->w_set_curswant;
|
||||
colnr_T save_curswant = curwin->w_curswant;
|
||||
colnr_T save_virtcol = curwin->w_virtcol;
|
||||
|
||||
if (wp == curwin)
|
||||
update_curswant();
|
||||
list_append_number(l, wp == NULL ? 0 : wp->w_curswant == MAXCOL
|
||||
? (varnumber_T)MAXCOL : (varnumber_T)wp->w_curswant + 1);
|
||||
|
||||
// Do not change "curswant", as it is unexpected that a get
|
||||
// function has a side effect.
|
||||
if (wp == curwin && save_set_curswant)
|
||||
{
|
||||
curwin->w_set_curswant = save_set_curswant;
|
||||
curwin->w_curswant = save_curswant;
|
||||
curwin->w_virtcol = save_virtcol;
|
||||
curwin->w_valid &= ~VALID_VIRTCOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
rettv->vval.v_number = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* "getcharpos()" function
|
||||
*/
|
||||
static void
|
||||
f_getcharpos(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
{
|
||||
getpos_both(argvars, rettv, FALSE, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* "getcharsearch()" function
|
||||
*/
|
||||
@@ -4019,77 +4156,19 @@ f_getpid(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
rettv->vval.v_number = mch_get_pid();
|
||||
}
|
||||
|
||||
static void
|
||||
getpos_both(
|
||||
typval_T *argvars,
|
||||
typval_T *rettv,
|
||||
int getcurpos)
|
||||
{
|
||||
pos_T *fp = NULL;
|
||||
win_T *wp = curwin;
|
||||
list_T *l;
|
||||
int fnum = -1;
|
||||
|
||||
if (rettv_list_alloc(rettv) == OK)
|
||||
{
|
||||
l = rettv->vval.v_list;
|
||||
if (getcurpos)
|
||||
{
|
||||
if (argvars[0].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
wp = find_win_by_nr_or_id(&argvars[0]);
|
||||
if (wp != NULL)
|
||||
fp = &wp->w_cursor;
|
||||
}
|
||||
else
|
||||
fp = &curwin->w_cursor;
|
||||
}
|
||||
else
|
||||
fp = var2fpos(&argvars[0], TRUE, &fnum);
|
||||
if (fnum != -1)
|
||||
list_append_number(l, (varnumber_T)fnum);
|
||||
else
|
||||
list_append_number(l, (varnumber_T)0);
|
||||
list_append_number(l, (fp != NULL) ? (varnumber_T)fp->lnum
|
||||
: (varnumber_T)0);
|
||||
list_append_number(l, (fp != NULL)
|
||||
? (varnumber_T)(fp->col == MAXCOL ? MAXCOL : fp->col + 1)
|
||||
: (varnumber_T)0);
|
||||
list_append_number(l, (fp != NULL) ? (varnumber_T)fp->coladd :
|
||||
(varnumber_T)0);
|
||||
if (getcurpos)
|
||||
{
|
||||
int save_set_curswant = curwin->w_set_curswant;
|
||||
colnr_T save_curswant = curwin->w_curswant;
|
||||
colnr_T save_virtcol = curwin->w_virtcol;
|
||||
|
||||
if (wp == curwin)
|
||||
update_curswant();
|
||||
list_append_number(l, wp == NULL ? 0 : wp->w_curswant == MAXCOL
|
||||
? (varnumber_T)MAXCOL : (varnumber_T)wp->w_curswant + 1);
|
||||
|
||||
// Do not change "curswant", as it is unexpected that a get
|
||||
// function has a side effect.
|
||||
if (wp == curwin && save_set_curswant)
|
||||
{
|
||||
curwin->w_set_curswant = save_set_curswant;
|
||||
curwin->w_curswant = save_curswant;
|
||||
curwin->w_virtcol = save_virtcol;
|
||||
curwin->w_valid &= ~VALID_VIRTCOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
rettv->vval.v_number = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* "getcurpos()" function
|
||||
*/
|
||||
static void
|
||||
f_getcurpos(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
getpos_both(argvars, rettv, TRUE);
|
||||
getpos_both(argvars, rettv, TRUE, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
f_getcursorcharpos(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
getpos_both(argvars, rettv, TRUE, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4098,7 +4177,7 @@ f_getcurpos(typval_T *argvars, typval_T *rettv)
|
||||
static void
|
||||
f_getpos(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
getpos_both(argvars, rettv, FALSE);
|
||||
getpos_both(argvars, rettv, FALSE, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -6183,14 +6262,14 @@ f_line(typval_T *argvars, typval_T *rettv)
|
||||
== OK)
|
||||
{
|
||||
check_cursor();
|
||||
fp = var2fpos(&argvars[0], TRUE, &fnum);
|
||||
fp = var2fpos(&argvars[0], TRUE, &fnum, FALSE);
|
||||
}
|
||||
restore_win_noblock(save_curwin, save_curtab, TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
// use current window
|
||||
fp = var2fpos(&argvars[0], TRUE, &fnum);
|
||||
fp = var2fpos(&argvars[0], TRUE, &fnum, FALSE);
|
||||
|
||||
if (fp != NULL)
|
||||
lnum = fp->lnum;
|
||||
@@ -8065,6 +8144,60 @@ f_searchpos(typval_T *argvars, typval_T *rettv)
|
||||
list_append_number(rettv->vval.v_list, (varnumber_T)n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the cursor or mark position.
|
||||
* If 'charpos' is TRUE, then use the column number as a character offet.
|
||||
* Otherwise use the column number as a byte offset.
|
||||
*/
|
||||
static void
|
||||
set_position(typval_T *argvars, typval_T *rettv, int charpos)
|
||||
{
|
||||
pos_T pos;
|
||||
int fnum;
|
||||
char_u *name;
|
||||
colnr_T curswant = -1;
|
||||
|
||||
rettv->vval.v_number = -1;
|
||||
|
||||
name = tv_get_string_chk(argvars);
|
||||
if (name != NULL)
|
||||
{
|
||||
if (list2fpos(&argvars[1], &pos, &fnum, &curswant, charpos) == OK)
|
||||
{
|
||||
if (pos.col != MAXCOL && --pos.col < 0)
|
||||
pos.col = 0;
|
||||
if ((name[0] == '.' && name[1] == NUL))
|
||||
{
|
||||
// set cursor; "fnum" is ignored
|
||||
curwin->w_cursor = pos;
|
||||
if (curswant >= 0)
|
||||
{
|
||||
curwin->w_curswant = curswant - 1;
|
||||
curwin->w_set_curswant = FALSE;
|
||||
}
|
||||
check_cursor();
|
||||
rettv->vval.v_number = 0;
|
||||
}
|
||||
else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL)
|
||||
{
|
||||
// set mark
|
||||
if (setmark_pos(name[1], &pos, fnum) == OK)
|
||||
rettv->vval.v_number = 0;
|
||||
}
|
||||
else
|
||||
emsg(_(e_invarg));
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* "setcharpos()" function
|
||||
*/
|
||||
static void
|
||||
f_setcharpos(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
set_position(argvars, rettv, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
f_setcharsearch(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
{
|
||||
@@ -8106,6 +8239,15 @@ f_setcharsearch(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "setcursorcharpos" function
|
||||
*/
|
||||
static void
|
||||
f_setcursorcharpos(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
{
|
||||
set_cursorpos(argvars, rettv, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* "setenv()" function
|
||||
*/
|
||||
@@ -8165,41 +8307,7 @@ f_setfperm(typval_T *argvars, typval_T *rettv)
|
||||
static void
|
||||
f_setpos(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
pos_T pos;
|
||||
int fnum;
|
||||
char_u *name;
|
||||
colnr_T curswant = -1;
|
||||
|
||||
rettv->vval.v_number = -1;
|
||||
name = tv_get_string_chk(argvars);
|
||||
if (name != NULL)
|
||||
{
|
||||
if (list2fpos(&argvars[1], &pos, &fnum, &curswant) == OK)
|
||||
{
|
||||
if (pos.col != MAXCOL && --pos.col < 0)
|
||||
pos.col = 0;
|
||||
if (name[0] == '.' && name[1] == NUL)
|
||||
{
|
||||
// set cursor; "fnum" is ignored
|
||||
curwin->w_cursor = pos;
|
||||
if (curswant >= 0)
|
||||
{
|
||||
curwin->w_curswant = curswant - 1;
|
||||
curwin->w_set_curswant = FALSE;
|
||||
}
|
||||
check_cursor();
|
||||
rettv->vval.v_number = 0;
|
||||
}
|
||||
else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL)
|
||||
{
|
||||
// set mark
|
||||
if (setmark_pos(name[1], &pos, fnum) == OK)
|
||||
rettv->vval.v_number = 0;
|
||||
}
|
||||
else
|
||||
emsg(_(e_invarg));
|
||||
}
|
||||
}
|
||||
set_position(argvars, rettv, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -9947,7 +10055,7 @@ f_virtcol(typval_T *argvars, typval_T *rettv)
|
||||
int fnum = curbuf->b_fnum;
|
||||
int len;
|
||||
|
||||
fp = var2fpos(&argvars[0], FALSE, &fnum);
|
||||
fp = var2fpos(&argvars[0], FALSE, &fnum, FALSE);
|
||||
if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count
|
||||
&& fnum == curbuf->b_fnum)
|
||||
{
|
||||
|
||||
@@ -55,8 +55,10 @@ char_u *echo_string_core(typval_T *tv, char_u **tofree, char_u *numbuf, int copy
|
||||
char_u *echo_string(typval_T *tv, char_u **tofree, char_u *numbuf, int copyID);
|
||||
char_u *string_quote(char_u *str, int function);
|
||||
int string2float(char_u *text, float_T *value);
|
||||
pos_T *var2fpos(typval_T *varp, int dollar_lnum, int *fnum);
|
||||
int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp);
|
||||
int buf_byteidx_to_charidx(buf_T *buf, int lnum, int byteidx);
|
||||
int buf_charidx_to_byteidx(buf_T *buf, int lnum, int charidx);
|
||||
pos_T *var2fpos(typval_T *varp, int dollar_lnum, int *fnum, int charcol);
|
||||
int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp, int char_col);
|
||||
int get_env_len(char_u **arg);
|
||||
int get_id_len(char_u **arg);
|
||||
int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose);
|
||||
|
||||
@@ -4201,7 +4201,7 @@ tagstack_push_items(win_T *wp, list_T *l)
|
||||
// parse 'from' for the cursor position before the tag jump
|
||||
if ((di = dict_find(itemdict, (char_u *)"from", -1)) == NULL)
|
||||
continue;
|
||||
if (list2fpos(&di->di_tv, &mark, &fnum, NULL) != OK)
|
||||
if (list2fpos(&di->di_tv, &mark, &fnum, NULL, FALSE) != OK)
|
||||
continue;
|
||||
if ((tagname =
|
||||
dict_get_string(itemdict, (char_u *)"tagname", TRUE)) == NULL)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
" Tests for cursor().
|
||||
" Tests for cursor() and other functions that get/set the cursor position
|
||||
|
||||
func Test_wrong_arguments()
|
||||
call assert_fails('call cursor(1. 3)', 'E474:')
|
||||
@@ -123,4 +123,187 @@ func Test_screenpos_number()
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
func SaveVisualStartCharPos()
|
||||
call add(g:VisualStartPos, getcharpos('v'))
|
||||
return ''
|
||||
endfunc
|
||||
|
||||
" Test for the getcharpos() function
|
||||
func Test_getcharpos()
|
||||
call assert_fails('call getcharpos({})', 'E731:')
|
||||
call assert_equal([0, 0, 0, 0], getcharpos(0))
|
||||
new
|
||||
call setline(1, ['', "01\tà4è678", 'Ⅵ', '012345678'])
|
||||
|
||||
" Test for '.' and '$'
|
||||
normal 1G
|
||||
call assert_equal([0, 1, 1, 0], getcharpos('.'))
|
||||
call assert_equal([0, 4, 1, 0], getcharpos('$'))
|
||||
normal 2G6l
|
||||
call assert_equal([0, 2, 7, 0], getcharpos('.'))
|
||||
normal 3G$
|
||||
call assert_equal([0, 3, 1, 0], getcharpos('.'))
|
||||
normal 4G$
|
||||
call assert_equal([0, 4, 9, 0], getcharpos('.'))
|
||||
|
||||
" Test for a mark
|
||||
normal 2G7lmmgg
|
||||
call assert_equal([0, 2, 8, 0], getcharpos("'m"))
|
||||
delmarks m
|
||||
call assert_equal([0, 0, 0, 0], getcharpos("'m"))
|
||||
|
||||
" Test for the visual start column
|
||||
vnoremap <expr> <F3> SaveVisualStartCharPos()
|
||||
let g:VisualStartPos = []
|
||||
exe "normal 2G6lv$\<F3>ohh\<F3>o\<F3>"
|
||||
call assert_equal([[0, 2, 7, 0], [0, 2, 9, 0], [0, 2, 5, 0]], g:VisualStartPos)
|
||||
call assert_equal([0, 2, 9, 0], getcharpos('v'))
|
||||
let g:VisualStartPos = []
|
||||
exe "normal 3Gv$\<F3>o\<F3>"
|
||||
call assert_equal([[0, 3, 1, 0], [0, 3, 1, 0]], g:VisualStartPos)
|
||||
let g:VisualStartPos = []
|
||||
exe "normal 1Gv$\<F3>o\<F3>"
|
||||
call assert_equal([[0, 1, 1, 0], [0, 1, 1, 0]], g:VisualStartPos)
|
||||
vunmap <F3>
|
||||
|
||||
%bw!
|
||||
endfunc
|
||||
|
||||
" Test for the setcharpos() function
|
||||
func Test_setcharpos()
|
||||
call assert_equal(-1, setcharpos('.', test_null_list()))
|
||||
new
|
||||
call setline(1, ['', "01\tà4è678", 'Ⅵ', '012345678'])
|
||||
call setcharpos('.', [0, 1, 1, 0])
|
||||
call assert_equal([1, 1], [line('.'), col('.')])
|
||||
call setcharpos('.', [0, 2, 7, 0])
|
||||
call assert_equal([2, 9], [line('.'), col('.')])
|
||||
call setcharpos('.', [0, 3, 4, 0])
|
||||
call assert_equal([3, 1], [line('.'), col('.')])
|
||||
call setcharpos('.', [0, 3, 1, 0])
|
||||
call assert_equal([3, 1], [line('.'), col('.')])
|
||||
call setcharpos('.', [0, 4, 0, 0])
|
||||
call assert_equal([4, 1], [line('.'), col('.')])
|
||||
call setcharpos('.', [0, 4, 20, 0])
|
||||
call assert_equal([4, 9], [line('.'), col('.')])
|
||||
|
||||
" Test for mark
|
||||
delmarks m
|
||||
call setcharpos("'m", [0, 2, 9, 0])
|
||||
normal `m
|
||||
call assert_equal([2, 11], [line('.'), col('.')])
|
||||
|
||||
%bw!
|
||||
call assert_equal(-1, setcharpos('.', [10, 3, 1, 0]))
|
||||
endfunc
|
||||
|
||||
func SaveVisualStartCharCol()
|
||||
call add(g:VisualStartCol, charcol('v'))
|
||||
return ''
|
||||
endfunc
|
||||
|
||||
" Test for the charcol() function
|
||||
func Test_charcol()
|
||||
call assert_fails('call charcol({})', 'E731:')
|
||||
call assert_equal(0, charcol(0))
|
||||
new
|
||||
call setline(1, ['', "01\tà4è678", 'Ⅵ', '012345678'])
|
||||
|
||||
" Test for '.' and '$'
|
||||
normal 1G
|
||||
call assert_equal(1, charcol('.'))
|
||||
call assert_equal(1, charcol('$'))
|
||||
normal 2G6l
|
||||
call assert_equal(7, charcol('.'))
|
||||
call assert_equal(10, charcol('$'))
|
||||
normal 3G$
|
||||
call assert_equal(1, charcol('.'))
|
||||
call assert_equal(2, charcol('$'))
|
||||
normal 4G$
|
||||
call assert_equal(9, charcol('.'))
|
||||
call assert_equal(10, charcol('$'))
|
||||
|
||||
" Test for [lnum, '$']
|
||||
call assert_equal(1, charcol([1, '$']))
|
||||
call assert_equal(10, charcol([2, '$']))
|
||||
call assert_equal(2, charcol([3, '$']))
|
||||
call assert_equal(0, charcol([5, '$']))
|
||||
|
||||
" Test for a mark
|
||||
normal 2G7lmmgg
|
||||
call assert_equal(8, charcol("'m"))
|
||||
delmarks m
|
||||
call assert_equal(0, charcol("'m"))
|
||||
|
||||
" Test for the visual start column
|
||||
vnoremap <expr> <F3> SaveVisualStartCharCol()
|
||||
let g:VisualStartCol = []
|
||||
exe "normal 2G6lv$\<F3>ohh\<F3>o\<F3>"
|
||||
call assert_equal([7, 9, 5], g:VisualStartCol)
|
||||
call assert_equal(9, charcol('v'))
|
||||
let g:VisualStartCol = []
|
||||
exe "normal 3Gv$\<F3>o\<F3>"
|
||||
call assert_equal([1, 1], g:VisualStartCol)
|
||||
let g:VisualStartCol = []
|
||||
exe "normal 1Gv$\<F3>o\<F3>"
|
||||
call assert_equal([1, 1], g:VisualStartCol)
|
||||
vunmap <F3>
|
||||
|
||||
%bw!
|
||||
endfunc
|
||||
|
||||
" Test for getcursorcharpos()
|
||||
func Test_getcursorcharpos()
|
||||
call assert_equal(getcursorcharpos(), getcursorcharpos(0))
|
||||
call assert_equal([0, 0, 0, 0, 0], getcursorcharpos(-1))
|
||||
call assert_equal([0, 0, 0, 0, 0], getcursorcharpos(1999))
|
||||
|
||||
new
|
||||
call setline(1, ['', "01\tà4è678", 'Ⅵ', '012345678'])
|
||||
normal 1G9l
|
||||
call assert_equal([0, 1, 1, 0, 1], getcursorcharpos())
|
||||
normal 2G9l
|
||||
call assert_equal([0, 2, 9, 0, 14], getcursorcharpos())
|
||||
normal 3G9l
|
||||
call assert_equal([0, 3, 1, 0, 1], getcursorcharpos())
|
||||
normal 4G9l
|
||||
call assert_equal([0, 4, 9, 0, 9], getcursorcharpos())
|
||||
|
||||
let winid = win_getid()
|
||||
normal 2G5l
|
||||
wincmd w
|
||||
call assert_equal([0, 2, 6, 0, 11], getcursorcharpos(winid))
|
||||
%bw!
|
||||
endfunc
|
||||
|
||||
" Test for setcursorcharpos()
|
||||
func Test_setcursorcharpos()
|
||||
call assert_fails('call setcursorcharpos(test_null_list())', 'E474:')
|
||||
call assert_fails('call setcursorcharpos([1])', 'E474:')
|
||||
call assert_fails('call setcursorcharpos([1, 1, 1, 1, 1])', 'E474:')
|
||||
new
|
||||
call setline(1, ['', "01\tà4è678", 'Ⅵ', '012345678'])
|
||||
normal G
|
||||
call setcursorcharpos([1, 1])
|
||||
call assert_equal([1, 1], [line('.'), col('.')])
|
||||
call setcursorcharpos([2, 7, 0])
|
||||
call assert_equal([2, 9], [line('.'), col('.')])
|
||||
call setcursorcharpos(3, 4)
|
||||
call assert_equal([3, 1], [line('.'), col('.')])
|
||||
call setcursorcharpos([3, 1])
|
||||
call assert_equal([3, 1], [line('.'), col('.')])
|
||||
call setcursorcharpos([4, 0, 0, 0])
|
||||
call assert_equal([4, 1], [line('.'), col('.')])
|
||||
call setcursorcharpos([4, 20])
|
||||
call assert_equal([4, 9], [line('.'), col('.')])
|
||||
normal 1G
|
||||
call setcursorcharpos([100, 100, 100, 100])
|
||||
call assert_equal([4, 9], [line('.'), col('.')])
|
||||
normal 1G
|
||||
call setcursorcharpos('$', 1)
|
||||
call assert_equal([4, 1], [line('.'), col('.')])
|
||||
|
||||
%bw!
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -1579,7 +1579,7 @@ tv_get_lnum(typval_T *argvars)
|
||||
if (lnum <= 0) // no valid number, try using arg like line()
|
||||
{
|
||||
int fnum;
|
||||
pos_T *fp = var2fpos(&argvars[0], TRUE, &fnum);
|
||||
pos_T *fp = var2fpos(&argvars[0], TRUE, &fnum, FALSE);
|
||||
|
||||
if (fp != NULL)
|
||||
lnum = fp->lnum;
|
||||
|
||||
@@ -750,6 +750,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
2324,
|
||||
/**/
|
||||
2323,
|
||||
/**/
|
||||
|
||||
Reference in New Issue
Block a user