Merge pull request #20163 from zeertzjq/vim-8.2.5034

vim-patch:8.2.5034: there is no way to get the byte index from a virtual column
This commit is contained in:
zeertzjq 2022-09-12 18:10:13 +08:00 committed by GitHub
commit 2ea6584a1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 127 additions and 27 deletions

View File

@ -526,6 +526,8 @@ 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}) Number 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
wait({timeout}, {condition} [, {interval}]) wait({timeout}, {condition} [, {interval}])
Number Wait until {condition} is satisfied Number Wait until {condition} is satisfied
@ -5620,12 +5622,19 @@ nvim_...({...}) *E5555* *nvim_...()* *eval-api*
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)
pathshorten({expr} [, {len}]) *pathshorten()* < 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()*
Shorten directory names in the path {path} and return the Shorten directory names in the path {path} and return the
result. The tail, the file name, is kept as-is. The other result. The tail, the file name, is kept as-is. The other
components in the path are reduced to {len} letters in length. components in the path are reduced to {len} letters in length.
@ -8831,6 +8840,26 @@ virtcol({expr}) *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
used in the current buffer. Initially it returns an empty used in the current buffer. Initially it returns an empty
@ -9262,6 +9291,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

@ -745,6 +745,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

@ -425,6 +425,7 @@ return {
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, base=1},
virtcol2col={args=3, base=1},
visualmode={args={0, 1}}, visualmode={args={0, 1}},
wait={args={2,3}}, wait={args={2,3}},
wildmenumode={}, wildmenumode={},

View File

@ -7057,32 +7057,6 @@ static void f_screencol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->vval.v_number = ui_current_col() + 1; rettv->vval.v_number = ui_current_col() + 1;
} }
/// "screenpos({winid}, {lnum}, {col})" function
static void f_screenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_alloc_ret(rettv);
dict_T *dict = rettv->vval.v_dict;
win_T *wp = find_win_by_nr_or_id(&argvars[0]);
if (wp == NULL) {
return;
}
pos_T pos = {
.lnum = (linenr_T)tv_get_number(&argvars[1]),
.col = (colnr_T)tv_get_number(&argvars[2]) - 1,
.coladd = 0
};
int row = 0;
int scol = 0, ccol = 0, ecol = 0;
textpos2screenpos(wp, &pos, &row, &scol, &ccol, &ecol, false);
tv_dict_add_nr(dict, S_LEN("row"), row);
tv_dict_add_nr(dict, S_LEN("col"), scol);
tv_dict_add_nr(dict, S_LEN("curscol"), ccol);
tv_dict_add_nr(dict, S_LEN("endcol"), ecol);
}
/// "screenrow()" function /// "screenrow()" function
static void f_screenrow(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) static void f_screenrow(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{ {

View File

@ -44,6 +44,8 @@ static char e_string_required_for_argument_nr[]
= N_("E1174: String required for argument %d"); = N_("E1174: String required for argument %d");
static char e_non_empty_string_required_for_argument_nr[] static char e_non_empty_string_required_for_argument_nr[]
= N_("E1142: Non-empty string required for argument %d"); = N_("E1142: Non-empty string required for argument %d");
static char e_number_required_for_argument_nr[]
= N_("E1210: Number required for argument %d");
bool tv_in_free_unref_items = false; bool tv_in_free_unref_items = false;
@ -3830,6 +3832,17 @@ int tv_check_for_nonempty_string_arg(const typval_T *const args, const int idx)
return OK; return OK;
} }
/// Give an error and return FAIL unless "args[idx]" is a number.
int tv_check_for_number_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_NUMBER) {
semsg(_(e_number_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

@ -21,12 +21,15 @@
#include "nvim/diff.h" #include "nvim/diff.h"
#include "nvim/drawscreen.h" #include "nvim/drawscreen.h"
#include "nvim/edit.h" #include "nvim/edit.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
#include "nvim/fold.h" #include "nvim/fold.h"
#include "nvim/getchar.h" #include "nvim/getchar.h"
#include "nvim/grid.h" #include "nvim/grid.h"
#include "nvim/highlight.h" #include "nvim/highlight.h"
#include "nvim/mbyte.h" #include "nvim/mbyte.h"
#include "nvim/memline.h" #include "nvim/memline.h"
#include "nvim/mouse.h"
#include "nvim/move.h" #include "nvim/move.h"
#include "nvim/option.h" #include "nvim/option.h"
#include "nvim/plines.h" #include "nvim/plines.h"
@ -977,6 +980,62 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, int *ccolp,
*ecolp = ecol + coloff; *ecolp = ecol + coloff;
} }
/// "screenpos({winid}, {lnum}, {col})" function
void f_screenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_alloc_ret(rettv);
dict_T *dict = rettv->vval.v_dict;
win_T *wp = find_win_by_nr_or_id(&argvars[0]);
if (wp == NULL) {
return;
}
pos_T pos = {
.lnum = (linenr_T)tv_get_number(&argvars[1]),
.col = (colnr_T)tv_get_number(&argvars[2]) - 1,
.coladd = 0
};
int row = 0;
int scol = 0, ccol = 0, ecol = 0;
textpos2screenpos(wp, &pos, &row, &scol, &ccol, &ecol, false);
tv_dict_add_nr(dict, S_LEN("row"), row);
tv_dict_add_nr(dict, S_LEN("col"), scol);
tv_dict_add_nr(dict, S_LEN("curscol"), ccol);
tv_dict_add_nr(dict, S_LEN("endcol"), ecol);
}
/// "virtcol2col({winid}, {lnum}, {col})" function
void f_virtcol2col(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = -1;
if (tv_check_for_number_arg(argvars, 0) == FAIL
|| tv_check_for_number_arg(argvars, 1) == FAIL
|| tv_check_for_number_arg(argvars, 2) == FAIL) {
return;
}
win_T *wp = find_win_by_nr_or_id(&argvars[0]);
if (wp == NULL) {
return;
}
bool error = false;
linenr_T lnum = (linenr_T)tv_get_number_chk(&argvars[1], &error);
if (error || lnum < 0 || lnum > wp->w_buffer->b_ml.ml_line_count) {
return;
}
int screencol = (int)tv_get_number_chk(&argvars[2], &error);
if (error || screencol < 0) {
return;
}
rettv->vval.v_number = vcol2col(wp, lnum, screencol);
}
/// Scroll the current window down by "line_count" logical lines. "CTRL-Y" /// Scroll the current window down by "line_count" logical lines. "CTRL-Y"
/// ///
/// @param line_count number of lines to scroll /// @param line_count number of lines to scroll

View File

@ -373,4 +373,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