Merge pull request #21149 from zeertzjq/vim-9.0.0916

vim-patch:8.2.{2435,2479},9.0.0916
This commit is contained in:
zeertzjq
2022-11-22 07:55:08 +08:00
committed by GitHub
8 changed files with 80 additions and 27 deletions

View File

@@ -170,6 +170,7 @@ get({func}, {what}) any get property of funcref/partial {func}
getbufinfo([{buf}]) List information about buffers getbufinfo([{buf}]) List information about buffers
getbufline({buf}, {lnum} [, {end}]) getbufline({buf}, {lnum} [, {end}])
List lines {lnum} to {end} of buffer {buf} List lines {lnum} to {end} of buffer {buf}
getbufoneline({buf}, {lnum}) String line {lnum} of buffer {buf}
getbufvar({buf}, {varname} [, {def}]) getbufvar({buf}, {varname} [, {def}])
any variable {varname} in buffer {buf} any variable {varname} in buffer {buf}
getchangelist([{buf}]) List list of change list items getchangelist([{buf}]) List list of change list items
@@ -638,6 +639,7 @@ append({lnum}, {text}) *append()*
text line below line {lnum} in the current buffer. text line below line {lnum} in the current buffer.
Otherwise append {text} as one text line below line {lnum} in Otherwise append {text} as one text line below line {lnum} in
the current buffer. the current buffer.
Any type of item is accepted and converted to a String.
{lnum} can be zero to insert a line before the first one. {lnum} can be zero to insert a line before the first one.
{lnum} is used like with |getline()|. {lnum} is used like with |getline()|.
Returns 1 for failure ({lnum} out of range or out of memory), Returns 1 for failure ({lnum} out of range or out of memory),
@@ -2684,11 +2686,13 @@ getbufinfo([{dict}])
Can also be used as a |method|: > Can also be used as a |method|: >
GetBufnr()->getbufinfo() GetBufnr()->getbufinfo()
< <
*getbufline()* *getbufline()*
getbufline({buf}, {lnum} [, {end}]) getbufline({buf}, {lnum} [, {end}])
Return a |List| with the lines starting from {lnum} to {end} Return a |List| with the lines starting from {lnum} to {end}
(inclusive) in the buffer {buf}. If {end} is omitted, a (inclusive) in the buffer {buf}. If {end} is omitted, a
|List| with only the line {lnum} is returned. |List| with only the line {lnum} is returned. See
`getbufoneline()` for only getting the line.
For the use of {buf}, see |bufname()| above. For the use of {buf}, see |bufname()| above.
@@ -2711,6 +2715,11 @@ getbufline({buf}, {lnum} [, {end}])
< Can also be used as a |method|: > < Can also be used as a |method|: >
GetBufnr()->getbufline(lnum) GetBufnr()->getbufline(lnum)
<
*getbufoneline()*
getbufoneline({buf}, {lnum})
Just like `getbufline()` but only get one line and return it
as a string.
getbufvar({buf}, {varname} [, {def}]) *getbufvar()* getbufvar({buf}, {varname} [, {def}]) *getbufvar()*
The result is the value of option or local buffer variable The result is the value of option or local buffer variable
@@ -3198,7 +3207,8 @@ getline({lnum} [, {end}])
< Can also be used as a |method|: > < Can also be used as a |method|: >
ComputeLnum()->getline() ComputeLnum()->getline()
< To get lines from another buffer see |getbufline()| < To get lines from another buffer see |getbufline()| and
|getbufoneline()|
getloclist({nr} [, {what}]) *getloclist()* getloclist({nr} [, {what}]) *getloclist()*
Returns a |List| with all the entries in the location list for Returns a |List| with all the entries in the location list for
@@ -7054,6 +7064,8 @@ setline({lnum}, {text}) *setline()*
{lnum} is used like with |getline()|. {lnum} is used like with |getline()|.
When {lnum} is just below the last line the {text} will be When {lnum} is just below the last line the {text} will be
added below the last line. added below the last line.
{text} can be any type or a List of any type, each item is
converted to a String.
If this succeeds, FALSE is returned. If this fails (most likely If this succeeds, FALSE is returned. If this fails (most likely
because {lnum} is invalid) TRUE is returned. because {lnum} is invalid) TRUE is returned.

View File

@@ -229,13 +229,13 @@ is not available it returns zero or the default value you specify: >
List concatenation ~ List concatenation ~
*list-concatenation*
Two lists can be concatenated with the "+" operator: > Two lists can be concatenated with the "+" operator: >
:let longlist = mylist + [5, 6] :let longlist = mylist + [5, 6]
:let mylist += [7, 8] :let mylist += [7, 8]
To prepend or append an item turn the item into a list by putting [] around To prepend or append an item, turn the item into a list by putting [] around
it. To change a list in-place see |list-modification| below. it. To change a list in-place, refer to |list-modification| below.
Sublist ~ Sublist ~

View File

@@ -785,6 +785,13 @@ Working with text in the current buffer: *text-functions*
getcharsearch() return character search information getcharsearch() return character search information
setcharsearch() set character search information setcharsearch() set character search information
Working with text in another buffer:
getbufline() get a list of lines from the specified buffer
getbufoneline() get a one line from the specified buffer
setbufline() replace a line in the specified buffer
appendbufline() append a list of lines in the specified buffer
deletebufline() delete lines from a specified buffer
*system-functions* *file-functions* *system-functions* *file-functions*
System functions and manipulation of files: System functions and manipulation of files:
glob() expand wildcards glob() expand wildcards
@@ -838,8 +845,10 @@ Buffers, windows and the argument list:
argidx() current position in the argument list argidx() current position in the argument list
arglistid() get id of the argument list arglistid() get id of the argument list
argv() get one entry from the argument list argv() get one entry from the argument list
bufadd() add a file to the list of buffers
bufexists() check if a buffer exists bufexists() check if a buffer exists
buflisted() check if a buffer exists and is listed buflisted() check if a buffer exists and is listed
bufload() ensure a buffer is loaded
bufloaded() check if a buffer exists and is loaded bufloaded() check if a buffer exists and is loaded
bufname() get the name of a specific buffer bufname() get the name of a specific buffer
bufnr() get the buffer number of a specific buffer bufnr() get the buffer number of a specific buffer
@@ -850,10 +859,6 @@ Buffers, windows and the argument list:
bufwinid() get the window ID of a specific buffer bufwinid() get the window ID of a specific buffer
bufwinnr() get the window number of a specific buffer bufwinnr() get the window number of a specific buffer
winbufnr() get the buffer number of a specific window winbufnr() get the buffer number of a specific window
getbufline() get a list of lines from the specified buffer
setbufline() replace a line in the specified buffer
appendbufline() append a list of lines in the specified buffer
deletebufline() delete lines from a specified buffer
win_findbuf() find windows containing a buffer win_findbuf() find windows containing a buffer
win_getid() get window ID of a window win_getid() get window ID of a window
win_gettype() get type of window win_gettype() get type of window

View File

@@ -808,26 +808,26 @@ static linenr_T debuggy_find(bool file, char_u *fname, linenr_T after, garray_T
typval_T *const tv = eval_expr_no_emsg(bp); typval_T *const tv = eval_expr_no_emsg(bp);
if (tv != NULL) { if (tv != NULL) {
if (bp->dbg_val == NULL) { if (bp->dbg_val == NULL) {
debug_oldval = typval_tostring(NULL); debug_oldval = typval_tostring(NULL, true);
bp->dbg_val = tv; bp->dbg_val = tv;
debug_newval = typval_tostring(bp->dbg_val); debug_newval = typval_tostring(bp->dbg_val, true);
line = true; line = true;
} else { } else {
if (typval_compare(tv, bp->dbg_val, EXPR_IS, false) == OK if (typval_compare(tv, bp->dbg_val, EXPR_IS, false) == OK
&& tv->vval.v_number == false) { && tv->vval.v_number == false) {
line = true; line = true;
debug_oldval = typval_tostring(bp->dbg_val); debug_oldval = typval_tostring(bp->dbg_val, true);
// Need to evaluate again, typval_compare() overwrites "tv". // Need to evaluate again, typval_compare() overwrites "tv".
typval_T *const v = eval_expr_no_emsg(bp); typval_T *const v = eval_expr_no_emsg(bp);
debug_newval = typval_tostring(v); debug_newval = typval_tostring(v, true);
tv_free(bp->dbg_val); tv_free(bp->dbg_val);
bp->dbg_val = v; bp->dbg_val = v;
} }
tv_free(tv); tv_free(tv);
} }
} else if (bp->dbg_val != NULL) { } else if (bp->dbg_val != NULL) {
debug_oldval = typval_tostring(bp->dbg_val); debug_oldval = typval_tostring(bp->dbg_val, true);
debug_newval = typval_tostring(NULL); debug_newval = typval_tostring(NULL, true);
tv_free(bp->dbg_val); tv_free(bp->dbg_val);
bp->dbg_val = NULL; bp->dbg_val = NULL;
line = true; line = true;

View File

@@ -5592,9 +5592,9 @@ void screenchar_adjust(ScreenGrid **grid, int *row, int *col)
*col -= (*grid)->comp_col; *col -= (*grid)->comp_col;
} }
/// Set line or list of lines in buffer "buf". /// Set line or list of lines in buffer "buf" to "lines".
void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, const typval_T *lines, /// Any type is allowed and converted to a string.
typval_T *rettv) void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, typval_T *lines, typval_T *rettv)
FUNC_ATTR_NONNULL_ARG(4, 5) FUNC_ATTR_NONNULL_ARG(4, 5)
{ {
linenr_T lnum = lnum_arg + (append ? 1 : 0); linenr_T lnum = lnum_arg + (append ? 1 : 0);
@@ -5632,7 +5632,7 @@ void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, const typval_T
list_T *l = NULL; list_T *l = NULL;
listitem_T *li = NULL; listitem_T *li = NULL;
const char *line = NULL; char *line = NULL;
if (lines->v_type == VAR_LIST) { if (lines->v_type == VAR_LIST) {
l = lines->vval.v_list; l = lines->vval.v_list;
if (l == NULL || tv_list_len(l) == 0) { if (l == NULL || tv_list_len(l) == 0) {
@@ -5644,7 +5644,7 @@ void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, const typval_T
} }
li = tv_list_first(l); li = tv_list_first(l);
} else { } else {
line = tv_get_string_chk(lines); line = typval_tostring(lines, false);
} }
// Default result is zero == OK. // Default result is zero == OK.
@@ -5654,7 +5654,8 @@ void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, const typval_T
if (li == NULL) { if (li == NULL) {
break; break;
} }
line = tv_get_string_chk(TV_LIST_ITEM_TV(li)); xfree(line);
line = typval_tostring(TV_LIST_ITEM_TV(li), false);
li = TV_LIST_ITEM_NEXT(l, li); li = TV_LIST_ITEM_NEXT(l, li);
} }
@@ -5674,7 +5675,7 @@ void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, const typval_T
// Existing line, replace it. // Existing line, replace it.
int old_len = (int)strlen(ml_get(lnum)); int old_len = (int)strlen(ml_get(lnum));
if (u_savesub(lnum) == OK if (u_savesub(lnum) == OK
&& ml_replace(lnum, (char *)line, true) == OK) { && ml_replace(lnum, line, true) == OK) {
inserted_bytes(lnum, 0, old_len, (int)strlen(line)); inserted_bytes(lnum, 0, old_len, (int)strlen(line));
if (is_curbuf && lnum == curwin->w_cursor.lnum) { if (is_curbuf && lnum == curwin->w_cursor.lnum) {
check_cursor_col(); check_cursor_col();
@@ -5684,7 +5685,7 @@ void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, const typval_T
} else if (added > 0 || u_save(lnum - 1, lnum) == OK) { } else if (added > 0 || u_save(lnum - 1, lnum) == OK) {
// append the line. // append the line.
added++; added++;
if (ml_append(lnum - 1, (char *)line, 0, false) == OK) { if (ml_append(lnum - 1, line, 0, false) == OK) {
rettv->vval.v_number = 0; // OK rettv->vval.v_number = 0; // OK
} }
} }
@@ -5694,6 +5695,7 @@ void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, const typval_T
} }
lnum++; lnum++;
} }
xfree(line);
if (added > 0) { if (added > 0) {
appended_lines_mark(append_lnum, added); appended_lines_mark(append_lnum, added);
@@ -8965,10 +8967,16 @@ int typval_compare(typval_T *typ1, typval_T *typ2, exprtype_T type, bool ic)
return OK; return OK;
} }
char *typval_tostring(typval_T *arg) /// Convert any type to a string, never give an error.
/// When "quotes" is true add quotes to a string.
/// Returns an allocated string.
char *typval_tostring(typval_T *arg, bool quotes)
{ {
if (arg == NULL) { if (arg == NULL) {
return xstrdup("(does not exist)"); return xstrdup("(does not exist)");
} }
if (!quotes && arg->v_type == VAR_STRING) {
return xstrdup(arg->vval.v_string == NULL ? "" : arg->vval.v_string);
}
return encode_tv2string(arg, NULL); return encode_tv2string(arg, NULL);
} }

View File

@@ -146,6 +146,7 @@ return {
get={args={2, 3}, base=1}, get={args={2, 3}, base=1},
getbufinfo={args={0, 1}, base=1}, getbufinfo={args={0, 1}, base=1},
getbufline={args={2, 3}, base=1}, getbufline={args={2, 3}, base=1},
getbufoneline={args=2, base=1},
getbufvar={args={2, 3}, base=1}, getbufvar={args={2, 3}, base=1},
getchangelist={args={0, 1}, base=1}, getchangelist={args={0, 1}, base=1},
getchar={args={0, 1}}, getchar={args={0, 1}},

View File

@@ -2671,8 +2671,9 @@ static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retli
} }
} }
/// "getbufline()" function /// @param retlist true: "getbufline()" function
static void f_getbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// false: "getbufoneline()" function
static void getbufline(typval_T *argvars, typval_T *rettv, bool retlist)
{ {
const int did_emsg_before = did_emsg; const int did_emsg_before = did_emsg;
buf_T *const buf = tv_get_buf_from_arg(&argvars[0]); buf_T *const buf = tv_get_buf_from_arg(&argvars[0]);
@@ -2684,7 +2685,19 @@ static void f_getbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
? lnum ? lnum
: tv_get_lnum_buf(&argvars[2], buf)); : tv_get_lnum_buf(&argvars[2], buf));
get_buffer_lines(buf, lnum, end, true, rettv); get_buffer_lines(buf, lnum, end, retlist, rettv);
}
/// "getbufline()" function
static void f_getbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
getbufline(argvars, rettv, true);
}
/// "getbufoneline()" function
static void f_getbufoneline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
getbufline(argvars, rettv, false);
} }
/// "getchangelist()" function /// "getchangelist()" function

View File

@@ -5,12 +5,15 @@ source screendump.vim
source check.vim source check.vim
func Test_setbufline_getbufline() func Test_setbufline_getbufline()
" similar to Test_set_get_bufline()
new new
let b = bufnr('%') let b = bufnr('%')
hide hide
call assert_equal(0, setbufline(b, 1, ['foo', 'bar'])) call assert_equal(0, setbufline(b, 1, ['foo', 'bar']))
call assert_equal(['foo'], getbufline(b, 1)) call assert_equal(['foo'], getbufline(b, 1))
call assert_equal('foo', getbufoneline(b, 1))
call assert_equal(['bar'], getbufline(b, '$')) call assert_equal(['bar'], getbufline(b, '$'))
call assert_equal('bar', getbufoneline(b, '$'))
call assert_equal(['foo', 'bar'], getbufline(b, 1, 2)) call assert_equal(['foo', 'bar'], getbufline(b, 1, 2))
exe "bd!" b exe "bd!" b
call assert_equal([], getbufline(b, 1, 2)) call assert_equal([], getbufline(b, 1, 2))
@@ -34,10 +37,21 @@ func Test_setbufline_getbufline()
call assert_equal(0, setbufline(b, 4, ['d', 'e'])) call assert_equal(0, setbufline(b, 4, ['d', 'e']))
call assert_equal(['c'], b->getbufline(3)) call assert_equal(['c'], b->getbufline(3))
call assert_equal('c', b->getbufoneline(3))
call assert_equal(['d'], getbufline(b, 4)) call assert_equal(['d'], getbufline(b, 4))
call assert_equal('d', getbufoneline(b, 4))
call assert_equal(['e'], getbufline(b, 5)) call assert_equal(['e'], getbufline(b, 5))
call assert_equal('e', getbufoneline(b, 5))
call assert_equal([], getbufline(b, 6)) call assert_equal([], getbufline(b, 6))
call assert_equal([], getbufline(b, 2, 1)) call assert_equal([], getbufline(b, 2, 1))
if has('job')
call setbufline(b, 2, [function('eval'), #{key: 123}, test_null_job()])
call assert_equal(["function('eval')",
\ "{'key': 123}",
\ "no process"],
\ getbufline(b, 2, 4))
endif
exe "bwipe! " . b exe "bwipe! " . b
endfunc endfunc