mirror of
https://github.com/neovim/neovim.git
synced 2025-09-07 11:58:17 +00:00
Compare commits
24 Commits
v0.10.4
...
release-0.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0c995c0efb | ||
![]() |
aab7129abe | ||
![]() |
52ad6adc8d | ||
![]() |
c5eeb1b9ee | ||
![]() |
3e7f0a13e1 | ||
![]() |
2010f398f4 | ||
![]() |
f0790c565c | ||
![]() |
ecaece926e | ||
![]() |
28a8d59cc7 | ||
![]() |
3c57ee079d | ||
![]() |
e6432b0094 | ||
![]() |
00d3956109 | ||
![]() |
d65ce60f49 | ||
![]() |
0f0959ca32 | ||
![]() |
6b6abb8969 | ||
![]() |
6ca2ef8dfe | ||
![]() |
3fd08c2eb2 | ||
![]() |
7e5b7ae4e0 | ||
![]() |
c40057f372 | ||
![]() |
c7bb6bbdea | ||
![]() |
c3866cea60 | ||
![]() |
d6da862ce0 | ||
![]() |
452ed57b71 | ||
![]() |
44c6fbaf9a |
@@ -6,7 +6,7 @@ freebsd_task:
|
|||||||
name: FreeBSD
|
name: FreeBSD
|
||||||
only_if: $BRANCH != "master"
|
only_if: $BRANCH != "master"
|
||||||
freebsd_instance:
|
freebsd_instance:
|
||||||
image_family: freebsd-14-0
|
image_family: freebsd-14-2
|
||||||
timeout_in: 30m
|
timeout_in: 30m
|
||||||
install_script:
|
install_script:
|
||||||
- pkg install -y cmake gmake ninja unzip wget gettext python git
|
- pkg install -y cmake gmake ninja unzip wget gettext python git
|
||||||
|
@@ -145,8 +145,8 @@ endif()
|
|||||||
# version string, else they are combined with the result of `git describe`.
|
# version string, else they are combined with the result of `git describe`.
|
||||||
set(NVIM_VERSION_MAJOR 0)
|
set(NVIM_VERSION_MAJOR 0)
|
||||||
set(NVIM_VERSION_MINOR 10)
|
set(NVIM_VERSION_MINOR 10)
|
||||||
set(NVIM_VERSION_PATCH 4)
|
set(NVIM_VERSION_PATCH 5)
|
||||||
set(NVIM_VERSION_PRERELEASE "") # for package maintainers
|
set(NVIM_VERSION_PRERELEASE "-dev") # for package maintainers
|
||||||
|
|
||||||
# API level
|
# API level
|
||||||
set(NVIM_API_LEVEL 12) # Bump this after any API change.
|
set(NVIM_API_LEVEL 12) # Bump this after any API change.
|
||||||
|
@@ -343,6 +343,10 @@ function STHighlighter:process_response(response, client, version)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if not api.nvim_buf_is_valid(self.bufnr) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
-- if we have a response to a delta request, update the state of our tokens
|
-- if we have a response to a delta request, update the state of our tokens
|
||||||
-- appropriately. if it's a full response, just use that
|
-- appropriately. if it's a full response, just use that
|
||||||
local tokens ---@type integer[]
|
local tokens ---@type integer[]
|
||||||
@@ -382,8 +386,10 @@ function STHighlighter:process_response(response, client, version)
|
|||||||
current_result.highlights = highlights
|
current_result.highlights = highlights
|
||||||
current_result.namespace_cleared = false
|
current_result.namespace_cleared = false
|
||||||
|
|
||||||
-- redraw all windows displaying buffer
|
-- redraw all windows displaying buffer (if still valid)
|
||||||
|
if api.nvim_buf_is_valid(self.bufnr) then
|
||||||
api.nvim__redraw({ buf = self.bufnr, valid = true })
|
api.nvim__redraw({ buf = self.bufnr, valid = true })
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- on_win handler for the decoration provider (see |nvim_set_decoration_provider|)
|
--- on_win handler for the decoration provider (see |nvim_set_decoration_provider|)
|
||||||
|
@@ -212,7 +212,8 @@ end
|
|||||||
---@param lastline integer
|
---@param lastline integer
|
||||||
---@param new_lastline integer
|
---@param new_lastline integer
|
||||||
---@param offset_encoding string
|
---@param offset_encoding string
|
||||||
---@return vim.lsp.sync.Range, vim.lsp.sync.Range
|
---@return vim.lsp.sync.Range prev_end_range
|
||||||
|
---@return vim.lsp.sync.Range curr_end_range
|
||||||
local function compute_end_range(
|
local function compute_end_range(
|
||||||
prev_lines,
|
prev_lines,
|
||||||
curr_lines,
|
curr_lines,
|
||||||
@@ -222,6 +223,16 @@ local function compute_end_range(
|
|||||||
new_lastline,
|
new_lastline,
|
||||||
offset_encoding
|
offset_encoding
|
||||||
)
|
)
|
||||||
|
-- A special case for the following `firstline == new_lastline` case where lines are deleted.
|
||||||
|
-- Even if the buffer has become empty, nvim behaves as if it has an empty line with eol.
|
||||||
|
if #curr_lines == 1 and curr_lines[1] == '' then
|
||||||
|
local prev_line = prev_lines[lastline - 1]
|
||||||
|
return {
|
||||||
|
line_idx = lastline - 1,
|
||||||
|
byte_idx = #prev_line + 1,
|
||||||
|
char_idx = compute_line_length(prev_line, offset_encoding) + 1,
|
||||||
|
}, { line_idx = 1, byte_idx = 1, char_idx = 1 }
|
||||||
|
end
|
||||||
-- If firstline == new_lastline, the first change occurred on a line that was deleted.
|
-- If firstline == new_lastline, the first change occurred on a line that was deleted.
|
||||||
-- In this case, the last_byte...
|
-- In this case, the last_byte...
|
||||||
if firstline == new_lastline then
|
if firstline == new_lastline then
|
||||||
|
@@ -240,7 +240,12 @@ end
|
|||||||
---@return vim.treesitter.highlighter.Query
|
---@return vim.treesitter.highlighter.Query
|
||||||
function TSHighlighter:get_query(lang)
|
function TSHighlighter:get_query(lang)
|
||||||
if not self._queries[lang] then
|
if not self._queries[lang] then
|
||||||
self._queries[lang] = TSHighlighterQuery.new(lang)
|
local success, result = pcall(TSHighlighterQuery.new, lang)
|
||||||
|
if not success then
|
||||||
|
self:destroy()
|
||||||
|
error(result)
|
||||||
|
end
|
||||||
|
self._queries[lang] = result
|
||||||
end
|
end
|
||||||
|
|
||||||
return self._queries[lang]
|
return self._queries[lang]
|
||||||
|
4
runtime/windows_icon.rc
Normal file
4
runtime/windows_icon.rc
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
// NOTE: this resource file *must* be in the same folder as the icon.
|
||||||
|
// Otherwise, absolute paths would need to be used.
|
||||||
|
// see https://learn.microsoft.com/en-us/windows/win32/menurc/icon-resource
|
||||||
|
NEOVIM_ICON ICON "neovim.ico"
|
@@ -708,6 +708,12 @@ target_sources(main_lib INTERFACE
|
|||||||
${EXTERNAL_SOURCES}
|
${EXTERNAL_SOURCES}
|
||||||
${EXTERNAL_HEADERS})
|
${EXTERNAL_HEADERS})
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
# add windows resource file pointing to the neovim icon
|
||||||
|
# this makes the icon appear for the neovim exe and associated filetypes
|
||||||
|
target_sources(nvim_bin PRIVATE ${NVIM_RUNTIME_DIR}/windows_icon.rc)
|
||||||
|
endif()
|
||||||
|
|
||||||
target_sources(nlua0 PUBLIC ${NLUA0_SOURCES})
|
target_sources(nlua0 PUBLIC ${NLUA0_SOURCES})
|
||||||
|
|
||||||
target_link_libraries(nvim_bin PRIVATE main_lib PUBLIC libuv)
|
target_link_libraries(nvim_bin PRIVATE main_lib PUBLIC libuv)
|
||||||
|
@@ -342,8 +342,8 @@ static void changed_common(buf_T *buf, linenr_T lnum, colnr_T col, linenr_T lnum
|
|||||||
&& (last < wp->w_topline
|
&& (last < wp->w_topline
|
||||||
|| (wp->w_topline >= lnum
|
|| (wp->w_topline >= lnum
|
||||||
&& wp->w_topline < lnume
|
&& wp->w_topline < lnume
|
||||||
&& win_linetabsize(wp, wp->w_topline, ml_get_buf(buf, wp->w_topline), MAXCOL)
|
&& (linetabsize_eol(wp, wp->w_topline)
|
||||||
<= (wp->w_skipcol + sms_marker_overlap(wp, -1))))) {
|
<= wp->w_skipcol + sms_marker_overlap(wp, -1))))) {
|
||||||
wp->w_skipcol = 0;
|
wp->w_skipcol = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -129,7 +129,7 @@ static int coladvance2(win_T *wp, pos_T *pos, bool addspaces, bool finetune, col
|
|||||||
&& wp->w_width_inner != 0
|
&& wp->w_width_inner != 0
|
||||||
&& wcol >= (colnr_T)width
|
&& wcol >= (colnr_T)width
|
||||||
&& width > 0) {
|
&& width > 0) {
|
||||||
csize = linetabsize(wp, pos->lnum);
|
csize = linetabsize_eol(wp, pos->lnum);
|
||||||
if (csize > 0) {
|
if (csize > 0) {
|
||||||
csize--;
|
csize--;
|
||||||
}
|
}
|
||||||
|
@@ -1880,6 +1880,11 @@ static char *ml_get_buf_impl(buf_T *buf, linenr_T lnum, bool will_change)
|
|||||||
static int recursive = 0;
|
static int recursive = 0;
|
||||||
static char questions[4];
|
static char questions[4];
|
||||||
|
|
||||||
|
if (buf->b_ml.ml_mfp == NULL) { // there are no lines
|
||||||
|
buf->b_ml.ml_line_len = 1;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
if (lnum > buf->b_ml.ml_line_count) { // invalid line number
|
if (lnum > buf->b_ml.ml_line_count) { // invalid line number
|
||||||
if (recursive == 0) {
|
if (recursive == 0) {
|
||||||
// Avoid giving this message for a recursive call, may happen when
|
// Avoid giving this message for a recursive call, may happen when
|
||||||
@@ -1899,11 +1904,6 @@ errorret:
|
|||||||
lnum = 1;
|
lnum = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf->b_ml.ml_mfp == NULL) { // there are no lines
|
|
||||||
buf->b_ml.ml_line_len = 1;
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// See if it is the same line as requested last time.
|
// See if it is the same line as requested last time.
|
||||||
// Otherwise may need to flush last used line.
|
// Otherwise may need to flush last used line.
|
||||||
// Don't use the last used line when 'swapfile' is reset, need to load all
|
// Don't use the last used line when 'swapfile' is reset, need to load all
|
||||||
|
@@ -1576,7 +1576,7 @@ int msg_outtrans_len(const char *msgstr, int len, int attr)
|
|||||||
|
|
||||||
// When drawing over the command line no need to clear it later or remove
|
// When drawing over the command line no need to clear it later or remove
|
||||||
// the mode message.
|
// the mode message.
|
||||||
if (msg_row >= cmdline_row && msg_col == 0) {
|
if (msg_silent == 0 && len > 0 && msg_row >= cmdline_row && msg_col == 0) {
|
||||||
clear_cmdline = false;
|
clear_cmdline = false;
|
||||||
mode_displayed = false;
|
mode_displayed = false;
|
||||||
}
|
}
|
||||||
|
@@ -1208,9 +1208,7 @@ static void cursor_correct_sms(win_T *wp)
|
|||||||
int width2 = width1 + win_col_off2(wp);
|
int width2 = width1 + win_col_off2(wp);
|
||||||
int so_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
|
int so_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
|
||||||
int space_cols = (wp->w_height_inner - 1) * width2;
|
int space_cols = (wp->w_height_inner - 1) * width2;
|
||||||
int size = so == 0 ? 0 : win_linetabsize(wp, wp->w_topline,
|
int size = so == 0 ? 0 : linetabsize_eol(wp, wp->w_topline);
|
||||||
ml_get_buf(wp->w_buffer, wp->w_topline),
|
|
||||||
(colnr_T)MAXCOL);
|
|
||||||
|
|
||||||
if (wp->w_topline == 1 && wp->w_skipcol == 0) {
|
if (wp->w_topline == 1 && wp->w_skipcol == 0) {
|
||||||
so_cols = 0; // Ignore 'scrolloff' at top of buffer.
|
so_cols = 0; // Ignore 'scrolloff' at top of buffer.
|
||||||
@@ -1226,9 +1224,10 @@ static void cursor_correct_sms(win_T *wp)
|
|||||||
so_cols -= width1;
|
so_cols -= width1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is no marker or we have non-zero scrolloff, just ignore it.
|
int overlap = wp->w_skipcol == 0
|
||||||
int overlap = (wp->w_skipcol == 0 || so_cols != 0) ? 0 : sms_marker_overlap(wp, -1);
|
? 0 : sms_marker_overlap(wp, wp->w_width_inner - width2);
|
||||||
int top = wp->w_skipcol + overlap + so_cols;
|
// If we have non-zero scrolloff, ignore marker overlap.
|
||||||
|
int top = wp->w_skipcol + (so_cols != 0 ? so_cols : overlap);
|
||||||
int bot = wp->w_skipcol + width1 + (wp->w_height_inner - 1) * width2 - so_cols;
|
int bot = wp->w_skipcol + width1 + (wp->w_height_inner - 1) * width2 - so_cols;
|
||||||
|
|
||||||
validate_virtcol(wp);
|
validate_virtcol(wp);
|
||||||
@@ -1249,10 +1248,22 @@ static void cursor_correct_sms(win_T *wp)
|
|||||||
|
|
||||||
if (col != wp->w_virtcol) {
|
if (col != wp->w_virtcol) {
|
||||||
wp->w_curswant = col;
|
wp->w_curswant = col;
|
||||||
coladvance(wp, wp->w_curswant);
|
int rc = coladvance(wp, wp->w_curswant);
|
||||||
// validate_virtcol() marked various things as valid, but after
|
// validate_virtcol() marked various things as valid, but after
|
||||||
// moving the cursor they need to be recomputed
|
// moving the cursor they need to be recomputed
|
||||||
wp->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW|VALID_VIRTCOL);
|
wp->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW|VALID_VIRTCOL);
|
||||||
|
if (rc == FAIL && wp->w_skipcol > 0
|
||||||
|
&& wp->w_cursor.lnum < wp->w_buffer->b_ml.ml_line_count) {
|
||||||
|
validate_virtcol(wp);
|
||||||
|
if (wp->w_virtcol < wp->w_skipcol + overlap) {
|
||||||
|
// Cursor still not visible: move it to the next line instead.
|
||||||
|
wp->w_cursor.lnum++;
|
||||||
|
wp->w_cursor.col = 0;
|
||||||
|
wp->w_cursor.coladd = 0;
|
||||||
|
wp->w_curswant = 0;
|
||||||
|
wp->w_valid &= ~VALID_VIRTCOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1365,8 +1376,7 @@ bool scrolldown(win_T *wp, linenr_T line_count, int byfold)
|
|||||||
wp->w_topline = first;
|
wp->w_topline = first;
|
||||||
} else {
|
} else {
|
||||||
if (do_sms) {
|
if (do_sms) {
|
||||||
int size = win_linetabsize(wp, wp->w_topline,
|
int size = linetabsize_eol(wp, wp->w_topline);
|
||||||
ml_get_buf(wp->w_buffer, wp->w_topline), MAXCOL);
|
|
||||||
if (size > width1) {
|
if (size > width1) {
|
||||||
wp->w_skipcol = width1;
|
wp->w_skipcol = width1;
|
||||||
size -= width1;
|
size -= width1;
|
||||||
@@ -1449,7 +1459,7 @@ bool scrollup(win_T *wp, linenr_T line_count, bool byfold)
|
|||||||
const colnr_T prev_skipcol = wp->w_skipcol;
|
const colnr_T prev_skipcol = wp->w_skipcol;
|
||||||
|
|
||||||
if (do_sms) {
|
if (do_sms) {
|
||||||
size = linetabsize(wp, wp->w_topline);
|
size = linetabsize_eol(wp, wp->w_topline);
|
||||||
}
|
}
|
||||||
|
|
||||||
// diff mode: first consume "topfill"
|
// diff mode: first consume "topfill"
|
||||||
@@ -1492,7 +1502,7 @@ bool scrollup(win_T *wp, linenr_T line_count, bool byfold)
|
|||||||
wp->w_topfill = win_get_fill(wp, lnum);
|
wp->w_topfill = win_get_fill(wp, lnum);
|
||||||
wp->w_skipcol = 0;
|
wp->w_skipcol = 0;
|
||||||
if (todo > 1 && do_sms) {
|
if (todo > 1 && do_sms) {
|
||||||
size = linetabsize(wp, wp->w_topline);
|
size = linetabsize_eol(wp, wp->w_topline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1563,7 +1573,7 @@ void adjust_skipcol(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
validate_virtcol(curwin);
|
validate_virtcol(curwin);
|
||||||
int overlap = sms_marker_overlap(curwin, -1);
|
int overlap = sms_marker_overlap(curwin, curwin->w_width_inner - width2);
|
||||||
while (curwin->w_skipcol > 0
|
while (curwin->w_skipcol > 0
|
||||||
&& curwin->w_virtcol < curwin->w_skipcol + overlap + scrolloff_cols) {
|
&& curwin->w_virtcol < curwin->w_skipcol + overlap + scrolloff_cols) {
|
||||||
// scroll a screen line down
|
// scroll a screen line down
|
||||||
@@ -1584,8 +1594,7 @@ void adjust_skipcol(void)
|
|||||||
|
|
||||||
// Avoid adjusting for 'scrolloff' beyond the text line height.
|
// Avoid adjusting for 'scrolloff' beyond the text line height.
|
||||||
if (scrolloff_cols > 0) {
|
if (scrolloff_cols > 0) {
|
||||||
int size = win_linetabsize(curwin, curwin->w_topline,
|
int size = linetabsize_eol(curwin, curwin->w_topline);
|
||||||
ml_get(curwin->w_topline), (colnr_T)MAXCOL);
|
|
||||||
size = width1 + width2 * ((size - width1 + width2 - 1) / width2);
|
size = width1 + width2 * ((size - width1 + width2 - 1) / width2);
|
||||||
while (col > size) {
|
while (col > size) {
|
||||||
col -= width2;
|
col -= width2;
|
||||||
|
@@ -5197,7 +5197,7 @@ void nv_g_home_m_cmd(cmdarg_T *cap)
|
|||||||
// When ending up below 'smoothscroll' marker, move just beyond it so
|
// When ending up below 'smoothscroll' marker, move just beyond it so
|
||||||
// that skipcol is not adjusted later.
|
// that skipcol is not adjusted later.
|
||||||
if (curwin->w_skipcol > 0 && curwin->w_cursor.lnum == curwin->w_topline) {
|
if (curwin->w_skipcol > 0 && curwin->w_cursor.lnum == curwin->w_topline) {
|
||||||
int overlap = sms_marker_overlap(curwin, -1);
|
int overlap = sms_marker_overlap(curwin, curwin->w_width_inner - width2);
|
||||||
if (overlap > 0 && i == curwin->w_skipcol) {
|
if (overlap > 0 && i == curwin->w_skipcol) {
|
||||||
i += overlap;
|
i += overlap;
|
||||||
}
|
}
|
||||||
|
@@ -619,7 +619,6 @@ static size_t do_path_expand(garray_T *gap, const char *path, size_t wildoff, in
|
|||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
int start_len = gap->ga_len;
|
int start_len = gap->ga_len;
|
||||||
size_t len;
|
|
||||||
bool starstar = false;
|
bool starstar = false;
|
||||||
static int stardepth = 0; // depth for "**" expansion
|
static int stardepth = 0; // depth for "**" expansion
|
||||||
|
|
||||||
@@ -631,9 +630,9 @@ static size_t do_path_expand(garray_T *gap, const char *path, size_t wildoff, in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make room for file name. When doing encoding conversion the actual
|
// Make room for file name (a bit too much to stay on the safe side).
|
||||||
// length may be quite a bit longer, thus use the maximum possible length.
|
const size_t buflen = strlen(path) + MAXPATHL;
|
||||||
char *buf = xmalloc(MAXPATHL);
|
char *buf = xmalloc(buflen);
|
||||||
|
|
||||||
// Find the first part in the path name that contains a wildcard.
|
// Find the first part in the path name that contains a wildcard.
|
||||||
// When EW_ICASE is set every letter is considered to be a wildcard.
|
// When EW_ICASE is set every letter is considered to be a wildcard.
|
||||||
@@ -662,10 +661,10 @@ static size_t do_path_expand(garray_T *gap, const char *path, size_t wildoff, in
|
|||||||
) {
|
) {
|
||||||
e = p;
|
e = p;
|
||||||
}
|
}
|
||||||
len = (size_t)(utfc_ptr2len(path_end));
|
int charlen = utfc_ptr2len(path_end);
|
||||||
memcpy(p, path_end, len);
|
memcpy(p, path_end, (size_t)charlen);
|
||||||
p += len;
|
p += charlen;
|
||||||
path_end += len;
|
path_end += charlen;
|
||||||
}
|
}
|
||||||
e = p;
|
e = p;
|
||||||
*e = NUL;
|
*e = NUL;
|
||||||
@@ -719,13 +718,14 @@ static size_t do_path_expand(garray_T *gap, const char *path, size_t wildoff, in
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t len = (size_t)(s - buf);
|
||||||
// If "**" is by itself, this is the first time we encounter it and more
|
// If "**" is by itself, this is the first time we encounter it and more
|
||||||
// is following then find matches without any directory.
|
// is following then find matches without any directory.
|
||||||
if (!didstar && stardepth < 100 && starstar && e - s == 2
|
if (!didstar && stardepth < 100 && starstar && e - s == 2
|
||||||
&& *path_end == '/') {
|
&& *path_end == '/') {
|
||||||
STRCPY(s, path_end + 1);
|
vim_snprintf(s, buflen - len, "%s", path_end + 1);
|
||||||
stardepth++;
|
stardepth++;
|
||||||
do_path_expand(gap, buf, (size_t)(s - buf), flags, true);
|
do_path_expand(gap, buf, len, flags, true);
|
||||||
stardepth--;
|
stardepth--;
|
||||||
}
|
}
|
||||||
*s = NUL;
|
*s = NUL;
|
||||||
@@ -737,6 +737,7 @@ static size_t do_path_expand(garray_T *gap, const char *path, size_t wildoff, in
|
|||||||
const char *name;
|
const char *name;
|
||||||
scandir_next_with_dots(NULL); // initialize
|
scandir_next_with_dots(NULL); // initialize
|
||||||
while (!got_int && (name = scandir_next_with_dots(&dir)) != NULL) {
|
while (!got_int && (name = scandir_next_with_dots(&dir)) != NULL) {
|
||||||
|
len = (size_t)(s - buf);
|
||||||
if ((name[0] != '.'
|
if ((name[0] != '.'
|
||||||
|| starts_with_dot
|
|| starts_with_dot
|
||||||
|| ((flags & EW_DODOT)
|
|| ((flags & EW_DODOT)
|
||||||
@@ -744,21 +745,22 @@ static size_t do_path_expand(garray_T *gap, const char *path, size_t wildoff, in
|
|||||||
&& (name[1] != '.' || name[2] != NUL)))
|
&& (name[1] != '.' || name[2] != NUL)))
|
||||||
&& ((regmatch.regprog != NULL && vim_regexec(®match, name, 0))
|
&& ((regmatch.regprog != NULL && vim_regexec(®match, name, 0))
|
||||||
|| ((flags & EW_NOTWILD)
|
|| ((flags & EW_NOTWILD)
|
||||||
&& path_fnamencmp(path + (s - buf), name, (size_t)(e - s)) == 0))) {
|
&& path_fnamencmp(path + len, name, (size_t)(e - s)) == 0))) {
|
||||||
STRCPY(s, name);
|
len += (size_t)vim_snprintf(s, buflen - len, "%s", name);
|
||||||
len = strlen(buf);
|
if (len + 1 >= buflen) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (starstar && stardepth < 100) {
|
if (starstar && stardepth < 100) {
|
||||||
// For "**" in the pattern first go deeper in the tree to
|
// For "**" in the pattern first go deeper in the tree to
|
||||||
// find matches.
|
// find matches.
|
||||||
STRCPY(buf + len, "/**"); // NOLINT
|
vim_snprintf(buf + len, buflen - len, "/**%s", path_end); // NOLINT
|
||||||
STRCPY(buf + len + 3, path_end);
|
|
||||||
stardepth++;
|
stardepth++;
|
||||||
do_path_expand(gap, buf, len + 1, flags, true);
|
do_path_expand(gap, buf, len + 1, flags, true);
|
||||||
stardepth--;
|
stardepth--;
|
||||||
}
|
}
|
||||||
|
|
||||||
STRCPY(buf + len, path_end);
|
vim_snprintf(buf + len, buflen - len, "%s", path_end);
|
||||||
if (path_has_exp_wildcard(path_end)) { // handle more wildcards
|
if (path_has_exp_wildcard(path_end)) { // handle more wildcards
|
||||||
// need to expand another component of the path
|
// need to expand another component of the path
|
||||||
// remove backslashes for the remaining components only
|
// remove backslashes for the remaining components only
|
||||||
|
@@ -74,11 +74,19 @@ int linetabsize_col(int startvcol, char *s)
|
|||||||
|
|
||||||
/// Return the number of cells line "lnum" of window "wp" will take on the
|
/// Return the number of cells line "lnum" of window "wp" will take on the
|
||||||
/// screen, taking into account the size of a tab and inline virtual text.
|
/// screen, taking into account the size of a tab and inline virtual text.
|
||||||
|
/// Doesn't count the size of 'listchars' "eol".
|
||||||
int linetabsize(win_T *wp, linenr_T lnum)
|
int linetabsize(win_T *wp, linenr_T lnum)
|
||||||
{
|
{
|
||||||
return win_linetabsize(wp, lnum, ml_get_buf(wp->w_buffer, lnum), MAXCOL);
|
return win_linetabsize(wp, lnum, ml_get_buf(wp->w_buffer, lnum), MAXCOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Like linetabsize(), but counts the size of 'listchars' "eol".
|
||||||
|
int linetabsize_eol(win_T *wp, linenr_T lnum)
|
||||||
|
{
|
||||||
|
return linetabsize(wp, lnum)
|
||||||
|
+ ((wp->w_p_list && wp->w_p_lcs_chars.eol != NUL) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
static const uint32_t inline_filter[4] = {[kMTMetaInline] = kMTFilterSelect };
|
static const uint32_t inline_filter[4] = {[kMTMetaInline] = kMTFilterSelect };
|
||||||
|
|
||||||
/// Prepare the structure passed to charsize functions.
|
/// Prepare the structure passed to charsize functions.
|
||||||
|
@@ -81,6 +81,7 @@ static inline int win_linetabsize(win_T *wp, linenr_T lnum, char *line, colnr_T
|
|||||||
REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE;
|
REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE;
|
||||||
|
|
||||||
/// Like linetabsize_str(), but for a given window instead of the current one.
|
/// Like linetabsize_str(), but for a given window instead of the current one.
|
||||||
|
/// Doesn't count the size of 'listchars' "eol".
|
||||||
///
|
///
|
||||||
/// @param wp
|
/// @param wp
|
||||||
/// @param line
|
/// @param line
|
||||||
|
@@ -1677,8 +1677,6 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (fmt_spec) {
|
switch (fmt_spec) {
|
||||||
case 'b':
|
|
||||||
case 'B':
|
|
||||||
case 'd':
|
case 'd':
|
||||||
case 'u':
|
case 'u':
|
||||||
case 'o':
|
case 'o':
|
||||||
@@ -1802,6 +1800,13 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
|
|||||||
if (ptr_arg) {
|
if (ptr_arg) {
|
||||||
arg_sign = 1;
|
arg_sign = 1;
|
||||||
}
|
}
|
||||||
|
} else if (fmt_spec == 'b' || fmt_spec == 'B') {
|
||||||
|
uarg = (tvs
|
||||||
|
? (unsigned long long)tv_nr(tvs, &arg_idx) // NOLINT(runtime/int)
|
||||||
|
: (skip_to_arg(ap_types, ap_start, &ap, &arg_idx,
|
||||||
|
&arg_cur, fmt),
|
||||||
|
va_arg(ap, unsigned long long))); // NOLINT(runtime/int)
|
||||||
|
arg_sign = (uarg != 0);
|
||||||
} else if (fmt_spec == 'd') {
|
} else if (fmt_spec == 'd') {
|
||||||
// signed
|
// signed
|
||||||
switch (length_modifier) {
|
switch (length_modifier) {
|
||||||
|
@@ -1649,7 +1649,7 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
|
|||||||
? !(spp->sp_flags & HL_CONTAINED)
|
? !(spp->sp_flags & HL_CONTAINED)
|
||||||
: in_id_list(cur_si,
|
: in_id_list(cur_si,
|
||||||
cur_si->si_cont_list, &spp->sp_syn,
|
cur_si->si_cont_list, &spp->sp_syn,
|
||||||
spp->sp_flags & HL_CONTAINED)))) {
|
spp->sp_flags)))) {
|
||||||
// If we already tried matching in this line, and
|
// If we already tried matching in this line, and
|
||||||
// there isn't a match before next_match_col, skip
|
// there isn't a match before next_match_col, skip
|
||||||
// this item.
|
// this item.
|
||||||
@@ -2774,7 +2774,7 @@ static keyentry_T *match_keyword(char *keyword, hashtab_T *ht, stateitem_T *cur_
|
|||||||
: (cur_si == NULL
|
: (cur_si == NULL
|
||||||
? !(kp->flags & HL_CONTAINED)
|
? !(kp->flags & HL_CONTAINED)
|
||||||
: in_id_list(cur_si, cur_si->si_cont_list,
|
: in_id_list(cur_si, cur_si->si_cont_list,
|
||||||
&kp->k_syn, kp->flags & HL_CONTAINED))) {
|
&kp->k_syn, kp->flags))) {
|
||||||
return kp;
|
return kp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3927,7 +3927,7 @@ static void syn_incl_toplevel(int id, int *flagsp)
|
|||||||
if ((*flagsp & HL_CONTAINED) || curwin->w_s->b_syn_topgrp == 0) {
|
if ((*flagsp & HL_CONTAINED) || curwin->w_s->b_syn_topgrp == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*flagsp |= HL_CONTAINED;
|
*flagsp |= HL_CONTAINED | HL_INCLUDED_TOPLEVEL;
|
||||||
if (curwin->w_s->b_syn_topgrp >= SYNID_CLUSTER) {
|
if (curwin->w_s->b_syn_topgrp >= SYNID_CLUSTER) {
|
||||||
// We have to alloc this, because syn_combine_list() will free it.
|
// We have to alloc this, because syn_combine_list() will free it.
|
||||||
int16_t *grp_list = xmalloc(2 * sizeof(*grp_list));
|
int16_t *grp_list = xmalloc(2 * sizeof(*grp_list));
|
||||||
@@ -4968,16 +4968,13 @@ static int get_id_list(char **const arg, const int keylen, int16_t **const list,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (name[1] == 'A') {
|
if (name[1] == 'A') {
|
||||||
id = SYNID_ALLBUT + current_syn_inc_tag;
|
id = SYNID_ALLBUT;
|
||||||
} else if (name[1] == 'T') {
|
} else if (name[1] == 'T') {
|
||||||
if (curwin->w_s->b_syn_topgrp >= SYNID_CLUSTER) {
|
id = SYNID_TOP;
|
||||||
id = curwin->w_s->b_syn_topgrp;
|
|
||||||
} else {
|
} else {
|
||||||
id = SYNID_TOP + current_syn_inc_tag;
|
id = SYNID_CONTAINED;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
id = SYNID_CONTAINED + current_syn_inc_tag;
|
|
||||||
}
|
}
|
||||||
|
id += current_syn_inc_tag;
|
||||||
} else if (name[1] == '@') {
|
} else if (name[1] == '@') {
|
||||||
if (skip) {
|
if (skip) {
|
||||||
id = -1;
|
id = -1;
|
||||||
@@ -5095,8 +5092,8 @@ static int16_t *copy_id_list(const int16_t *const list)
|
|||||||
/// @param cur_si current item or NULL
|
/// @param cur_si current item or NULL
|
||||||
/// @param list id list
|
/// @param list id list
|
||||||
/// @param ssp group id and ":syn include" tag of group
|
/// @param ssp group id and ":syn include" tag of group
|
||||||
/// @param contained group id is contained
|
/// @param flags group flags
|
||||||
static int in_id_list(stateitem_T *cur_si, int16_t *list, struct sp_syn *ssp, int contained)
|
static int in_id_list(stateitem_T *cur_si, int16_t *list, struct sp_syn *ssp, int flags)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
int16_t id = ssp->id;
|
int16_t id = ssp->id;
|
||||||
@@ -5114,8 +5111,7 @@ static int in_id_list(stateitem_T *cur_si, int16_t *list, struct sp_syn *ssp, in
|
|||||||
// cur_si->si_idx is -1 for keywords, these never contain anything.
|
// cur_si->si_idx is -1 for keywords, these never contain anything.
|
||||||
if (cur_si->si_idx >= 0 && in_id_list(NULL, ssp->cont_in_list,
|
if (cur_si->si_idx >= 0 && in_id_list(NULL, ssp->cont_in_list,
|
||||||
&(SYN_ITEMS(syn_block)[cur_si->si_idx].sp_syn),
|
&(SYN_ITEMS(syn_block)[cur_si->si_idx].sp_syn),
|
||||||
SYN_ITEMS(syn_block)[cur_si->si_idx].sp_flags &
|
SYN_ITEMS(syn_block)[cur_si->si_idx].sp_flags)) {
|
||||||
HL_CONTAINED)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5127,9 +5123,14 @@ static int in_id_list(stateitem_T *cur_si, int16_t *list, struct sp_syn *ssp, in
|
|||||||
// If list is ID_LIST_ALL, we are in a transparent item that isn't
|
// If list is ID_LIST_ALL, we are in a transparent item that isn't
|
||||||
// inside anything. Only allow not-contained groups.
|
// inside anything. Only allow not-contained groups.
|
||||||
if (list == ID_LIST_ALL) {
|
if (list == ID_LIST_ALL) {
|
||||||
return !contained;
|
return !(flags & HL_CONTAINED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is this top-level (i.e. not 'contained') in the file it was declared in?
|
||||||
|
// For included files, this is different from HL_CONTAINED, which is set
|
||||||
|
// unconditionally.
|
||||||
|
bool toplevel = !(flags & HL_CONTAINED) || (flags & HL_INCLUDED_TOPLEVEL);
|
||||||
|
|
||||||
// If the first item is "ALLBUT", return true if "id" is NOT in the
|
// If the first item is "ALLBUT", return true if "id" is NOT in the
|
||||||
// contains list. We also require that "id" is at the same ":syn include"
|
// contains list. We also require that "id" is at the same ":syn include"
|
||||||
// level as the list.
|
// level as the list.
|
||||||
@@ -5142,12 +5143,12 @@ static int in_id_list(stateitem_T *cur_si, int16_t *list, struct sp_syn *ssp, in
|
|||||||
}
|
}
|
||||||
} else if (item < SYNID_CONTAINED) {
|
} else if (item < SYNID_CONTAINED) {
|
||||||
// TOP: accept all not-contained groups in the same file
|
// TOP: accept all not-contained groups in the same file
|
||||||
if (item - SYNID_TOP != ssp->inc_tag || contained) {
|
if (item - SYNID_TOP != ssp->inc_tag || !toplevel) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// CONTAINED: accept all contained groups in the same file
|
// CONTAINED: accept all contained groups in the same file
|
||||||
if (item - SYNID_CONTAINED != ssp->inc_tag || !contained) {
|
if (item - SYNID_CONTAINED != ssp->inc_tag || toplevel) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5168,7 +5169,7 @@ static int in_id_list(stateitem_T *cur_si, int16_t *list, struct sp_syn *ssp, in
|
|||||||
// cluster that includes itself (indirectly)
|
// cluster that includes itself (indirectly)
|
||||||
if (scl_list != NULL && depth < 30) {
|
if (scl_list != NULL && depth < 30) {
|
||||||
depth++;
|
depth++;
|
||||||
int r = in_id_list(NULL, scl_list, ssp, contained);
|
int r = in_id_list(NULL, scl_list, ssp, flags);
|
||||||
depth--;
|
depth--;
|
||||||
if (r) {
|
if (r) {
|
||||||
return retval;
|
return retval;
|
||||||
|
@@ -26,6 +26,7 @@ enum {
|
|||||||
HL_TRANS_CONT = 0x10000, ///< transparent item without contains arg
|
HL_TRANS_CONT = 0x10000, ///< transparent item without contains arg
|
||||||
HL_CONCEAL = 0x20000, ///< can be concealed
|
HL_CONCEAL = 0x20000, ///< can be concealed
|
||||||
HL_CONCEALENDS = 0x40000, ///< can be concealed
|
HL_CONCEALENDS = 0x40000, ///< can be concealed
|
||||||
|
HL_INCLUDED_TOPLEVEL = 0x80000, ///< toplevel item in included syntax, allowed by contains=TOP
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SYN_GROUP_STATIC(s) syn_check_group(S_LEN(s))
|
#define SYN_GROUP_STATIC(s) syn_check_group(S_LEN(s))
|
||||||
|
@@ -3014,6 +3014,8 @@ static int jumpto_tag(const char *lbuf_arg, int forceit, bool keep_help)
|
|||||||
secure = 1;
|
secure = 1;
|
||||||
sandbox++;
|
sandbox++;
|
||||||
curwin->w_cursor.lnum = 1; // start command in line 1
|
curwin->w_cursor.lnum = 1; // start command in line 1
|
||||||
|
curwin->w_cursor.col = 0;
|
||||||
|
curwin->w_cursor.coladd = 0;
|
||||||
do_cmdline_cmd(pbuf);
|
do_cmdline_cmd(pbuf);
|
||||||
retval = OK;
|
retval = OK;
|
||||||
|
|
||||||
|
@@ -89,6 +89,34 @@ describe('messages', function()
|
|||||||
]])
|
]])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
-- oldtest: Test_mode_cleared_after_silent_message()
|
||||||
|
it('mode is cleared properly after slient message', function()
|
||||||
|
screen = Screen.new(60, 10)
|
||||||
|
screen:attach()
|
||||||
|
exec([[
|
||||||
|
edit XsilentMessageMode.txt
|
||||||
|
call setline(1, 'foobar')
|
||||||
|
autocmd TextChanged * silent update
|
||||||
|
]])
|
||||||
|
finally(function()
|
||||||
|
os.remove('XsilentMessageMode.txt')
|
||||||
|
end)
|
||||||
|
|
||||||
|
feed('v')
|
||||||
|
screen:expect([[
|
||||||
|
^foobar |
|
||||||
|
{1:~ }|*8
|
||||||
|
{5:-- VISUAL --} |
|
||||||
|
]])
|
||||||
|
|
||||||
|
feed('d')
|
||||||
|
screen:expect([[
|
||||||
|
^oobar |
|
||||||
|
{1:~ }|*8
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
describe('more prompt', function()
|
describe('more prompt', function()
|
||||||
before_each(function()
|
before_each(function()
|
||||||
command('set more')
|
command('set more')
|
||||||
|
@@ -300,6 +300,24 @@ describe('lua buffer event callbacks: on_lines', function()
|
|||||||
n.assert_alive()
|
n.assert_alive()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('no invalid lnum error for closed memline in on_detach #31251', function()
|
||||||
|
eq(vim.NIL, exec_lua('return _G.did_detach'))
|
||||||
|
exec_lua([[
|
||||||
|
vim.api.nvim_buf_set_lines(0, 0, -1, false, { '' })
|
||||||
|
local bufname = 'buf2'
|
||||||
|
local buf = vim.api.nvim_create_buf(false, true)
|
||||||
|
vim.api.nvim_buf_set_name(buf, bufname)
|
||||||
|
vim.bo[buf].bufhidden = 'wipe'
|
||||||
|
vim.cmd('vertical diffsplit '..bufname)
|
||||||
|
vim.api.nvim_buf_attach(0, false, { on_detach = function()
|
||||||
|
vim.cmd("redraw")
|
||||||
|
_G.did_detach = true
|
||||||
|
end})
|
||||||
|
vim.cmd.bdelete()
|
||||||
|
]])
|
||||||
|
eq(true, exec_lua('return _G.did_detach'))
|
||||||
|
end)
|
||||||
|
|
||||||
it('#12718 lnume', function()
|
it('#12718 lnume', function()
|
||||||
api.nvim_buf_set_lines(0, 0, -1, true, { '1', '2', '3' })
|
api.nvim_buf_set_lines(0, 0, -1, true, { '1', '2', '3' })
|
||||||
exec_lua([[
|
exec_lua([[
|
||||||
|
@@ -170,7 +170,7 @@ describe('incremental synchronization', function()
|
|||||||
}
|
}
|
||||||
test_edit({ 'a' }, { 'rb' }, expected_text_changes, 'utf-16', '\n')
|
test_edit({ 'a' }, { 'rb' }, expected_text_changes, 'utf-16', '\n')
|
||||||
end)
|
end)
|
||||||
it('deleting a line', function()
|
it('deleting the first line', function()
|
||||||
local expected_text_changes = {
|
local expected_text_changes = {
|
||||||
{
|
{
|
||||||
range = {
|
range = {
|
||||||
@@ -183,11 +183,49 @@ describe('incremental synchronization', function()
|
|||||||
line = 1,
|
line = 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
rangeLength = 12,
|
rangeLength = 6,
|
||||||
text = '',
|
text = '',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
test_edit({ 'hello world' }, { 'dd' }, expected_text_changes, 'utf-16', '\n')
|
test_edit({ 'hello', 'world' }, { 'ggdd' }, expected_text_changes, 'utf-16', '\n')
|
||||||
|
end)
|
||||||
|
it('deleting the last line', function()
|
||||||
|
local expected_text_changes = {
|
||||||
|
{
|
||||||
|
range = {
|
||||||
|
['start'] = {
|
||||||
|
character = 0,
|
||||||
|
line = 1,
|
||||||
|
},
|
||||||
|
['end'] = {
|
||||||
|
character = 0,
|
||||||
|
line = 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rangeLength = 6,
|
||||||
|
text = '',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
test_edit({ 'hello', 'world' }, { '2ggdd' }, expected_text_changes, 'utf-16', '\n')
|
||||||
|
end)
|
||||||
|
it('deleting all lines', function()
|
||||||
|
local expected_text_changes = {
|
||||||
|
{
|
||||||
|
range = {
|
||||||
|
['start'] = {
|
||||||
|
character = 0,
|
||||||
|
line = 0,
|
||||||
|
},
|
||||||
|
['end'] = {
|
||||||
|
character = 5,
|
||||||
|
line = 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rangeLength = 11,
|
||||||
|
text = '',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
test_edit({ 'hello', 'world' }, { 'ggdG' }, expected_text_changes, 'utf-16', '\n')
|
||||||
end)
|
end)
|
||||||
it('deleting an empty line', function()
|
it('deleting an empty line', function()
|
||||||
local expected_text_changes = {
|
local expected_text_changes = {
|
||||||
|
@@ -13,6 +13,9 @@
|
|||||||
" For csh:
|
" For csh:
|
||||||
" setenv TEST_FILTER Test_channel
|
" setenv TEST_FILTER Test_channel
|
||||||
"
|
"
|
||||||
|
" If the environment variable $TEST_SKIP_PAT is set then test functions
|
||||||
|
" matching this pattern will be skipped. It's the opposite of $TEST_FILTER.
|
||||||
|
"
|
||||||
" While working on a test you can make $TEST_NO_RETRY non-empty to not retry:
|
" While working on a test you can make $TEST_NO_RETRY non-empty to not retry:
|
||||||
" export TEST_NO_RETRY=yes
|
" export TEST_NO_RETRY=yes
|
||||||
"
|
"
|
||||||
@@ -92,7 +95,12 @@ set encoding=utf-8
|
|||||||
" REDIR_TEST_TO_NULL has a very permissive SwapExists autocommand which is for
|
" REDIR_TEST_TO_NULL has a very permissive SwapExists autocommand which is for
|
||||||
" the test_name.vim file itself. Replace it here with a more restrictive one,
|
" the test_name.vim file itself. Replace it here with a more restrictive one,
|
||||||
" so we still catch mistakes.
|
" so we still catch mistakes.
|
||||||
let s:test_script_fname = expand('%')
|
if has("win32")
|
||||||
|
" replace any '/' directory separators by '\\'
|
||||||
|
let s:test_script_fname = substitute(expand('%'), '/', '\\', 'g')
|
||||||
|
else
|
||||||
|
let s:test_script_fname = expand('%')
|
||||||
|
endif
|
||||||
au! SwapExists * call HandleSwapExists()
|
au! SwapExists * call HandleSwapExists()
|
||||||
func HandleSwapExists()
|
func HandleSwapExists()
|
||||||
if exists('g:ignoreSwapExists')
|
if exists('g:ignoreSwapExists')
|
||||||
@@ -431,13 +439,17 @@ func FinishTesting()
|
|||||||
|
|
||||||
if s:done == 0
|
if s:done == 0
|
||||||
if s:filtered > 0
|
if s:filtered > 0
|
||||||
|
if $TEST_FILTER != ''
|
||||||
let message = "NO tests match $TEST_FILTER: '" .. $TEST_FILTER .. "'"
|
let message = "NO tests match $TEST_FILTER: '" .. $TEST_FILTER .. "'"
|
||||||
|
else
|
||||||
|
let message = "ALL tests match $TEST_SKIP_PAT: '" .. $TEST_SKIP_PAT .. "'"
|
||||||
|
endif
|
||||||
else
|
else
|
||||||
let message = 'NO tests executed'
|
let message = 'NO tests executed'
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
if s:filtered > 0
|
if s:filtered > 0
|
||||||
call add(s:messages, "Filtered " .. s:filtered .. " tests with $TEST_FILTER")
|
call add(s:messages, "Filtered " .. s:filtered .. " tests with $TEST_FILTER and $TEST_SKIP_PAT")
|
||||||
endif
|
endif
|
||||||
let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
|
let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
|
||||||
endif
|
endif
|
||||||
@@ -530,6 +542,12 @@ endif
|
|||||||
|
|
||||||
" Execute the tests in alphabetical order.
|
" Execute the tests in alphabetical order.
|
||||||
for g:testfunc in sort(s:tests)
|
for g:testfunc in sort(s:tests)
|
||||||
|
if $TEST_SKIP_PAT != '' && g:testfunc =~ $TEST_SKIP_PAT
|
||||||
|
call add(s:messages, g:testfunc .. ' matches $TEST_SKIP_PAT')
|
||||||
|
let s:filtered += 1
|
||||||
|
continue
|
||||||
|
endif
|
||||||
|
|
||||||
" Silence, please!
|
" Silence, please!
|
||||||
set belloff=all
|
set belloff=all
|
||||||
let prev_error = ''
|
let prev_error = ''
|
||||||
|
@@ -143,4 +143,11 @@ func Test_expand_wildignore()
|
|||||||
set wildignore&
|
set wildignore&
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Passing a long string to expand with 'wildignorecase' should not crash Vim.
|
||||||
|
func Test_expand_long_str()
|
||||||
|
set wildignorecase
|
||||||
|
call expand('a'->repeat(99999))
|
||||||
|
set wildignorecase&
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
@@ -386,6 +386,29 @@ func Test_message_not_cleared_after_mode()
|
|||||||
call StopVimInTerminal(buf)
|
call StopVimInTerminal(buf)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_mode_cleared_after_silent_message()
|
||||||
|
CheckRunVimInTerminal
|
||||||
|
|
||||||
|
let lines =<< trim END
|
||||||
|
edit XsilentMessageMode.txt
|
||||||
|
call setline(1, 'foobar')
|
||||||
|
autocmd TextChanged * silent update
|
||||||
|
END
|
||||||
|
call writefile(lines, 'XsilentMessageMode', 'D')
|
||||||
|
let buf = RunVimInTerminal('-S XsilentMessageMode', {'rows': 10})
|
||||||
|
|
||||||
|
call term_sendkeys(buf, 'v')
|
||||||
|
call TermWait(buf)
|
||||||
|
call VerifyScreenDump(buf, 'Test_mode_cleared_after_silent_message_1', {})
|
||||||
|
|
||||||
|
call term_sendkeys(buf, 'd')
|
||||||
|
call TermWait(buf)
|
||||||
|
call VerifyScreenDump(buf, 'Test_mode_cleared_after_silent_message_2', {})
|
||||||
|
|
||||||
|
call StopVimInTerminal(buf)
|
||||||
|
call delete('XsilentMessageMode.txt')
|
||||||
|
endfunc
|
||||||
|
|
||||||
" Test verbose message before echo command
|
" Test verbose message before echo command
|
||||||
func Test_echo_verbose_system()
|
func Test_echo_verbose_system()
|
||||||
CheckRunVimInTerminal
|
CheckRunVimInTerminal
|
||||||
|
@@ -1219,4 +1219,59 @@ func Test_smooth_long_scrolloff()
|
|||||||
call StopVimInTerminal(buf)
|
call StopVimInTerminal(buf)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_smoothscroll_listchars_eol()
|
||||||
|
call NewWindow(10, 40)
|
||||||
|
setlocal list listchars=eol:$ scrolloff=0 smoothscroll
|
||||||
|
call setline(1, repeat('-', 40))
|
||||||
|
call append(1, repeat(['foobar'], 10))
|
||||||
|
|
||||||
|
normal! G
|
||||||
|
call assert_equal(2, line('w0'))
|
||||||
|
call assert_equal(0, winsaveview().skipcol)
|
||||||
|
|
||||||
|
exe "normal! \<C-Y>"
|
||||||
|
call assert_equal(1, line('w0'))
|
||||||
|
call assert_equal(40, winsaveview().skipcol)
|
||||||
|
|
||||||
|
exe "normal! \<C-Y>"
|
||||||
|
call assert_equal(1, line('w0'))
|
||||||
|
call assert_equal(0, winsaveview().skipcol)
|
||||||
|
|
||||||
|
exe "normal! \<C-Y>"
|
||||||
|
call assert_equal(1, line('w0'))
|
||||||
|
call assert_equal(0, winsaveview().skipcol)
|
||||||
|
|
||||||
|
exe "normal! \<C-E>"
|
||||||
|
call assert_equal(1, line('w0'))
|
||||||
|
call assert_equal(40, winsaveview().skipcol)
|
||||||
|
|
||||||
|
exe "normal! \<C-E>"
|
||||||
|
call assert_equal(2, line('w0'))
|
||||||
|
call assert_equal(0, winsaveview().skipcol)
|
||||||
|
|
||||||
|
for ve in ['', 'all', 'onemore']
|
||||||
|
let &virtualedit = ve
|
||||||
|
normal! gg
|
||||||
|
call assert_equal(1, line('w0'))
|
||||||
|
call assert_equal(0, winsaveview().skipcol)
|
||||||
|
|
||||||
|
exe "normal! \<C-E>"
|
||||||
|
redraw " redrawing should not cause another scroll
|
||||||
|
call assert_equal(1, line('w0'))
|
||||||
|
call assert_equal(40, winsaveview().skipcol)
|
||||||
|
|
||||||
|
exe "normal! \<C-E>"
|
||||||
|
redraw
|
||||||
|
call assert_equal(2, line('w0'))
|
||||||
|
call assert_equal(0, winsaveview().skipcol)
|
||||||
|
|
||||||
|
if ve != 'all'
|
||||||
|
call assert_equal([0, 2, 1, 0], getpos('.'))
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
set virtualedit&
|
||||||
|
bwipe!
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
@@ -949,7 +949,7 @@ func Test_syn_contained_transparent()
|
|||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_syn_include_contains_TOP()
|
func Test_syn_include_contains_TOP()
|
||||||
let l:case = "TOP in included syntax means its group list name"
|
let l:case = "TOP in included syntax refers to top level of that included syntax"
|
||||||
new
|
new
|
||||||
syntax include @INCLUDED syntax/c.vim
|
syntax include @INCLUDED syntax/c.vim
|
||||||
syntax region FencedCodeBlockC start=/```c/ end=/```/ contains=@INCLUDED
|
syntax region FencedCodeBlockC start=/```c/ end=/```/ contains=@INCLUDED
|
||||||
@@ -964,6 +964,18 @@ func Test_syn_include_contains_TOP()
|
|||||||
bw!
|
bw!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_syn_include_contains_TOP_excluding()
|
||||||
|
new
|
||||||
|
syntax include @INCLUDED syntax/c.vim
|
||||||
|
syntax region FencedCodeBlockC start=/```c/ end=/```/ contains=@INCLUDED
|
||||||
|
|
||||||
|
call setline(1, ['```c', '#if 0', 'int', '#else', 'int', '#if', '#endif', '```' ])
|
||||||
|
let l:expected = ["cCppOutElse", "cConditional"]
|
||||||
|
eval AssertHighlightGroups(6, 1, l:expected, 1)
|
||||||
|
syntax clear
|
||||||
|
bw!
|
||||||
|
endfunc
|
||||||
|
|
||||||
" This was using freed memory
|
" This was using freed memory
|
||||||
func Test_WinEnter_synstack_synID()
|
func Test_WinEnter_synstack_synID()
|
||||||
autocmd WinEnter * call synstack(line("."), col("."))
|
autocmd WinEnter * call synstack(line("."), col("."))
|
||||||
|
@@ -1623,4 +1623,39 @@ func Test_tagbsearch()
|
|||||||
set tags& tagbsearch&
|
set tags& tagbsearch&
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Test tag guessing with very short names
|
||||||
|
func Test_tag_guess_short()
|
||||||
|
call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
|
||||||
|
\ "y\tXf\t/^y()/"],
|
||||||
|
\ 'Xt', 'D')
|
||||||
|
set tags=Xt cpoptions+=t
|
||||||
|
call writefile(['', 'int * y () {}', ''], 'Xf', 'D')
|
||||||
|
|
||||||
|
let v:statusmsg = ''
|
||||||
|
let @/ = ''
|
||||||
|
ta y
|
||||||
|
call assert_match('E435:', v:statusmsg)
|
||||||
|
call assert_equal(2, line('.'))
|
||||||
|
call assert_match('<y', @/)
|
||||||
|
|
||||||
|
set tags& cpoptions-=t
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_tag_excmd_with_nostartofline()
|
||||||
|
call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
|
||||||
|
\ "f\tXfile\tascii"],
|
||||||
|
\ 'Xtags', 'D')
|
||||||
|
call writefile(['f', 'foobar'], 'Xfile', 'D')
|
||||||
|
|
||||||
|
set nostartofline
|
||||||
|
new Xfile
|
||||||
|
setlocal tags=Xtags
|
||||||
|
normal! G$
|
||||||
|
" This used to cause heap-buffer-overflow
|
||||||
|
tag f
|
||||||
|
|
||||||
|
bwipe!
|
||||||
|
set startofline&
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
local t = require('test.unit.testutil')
|
local t = require('test.unit.testutil')
|
||||||
local itp = t.gen_itp(it)
|
local itp = t.gen_itp(it)
|
||||||
|
|
||||||
|
local child_call_once = t.child_call_once
|
||||||
local cimport = t.cimport
|
local cimport = t.cimport
|
||||||
local eq = t.eq
|
local eq = t.eq
|
||||||
local ffi = t.ffi
|
local ffi = t.ffi
|
||||||
@@ -8,6 +9,12 @@ local to_cstr = t.to_cstr
|
|||||||
|
|
||||||
local strings = cimport('stdlib.h', './src/nvim/strings.h', './src/nvim/memory.h')
|
local strings = cimport('stdlib.h', './src/nvim/strings.h', './src/nvim/memory.h')
|
||||||
|
|
||||||
|
local UVARNUM_TYPE
|
||||||
|
|
||||||
|
child_call_once(function()
|
||||||
|
UVARNUM_TYPE = ffi.typeof('uvarnumber_T')
|
||||||
|
end)
|
||||||
|
|
||||||
describe('vim_strsave_escaped()', function()
|
describe('vim_strsave_escaped()', function()
|
||||||
local vim_strsave_escaped = function(s, chars)
|
local vim_strsave_escaped = function(s, chars)
|
||||||
local res = strings.vim_strsave_escaped(to_cstr(s), to_cstr(chars))
|
local res = strings.vim_strsave_escaped(to_cstr(s), to_cstr(chars))
|
||||||
@@ -140,13 +147,22 @@ end)
|
|||||||
|
|
||||||
describe('vim_snprintf()', function()
|
describe('vim_snprintf()', function()
|
||||||
local function a(expected, buf, bsize, fmt, ...)
|
local function a(expected, buf, bsize, fmt, ...)
|
||||||
eq(#expected, strings.vim_snprintf(buf, bsize, fmt, ...))
|
local args = { ... }
|
||||||
|
local ctx = string.format('snprintf(buf, %d, "%s"', bsize, fmt)
|
||||||
|
for _, x in ipairs(args) do
|
||||||
|
ctx = ctx .. ', ' .. tostring(x)
|
||||||
|
end
|
||||||
|
ctx = ctx .. string.format(') = %s', expected)
|
||||||
|
eq(#expected, strings.vim_snprintf(buf, bsize, fmt, ...), ctx)
|
||||||
if bsize > 0 then
|
if bsize > 0 then
|
||||||
local actual = ffi.string(buf, math.min(#expected + 1, bsize))
|
local actual = ffi.string(buf, math.min(#expected + 1, bsize))
|
||||||
eq(expected:sub(1, bsize - 1) .. '\0', actual)
|
eq(expected:sub(1, bsize - 1) .. '\0', actual, ctx)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function uv(n)
|
||||||
|
return ffi.cast(UVARNUM_TYPE, n)
|
||||||
|
end
|
||||||
local function i(n)
|
local function i(n)
|
||||||
return ffi.cast('int', n)
|
return ffi.cast('int', n)
|
||||||
end
|
end
|
||||||
@@ -181,7 +197,7 @@ describe('vim_snprintf()', function()
|
|||||||
a(' 1234567', buf, bsize, '%9ld', l(1234567))
|
a(' 1234567', buf, bsize, '%9ld', l(1234567))
|
||||||
a('1234567 ', buf, bsize, '%-9ld', l(1234567))
|
a('1234567 ', buf, bsize, '%-9ld', l(1234567))
|
||||||
a('deadbeef', buf, bsize, '%x', u(0xdeadbeef))
|
a('deadbeef', buf, bsize, '%x', u(0xdeadbeef))
|
||||||
a('001100', buf, bsize, '%06b', u(12))
|
a('001100', buf, bsize, '%06b', uv(12))
|
||||||
a('one two', buf, bsize, '%s %s', 'one', 'two')
|
a('one two', buf, bsize, '%s %s', 'one', 'two')
|
||||||
a('1.234000', buf, bsize, '%f', 1.234)
|
a('1.234000', buf, bsize, '%f', 1.234)
|
||||||
a('1.234000e+00', buf, bsize, '%e', 1.234)
|
a('1.234000e+00', buf, bsize, '%e', 1.234)
|
||||||
@@ -223,10 +239,10 @@ describe('vim_snprintf()', function()
|
|||||||
a('three one two', buf, bsize, '%3$s %1$s %2$s', 'one', 'two', 'three')
|
a('three one two', buf, bsize, '%3$s %1$s %2$s', 'one', 'two', 'three')
|
||||||
a('1234567', buf, bsize, '%1$d', i(1234567))
|
a('1234567', buf, bsize, '%1$d', i(1234567))
|
||||||
a('deadbeef', buf, bsize, '%1$x', u(0xdeadbeef))
|
a('deadbeef', buf, bsize, '%1$x', u(0xdeadbeef))
|
||||||
a('001100', buf, bsize, '%2$0*1$b', i(6), u(12))
|
a('001100', buf, bsize, '%2$0*1$b', i(6), uv(12))
|
||||||
a('001100', buf, bsize, '%1$0.*2$b', u(12), i(6))
|
a('001100', buf, bsize, '%1$0.*2$b', uv(12), i(6))
|
||||||
a('one two', buf, bsize, '%1$s %2$s', 'one', 'two')
|
a('one two', buf, bsize, '%1$s %2$s', 'one', 'two')
|
||||||
a('001100', buf, bsize, '%06b', u(12))
|
a('001100', buf, bsize, '%06b', uv(12))
|
||||||
a('two one', buf, bsize, '%2$s %1$s', 'one', 'two')
|
a('two one', buf, bsize, '%2$s %1$s', 'one', 'two')
|
||||||
a('1.234000', buf, bsize, '%1$f', 1.234)
|
a('1.234000', buf, bsize, '%1$f', 1.234)
|
||||||
a('1.234000e+00', buf, bsize, '%1$e', 1.234)
|
a('1.234000e+00', buf, bsize, '%1$e', 1.234)
|
||||||
|
@@ -146,11 +146,16 @@ local function filter_complex_blocks(body)
|
|||||||
or string.find(line, 'value_init_')
|
or string.find(line, 'value_init_')
|
||||||
or string.find(line, 'UUID_NULL') -- static const uuid_t UUID_NULL = {...}
|
or string.find(line, 'UUID_NULL') -- static const uuid_t UUID_NULL = {...}
|
||||||
or string.find(line, 'inline _Bool')
|
or string.find(line, 'inline _Bool')
|
||||||
|
-- used by musl libc headers on 32-bit arches via __REDIR marco
|
||||||
|
or string.find(line, '__typeof__')
|
||||||
-- used by macOS headers
|
-- used by macOS headers
|
||||||
or string.find(line, 'typedef enum : ')
|
or string.find(line, 'typedef enum : ')
|
||||||
or string.find(line, 'mach_vm_range_recipe')
|
or string.find(line, 'mach_vm_range_recipe')
|
||||||
)
|
)
|
||||||
then
|
then
|
||||||
|
-- Remove GCC's extension keyword which is just used to disable warnings.
|
||||||
|
line = string.gsub(line, '__extension__', '')
|
||||||
|
|
||||||
result[#result + 1] = line
|
result[#result + 1] = line
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Reference in New Issue
Block a user