aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/eval.c4
-rw-r--r--src/nvim/eval.lua1
-rw-r--r--src/nvim/eval/funcs.c97
-rw-r--r--src/nvim/lua/vim.lua12
-rw-r--r--src/nvim/option.c5
-rw-r--r--src/nvim/tag.c2
-rw-r--r--src/nvim/terminal.c8
-rw-r--r--src/nvim/testdir/test_functions.vim30
8 files changed, 153 insertions, 6 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index a6162af472..4a0876a952 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -915,7 +915,7 @@ varnumber_T eval_to_number(char_u *expr)
* Save the current typeval in "save_tv".
* When not used yet add the variable to the v: hashtable.
*/
-static void prepare_vimvar(int idx, typval_T *save_tv)
+void prepare_vimvar(int idx, typval_T *save_tv)
{
*save_tv = vimvars[idx].vv_tv;
if (vimvars[idx].vv_type == VAR_UNKNOWN)
@@ -926,7 +926,7 @@ static void prepare_vimvar(int idx, typval_T *save_tv)
* Restore v: variable "idx" to typeval "save_tv".
* When no longer defined, remove the variable from the v: hashtable.
*/
-static void restore_vimvar(int idx, typval_T *save_tv)
+void restore_vimvar(int idx, typval_T *save_tv)
{
hashitem_T *hi;
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index d3e769a7ef..65c4cfe553 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -255,6 +255,7 @@ return {
pyeval={args=1},
pyxeval={args=1},
range={args={1, 3}},
+ readdir={args={1, 2}},
readfile={args={1, 3}},
reg_executing={},
reg_recording={},
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index bbe6f6de9d..217490ad10 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -2063,8 +2063,10 @@ static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (result != NULL) {
tv_list_append_string(rettv->vval.v_list, (const char *)result, -1);
}
- } else
+ XFREE_CLEAR(result);
+ } else {
rettv->vval.v_string = result;
+ }
} else {
// When the optional second argument is non-zero, don't remove matches
// for 'wildignore' and don't put matches for 'suffixes' at the end.
@@ -6314,6 +6316,99 @@ static void f_range(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
+// Evaluate "expr" for readdir().
+static varnumber_T readdir_checkitem(typval_T *expr, const char *name)
+{
+ typval_T save_val;
+ typval_T rettv;
+ typval_T argv[2];
+ varnumber_T retval = 0;
+ bool error = false;
+
+ prepare_vimvar(VV_VAL, &save_val);
+ set_vim_var_string(VV_VAL, name, -1);
+ argv[0].v_type = VAR_STRING;
+ argv[0].vval.v_string = (char_u *)name;
+
+ if (eval_expr_typval(expr, argv, 1, &rettv) == FAIL) {
+ goto theend;
+ }
+
+ retval = tv_get_number_chk(&rettv, &error);
+ if (error) {
+ retval = -1;
+ }
+
+ tv_clear(&rettv);
+
+theend:
+ set_vim_var_string(VV_VAL, NULL, 0);
+ restore_vimvar(VV_VAL, &save_val);
+ return retval;
+}
+
+// "readdir()" function
+static void f_readdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ typval_T *expr;
+ const char *path;
+ garray_T ga;
+ Directory dir;
+
+ tv_list_alloc_ret(rettv, kListLenUnknown);
+ path = tv_get_string(&argvars[0]);
+ expr = &argvars[1];
+ ga_init(&ga, (int)sizeof(char *), 20);
+
+ if (!os_scandir(&dir, path)) {
+ smsg(_(e_notopen), path);
+ } else {
+ for (;;) {
+ bool ignore;
+
+ path = os_scandir_next(&dir);
+ if (path == NULL) {
+ break;
+ }
+
+ ignore = (path[0] == '.'
+ && (path[1] == NUL || (path[1] == '.' && path[2] == NUL)));
+ if (!ignore && expr->v_type != VAR_UNKNOWN) {
+ varnumber_T r = readdir_checkitem(expr, path);
+
+ if (r < 0) {
+ break;
+ }
+ if (r == 0) {
+ ignore = true;
+ }
+ }
+
+ if (!ignore) {
+ ga_grow(&ga, 1);
+ ((char **)ga.ga_data)[ga.ga_len++] = xstrdup(path);
+ }
+ }
+
+ os_closedir(&dir);
+ }
+
+ rettv->vval.v_list = tv_list_alloc(kListLenShouldKnow);
+ if (rettv->vval.v_list != NULL) {
+ tv_list_ref(rettv->vval.v_list);
+ sort_strings((char_u **)ga.ga_data, ga.ga_len);
+ for (int i = 0; i < ga.ga_len; i++) {
+ path = ((const char **)ga.ga_data)[i];
+ tv_list_append_string(rettv->vval.v_list, path, -1);
+ }
+ }
+ for (int i = 0; i < ga.ga_len; i++) {
+ xfree(((uint8_t **)ga.ga_data)[i]);
+ }
+
+ ga_clear(&ga);
+}
+
/*
* "readfile()" function
*/
diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua
index 8ba550ea31..fc337c5e7e 100644
--- a/src/nvim/lua/vim.lua
+++ b/src/nvim/lua/vim.lua
@@ -212,6 +212,18 @@ do
vim.api.nvim_put(lines, 'c', true, true)
-- XXX: Normal-mode: workaround bad cursor-placement after first chunk.
vim.api.nvim_command('normal! a')
+ elseif phase < 2 and mode == 'R' then
+ local nchars = 0
+ for _, line in ipairs(lines) do
+ nchars = nchars + line:len()
+ end
+ local row, col = unpack(vim.api.nvim_win_get_cursor(0))
+ local bufline = vim.api.nvim_buf_get_lines(0, row-1, row, true)[1]
+ local firstline = lines[1]
+ firstline = bufline:sub(1, col)..firstline
+ lines[1] = firstline
+ lines[#lines] = lines[#lines]..bufline:sub(col + nchars + 1, bufline:len())
+ vim.api.nvim_buf_set_lines(0, row-1, row, false, lines)
else
vim.api.nvim_put(lines, 'c', false, true)
end
diff --git a/src/nvim/option.c b/src/nvim/option.c
index d7675f48d7..84ace55d91 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -7453,6 +7453,10 @@ dict_T *get_winbuf_options(const int bufopt)
/// global value when appropriate.
long get_scrolloff_value(void)
{
+ // Disallow scrolloff in terminal-mode. #11915
+ if (State & TERM_FOCUS) {
+ return 0;
+ }
return curwin->w_p_so < 0 ? p_so : curwin->w_p_so;
}
@@ -7462,4 +7466,3 @@ long get_sidescrolloff_value(void)
{
return curwin->w_p_siso < 0 ? p_siso : curwin->w_p_siso;
}
-
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index ff07a00952..81d1ef4c9f 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -1182,7 +1182,7 @@ static int find_tagfunc_tags(
if (result == FAIL) {
return FAIL;
}
- if (rettv.v_type == VAR_SPECIAL && rettv.vval.v_number == VV_NULL) {
+ if (rettv.v_type == VAR_SPECIAL && rettv.vval.v_special == kSpecialVarNull) {
tv_clear(&rettv);
return NOTDONE;
}
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 560a345333..a096b77ac6 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -343,12 +343,16 @@ void terminal_enter(void)
RedrawingDisabled = false;
// Disable these options in terminal-mode. They are nonsense because cursor is
- // placed at end of buffer to "follow" output.
+ // placed at end of buffer to "follow" output. #11072
win_T *save_curwin = curwin;
int save_w_p_cul = curwin->w_p_cul;
int save_w_p_cuc = curwin->w_p_cuc;
+ long save_w_p_so = curwin->w_p_so;
+ long save_w_p_siso = curwin->w_p_siso;
curwin->w_p_cul = false;
curwin->w_p_cuc = false;
+ curwin->w_p_so = 0;
+ curwin->w_p_siso = 0;
adjust_topline(s->term, buf, 0); // scroll to end
// erase the unfocused cursor
@@ -370,6 +374,8 @@ void terminal_enter(void)
if (save_curwin == curwin) { // save_curwin may be invalid (window closed)!
curwin->w_p_cul = save_w_p_cul;
curwin->w_p_cuc = save_w_p_cuc;
+ curwin->w_p_so = save_w_p_so;
+ curwin->w_p_siso = save_w_p_siso;
}
// draw the unfocused cursor
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index bd5cb6ad19..51689db9c4 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -1307,3 +1307,33 @@ func Test_bufadd_bufload()
bwipe otherName
call assert_equal(0, bufexists('someName'))
endfunc
+
+func Test_readdir()
+ call mkdir('Xdir')
+ call writefile([], 'Xdir/foo.txt')
+ call writefile([], 'Xdir/bar.txt')
+ call mkdir('Xdir/dir')
+
+ " All results
+ let files = readdir('Xdir')
+ call assert_equal(['bar.txt', 'dir', 'foo.txt'], sort(files))
+
+ " Only results containing "f"
+ let files = readdir('Xdir', { x -> stridx(x, 'f') !=- 1 })
+ call assert_equal(['foo.txt'], sort(files))
+
+ " Only .txt files
+ let files = readdir('Xdir', { x -> x =~ '.txt$' })
+ call assert_equal(['bar.txt', 'foo.txt'], sort(files))
+
+ " Only .txt files with string
+ let files = readdir('Xdir', 'v:val =~ ".txt$"')
+ call assert_equal(['bar.txt', 'foo.txt'], sort(files))
+
+ " Limit to 1 result.
+ let l = []
+ let files = readdir('Xdir', {x -> len(add(l, x)) == 2 ? -1 : 1})
+ call assert_equal(1, len(files))
+
+ call delete('Xdir', 'rf')
+endfunc