aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/cmdline.txt3
-rw-r--r--runtime/doc/starting.txt28
-rw-r--r--runtime/doc/vim_diff.txt3
-rw-r--r--src/nvim/ex_getln.c5
-rw-r--r--src/nvim/lua/executor.c31
-rw-r--r--src/nvim/main.c34
-rw-r--r--src/nvim/path.c7
-rw-r--r--test/functional/core/startup_spec.lua85
-rw-r--r--test/functional/helpers.lua1
-rw-r--r--test/functional/ui/wildmode_spec.lua59
-rw-r--r--test/unit/path_spec.lua17
11 files changed, 242 insertions, 31 deletions
diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt
index 562a1f23ac..098245b5a8 100644
--- a/runtime/doc/cmdline.txt
+++ b/runtime/doc/cmdline.txt
@@ -215,6 +215,9 @@ CTRL-Y When there is a modeless selection, copy the selection into
the clipboard.
If there is no selection CTRL-Y is inserted as a character.
+ *c_CTRL-Z*
+CTRL-Z Trigger 'wildmode'. Same as 'wildcharm', but always available.
+
CTRL-M or CTRL-J *c_CTRL-M* *c_CTRL-J* *c_<NL>* *c_<CR>* *c_CR*
<CR> or <NL> start entered command
diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt
index f58b0d5030..160995b440 100644
--- a/runtime/doc/starting.txt
+++ b/runtime/doc/starting.txt
@@ -104,7 +104,7 @@ argument.
--startuptime {fname} *--startuptime*
During startup write timing messages to the file {fname}.
This can be used to find out where time is spent while loading
- your |init.vim|, plugins and opening the first file.
+ your |config|, plugins and opening the first file.
When {fname} already exists new messages are appended.
(Only available when compiled with the |+startuptime|
feature).
@@ -211,7 +211,7 @@ argument.
When 'verbose' is set messages are printed to stderr. >
echo foo | nvim -V1 -es
-< User |init.vim| is skipped (unless given with |-u|).
+< User |config| is skipped (unless given with |-u|).
Swap file is skipped (like |-n|).
User |shada| is loaded (unless "-i NONE" is given).
@@ -406,12 +406,14 @@ accordingly. Vim proceeds in this order:
proceeding to load user configuration.
4. Load user config (execute Ex commands from files, environment, …).
- $VIMINIT environment variable is read as one Ex command line (separate
- multiple commands with '|' or <NL>).
- *config* *init.vim* *vimrc* *exrc*
- A file containing init commands is generically called a "vimrc" or
- "config". Each line in such a file is executed as an Ex command.
- |vimrc-intro| |base-directories|
+ An environment variable (e.g. $VIMINIT) is read as one Ex command
+ line, where multiple commands must be separated with '|' or <NL>.
+ *config* *init.vim* *init.lua* *vimrc* *exrc*
+ A file that contains initialization commands is generically called
+ a "vimrc" or config file. It can be a Vimscript or Lua file named
+ "init.vim" or "init.lua" respectively. It is an error to use both at
+ the same time. Each line in a "init.vim" is executed as an Ex command
+ line. See also |vimrc-intro| and |base-directories|.
The Nvim config file is "init.vim", located at:
Unix ~/.config/nvim/init.vim
@@ -578,7 +580,7 @@ The extreme flexibility of editors like Vim and Emacs means that any plugin or
setting can affect the entire editor in ways that are not initially obvious.
To find the cause of a problem in your config, you must "bisect" it:
-1. Remove or disable half of your `init.vim`.
+1. Remove or disable half of your |config|.
2. Restart Nvim.
3. If the problem still occurs, goto 1.
4. If the problem is gone, restore half of the removed lines.
@@ -597,7 +599,7 @@ to 'shortmess'.
$VIM and $VIMRUNTIME
*$VIM*
The environment variable "$VIM" is used to locate various user files for Nvim,
-such as the user startup script |init.vim|. This depends on the system, see
+such as the user |config|. This depends on the system, see
|startup|.
Nvim will try to get the value for $VIM in this order:
@@ -709,11 +711,11 @@ can be used with different terminals.
Only global mappings are stored, not mappings local to a buffer.
-A common method is to use a default |init.vim| file, make some modifications
+A common method is to use a default |config| file, make some modifications
with ":map" and ":set" commands and write the modified file. First read the
default vimrc in with a command like ":source ~piet/.vimrc.Cprogs", change
the settings and then save them in the current directory with ":mkvimrc!". If
-you want to make this file your default |init.vim|, move it to
+you want to make this file your default |config|, move it to
$XDG_CONFIG_HOME/nvim. You could also use autocommands |autocommand| and/or
modelines |modeline|.
@@ -1065,7 +1067,7 @@ do this. This can be useful in order to create a second file, say
"~/.my.shada" which could contain certain settings that you always want when
you first start Neovim. For example, you can preload registers with
particular data, or put certain commands in the command line history. A line
-in your |init.vim| file like >
+in your |config| file like >
:rshada! ~/.my.shada
can be used to load this information. You could even have different ShaDa
files for different types of files (e.g., C code) and load them based on the
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index 0f15aefd17..808af5f544 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -182,8 +182,6 @@ Highlight groups:
|hl-Whitespace| highlights 'listchars' whitespace
Input/Mappings:
- |<Cmd>| pseudokey
-
ALT (|META|) chords always work (even in the |TUI|). Map |<M-| with any key:
<M-1>, <M-BS>, <M-Del>, <M-Ins>, <M-/>, <M-\>, <M-Space>, <M-Enter>, etc.
Case-sensitive: <M-a> and <M-A> are two different keycodes.
@@ -215,7 +213,6 @@ Signs:
Signs are removed if the associated line is deleted.
Variables:
- |v:exiting|
|v:progpath| is always absolute ("full")
|v:windowid| is always available (for use by external UIs)
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 0100be15bc..ed408c28e5 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -1024,7 +1024,7 @@ static int command_line_execute(VimState *state, int key)
}
// free expanded names when finished walking through matches
- if (!(s->c == p_wc && KeyTyped) && s->c != p_wcm
+ if (!(s->c == p_wc && KeyTyped) && s->c != p_wcm && s->c != Ctrl_Z
&& s->c != Ctrl_N && s->c != Ctrl_P && s->c != Ctrl_A
&& s->c != Ctrl_L) {
if (compl_match_array) {
@@ -1328,7 +1328,8 @@ static int command_line_execute(VimState *state, int key)
// - hitting <ESC> twice means: abandon command line.
// - wildcard expansion is only done when the 'wildchar' key is really
// typed, not when it comes from a macro
- if ((s->c == p_wc && !s->gotesc && KeyTyped) || s->c == p_wcm) {
+ if ((s->c == p_wc && !s->gotesc && KeyTyped) || s->c == p_wcm
+ || s->c == Ctrl_Z) {
int options = WILD_NO_BEEP;
if (wim_flags[s->wim_index] & WIM_BUFLASTUSED) {
options |= WILD_BUFLASTUSED;
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 0a3c30134b..344a2387d6 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -927,7 +927,7 @@ void nlua_typval_eval(const String str, typval_T *const arg,
memcpy(lcmd + sizeof(EVALHEADER) - 1, str.data, str.size);
lcmd[lcmd_len - 1] = ')';
#undef EVALHEADER
- typval_exec_lua(lcmd, lcmd_len, "luaeval()", arg, 1, true, ret_tv);
+ nlua_typval_exec(lcmd, lcmd_len, "luaeval()", arg, 1, true, ret_tv);
if (lcmd != (char *)IObuff) {
xfree(lcmd);
@@ -954,16 +954,16 @@ void nlua_typval_call(const char *str, size_t len, typval_T *const args,
#undef CALLHEADER
#undef CALLSUFFIX
- typval_exec_lua(lcmd, lcmd_len, "v:lua", args, argcount, false, ret_tv);
+ nlua_typval_exec(lcmd, lcmd_len, "v:lua", args, argcount, false, ret_tv);
if (lcmd != (char *)IObuff) {
xfree(lcmd);
}
}
-static void typval_exec_lua(const char *lcmd, size_t lcmd_len, const char *name,
- typval_T *const args, int argcount, bool special,
- typval_T *ret_tv)
+static void nlua_typval_exec(const char *lcmd, size_t lcmd_len,
+ const char *name, typval_T *const args,
+ int argcount, bool special, typval_T *ret_tv)
{
if (check_secure()) {
if (ret_tv) {
@@ -1140,7 +1140,7 @@ void ex_lua(exarg_T *const eap)
xfree(code);
return;
}
- typval_exec_lua(code, len, ":lua", NULL, 0, false, NULL);
+ nlua_typval_exec(code, len, ":lua", NULL, 0, false, NULL);
xfree(code);
}
@@ -1231,17 +1231,30 @@ void ex_luado(exarg_T *const eap)
void ex_luafile(exarg_T *const eap)
FUNC_ATTR_NONNULL_ALL
{
+ nlua_exec_file((const char *)eap->arg);
+}
+
+/// execute lua code from a file.
+///
+/// @param path path of the file
+///
+/// @return true if everything ok, false if there was an error (echoed)
+bool nlua_exec_file(const char *path)
+ FUNC_ATTR_NONNULL_ALL
+{
lua_State *const lstate = nlua_enter();
- if (luaL_loadfile(lstate, (const char *)eap->arg)) {
+ if (luaL_loadfile(lstate, path)) {
nlua_error(lstate, _("E5112: Error while creating lua chunk: %.*s"));
- return;
+ return false;
}
if (lua_pcall(lstate, 0, 0, 0)) {
nlua_error(lstate, _("E5113: Error while calling lua chunk: %.*s"));
- return;
+ return false;
}
+
+ return true;
}
static void nlua_add_treesitter(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 63249416b1..79c165419e 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -1069,9 +1069,14 @@ static void command_line_scan(mparm_T *parmp)
} else {
a = argv[0];
}
- size_t s_size = STRLEN(a) + 4;
+
+ size_t s_size = STRLEN(a) + 9;
char *s = xmalloc(s_size);
- snprintf(s, s_size, "so %s", a);
+ if (path_with_extension(a, "lua")) {
+ snprintf(s, s_size, "luafile %s", a);
+ } else {
+ snprintf(s, s_size, "so %s", a);
+ }
parmp->cmds_tofree[parmp->n_commands] = true;
parmp->commands[parmp->n_commands++] = s;
} else {
@@ -1770,6 +1775,23 @@ static bool do_user_initialization(void)
do_exrc = p_exrc;
return do_exrc;
}
+
+ char_u *init_lua_path = (char_u *)stdpaths_user_conf_subpath("init.lua");
+ if (os_path_exists(init_lua_path)
+ && nlua_exec_file((const char *)init_lua_path)) {
+ os_setenv("MYVIMRC", (const char *)init_lua_path, 1);
+ char_u *vimrc_path = (char_u *)stdpaths_user_conf_subpath("init.vim");
+
+ if (os_path_exists(vimrc_path)) {
+ EMSG3(_("Conflicting configs: \"%s\" \"%s\""), init_lua_path, vimrc_path);
+ }
+
+ xfree(vimrc_path);
+ xfree(init_lua_path);
+ return false;
+ }
+ xfree(init_lua_path);
+
char_u *user_vimrc = (char_u *)stdpaths_user_conf_subpath("init.vim");
if (do_source(user_vimrc, true, DOSO_VIMRC) != FAIL) {
do_exrc = p_exrc;
@@ -1829,8 +1851,12 @@ static void source_startup_scripts(const mparm_T *const parmp)
|| strequal(parmp->use_vimrc, "NORC")) {
// Do nothing.
} else {
- if (do_source((char_u *)parmp->use_vimrc, false, DOSO_NONE) != OK) {
- EMSG2(_("E282: Cannot read from \"%s\""), parmp->use_vimrc);
+ if (path_with_extension(parmp->use_vimrc, "lua")) {
+ nlua_exec_file(parmp->use_vimrc);
+ } else {
+ if (do_source((char_u *)parmp->use_vimrc, false, DOSO_NONE) != OK) {
+ EMSG2(_("E282: Cannot read from \"%s\""), parmp->use_vimrc);
+ }
}
}
} else if (!silent_mode) {
diff --git a/src/nvim/path.c b/src/nvim/path.c
index f52fbbd5c8..2de7e00ddb 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -1704,6 +1704,13 @@ int path_with_url(const char *fname)
return path_is_url(p);
}
+bool path_with_extension(const char *path, const char *extension)
+{
+ const char *last_dot = strrchr(path, '.');
+ if (!last_dot) { return false; }
+ return strcmp(last_dot + 1, extension) == 0;
+}
+
/*
* Return TRUE if "name" is a full (absolute) path name or URL.
*/
diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua
index 27793ab936..ff0fdbea45 100644
--- a/test/functional/core/startup_spec.lua
+++ b/test/functional/core/startup_spec.lua
@@ -432,3 +432,88 @@ describe('clean', function()
clear('--clean')
ok(string.match(meths.get_option('runtimepath'), funcs.stdpath('config')) == nil)
end)
+
+describe('user config init', function()
+ local xhome = 'Xhome'
+ local pathsep = helpers.get_pathsep()
+ local xconfig = xhome .. pathsep .. 'Xconfig'
+ local init_lua_path = table.concat({xconfig, 'nvim', 'init.lua'}, pathsep)
+
+ before_each(function()
+ rmdir(xhome)
+
+ -- TODO, make mkdir_p helper
+ mkdir(xhome)
+ mkdir(xconfig)
+ mkdir(xconfig .. pathsep .. 'nvim')
+
+ write_file(init_lua_path, [[
+ vim.g.lua_rc = 1
+ ]])
+ end)
+
+ after_each(function()
+ rmdir(xhome)
+ end)
+
+ it('loads init.lua from XDG config home by default', function()
+ clear{ args_rm={'-u' }, env={ XDG_CONFIG_HOME=xconfig }}
+
+ eq(1, eval('g:lua_rc'))
+ eq(init_lua_path, eval('$MYVIMRC'))
+ end)
+
+ describe 'with explicitly provided config'(function()
+ local custom_lua_path = table.concat({xhome, 'custom.lua'}, pathsep)
+ before_each(function()
+ write_file(custom_lua_path, [[
+ vim.g.custom_lua_rc = 1
+ ]])
+ end)
+
+ it('loads custom lua config and does not set $MYVIMRC', function()
+ clear{ args={'-u', custom_lua_path }, env={ XDG_CONFIG_HOME=xconfig }}
+ eq(1, eval('g:custom_lua_rc'))
+ eq('', eval('$MYVIMRC'))
+ end)
+ end)
+
+ describe 'VIMRC also exists'(function()
+ before_each(function()
+ write_file(table.concat({xconfig, 'nvim', 'init.vim'}, pathsep), [[
+ let g:vim_rc = 1
+ ]])
+ end)
+
+ it('loads default lua config, but shows an error', function()
+ clear{ args_rm={'-u'}, env={ XDG_CONFIG_HOME=xconfig }}
+ feed('<cr>') -- TODO check this, test execution is blocked without it
+ eq(1, eval('g:lua_rc'))
+ matches('Conflicting configs', meths.exec('messages', true))
+ end)
+ end)
+end)
+
+describe('user session', function()
+ local xhome = 'Xhome'
+ local pathsep = helpers.get_pathsep()
+ local session_file = table.concat({xhome, 'session.lua'}, pathsep)
+
+ before_each(function()
+ rmdir(xhome)
+
+ mkdir(xhome)
+ write_file(session_file, [[
+ vim.g.lua_session = 1
+ ]])
+ end)
+
+ after_each(function()
+ rmdir(xhome)
+ end)
+
+ it('loads session from the provided lua file', function()
+ clear{ args={'-S', session_file }, env={ HOME=xhome }}
+ eq(1, eval('g:lua_session'))
+ end)
+end)
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index d85a6a3cfe..0829560b9c 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -442,6 +442,7 @@ function module.new_argv(...)
'NVIM_LOG_FILE',
'NVIM_RPLUGIN_MANIFEST',
'GCOV_ERROR_FILE',
+ 'XDG_DATA_DIRS',
'TMPDIR',
}) do
if not env_tbl[k] then
diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua
index 6e736b2534..65c6fabfa8 100644
--- a/test/functional/ui/wildmode_spec.lua
+++ b/test/functional/ui/wildmode_spec.lua
@@ -3,6 +3,7 @@ local Screen = require('test.functional.ui.screen')
local clear, feed, command = helpers.clear, helpers.feed, helpers.command
local iswin = helpers.iswin
local funcs = helpers.funcs
+local meths = helpers.meths
local eq = helpers.eq
local eval = helpers.eval
local retry = helpers.retry
@@ -397,6 +398,64 @@ describe("'wildmenu'", function()
|
]])
end)
+
+ it('works with c_CTRL_Z standard mapping', function()
+ screen:set_default_attr_ids {
+ [1] = {bold = true, foreground = Screen.colors.Blue1};
+ [2] = {foreground = Screen.colors.Grey0, background = Screen.colors.Yellow};
+ [3] = {bold = true, reverse = true};
+ }
+
+ -- Wildcharm? where we are going we aint't no need no wildcharm.
+ eq(0, meths.get_option'wildcharm')
+ -- Don't mess the defaults yet (neovim is about backwards compatibility)
+ eq(9, meths.get_option'wildchar')
+ -- Lol what is cnoremap? Some say it can define mappings.
+ command 'set wildchar=0'
+ eq(0, meths.get_option'wildchar')
+
+ command 'cnoremap <f2> <c-z>'
+ feed(':syntax <f2>')
+ screen:expect{grid=[[
+ |
+ {1:~ }|
+ {1:~ }|
+ {2:case}{3: clear cluster > }|
+ :syntax case^ |
+ ]]}
+ feed '<esc>'
+
+ command 'set wildmode=longest:full,full'
+ -- this will get cleaner once we have native lua expr mappings:
+ command [[cnoremap <expr> <tab> luaeval("not rawset(_G, 'coin', not coin).coin") ? "<c-z>" : "c"]]
+
+ feed ':syntax <tab>'
+ screen:expect{grid=[[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ :syntax c^ |
+ ]]}
+
+ feed '<tab>'
+ screen:expect{grid=[[
+ |
+ {1:~ }|
+ {1:~ }|
+ {3:case clear cluster > }|
+ :syntax c^ |
+ ]]}
+
+ feed '<tab>'
+ screen:expect{grid=[[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ :syntax cc^ |
+ ]]}
+ end)
end)
describe('command line completion', function()
diff --git a/test/unit/path_spec.lua b/test/unit/path_spec.lua
index 356c4997fa..41954de9be 100644
--- a/test/unit/path_spec.lua
+++ b/test/unit/path_spec.lua
@@ -603,4 +603,21 @@ describe('path.c', function()
eq(FAIL, path_is_absolute('not/in/my/home~/directory'))
end)
end)
+
+ describe('path_with_extension', function()
+ local function path_with_extension(filename, extension)
+ local c_filename = to_cstr(filename)
+ local c_extension = to_cstr(extension)
+ return cimp.path_with_extension(c_filename, c_extension)
+ end
+
+ itp('returns true if filename includes a provided extension', function()
+ eq(true, path_with_extension('/some/path/file.lua', 'lua'))
+ end)
+
+ itp('returns false if filename does not include a provided extension', function()
+ eq(false, path_with_extension('/some/path/file.vim', 'lua'))
+ eq(false, path_with_extension('/some/path/file', 'lua'))
+ end)
+ end)
end)