1
0
forked from aniani/vim

patch 8.2.5034: there is no way to get the byte index from a virtual column

Problem:    There is no way to get the byte index from a virtual column.
Solution:   Add virtcol2col(). (Yegappan Lakshmanan, closes #10477,
            closes #10098)
This commit is contained in:
Bram Moolenaar
2022-05-27 21:58:00 +01:00
parent 968443efb5
commit 5a6ec10cc8
7 changed files with 89 additions and 0 deletions

View File

@@ -691,6 +691,8 @@ uniq({list} [, {func} [, {dict}]])
values({dict}) List values in {dict} values({dict}) List values in {dict}
virtcol({expr} [, {list}]) Number or List virtcol({expr} [, {list}]) Number or List
screen column of cursor or mark screen column of cursor or mark
virtcol2col({winid}, {lnum}, {col})
Number byte index of a character on screen
visualmode([expr]) String last visual mode used visualmode([expr]) String last visual mode used
wildmenumode() Number whether 'wildmenu' mode is active wildmenumode() Number whether 'wildmenu' mode is active
win_execute({id}, {command} [, {silent}]) win_execute({id}, {command} [, {silent}])
@@ -6211,11 +6213,17 @@ nr2char({expr} [, {utf8}]) *nr2char()*
or({expr}, {expr}) *or()* or({expr}, {expr}) *or()*
Bitwise OR on the two arguments. The arguments are converted Bitwise OR on the two arguments. The arguments are converted
to a number. A List, Dict or Float argument causes an error. to a number. A List, Dict or Float argument causes an error.
Also see `and()` and `xor()`.
Example: > Example: >
:let bits = or(bits, 0x80) :let bits = or(bits, 0x80)
< Can also be used as a |method|: > < Can also be used as a |method|: >
:let bits = bits->or(0x80) :let bits = bits->or(0x80)
< Rationale: The reason this is a function and not using the "|"
character like many languages, is that Vi has always used "|"
to separate commands. In many places it would not be clear if
"|" is an operator or a command separator.
pathshorten({path} [, {len}]) *pathshorten()* pathshorten({path} [, {len}]) *pathshorten()*
Shorten directory names in the path {path} and return the Shorten directory names in the path {path} and return the
@@ -9788,6 +9796,25 @@ virtcol({expr} [, {list}]) *virtcol()*
< Can also be used as a |method|: > < Can also be used as a |method|: >
GetPos()->virtcol() GetPos()->virtcol()
virtcol2col({winid}, {lnum}, {col}) *virtcol2col()*
The result is a Number, which is the byte index of the
character in window {winid} at buffer line {lnum} and virtual
column {col}.
If {col} is greater than the last virtual column in line
{lnum}, then the byte index of the character at the last
virtual column is returned.
The {winid} argument can be the window number or the
|window-ID|. If this is zero, then the current window is used.
Returns -1 if the window {winid} doesn't exist or the buffer
line {lnum} or virtual column {col} is invalid.
See also |screenpos()|, |virtcol()| and |col()|.
Can also be used as a |method|: >
GetWinid()->virtcol2col(lnum, col)
visualmode([{expr}]) *visualmode()* visualmode([{expr}]) *visualmode()*
The result is a String, which describes the last Visual mode The result is a String, which describes the last Visual mode
@@ -10220,6 +10247,7 @@ writefile({object}, {fname} [, {flags}])
xor({expr}, {expr}) *xor()* xor({expr}, {expr}) *xor()*
Bitwise XOR on the two arguments. The arguments are converted Bitwise XOR on the two arguments. The arguments are converted
to a number. A List, Dict or Float argument causes an error. to a number. A List, Dict or Float argument causes an error.
Also see `and()` and `or()`.
Example: > Example: >
:let bits = xor(bits, 0x80) :let bits = xor(bits, 0x80)
< <

View File

@@ -835,6 +835,7 @@ Cursor and mark position: *cursor-functions* *mark-functions*
screencol() get screen column of the cursor screencol() get screen column of the cursor
screenrow() get screen row of the cursor screenrow() get screen row of the cursor
screenpos() screen row and col of a text character screenpos() screen row and col of a text character
virtcol2col() byte index of a text character on screen
getcurpos() get position of the cursor getcurpos() get position of the cursor
getpos() get position of cursor, mark, etc. getpos() get position of cursor, mark, etc.
setpos() set position of cursor, mark, etc. setpos() set position of cursor, mark, etc.

View File

@@ -2682,6 +2682,8 @@ static funcentry_T global_functions[] =
ret_list_any, f_values}, ret_list_any, f_values},
{"virtcol", 1, 2, FEARG_1, arg2_string_or_list_bool, {"virtcol", 1, 2, FEARG_1, arg2_string_or_list_bool,
ret_virtcol, f_virtcol}, ret_virtcol, f_virtcol},
{"virtcol2col", 3, 3, FEARG_1, arg3_number,
ret_number, f_virtcol2col},
{"visualmode", 0, 1, 0, arg1_bool, {"visualmode", 0, 1, 0, arg1_bool,
ret_string, f_visualmode}, ret_string, f_visualmode},
{"wildmenumode", 0, 0, 0, NULL, {"wildmenumode", 0, 0, 0, NULL,

View File

@@ -1322,6 +1322,39 @@ f_screenpos(typval_T *argvars UNUSED, typval_T *rettv)
dict_add_number(dict, "curscol", ccol); dict_add_number(dict, "curscol", ccol);
dict_add_number(dict, "endcol", ecol); dict_add_number(dict, "endcol", ecol);
} }
/*
* "virtcol2col({winid}, {lnum}, {col})" function
*/
void
f_virtcol2col(typval_T *argvars UNUSED, typval_T *rettv)
{
win_T *wp;
linenr_T lnum;
int screencol;
int error = FALSE;
rettv->vval.v_number = -1;
if (check_for_number_arg(argvars, 0) == FAIL
|| check_for_number_arg(argvars, 1) == FAIL
|| check_for_number_arg(argvars, 2) == FAIL)
return;
wp = find_win_by_nr_or_id(&argvars[0]);
if (wp == NULL)
return;
lnum = tv_get_number_chk(&argvars[1], &error);
if (error || lnum < 0 || lnum > wp->w_buffer->b_ml.ml_line_count)
return;
screencol = tv_get_number_chk(&argvars[2], &error);
if (error || screencol < 0)
return;
rettv->vval.v_number = vcol2col(wp, lnum, screencol);
}
#endif #endif
/* /*

View File

@@ -30,6 +30,7 @@ int curwin_col_off2(void);
void curs_columns(int may_scroll); void curs_columns(int may_scroll);
void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, int *ccolp, int *ecolp); void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, int *ccolp, int *ecolp);
void f_screenpos(typval_T *argvars, typval_T *rettv); void f_screenpos(typval_T *argvars, typval_T *rettv);
void f_virtcol2col(typval_T *argvars, typval_T *rettv);
void scrolldown(long line_count, int byfold); void scrolldown(long line_count, int byfold);
void scrollup(long line_count, int byfold); void scrollup(long line_count, int byfold);
void check_topfill(win_T *wp, int down); void check_topfill(win_T *wp, int down);

View File

@@ -419,4 +419,26 @@ func Test_setcursorcharpos()
%bw! %bw!
endfunc endfunc
" Test for virtcol2col()
func Test_virtcol2col()
new
call setline(1, ["a\tb\tc"])
call assert_equal(1, virtcol2col(0, 1, 1))
call assert_equal(2, virtcol2col(0, 1, 2))
call assert_equal(2, virtcol2col(0, 1, 8))
call assert_equal(3, virtcol2col(0, 1, 9))
call assert_equal(4, virtcol2col(0, 1, 10))
call assert_equal(4, virtcol2col(0, 1, 16))
call assert_equal(5, virtcol2col(0, 1, 17))
call assert_equal(-1, virtcol2col(10, 1, 1))
call assert_equal(-1, virtcol2col(0, 10, 1))
call assert_equal(-1, virtcol2col(0, -1, 1))
call assert_equal(-1, virtcol2col(0, 1, -1))
call assert_equal(5, virtcol2col(0, 1, 20))
call assert_fails('echo virtcol2col("0", 1, 20)', 'E1210:')
call assert_fails('echo virtcol2col(0, "1", 20)', 'E1210:')
call assert_fails('echo virtcol2col(0, 1, "1")', 'E1210:')
bw!
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -734,6 +734,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
5034,
/**/ /**/
5033, 5033,
/**/ /**/