Merge pull request #12235 from dm1try/add_init_lua

add init.lua as an alternative user config
This commit is contained in:
Björn Linse 2020-12-01 18:54:50 +01:00 committed by GitHub
commit 72c22862dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 176 additions and 26 deletions

View File

@ -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

View File

@ -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);
}
@ -1230,18 +1230,31 @@ void ex_luado(exarg_T *const eap)
/// @param eap VimL command being run.
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

View File

@ -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) {

View File

@ -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.
*/

View File

@ -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)

View File

@ -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)