Compare commits

...

6 Commits

Author SHA1 Message Date
vanaigr 1c2d9e8727
Merge 630990934e into efb44e0cad 2024-05-05 10:05:59 -04:00
Maria José Solano efb44e0cad
docs: fix lua type warnings (#28633) 2024-05-05 06:08:17 +08:00
zeertzjq e948d7feba
vim-patch:ad4881cb3c04 (#28636)
runtime(doc): correct getscriptinfo() example (vim/vim#14718)

When "sid" is specified, it returns a List with a single item.

ad4881cb3c
2024-05-04 15:53:42 +08:00
VanaIgr 630990934e fix(linebreak): create line break only if next row has more space 2024-02-06 20:31:10 -06:00
VanaIgr 2d45936459 fix(linebreak): make 'linebreak' work with tabs more consistently 2024-02-06 20:31:08 -06:00
VanaIgr 0766cc5b33 test(linebreak): make expected 'linebreak' behavior more consistent for tabs 2024-02-06 20:29:48 -06:00
14 changed files with 218 additions and 65 deletions

View File

@ -3014,7 +3014,7 @@ getscriptinfo([{opts}]) *getscriptinfo()*
Examples: >vim
echo getscriptinfo({'name': 'myscript'})
echo getscriptinfo({'sid': 15}).variables
echo getscriptinfo({'sid': 15})[0].variables
<
gettabinfo([{tabnr}]) *gettabinfo()*

View File

@ -124,7 +124,7 @@ error('Cannot require a meta file')
--- @field commalist boolean
--- @field flaglist boolean
--- @field was_set boolean
--- @field last_set_id integer
--- @field last_set_sid integer
--- @field last_set_linenr integer
--- @field last_set_chan integer
--- @field type 'string'|'boolean'|'number'

View File

@ -127,3 +127,11 @@
--- @field skipcol integer
--- @field topfill integer
--- @field topline integer
--- @class vim.fn.getscriptinfo.ret
--- @field autoload false
--- @field functions? string[]
--- @field name string
--- @field sid string
--- @field variables? table<string, any>
--- @field version 1

View File

@ -3628,11 +3628,11 @@ function vim.fn.getregtype(regname) end
---
--- Examples: >vim
--- echo getscriptinfo({'name': 'myscript'})
--- echo getscriptinfo({'sid': 15}).variables
--- echo getscriptinfo({'sid': 15})[0].variables
--- <
---
--- @param opts? table
--- @return any
--- @return vim.fn.getscriptinfo.ret[]
function vim.fn.getscriptinfo(opts) end
--- If {tabnr} is not specified, then information about all the

View File

@ -310,6 +310,7 @@ local function is_empty_or_default(bufnr, option)
end
local info = api.nvim_get_option_info2(option, { buf = bufnr })
---@param e vim.fn.getscriptinfo.ret
local scriptinfo = vim.tbl_filter(function(e)
return e.sid == info.last_set_sid
end, vim.fn.getscriptinfo())
@ -515,7 +516,7 @@ local function buf_attach(bufnr)
textDocument = {
uri = uri,
},
reason = protocol.TextDocumentSaveReason.Manual,
reason = protocol.TextDocumentSaveReason.Manual, ---@type integer
}
if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'willSave') then
client.notify(ms.textDocument_willSave, params)
@ -899,7 +900,7 @@ end
--- a `client_id:result` map.
---@return function cancel Function that cancels all requests.
function lsp.buf_request_all(bufnr, method, params, handler)
local results = {} --- @type table<integer,{error:string, result:any}>
local results = {} --- @type table<integer,{error:lsp.ResponseError, result:any}>
local result_count = 0
local expected_result_count = 0
@ -940,7 +941,7 @@ end
---@return table<integer, {err: lsp.ResponseError, result: any}>? result Map of client_id:request_result.
---@return string? err On timeout, cancel, or error, `err` is a string describing the failure reason, and `result` is nil.
function lsp.buf_request_sync(bufnr, method, params, timeout_ms)
local request_results
local request_results ---@type table
local cancel = lsp.buf_request_all(bufnr, method, params, function(it)
request_results = it

View File

@ -327,7 +327,7 @@ function M.get_captures_at_cursor(winnr)
end
--- Optional keyword arguments:
--- @class vim.treesitter.get_node.Opts
--- @class vim.treesitter.get_node.Opts : vim.treesitter.LanguageTree.tree_for_range.Opts
--- @inlinedoc
---
--- Buffer number (nil or 0 for current buffer)

View File

@ -4470,11 +4470,12 @@ M.funcs = {
Examples: >vim
echo getscriptinfo({'name': 'myscript'})
echo getscriptinfo({'sid': 15}).variables
echo getscriptinfo({'sid': 15})[0].variables
<
]=],
name = 'getscriptinfo',
params = { { 'opts', 'table' } },
returns = 'vim.fn.getscriptinfo.ret[]',
signature = 'getscriptinfo([{opts}])',
},
gettabinfo = {

View File

@ -95,6 +95,7 @@ CSType init_charsize_arg(CharsizeArg *csarg, win_T *wp, linenr_T lnum, char *lin
csarg->virt_row = -1;
csarg->indent_width = INT_MIN;
csarg->use_tabstop = !wp->w_p_list || wp->w_p_lcs_chars.tab1;
csarg->lbr_skip_count = -1;
if (lnum > 0) {
if (marktree_itr_get_filter(wp->w_buffer->b_marktree, lnum - 1, 0, lnum, 0,
@ -283,46 +284,98 @@ CharSize charsize_regular(CharsizeArg *csarg, char *const cur, colnr_T const vco
}
bool need_lbr = false;
// If 'linebreak' set check at a blank before a non-blank if the line
// needs a break here.
if (wp->w_p_lbr && wp->w_p_wrap && wp->w_width_inner != 0
&& vim_isbreak((uint8_t)cur[0]) && !vim_isbreak((uint8_t)cur[1])) {
char *t = csarg->line;
while (vim_isbreak((uint8_t)t[0])) {
t++;
if (wp->w_p_wrap && wp->w_p_lbr && wp->w_width_inner != 0) {
// note: cur[1] may be a part of current char.
need_lbr = vim_isbreak((uint8_t)cur[0]) && !vim_isbreak((uint8_t)cur[1]);
// Determine if a line break should be skipped.
// If the line starts with 'breakat' characters
// then the first line break is skipped.
if (csarg->lbr_skip_count < 0) {
if (EXPECT(cur == csarg->line, true)) {
// If iterating from the start of the line,
// the first time a possible linebreak position is encountered
// would be the first such position for the entire line.
csarg->lbr_skip_count = vim_isbreak((uint8_t)cur[0]) ? 1 : 0;
} else if (need_lbr) {
// CharsizeArg is initialized in the middle of the line.
// Need to scan the line from the start to find if there was a
// possible linebreak position before this one.
char *first_word = csarg->line;
while (vim_isbreak((uint8_t)(*first_word))) {
first_word++;
}
csarg->lbr_skip_count = cur < first_word ? 1 : 0;
}
}
// 'linebreak' is only needed when not in leading whitespace.
need_lbr = cur >= t;
}
if (need_lbr) {
char *s = cur;
// Count all characters from first non-blank after a blank up to next
// non-blank after a blank.
int numberextra = win_col_off(wp);
colnr_T col_adj = size - 1;
colnr_T colmax = (colnr_T)(wp->w_width_inner - numberextra - col_adj);
if (vcol >= colmax) {
colmax += col_adj;
int n = colmax + win_col_off2(wp);
if (n > 0) {
colmax += (((vcol - colmax) / n) + 1) * n - col_adj;
if (need_lbr && csarg->lbr_skip_count > 0) {
csarg->lbr_skip_count--;
} else if (need_lbr) {
int const width = wp->w_width_inner - win_col_off(wp);
int const width2 = width + win_col_off2(wp);
int cur_vcol = vcol + size; // start of the word (next character)
bool can_break;
int colmax;
if (width <= 0 || cur_vcol == width) {
can_break = false;
} else if (cur_vcol < width) {
can_break = true;
colmax = width;
} else {
assert(width2 > 0); // win_col__off2() >= 0, width > 0
int const line_count = (cur_vcol - width) / width2;
int const line_vcol = (cur_vcol - width) % width2;
if (line_vcol == 0) { // next char is at the start of the line
can_break = false;
} else {
can_break = true;
colmax = width + (line_count + 1) * width2;
}
}
colnr_T vcol2 = vcol;
while (true) {
char *ps = s;
MB_PTR_ADV(s);
int c = (uint8_t)(*s);
if (!(c != NUL
&& (vim_isbreak(c) || vcol2 == vcol || !vim_isbreak((uint8_t)(*ps))))) {
break;
if (can_break) {
int indent_width = csarg->indent_width;
if (indent_width == INT_MIN) {
indent_width = 0;
if (*sbr != NUL) {
indent_width += vim_strsize(sbr);
}
if (wp->w_p_bri) {
indent_width += get_breakindent_win(wp, line);
}
csarg->indent_width = indent_width;
}
vcol2 += win_chartabsize(wp, s, vcol2);
if (vcol2 >= colmax) { // doesn't fit
size = colmax - vcol + col_adj;
break;
can_break = (width2 - indent_width) > (colmax - cur_vcol);
}
if (can_break) {
int const start_vcol = cur_vcol;
bool const tabstop = csarg->use_tabstop;
StrCharInfo sci = utf_ptr2StrCharInfo(cur);
bool prev_break = true;
// Count all characters from first non-blank after a blank up to next
// non-blank after a blank.
// note: doesn't consider inline virtual text
while (true) {
sci = utfc_next(sci);
bool const cur_break = vim_isbreak((uint8_t)(*sci.ptr));
if (*sci.ptr == NUL || (prev_break && !cur_break && cur_vcol != start_vcol)) {
break;
}
prev_break = cur_break;
cur_vcol += charsize_nowrap(buf, tabstop, cur_vcol, sci.chr.value);
if (cur_vcol > colmax) {
size = colmax - vcol;
break;
}
}
}
}
@ -330,6 +383,19 @@ CharSize charsize_regular(CharsizeArg *csarg, char *const cur, colnr_T const vco
return (CharSize){ .width = size, .head = head };
}
/// Return the number of cells the cur_char will take on the screen.
int charsize_nowrap(buf_T *buf, bool use_tabstop, int vcol, int32_t cur_char)
FUNC_ATTR_PURE
{
if (cur_char == TAB && use_tabstop) {
return tabstop_padding(vcol, buf->b_p_ts, buf->b_p_vts_array);
} else if (cur_char < 0) {
return kInvalidByteCells;
} else {
return char2cells(cur_char);
}
}
/// Like charsize_regular(), except it doesn't handle inline virtual text,
/// 'linebreak', 'breakindent' or 'showbreak'.
/// Handles normal characters, tabs and wrapping.

View File

@ -21,6 +21,7 @@ typedef struct {
char *line; ///< Start of the line.
bool use_tabstop; ///< Use 'tabstop' instead of char2cells() for a TAB.
int8_t lbr_skip_count; ///< Positive - skip next n line breaks, negative - not calculated.
int indent_width; ///< Width of 'showbreak' and 'breakindent' on wrapped
///< parts of lines, INT_MIN if not yet calculated.

View File

@ -142,10 +142,10 @@ describe('listlbr', function()
abcdef hijklmn pqrstuvwxyz_1060ABCDEFGHIJKLMNOP
Test 1: set linebreak
abcdef
+hijklmn
abcdef hijklmn
+pqrstuvwxyz_1060ABC
+DEFGHIJKLMNOP
~
Test 2: set linebreak + set list
^Iabcdef hijklmn^I
@ -154,10 +154,10 @@ describe('listlbr', function()
Test 3: set linebreak nolist
abcdef
+hijklmn
abcdef hijklmn
+pqrstuvwxyz_1060ABC
+DEFGHIJKLMNOP
1 aaaaaaaaaaaaaaaaaa
Test 4: set linebreak with tab and 1 line as long as screen: should break!

View File

@ -157,10 +157,10 @@ describe('linebreak', function()
abcdef hijklmn pqrstuvwxyz 1060ABCDEFGHIJKLMNOP
Test 1: set linebreak + set list + fancy listchars
abcdef
+hijklmn
abcdef hijklmn
+pqrstuvwxyz1060ABC
+DEFGHIJKLMNOPˑ
~
Test 2: set nolinebreak list
abcdef hijklmn

View File

@ -33,10 +33,10 @@ func Test_set_linebreak()
call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP ")
let lines = s:screen_lines([1, 4], winwidth(0))
let expect = [
\ " abcdef ",
\ "+hijklmn ",
\ " abcdef hijklmn ",
\ "+pqrstuvwxyz_1060ABC",
\ "+DEFGHIJKLMNOP ",
\ "~ ",
\ ]
call s:compare_lines(expect, lines)
call s:close_windows()
@ -64,10 +64,10 @@ func Test_linebreak_with_nolist()
call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP ")
let lines = s:screen_lines([1, 4], winwidth(0))
let expect = [
\ " abcdef ",
\ "+hijklmn ",
\ " abcdef hijklmn ",
\ "+pqrstuvwxyz_1060ABC",
\ "+DEFGHIJKLMNOP ",
\ "~ ",
\ ]
call s:compare_lines(expect, lines)
call s:close_windows()
@ -373,19 +373,95 @@ func Test_ctrl_char_on_wrap_column()
call s:close_windows()
endfunc
func Test_linebreak_no_break_after_whitespace_only()
func Test_linebreak_break_after_whitespace()
call s:test_windows('setl ts=4 linebreak wrap')
call setline(1, "\t abcdefghijklmnopqrstuvwxyz" ..
setl list listchars=tab:>-,space:.
call setline(1, "\t abcdefghijklmnopqrstuvwxyz" ..
\ "abcdefghijklmnopqrstuvwxyz")
let lines = s:screen_lines([1, 4], winwidth(0))
let expect = [
\ " abcdefghijklmn",
\ "opqrstuvwxyzabcdefgh",
\ "ijklmnopqrstuvwxyz ",
\ "~ ",
\ ]
\ ">---.abcdefghijklmno",
\ 'pqrstuvwxyzabcdefghi',
\ "jklmnopqrstuvwxyz ",
\ "~ "]
call s:compare_lines(expect, lines)
call s:close_windows()
endfunc
func Test_linebreak_with_breakindent()
call s:test_windows('setl ts=4 breakindent briopt=min:15 sbr=>>')
setl list listchars=tab:>-,space:.
call setline(1, "\t a bcdefghijklmnopqrstuvwxyz" ..
\ "abcdefghijklmnopqrstuvwxyz")
let lines = s:screen_lines([1, 4], winwidth(0))
let expect = [
\ ">---.a.bcdefghijklmn",
\ " >>opqrstuvwxyza",
\ " >>bcdefghijklmn",
\ " >>opqrstuvwxyz "]
call s:compare_lines(expect, lines)
call s:close_windows()
call s:test_windows('setl ts=4 breakindent briopt=min:16 sbr=>>')
setl list listchars=tab:>-,space:.
call setline(1, "\t a bcdefghijklmnopqrstuvwxyz" ..
\ "abcdefghijklmnopqrstuvwxyz")
let lines = s:screen_lines([1, 4], winwidth(0))
let expect = [
\ ">---.a. ",
\ " >>bcdefghijklmno",
\ " >>pqrstuvwxyzabc",
\ " >>defghijklmnopq"]
call s:compare_lines(expect, lines)
call s:close_windows()
endfunc
func Test_linebreak_with_showbreak()
call s:test_windows('setl ts=4 linebreak showbreak=123456 wrap')
setl list listchars=tab:>-,space:.
call setline(1, "!@#$ abcdefghijklmnopqrstuvwxyz" ..
\ "abcdefghijklmnopqrstuvwxyz")
let lines = s:screen_lines([1, 4], winwidth(0))
let expect = [
\ '!@#$.abcdefghijklmno',
\ '123456pqrstuvwxyzabc',
\ '123456defghijklmnopq',
\ '123456rstuvwxyz ']
call s:compare_lines(expect, lines)
call s:close_windows()
call s:test_windows('setl ts=4 linebreak showbreak=12345 wrap')
setl list listchars=tab:>-,space:.
call setline(1, "!@#$ abcdefghijklmnopqrstuvwxyz" ..
\ "abcdefghijklmnopqrstuvwxyz")
let lines = s:screen_lines([1, 4], winwidth(0))
let expect = [
\ '!@#$.abcdefghijklmno',
\ '12345pqrstuvwxyzabcd',
\ '12345efghijklmnopqrs',
\ '12345tuvwxyz ']
call s:compare_lines(expect, lines)
call s:close_windows()
call s:test_windows('setl ts=4 linebreak showbreak=1234 wrap')
setl list listchars=tab:>-,space:.
call setline(1, "!@#$ abcdefghijklmnopqrstuvwxyz" ..
\ "abcdefghijklmnopqrstuvwxyz")
let lines = s:screen_lines([1, 4], winwidth(0))
let expect = [
\ '!@#$. ',
\ '1234abcdefghijklmnop',
\ '1234qrstuvwxyzabcdef',
\ '1234ghijklmnopqrstuv']
call s:compare_lines(expect, lines)
call s:close_windows()
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -47,10 +47,10 @@ func Test_linebreak_with_fancy_listchars()
redraw!
let lines = s:screen_lines([1, 4], winwidth(0))
let expect = [
\ "▕———abcdef ",
\ "+hijklmn▕——— ",
\ "▕———abcdef hijklmn▕—",
\ "+pqrstuvwxyz␣1060ABC",
\ "+DEFGHIJKLMNOPˑ¶ ",
\ "~ ",
\ ]
call s:compare_lines(expect, lines)
call s:close_windows()

View File

@ -294,14 +294,14 @@ func Test_vartabs_linebreak()
call setline(1, "\tx\tx\tx\tx")
let expect = [' x ',
\ 'x x ',
\ 'x ']
\ 'x ',
\ 'x x ']
let lines = ScreenLines([1, 3], winwidth(0))
call s:compare_lines(expect, lines)
setl list listchars=tab:>-
let expect = ['>---------x>------------------ ',
\ 'x>------------------x>------------------',
\ 'x ']
\ 'x>------------------ ',
\ 'x>------------------x ']
let lines = ScreenLines([1, 3], winwidth(0))
call s:compare_lines(expect, lines)
setl linebreak vartabstop=40