vim-patch:8.2.5019: cannot get the first screen column of a character (#23312)

Problem:    Cannot get the first screen column of a character.
Solution:   Let virtcol() optionally return a list. (closes vim/vim#10482,
            closes vim/vim#7964)

0f7a3e1de6

Co-authored-by: LemonBoy <thatlemon@gmail.com>
This commit is contained in:
zeertzjq 2023-04-25 22:22:26 +08:00 committed by GitHub
parent 43c49746d9
commit bfa92d3861
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 17 deletions

View File

@ -546,7 +546,8 @@ undotree() List undo file tree
uniq({list} [, {func} [, {dict}]]) uniq({list} [, {func} [, {dict}]])
List remove adjacent duplicates from a list List remove adjacent duplicates from a list
values({dict}) List values in {dict} values({dict}) List values in {dict}
virtcol({expr}) Number screen column of cursor or mark virtcol({expr} [, {list}]) Number or List
screen column of cursor or mark
virtcol2col({winid}, {lnum}, {col}) virtcol2col({winid}, {lnum}, {col})
Number byte index of a character on screen Number byte index of a character on screen
visualmode([expr]) String last visual mode used visualmode([expr]) String last visual mode used
@ -637,6 +638,7 @@ add({object}, {expr}) *add()*
and({expr}, {expr}) *and()* and({expr}, {expr}) *and()*
Bitwise AND on the two arguments. The arguments are converted Bitwise AND 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 `or()` and `xor()`.
Example: > Example: >
:let flag = and(bits, 0x80) :let flag = and(bits, 0x80)
< Can also be used as a |method|: > < Can also be used as a |method|: >
@ -9070,7 +9072,7 @@ values({dict}) *values()*
Can also be used as a |method|: > Can also be used as a |method|: >
mydict->values() mydict->values()
virtcol({expr}) *virtcol()* virtcol({expr} [, {list}]) *virtcol()*
The result is a Number, which is the screen column of the file The result is a Number, which is the screen column of the file
position given with {expr}. That is, the last screen position position given with {expr}. That is, the last screen position
occupied by the character at that position, when the screen occupied by the character at that position, when the screen
@ -9079,13 +9081,17 @@ virtcol({expr}) *virtcol()*
the <Tab>. For example, for a <Tab> in column 1, with 'ts' the <Tab>. For example, for a <Tab> in column 1, with 'ts'
set to 8, it returns 8. |conceal| is ignored. set to 8, it returns 8. |conceal| is ignored.
For the byte position use |col()|. For the byte position use |col()|.
For the use of {expr} see |col()|. For the use of {expr} see |col()|.
When 'virtualedit' is used {expr} can be [lnum, col, off], where
"off" is the offset in screen columns from the start of the When 'virtualedit' is used {expr} can be [lnum, col, off],
character. E.g., a position within a <Tab> or after the last where "off" is the offset in screen columns from the start of
character. When "off" is omitted zero is used. the character. E.g., a position within a <Tab> or after the
When Virtual editing is active in the current mode, a position last character. When "off" is omitted zero is used. When
beyond the end of the line can be returned. |'virtualedit'| Virtual editing is active in the current mode, a position
beyond the end of the line can be returned. Also see
|'virtualedit'|
The accepted positions are: The accepted positions are:
. the cursor position . the cursor position
$ the end of the cursor line (the result is the $ the end of the cursor line (the result is the
@ -9097,11 +9103,22 @@ virtcol({expr}) *virtcol()*
cursor is the end). When not in Visual mode cursor is the end). When not in Visual mode
returns the cursor position. Differs from |'<| in returns the cursor position. Differs from |'<| in
that it's updated right away. that it's updated right away.
If {list} is present and non-zero then virtcol() returns a List
with the first and last screen position occupied by the
character.
Note that only marks in the current file can be used. Note that only marks in the current file can be used.
Examples: > Examples: >
virtcol(".") with text "foo^Lbar", with cursor on the "^L", returns 5 " With text "foo^Lbar" and cursor on the "^L":
virtcol("$") with text "foo^Lbar", returns 9
virtcol("'t") with text " there", with 't at 'h', returns 6 virtcol(".") " returns 5
virtcol(".", 1) " returns [4, 5]
virtcol("$") " returns 9
" With text " there", with 't at 'h':
virtcol("'t") " returns 6
< The first column is 1. 0 is returned for an error. < The first column is 1. 0 is returned for an error.
A more advanced example that echoes the maximum length of A more advanced example that echoes the maximum length of
all lines: > all lines: >

View File

@ -436,7 +436,7 @@ return {
undotree={}, undotree={},
uniq={args={1, 3}, base=1}, uniq={args={1, 3}, base=1},
values={args=1, base=1}, values={args=1, base=1},
virtcol={args=1, base=1}, virtcol={args={1, 2}, base=1},
virtcol2col={args=3, base=1}, virtcol2col={args=3, base=1},
visualmode={args={0, 1}}, visualmode={args={0, 1}},
wait={args={2,3}}, wait={args={2,3}},

View File

@ -9275,10 +9275,11 @@ static void f_undotree(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
tv_dict_add_list(dict, S_LEN("entries"), u_eval_tree(curbuf->b_u_oldhead)); tv_dict_add_list(dict, S_LEN("entries"), u_eval_tree(curbuf->b_u_oldhead));
} }
/// "virtcol(string)" function /// "virtcol(string, bool)" function
static void f_virtcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) static void f_virtcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{ {
colnr_T vcol = 0; colnr_T vcol_start = 0;
colnr_T vcol_end = 0;
int fnum = curbuf->b_fnum; int fnum = curbuf->b_fnum;
pos_T *fp = var2fpos(&argvars[0], false, &fnum, false); pos_T *fp = var2fpos(&argvars[0], false, &fnum, false);
@ -9293,11 +9294,18 @@ static void f_virtcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
fp->col = (colnr_T)len; fp->col = (colnr_T)len;
} }
} }
getvvcol(curwin, fp, NULL, NULL, &vcol); getvvcol(curwin, fp, &vcol_start, NULL, &vcol_end);
vcol++; vcol_start++;
vcol_end++;
} }
rettv->vval.v_number = vcol; if (argvars[1].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[1])) {
tv_list_alloc_ret(rettv, 2);
tv_list_append_number(rettv->vval.v_list, vcol_start);
tv_list_append_number(rettv->vval.v_list, vcol_end);
} else {
rettv->vval.v_number = vcol_end;
}
} }
/// "visualmode()" function /// "visualmode()" function

View File

@ -2607,4 +2607,15 @@ func Test_builtin_check()
endfunc endfunc
" Test for virtcol()
func Test_virtcol()
enew!
call setline(1, "the\tquick\tbrown\tfox")
norm! 4|
call assert_equal(8, virtcol('.'))
call assert_equal(8, virtcol('.', v:false))
call assert_equal([4, 8], virtcol('.', v:true))
bwipe!
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab