aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/eval.txt11
-rwxr-xr-xscripts/vim-patch.sh2
-rw-r--r--src/nvim/edit.c6
-rw-r--r--src/nvim/eval.c41
-rw-r--r--src/nvim/event/process.c3
-rw-r--r--src/nvim/ex_docmd.c8
-rw-r--r--src/nvim/ex_getln.c4
-rw-r--r--src/nvim/globals.h4
-rw-r--r--src/nvim/mark.c25
-rw-r--r--src/nvim/option.c9
-rw-r--r--src/nvim/screen.c2
-rw-r--r--src/nvim/search.c10
-rw-r--r--src/nvim/shada.c14
-rw-r--r--src/nvim/tag.c9
-rw-r--r--src/nvim/testdir/test_cmdline.vim44
-rw-r--r--src/nvim/testdir/test_mksession.vim11
-rw-r--r--src/nvim/testdir/test_popup.vim30
-rw-r--r--src/nvim/vim.h3
-rw-r--r--src/nvim/window.c41
-rw-r--r--test/README.md5
-rw-r--r--test/functional/api/vim_spec.lua9
-rw-r--r--test/functional/core/job_spec.lua42
-rw-r--r--test/functional/eval/ctx_functions_spec.lua8
-rw-r--r--test/functional/plugin/shada_spec.lua2
-rw-r--r--test/functional/ui/wildmode_spec.lua4
-rw-r--r--test/helpers.lua2
-rw-r--r--test/unit/viml/expressions/parser_spec.lua4
27 files changed, 226 insertions, 127 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index f45f99ede2..06f88955c9 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -5411,7 +5411,8 @@ jobstop({id}) *jobstop()*
See |job-control|.
jobwait({ids}[, {timeout}]) *jobwait()*
- Wait for a set of jobs to complete.
+ Wait for a set of jobs and their |on_exit| handlers to
+ complete.
{ids} is a list of |job-id|s to wait for.
{timeout} is the maximum waiting time in milliseconds, -1
@@ -5427,10 +5428,10 @@ jobwait({ids}[, {timeout}]) *jobwait()*
Returns a list of len({ids}) integers, where each integer is
the wait-result of the corresponding job. Each wait-result is
one of the following:
- * Exit-code, if the job exited
- * -1 if the timeout was exceeded
- * -2 if the job was interrupted
- * -3 if the |job-id| is invalid
+ Exit-code, if the job exited
+ -1 if the timeout was exceeded
+ -2 if the job was interrupted (by |CTRL-C|)
+ -3 if the job-id is invalid
join({list} [, {sep}]) *join()*
Join the items in {list} together into one String.
diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index a5dca26b46..2cc32f0dd0 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -430,6 +430,7 @@ list_missing_vimpatches() {
fi
# Get missing Vim commits
+ set +u # Avoid "unbound variable" with bash < 4.4 below.
for vim_commit in $(list_vim_commits "${git_log_args[@]}"); do
# Check for vim-patch:<commit_hash> (usually runtime updates).
token="vim-patch:${vim_commit:0:7}"
@@ -449,6 +450,7 @@ list_missing_vimpatches() {
echo "$vim_commit"
fi
done
+ set -u
}
# Prints a human-formatted list of Vim commits, with instructional messages.
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index ca64cc091d..16c4882975 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -5541,13 +5541,15 @@ insertchar (
// 'paste' is set)..
// Don't do this when there an InsertCharPre autocommand is defined,
// because we need to fire the event for every character.
+ // Do the check for InsertCharPre before the call to vpeekc() because the
+ // InsertCharPre autocommand could change the input buffer.
if (!ISSPECIAL(c)
&& (!has_mbyte || (*mb_char2len)(c) == 1)
+ && !has_event(EVENT_INSERTCHARPRE)
&& vpeekc() != NUL
&& !(State & REPLACE_FLAG)
&& !cindent_on()
- && !p_ri
- && !has_event(EVENT_INSERTCHARPRE)) {
+ && !p_ri) {
#define INPUT_BUFLEN 100
char_u buf[INPUT_BUFLEN + 1];
int i;
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index b9a0913baa..fa9777b651 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -12437,35 +12437,30 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (check_restricted() || check_secure()) {
return;
}
-
if (argvars[0].v_type != VAR_LIST || (argvars[1].v_type != VAR_NUMBER
&& argvars[1].v_type != VAR_UNKNOWN)) {
EMSG(_(e_invarg));
return;
}
-
+ ui_busy_start();
list_T *args = argvars[0].vval.v_list;
Channel **jobs = xcalloc(tv_list_len(args), sizeof(*jobs));
-
- ui_busy_start();
MultiQueue *waiting_jobs = multiqueue_new_parent(loop_on_put, &main_loop);
- // For each item in the input list append an integer to the output list. -3
- // is used to represent an invalid job id, -2 is for a interrupted job and
- // -1 for jobs that were skipped or timed out.
+ // Validate, prepare jobs for waiting.
int i = 0;
TV_LIST_ITER_CONST(args, arg, {
Channel *chan = NULL;
if (TV_LIST_ITEM_TV(arg)->v_type != VAR_NUMBER
|| !(chan = find_job(TV_LIST_ITEM_TV(arg)->vval.v_number, false))) {
- jobs[i] = NULL;
+ jobs[i] = NULL; // Invalid job.
} else {
jobs[i] = chan;
channel_incref(chan);
if (chan->stream.proc.status < 0) {
- // Process any pending events for the job because we'll temporarily
- // replace the parent queue
+ // Process any pending events on the job's queue before temporarily
+ // replacing it.
multiqueue_process_events(chan->events);
multiqueue_replace_parent(chan->events, waiting_jobs);
}
@@ -12482,40 +12477,36 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr)
for (i = 0; i < tv_list_len(args); i++) {
if (remaining == 0) {
- // timed out
- break;
+ break; // Timeout.
}
-
- // if the job already exited, but wasn't freed yet
- if (jobs[i] == NULL || jobs[i]->stream.proc.status >= 0) {
- continue;
+ if (jobs[i] == NULL) {
+ continue; // Invalid job, will assign status=-3 below.
}
-
int status = process_wait(&jobs[i]->stream.proc, remaining,
waiting_jobs);
if (status < 0) {
- // interrupted or timed out, skip remaining jobs.
- break;
+ break; // Interrupted (CTRL-C) or timeout, skip remaining jobs.
}
if (remaining > 0) {
uint64_t now = os_hrtime();
- remaining -= (int) ((now - before) / 1000000);
+ remaining = MIN(0, remaining - (int)((now - before) / 1000000));
before = now;
- if (remaining <= 0) {
- break;
- }
}
}
list_T *const rv = tv_list_alloc(tv_list_len(args));
- // restore the parent queue for any jobs still alive
+ // For each job:
+ // * Restore its parent queue if the job is still alive.
+ // * Append its status to the output list, or:
+ // -3 for "invalid job id"
+ // -2 for "interrupted" (user hit CTRL-C)
+ // -1 for jobs that were skipped or timed out
for (i = 0; i < tv_list_len(args); i++) {
if (jobs[i] == NULL) {
tv_list_append_number(rv, -3);
continue;
}
- // restore the parent queue for the job
multiqueue_process_events(jobs[i]->events);
multiqueue_replace_parent(jobs[i]->events, main_loop.events);
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c
index c31ecdaddf..8e9964bd37 100644
--- a/src/nvim/event/process.c
+++ b/src/nvim/event/process.c
@@ -181,8 +181,7 @@ int process_wait(Process *proc, int ms, MultiQueue *events)
got_int // interrupted by the user
|| proc->refcount == 1); // job exited
- // we'll assume that a user frantically hitting interrupt doesn't like
- // the current job. Signal that it has to be killed.
+ // Assume that a user hitting CTRL-C does not like the current job. Kill it.
if (got_int) {
got_int = false;
process_stop(proc);
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index b880ec4f6d..85ec4efd3a 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -9990,12 +9990,18 @@ static void ex_set(exarg_T *eap)
(void)do_set(eap->arg, flags);
}
+void set_no_hlsearch(bool flag)
+{
+ no_hlsearch = flag;
+ set_vim_var_nr(VV_HLSEARCH, !no_hlsearch && p_hls);
+}
+
/*
* ":nohlsearch"
*/
static void ex_nohlsearch(exarg_T *eap)
{
- SET_NO_HLSEARCH(TRUE);
+ set_no_hlsearch(true);
redraw_all_later(SOME_VALID);
}
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 4f35555098..f00367d9ca 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -1830,7 +1830,7 @@ static int command_line_changed(CommandLineState *s)
// If there is no command line, don't do anything
if (ccline.cmdlen == 0) {
i = 0;
- SET_NO_HLSEARCH(true); // turn off previous highlight
+ set_no_hlsearch(true); // turn off previous highlight
redraw_all_later(SOME_VALID);
} else {
int search_flags = SEARCH_OPT + SEARCH_NOOF + SEARCH_PEEK;
@@ -1888,7 +1888,7 @@ static int command_line_changed(CommandLineState *s)
// Disable 'hlsearch' highlighting if the pattern matches
// everything. Avoids a flash when typing "foo\|".
if (empty_pattern(ccline.cmdbuff)) {
- SET_NO_HLSEARCH(true);
+ set_no_hlsearch(true);
}
validate_cursor();
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index ad321963fe..9a7b5425bf 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -862,8 +862,8 @@ EXTERN char_u wim_flags[4];
# define STL_IN_TITLE 2
EXTERN int stl_syntax INIT(= 0);
-/* don't use 'hlsearch' temporarily */
-EXTERN int no_hlsearch INIT(= FALSE);
+// don't use 'hlsearch' temporarily
+EXTERN bool no_hlsearch INIT(= false);
/* Page number used for %N in 'pageheader' and 'guitablabel'. */
EXTERN linenr_T printer_page_num;
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index 9f357575d0..e103d3cb55 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -1162,21 +1162,18 @@ void mark_col_adjust(
// When deleting lines, this may create duplicate marks in the
// jumplist. They will be removed here for the specified window.
-// When "loadfiles" is true first ensure entries have the "fnum" field set
-// (this may be a bit slow).
-void cleanup_jumplist(win_T *wp, bool loadfiles)
+// When "checktail" is true, removes tail jump if it matches current position.
+void cleanup_jumplist(win_T *wp, bool checktail)
{
int i;
- if (loadfiles) {
- // If specified, load all the files from the jump list. This is
- // needed to properly clean up duplicate entries, but will take some
- // time.
- for (i = 0; i < wp->w_jumplistlen; i++) {
- if ((wp->w_jumplist[i].fmark.fnum == 0)
- && (wp->w_jumplist[i].fmark.mark.lnum != 0)) {
- fname2fnum(&wp->w_jumplist[i]);
- }
+ // Load all the files from the jump list. This is
+ // needed to properly clean up duplicate entries, but will take some
+ // time.
+ for (i = 0; i < wp->w_jumplistlen; i++) {
+ if ((wp->w_jumplist[i].fmark.fnum == 0)
+ && (wp->w_jumplist[i].fmark.mark.lnum != 0)) {
+ fname2fnum(&wp->w_jumplist[i]);
}
}
@@ -1213,8 +1210,8 @@ void cleanup_jumplist(win_T *wp, bool loadfiles)
// When pointer is below last jump, remove the jump if it matches the current
// line. This avoids useless/phantom jumps. #9805
- if (loadfiles // otherwise (i.e.: Shada), last entry should be kept
- && wp->w_jumplistlen && wp->w_jumplistidx == wp->w_jumplistlen) {
+ if (checktail && wp->w_jumplistlen
+ && wp->w_jumplistidx == wp->w_jumplistlen) {
const xfmark_T *fm_last = &wp->w_jumplist[wp->w_jumplistlen - 1];
if (fm_last->fmark.fnum == curbuf->b_fnum
&& fm_last->fmark.mark.lnum == wp->w_cursor.lnum) {
diff --git a/src/nvim/option.c b/src/nvim/option.c
index d1753526a7..ed9128dbbf 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -3959,7 +3959,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp,
redraw_all_later(SOME_VALID);
} else if ((int *)varp == &p_hls) {
// when 'hlsearch' is set or reset: reset no_hlsearch
- SET_NO_HLSEARCH(false);
+ set_no_hlsearch(false);
} else if ((int *)varp == &curwin->w_p_scb) {
// when 'scrollbind' is set: snapshot the current position to avoid a jump
// at the end of normal_cmd()
@@ -4330,19 +4330,26 @@ static char *set_num_option(int opt_idx, char_u *varp, long value,
// Number options that need some action when changed
if (pp == &p_wh) {
+ // 'winheight'
if (!ONE_WINDOW && curwin->w_height < p_wh) {
win_setheight((int)p_wh);
}
} else if (pp == &p_hh) {
+ // 'helpheight'
if (!ONE_WINDOW && curbuf->b_help && curwin->w_height < p_hh) {
win_setheight((int)p_hh);
}
} else if (pp == &p_wmh) {
+ // 'winminheight'
win_setminheight();
} else if (pp == &p_wiw) {
+ // 'winwidth'
if (!ONE_WINDOW && curwin->w_width < p_wiw) {
win_setwidth((int)p_wiw);
}
+ } else if (pp == &p_wmw) {
+ // 'winminwidth'
+ win_setminwidth();
} else if (pp == &p_ls) {
last_status(false); // (re)set last window status line.
} else if (pp == &p_stal) {
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index b9469686b5..13eb088813 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -5762,7 +5762,7 @@ next_search_hl (
if (shl == &search_hl) {
// don't free regprog in the match list, it's a copy
vim_regfree(shl->rm.regprog);
- SET_NO_HLSEARCH(TRUE);
+ set_no_hlsearch(true);
}
shl->rm.regprog = NULL;
shl->lnum = 0;
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 26549208a8..7d1c19d68c 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -100,7 +100,7 @@ static struct spat saved_spats[2];
// searching
static struct spat saved_last_search_spat;
static int saved_last_idx = 0;
-static int saved_no_hlsearch = 0;
+static bool saved_no_hlsearch = false;
static char_u *mr_pattern = NULL; // pattern used by search_regcomp()
static int mr_pattern_alloced = false; // mr_pattern was allocated
@@ -248,7 +248,7 @@ void save_re_pat(int idx, char_u *pat, int magic)
/* If 'hlsearch' set and search pat changed: need redraw. */
if (p_hls)
redraw_all_later(SOME_VALID);
- SET_NO_HLSEARCH(FALSE);
+ set_no_hlsearch(false);
}
}
@@ -281,7 +281,7 @@ void restore_search_patterns(void)
free_spat(&spats[1]);
spats[1] = saved_spats[1];
last_idx = saved_last_idx;
- SET_NO_HLSEARCH(saved_no_hlsearch);
+ set_no_hlsearch(saved_no_hlsearch);
}
}
@@ -330,7 +330,7 @@ void restore_last_search_pattern(void)
spats[RE_SEARCH] = saved_last_search_spat;
set_vv_searchforward();
last_idx = saved_last_idx;
- SET_NO_HLSEARCH(saved_no_hlsearch);
+ set_no_hlsearch(saved_no_hlsearch);
}
char_u *last_search_pattern(void)
@@ -1048,7 +1048,7 @@ int do_search(
*/
if (no_hlsearch && !(options & SEARCH_KEEP)) {
redraw_all_later(SOME_VALID);
- SET_NO_HLSEARCH(FALSE);
+ set_no_hlsearch(false);
}
/*
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index 69e6d61464..7e7e7cfdf7 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -32,6 +32,7 @@
#include "nvim/api/private/helpers.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
+#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
#include "nvim/search.h"
#include "nvim/regexp.h"
@@ -1274,7 +1275,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
if (cur_entry.data.search_pattern.is_last_used) {
set_last_used_pattern(
cur_entry.data.search_pattern.is_substitute_pattern);
- SET_NO_HLSEARCH(!cur_entry.data.search_pattern.highlighted);
+ set_no_hlsearch(!cur_entry.data.search_pattern.highlighted);
}
// Do not free shada entry: its allocated memory was saved above.
break;
@@ -2736,6 +2737,8 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer,
}
// Initialize jump list
+ setpcmark();
+ cleanup_jumplist(curwin, false);
wms->jumps_size = shada_init_jumps(wms->jumps, &removable_bufs);
// Initialize global marks
@@ -4085,11 +4088,13 @@ static bool shada_removable(const char *name)
static inline size_t shada_init_jumps(
PossiblyFreedShadaEntry *jumps, khash_t(bufset) *const removable_bufs)
{
- // Initialize jump list
+ if (!curwin->w_jumplistlen) {
+ return 0;
+ }
+
size_t jumps_size = 0;
const void *jump_iter = NULL;
- setpcmark();
- cleanup_jumplist(curwin, false);
+
do {
xfmark_T fm;
jump_iter = mark_jumplist_iter(jump_iter, curwin, &fm);
@@ -4163,6 +4168,7 @@ void shada_encode_jumps(msgpack_sbuffer *const sbuf)
khash_t(bufset) removable_bufs = KHASH_EMPTY_TABLE(bufset);
find_removable_bufs(&removable_bufs);
PossiblyFreedShadaEntry jumps[JUMPLISTSIZE];
+ cleanup_jumplist(curwin, true);
size_t jumps_size = shada_init_jumps(jumps, &removable_bufs);
msgpack_packer packer;
msgpack_packer_init(&packer, sbuf, msgpack_sbuffer_write);
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index 88676abc2e..beee3c7594 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -2310,7 +2310,6 @@ static int jumpto_tag(
int retval = FAIL;
int getfile_result = GETFILE_UNUSED;
int search_options;
- int save_no_hlsearch;
win_T *curwin_save = NULL;
char_u *full_fname = NULL;
const bool old_KeyTyped = KeyTyped; // getting the file may reset it
@@ -2453,9 +2452,9 @@ static int jumpto_tag(
secure = 1;
++sandbox;
save_magic = p_magic;
- p_magic = FALSE; /* always execute with 'nomagic' */
- /* Save value of no_hlsearch, jumping to a tag is not a real search */
- save_no_hlsearch = no_hlsearch;
+ p_magic = false; // always execute with 'nomagic'
+ // Save value of no_hlsearch, jumping to a tag is not a real search
+ const bool save_no_hlsearch = no_hlsearch;
/*
* If 'cpoptions' contains 't', store the search pattern for the "n"
@@ -2560,7 +2559,7 @@ static int jumpto_tag(
--sandbox;
/* restore no_hlsearch when keeping the old search pattern */
if (search_options) {
- SET_NO_HLSEARCH(save_no_hlsearch);
+ set_no_hlsearch(save_no_hlsearch);
}
// Return OK if jumped to another file (at least we found the file!).
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index f43ea0e923..e6aafd964b 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -15,14 +15,48 @@ func Test_complete_list()
endfunc
func Test_complete_wildmenu()
- call writefile(['testfile1'], 'Xtestfile1')
- call writefile(['testfile2'], 'Xtestfile2')
+ call mkdir('Xdir1/Xdir2', 'p')
+ call writefile(['testfile1'], 'Xdir1/Xtestfile1')
+ call writefile(['testfile2'], 'Xdir1/Xtestfile2')
+ call writefile(['testfile3'], 'Xdir1/Xdir2/Xtestfile3')
+ call writefile(['testfile3'], 'Xdir1/Xdir2/Xtestfile4')
set wildmenu
- call feedkeys(":e Xtestf\t\t\r", "tx")
+
+ " Pressing <Tab> completes, and moves to next files when pressing again.
+ call feedkeys(":e Xdir1/\<Tab>\<Tab>\<CR>", 'tx')
+ call assert_equal('testfile1', getline(1))
+ call feedkeys(":e Xdir1/\<Tab>\<Tab>\<Tab>\<CR>", 'tx')
+ call assert_equal('testfile2', getline(1))
+
+ " <S-Tab> is like <Tab> but begin with the last match and then go to
+ " previous.
+ call feedkeys(":e Xdir1/Xtest\<S-Tab>\<CR>", 'tx')
call assert_equal('testfile2', getline(1))
+ call feedkeys(":e Xdir1/Xtest\<S-Tab>\<S-Tab>\<CR>", 'tx')
+ call assert_equal('testfile1', getline(1))
- call delete('Xtestfile1')
- call delete('Xtestfile2')
+ " <Left>/<Right> to move to previous/next file.
+ call feedkeys(":e Xdir1/\<Tab>\<Right>\<CR>", 'tx')
+ call assert_equal('testfile1', getline(1))
+ call feedkeys(":e Xdir1/\<Tab>\<Right>\<Right>\<CR>", 'tx')
+ call assert_equal('testfile2', getline(1))
+ call feedkeys(":e Xdir1/\<Tab>\<Right>\<Right>\<Left>\<CR>", 'tx')
+ call assert_equal('testfile1', getline(1))
+
+ " <Up>/<Down> to go up/down directories.
+ call feedkeys(":e Xdir1/\<Tab>\<Down>\<CR>", 'tx')
+ call assert_equal('testfile3', getline(1))
+ call feedkeys(":e Xdir1/\<Tab>\<Down>\<Up>\<Right>\<CR>", 'tx')
+ call assert_equal('testfile1', getline(1))
+
+ " cleanup
+ %bwipe
+ call delete('Xdir1/Xdir2/Xtestfile4')
+ call delete('Xdir1/Xdir2/Xtestfile3')
+ call delete('Xdir1/Xtestfile2')
+ call delete('Xdir1/Xtestfile1')
+ call delete('Xdir1/Xdir2', 'd')
+ call delete('Xdir1', 'd')
set nowildmenu
endfunc
diff --git a/src/nvim/testdir/test_mksession.vim b/src/nvim/testdir/test_mksession.vim
index 0e56ed2ff3..b7169444d1 100644
--- a/src/nvim/testdir/test_mksession.vim
+++ b/src/nvim/testdir/test_mksession.vim
@@ -106,13 +106,22 @@ endfunc
func Test_mksession_winheight()
new
- set winheight=10 winminheight=2
+ set winheight=10
+ set winminheight=2
mksession! Xtest_mks.out
source Xtest_mks.out
call delete('Xtest_mks.out')
endfunc
+func Test_mksession_large_winheight()
+ set winheight=999
+ mksession! Xtest_mks_winheight.out
+ set winheight&
+ source Xtest_mks_winheight.out
+ call delete('Xtest_mks_winheight.out')
+endfunc
+
" Verify that arglist is stored correctly to the session file.
func Test_mksession_arglist()
argdel *
diff --git a/src/nvim/testdir/test_popup.vim b/src/nvim/testdir/test_popup.vim
index 162df4b76e..53df30bb19 100644
--- a/src/nvim/testdir/test_popup.vim
+++ b/src/nvim/testdir/test_popup.vim
@@ -746,6 +746,36 @@ func Test_popup_complete_backwards()
bwipe!
endfunc
+fun! Test_complete_o_tab()
+ throw 'skipped: Nvim does not support test_override()'
+ let s:o_char_pressed = 0
+
+ fun! s:act_on_text_changed()
+ if s:o_char_pressed
+ let s:o_char_pressed = 0
+ call feedkeys("\<c-x>\<c-n>", 'i')
+ endif
+ endf
+
+ set completeopt=menu,noselect
+ new
+ imap <expr> <buffer> <tab> pumvisible() ? "\<c-p>" : "X"
+ autocmd! InsertCharPre <buffer> let s:o_char_pressed = (v:char ==# 'o')
+ autocmd! TextChangedI <buffer> call <sid>act_on_text_changed()
+ call setline(1, ['hoard', 'hoax', 'hoarse', ''])
+ let l:expected = ['hoard', 'hoax', 'hoarse', 'hoax', 'hoax']
+ call cursor(4,1)
+ call test_override("char_avail", 1)
+ call feedkeys("Ahoa\<tab>\<tab>\<c-y>\<esc>", 'tx')
+ call feedkeys("oho\<tab>\<tab>\<c-y>\<esc>", 'tx')
+ call assert_equal(l:expected, getline(1,'$'))
+
+ call test_override("char_avail", 0)
+ bwipe!
+ set completeopt&
+ delfunc s:act_on_text_changed
+endf
+
func Test_popup_complete_info_01()
new
inoremap <buffer><F5> <C-R>=complete_info().mode<CR>
diff --git a/src/nvim/vim.h b/src/nvim/vim.h
index 60737014b3..51f143a3d7 100644
--- a/src/nvim/vim.h
+++ b/src/nvim/vim.h
@@ -296,9 +296,6 @@ enum { FOLD_TEXT_LEN = 51 }; //!< buffer size for get_foldtext()
#include "nvim/buffer_defs.h" // buffer and windows
#include "nvim/ex_cmds_defs.h" // Ex command defines
-# define SET_NO_HLSEARCH(flag) no_hlsearch = (flag); set_vim_var_nr( \
- VV_HLSEARCH, !no_hlsearch && p_hls)
-
// Used for flags in do_in_path()
#define DIP_ALL 0x01 // all matches, not just the first one
#define DIP_DIR 0x02 // find directories instead of files
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 0e8cfcedf5..6861e19ca7 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -5229,27 +5229,42 @@ static void frame_setwidth(frame_T *curfrp, int width)
}
}
-/*
- * Check 'winminheight' for a valid value.
- */
+// Check 'winminheight' for a valid value and reduce it if needed.
void win_setminheight(void)
{
- int room;
- int first = TRUE;
+ bool first = true;
- /* loop until there is a 'winminheight' that is possible */
+ // loop until there is a 'winminheight' that is possible
while (p_wmh > 0) {
- /* TODO: handle vertical splits */
- room = -p_wh;
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- room += wp->w_height - p_wmh;
+ const int room = Rows - p_ch;
+ const int needed = frame_minheight(topframe, NULL);
+ if (room >= needed) {
+ break;
+ }
+ p_wmh--;
+ if (first) {
+ EMSG(_(e_noroom));
+ first = false;
}
- if (room >= 0)
+ }
+}
+
+// Check 'winminwidth' for a valid value and reduce it if needed.
+void win_setminwidth(void)
+{
+ bool first = true;
+
+ // loop until there is a 'winminheight' that is possible
+ while (p_wmw > 0) {
+ const int room = Columns;
+ const int needed = frame_minwidth(topframe, NULL);
+ if (room >= needed) {
break;
- --p_wmh;
+ }
+ p_wmw--;
if (first) {
EMSG(_(e_noroom));
- first = FALSE;
+ first = false;
}
}
}
diff --git a/test/README.md b/test/README.md
index 73d51c995c..60279589b1 100644
--- a/test/README.md
+++ b/test/README.md
@@ -249,11 +249,6 @@ the file).
Configuration
=============
-busted (luassert) by default does not print the full result of deeply-nested
-tables. But sometimes it's useful while debugging a test.
-
- assert:set_parameter('TableFormatLevel', 1000000)
-
Test behaviour is affected by environment variables. Currently supported
(Functional, Unit, Benchmarks) (when Defined; when set to _1_; when defined,
treated as Integer; when defined, treated as String; when defined, treated as
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 851feddb54..07c0c5c8f3 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -922,11 +922,9 @@ describe('API', function()
},
['jumps'] = eval(([[
- filter(map(add(
- getjumplist()[0], { 'bufnr': bufnr('%'), 'lnum': getcurpos()[1] }),
- 'filter(
- { "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum },
- { k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)')
+ filter(map(getjumplist()[0], 'filter(
+ { "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum },
+ { k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)')
]]):gsub('\n', '')),
['buflist'] = eval([[
@@ -1568,7 +1566,6 @@ describe('API', function()
return ('%s(%s)%s'):format(typ, args, rest)
end
end
- assert:set_parameter('TableFormatLevel', 1000000)
require('test.unit.viml.expressions.parser_tests')(
it_maybe_pending, _check_parsing, hl, fmtn)
end)
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua
index 73b0a0009d..88951e5b51 100644
--- a/test/functional/core/job_spec.lua
+++ b/test/functional/core/job_spec.lua
@@ -582,13 +582,17 @@ describe('jobs', function()
it('will run callbacks while waiting', function()
source([[
- let g:dict = {'id': 10}
- let g:exits = 0
- function g:dict.on_exit(id, code, event)
+ let g:dict = {}
+ let g:jobs = []
+ let g:exits = []
+ function g:dict.on_stdout(id, code, event) abort
+ call add(g:jobs, a:id)
+ endfunction
+ function g:dict.on_exit(id, code, event) abort
if a:code != 5
throw 'Error!'
endif
- let g:exits += 1
+ call add(g:exits, a:id)
endfunction
call jobwait(has('win32') ? [
\ jobstart('Start-Sleep -Milliseconds 100; exit 5', g:dict),
@@ -601,9 +605,10 @@ describe('jobs', function()
\ jobstart('sleep 0.050; exit 5', g:dict),
\ jobstart('sleep 0.070; exit 5', g:dict)
\ ])
- call rpcnotify(g:channel, 'wait', g:exits)
+ call rpcnotify(g:channel, 'wait', sort(g:jobs), sort(g:exits))
]])
- eq({'notification', 'wait', {4}}, next_msg())
+ eq({'notification', 'wait',
+ {{3,4,5,6}, {3,4,5,6}}}, next_msg())
end)
it('will return status codes in the order of passed ids', function()
@@ -728,15 +733,28 @@ describe('jobs', function()
end)
end)
- -- FIXME need to wait until jobsend succeeds before calling jobstop
- pending('will only emit the "exit" event after "stdout" and "stderr"', function()
- nvim('command', "let g:job_opts.on_stderr = function('s:OnEvent')")
+ pending('exit event follows stdout, stderr', function()
+ nvim('command', "let g:job_opts.on_stderr = function('OnEvent')")
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
- local jobid = nvim('eval', 'j')
nvim('eval', 'jobsend(j, "abcdef")')
nvim('eval', 'jobstop(j)')
- eq({'notification', 'j', {0, {jobid, 'stdout', {'abcdef'}}}}, next_msg())
- eq({'notification', 'j', {0, {jobid, 'exit'}}}, next_msg())
+ expect_msg_seq(
+ { {'notification', 'stdout', {0, {'abcdef'}}},
+ {'notification', 'stdout', {0, {''}}},
+ {'notification', 'stderr', {0, {''}}},
+ },
+ -- Alternative sequence:
+ { {'notification', 'stderr', {0, {''}}},
+ {'notification', 'stdout', {0, {'abcdef'}}},
+ {'notification', 'stdout', {0, {''}}},
+ },
+ -- Alternative sequence:
+ { {'notification', 'stdout', {0, {'abcdef'}}},
+ {'notification', 'stderr', {0, {''}}},
+ {'notification', 'stdout', {0, {''}}},
+ }
+ )
+ eq({'notification', 'exit', {0, 143}}, next_msg())
end)
it('cannot have both rpc and pty options', function()
diff --git a/test/functional/eval/ctx_functions_spec.lua b/test/functional/eval/ctx_functions_spec.lua
index 35133e2341..742fc4893b 100644
--- a/test/functional/eval/ctx_functions_spec.lua
+++ b/test/functional/eval/ctx_functions_spec.lua
@@ -291,11 +291,9 @@ describe('context functions', function()
local with_jumps = {
['jumps'] = eval(([[
- filter(map(add(
- getjumplist()[0], { 'bufnr': bufnr('%'), 'lnum': getcurpos()[1] }),
- 'filter(
- { "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum },
- { k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)')
+ filter(map(getjumplist()[0], 'filter(
+ { "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum },
+ { k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)')
]]):gsub('\n', ''))
}
diff --git a/test/functional/plugin/shada_spec.lua b/test/functional/plugin/shada_spec.lua
index c0104a58f7..d96b479a62 100644
--- a/test/functional/plugin/shada_spec.lua
+++ b/test/functional/plugin/shada_spec.lua
@@ -1360,8 +1360,6 @@ describe('autoload/shada.vim', function()
nvim_command('unlet g:__actual')
end
- assert:set_parameter('TableFormatLevel', 100)
-
it('works with multiple items', function()
strings2sd_eq({{
type=11, timestamp=0, data={
diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua
index 738466ae2b..2215c0c7d9 100644
--- a/test/functional/ui/wildmode_spec.lua
+++ b/test/functional/ui/wildmode_spec.lua
@@ -98,8 +98,8 @@ describe("'wildmenu'", function()
]]}
-- cmdline CTRL-D display should also be preserved.
- feed([[<C-\><C-N>]])
- feed([[:sign <C-D>]]) -- Invoke cmdline CTRL-D.
+ feed([[<C-U>]])
+ feed([[sign <C-D>]]) -- Invoke cmdline CTRL-D.
expect_stay_unchanged{grid=[[
:sign |
define place |
diff --git a/test/helpers.lua b/test/helpers.lua
index 25fff55596..779d33e3b1 100644
--- a/test/helpers.lua
+++ b/test/helpers.lua
@@ -6,6 +6,8 @@ local lfs = require('lfs')
local relpath = require('pl.path').relpath
local Paths = require('test.config.paths')
+assert:set_parameter('TableFormatLevel', 100)
+
local quote_me = '[^.%w%+%-%@%_%/]' -- complement (needn't quote)
local function shell_quote(str)
if string.find(str, quote_me) or str == '' then
diff --git a/test/unit/viml/expressions/parser_spec.lua b/test/unit/viml/expressions/parser_spec.lua
index a8f29529ec..032baf6578 100644
--- a/test/unit/viml/expressions/parser_spec.lua
+++ b/test/unit/viml/expressions/parser_spec.lua
@@ -451,10 +451,6 @@ local function phl2lua(pstate)
return ret
end
-child_call_once(function()
- assert:set_parameter('TableFormatLevel', 1000000)
-end)
-
describe('Expressions parser', function()
local function _check_parsing(opts, str, exp_ast, exp_highlighting_fs,
nz_flags_exps)