diff options
-rw-r--r-- | runtime/doc/starting.txt | 28 | ||||
-rw-r--r-- | src/nvim/lua/executor.c | 31 | ||||
-rw-r--r-- | src/nvim/main.c | 34 | ||||
-rw-r--r-- | src/nvim/path.c | 7 | ||||
-rw-r--r-- | test/functional/core/startup_spec.lua | 85 | ||||
-rw-r--r-- | test/unit/path_spec.lua | 17 |
6 files changed, 176 insertions, 26 deletions
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/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/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) |