vim-patch:9.0.0863: col() and charcol() only work for the current window (#21038)

Problem:    col() and charcol() only work for the current window.
Solution:   Add an optional winid argument. (Yegappan Lakshmanan,
            closes vim/vim#11466, closes vim/vim#11461)

4c8d2f02b3

Cherry-pick test_functions.vim change from patch 8.2.0633.

Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
This commit is contained in:
zeertzjq
2022-11-13 08:29:05 +08:00
committed by GitHub
parent ec449c27fd
commit 849394e4e2
6 changed files with 87 additions and 12 deletions

View File

@@ -78,13 +78,13 @@ chanclose({id} [, {stream}]) Number Closes a channel or one of its streams
chansend({id}, {data}) Number Writes {data} to channel chansend({id}, {data}) Number Writes {data} to channel
char2nr({expr} [, {utf8}]) Number ASCII/UTF-8 value of first char in {expr} char2nr({expr} [, {utf8}]) Number ASCII/UTF-8 value of first char in {expr}
charclass({string}) Number character class of {string} charclass({string}) Number character class of {string}
charcol({expr}) Number column number of cursor or mark charcol({expr} [, {winid}]) Number column number of cursor or mark
charidx({string}, {idx} [, {countcc}]) charidx({string}, {idx} [, {countcc}])
Number char index of byte {idx} in {string} Number char index of byte {idx} in {string}
chdir({dir}) String change current working directory chdir({dir}) String change current working directory
cindent({lnum}) Number C indent for line {lnum} cindent({lnum}) Number C indent for line {lnum}
clearmatches([{win}]) none clear all matches clearmatches([{win}]) none clear all matches
col({expr}) Number column byte index of cursor or mark col({expr} [, {winid}]) Number column byte index of cursor or mark
complete({startcol}, {matches}) none set Insert mode completion complete({startcol}, {matches}) none set Insert mode completion
complete_add({expr}) Number add completion match complete_add({expr}) Number add completion match
complete_check() Number check for key typed during completion complete_check() Number check for key typed during completion
@@ -1089,8 +1089,8 @@ charclass({string}) *charclass()*
Returns 0 if {string} is not a |String|. Returns 0 if {string} is not a |String|.
*charcol()* charcol({expr} [, {winid}]) *charcol()*
charcol({expr}) Same as |col()| but returns the character index of the column Same as |col()| but returns the character index of the column
position given with {expr} instead of the byte position. position given with {expr} instead of the byte position.
Example: Example:
@@ -1172,8 +1172,8 @@ clearmatches([{win}]) *clearmatches()*
Can also be used as a |method|: > Can also be used as a |method|: >
GetWin()->clearmatches() GetWin()->clearmatches()
< <
*col()* col({expr} [, {winid}) *col()*
col({expr}) The result is a Number, which is the byte index of the column The result is a Number, which is the byte index of the column
position given with {expr}. The accepted positions are: position given with {expr}. 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
@@ -1188,6 +1188,8 @@ col({expr}) The result is a Number, which is the byte index of the column
and column number. Most useful when the column is "$", to get and column number. Most useful when the column is "$", to get
the last column of a specific line. When "lnum" or "col" is the last column of a specific line. When "lnum" or "col" is
out of range then col() returns zero. out of range then col() returns zero.
With the optional {winid} argument the values are obtained for
that window instead of the current window.
To get the line number use |line()|. To get both use To get the line number use |line()|. To get both use
|getpos()|. |getpos()|.
For the screen column position use |virtcol()|. For the For the screen column position use |virtcol()|. For the
@@ -1198,7 +1200,8 @@ col({expr}) The result is a Number, which is the byte index of the column
col("$") length of cursor line plus one col("$") length of cursor line plus one
col("'t") column of mark t col("'t") column of mark t
col("'" .. markname) column of mark markname col("'" .. markname) column of mark markname
< The first column is 1. Returns 0 if {expr} is invalid. < The first column is 1. Returns 0 if {expr} is invalid or when
the window with ID {winid} is not found.
For an uppercase mark the column may actually be in another For an uppercase mark the column may actually be in another
buffer. buffer.
For the cursor position, when 'virtualedit' is active, the For the cursor position, when 'virtualedit' is active, the

View File

@@ -73,12 +73,12 @@ return {
chansend={args=2}, chansend={args=2},
char2nr={args={1, 2}, base=1}, char2nr={args={1, 2}, base=1},
charclass={args=1, base=1}, charclass={args=1, base=1},
charcol={args=1, base=1}, charcol={args={1, 2}, base=1},
charidx={args={2, 3}, base=1}, charidx={args={2, 3}, base=1},
chdir={args=1, base=1}, chdir={args=1, base=1},
cindent={args=1, base=1}, cindent={args=1, base=1},
clearmatches={args={0, 1}, base=1}, clearmatches={args={0, 1}, base=1},
col={args=1, base=1}, col={args={1, 2}, base=1},
complete={args=2, base=2}, complete={args=2, base=2},
complete_add={args=1, base=1}, complete_add={args=1, base=1},
complete_check={}, complete_check={},

View File

@@ -846,9 +846,32 @@ static void f_char2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
/// otherwise the byte index of the column. /// otherwise the byte index of the column.
static void get_col(typval_T *argvars, typval_T *rettv, bool charcol) static void get_col(typval_T *argvars, typval_T *rettv, bool charcol)
{ {
if (tv_check_for_string_or_list_arg(argvars, 0) == FAIL
|| tv_check_for_opt_number_arg(argvars, 1) == FAIL) {
return;
}
switchwin_T switchwin;
bool winchanged = false;
if (argvars[1].v_type != VAR_UNKNOWN) {
// use the window specified in the second argument
tabpage_T *tp;
win_T *wp = win_id2wp_tp((int)tv_get_number(&argvars[1]), &tp);
if (wp == NULL || tp == NULL) {
return;
}
if (switch_win_noblock(&switchwin, wp, tp, true) != OK) {
return;
}
check_cursor();
winchanged = true;
}
colnr_T col = 0; colnr_T col = 0;
int fnum = curbuf->b_fnum; int fnum = curbuf->b_fnum;
pos_T *fp = var2fpos(&argvars[0], false, &fnum, charcol); pos_T *fp = var2fpos(&argvars[0], false, &fnum, charcol);
if (fp != NULL && fnum == curbuf->b_fnum) { if (fp != NULL && fnum == curbuf->b_fnum) {
if (fp->col == MAXCOL) { if (fp->col == MAXCOL) {
@@ -876,6 +899,10 @@ static void get_col(typval_T *argvars, typval_T *rettv, bool charcol)
} }
} }
rettv->vval.v_number = col; rettv->vval.v_number = col;
if (winchanged) {
restore_win_noblock(&switchwin, true);
}
} }
/// "charcol()" function /// "charcol()" function

View File

@@ -46,6 +46,8 @@ static char e_non_empty_string_required_for_argument_nr[]
= N_("E1175: Non-empty string required for argument %d"); = N_("E1175: Non-empty string required for argument %d");
static char e_number_required_for_argument_nr[] static char e_number_required_for_argument_nr[]
= N_("E1210: Number required for argument %d"); = N_("E1210: Number required for argument %d");
static char e_string_or_list_required_for_argument_nr[]
= N_("E1222: String or List required for argument %d");
bool tv_in_free_unref_items = false; bool tv_in_free_unref_items = false;
@@ -3880,6 +3882,17 @@ int tv_check_for_opt_number_arg(const typval_T *const args, const int idx)
|| tv_check_for_number_arg(args, idx) != FAIL) ? OK : FAIL; || tv_check_for_number_arg(args, idx) != FAIL) ? OK : FAIL;
} }
/// Give an error and return FAIL unless "args[idx]" is a string or a list.
int tv_check_for_string_or_list_arg(const typval_T *const args, const int idx)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
{
if (args[idx].v_type != VAR_STRING && args[idx].v_type != VAR_LIST) {
semsg(_(e_string_or_list_required_for_argument_nr), idx + 1);
return FAIL;
}
return OK;
}
/// Get the string value of a "stringish" VimL object. /// Get the string value of a "stringish" VimL object.
/// ///
/// @param[in] tv Object to get value of. /// @param[in] tv Object to get value of.

View File

@@ -241,8 +241,9 @@ endfunc
" Test for the charcol() function " Test for the charcol() function
func Test_charcol() func Test_charcol()
call assert_fails('call charcol({})', 'E731:') call assert_fails('call charcol({})', 'E1222:')
call assert_equal(0, charcol(0)) call assert_fails('call charcol(".", [])', 'E1210:')
call assert_fails('call charcol(0)', 'E1222:')
new new
call setline(1, ['', "01\tà4è678", 'Ⅵ', '012345678']) call setline(1, ['', "01\tà4è678", 'Ⅵ', '012345678'])
@@ -298,6 +299,25 @@ func Test_charcol()
call assert_equal([1, 10, 2, 10, 7], g:InsertCurrentCol) call assert_equal([1, 10, 2, 10, 7], g:InsertCurrentCol)
iunmap <F3> iunmap <F3>
" Test for getting the column number in another window.
let winid = win_getid()
new
call win_execute(winid, 'normal 1G')
call assert_equal(1, charcol('.', winid))
call assert_equal(1, charcol('$', winid))
call win_execute(winid, 'normal 2G6l')
call assert_equal(7, charcol('.', winid))
call assert_equal(10, charcol('$', winid))
" calling from another tab page also works
tabnew
call assert_equal(7, charcol('.', winid))
call assert_equal(10, charcol('$', winid))
tabclose
" unknown window ID
call assert_equal(0, charcol('.', 10001))
%bw! %bw!
endfunc endfunc

View File

@@ -1288,6 +1288,9 @@ func Test_col()
call assert_equal(0, col([2, '$'])) call assert_equal(0, col([2, '$']))
call assert_equal(0, col([1, 100])) call assert_equal(0, col([1, 100]))
call assert_equal(0, col([1])) call assert_equal(0, col([1]))
call assert_equal(0, col(v:_null_list))
call assert_fails('let c = col({})', 'E1222:')
call assert_fails('let c = col(".", [])', 'E1210:')
" test for getting the visual start column " test for getting the visual start column
func T() func T()
@@ -1317,6 +1320,15 @@ func Test_col()
call assert_equal(4, col('.')) call assert_equal(4, col('.'))
set virtualedit& set virtualedit&
" Test for getting the column number in another window
let winid = win_getid()
new
call win_execute(winid, 'normal 1G$')
call assert_equal(3, col('.', winid))
call win_execute(winid, 'normal 2G')
call assert_equal(8, col('$', winid))
call assert_equal(0, col('.', 5001))
bw! bw!
endfunc endfunc