aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2017-06-27 02:29:15 +0200
committerGitHub <noreply@github.com>2017-06-27 02:29:15 +0200
commitf34befe74c5a7b18a802f6f3c79607cb2124004c (patch)
tree955fc4456e7710213f7339e95cd40464088c08ec /src
parent1ef2d768e71981e4429376a0cb25dbed14dfae52 (diff)
parentcab3a248b2704e8f188eaf20206f2c87d1a76c0d (diff)
downloadrneovim-f34befe74c5a7b18a802f6f3c79607cb2124004c.tar.gz
rneovim-f34befe74c5a7b18a802f6f3c79607cb2124004c.tar.bz2
rneovim-f34befe74c5a7b18a802f6f3c79607cb2124004c.zip
Merge #6789 from ZyX-I/lua-path
lua: Add paths from &runtimepath to package.path and package.cpath
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/vim.c11
-rw-r--r--src/nvim/lua/executor.c71
-rw-r--r--src/nvim/lua/vim.lua64
3 files changed, 115 insertions, 31 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 92985b412a..80efe86ea3 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -300,7 +300,7 @@ ArrayOf(String) nvim_list_runtime_paths(void)
FUNC_API_SINCE(1)
{
Array rv = ARRAY_DICT_INIT;
- uint8_t *rtp = p_rtp;
+ char_u *rtp = p_rtp;
if (*rtp == NUL) {
// No paths
@@ -314,13 +314,14 @@ ArrayOf(String) nvim_list_runtime_paths(void)
}
rtp++;
}
+ rv.size++;
// Allocate memory for the copies
- rv.items = xmalloc(sizeof(Object) * rv.size);
+ rv.items = xmalloc(sizeof(*rv.items) * rv.size);
// Reset the position
rtp = p_rtp;
// Start copying
- for (size_t i = 0; i < rv.size && *rtp != NUL; i++) {
+ for (size_t i = 0; i < rv.size; i++) {
rv.items[i].type = kObjectTypeString;
rv.items[i].data.string.data = xmalloc(MAXPATHL);
// Copy the path from 'runtimepath' to rv.items[i]
@@ -709,7 +710,7 @@ void nvim_unsubscribe(uint64_t channel_id, String event)
Integer nvim_get_color_by_name(String name)
FUNC_API_SINCE(1)
{
- return name_to_color((uint8_t *)name.data);
+ return name_to_color((char_u *)name.data);
}
Dictionary nvim_get_color_map(void)
@@ -871,7 +872,7 @@ static void write_msg(String message, bool to_err)
#define PUSH_CHAR(i, pos, line_buf, msg) \
if (message.data[i] == NL || pos == LINE_BUFFER_SIZE - 1) { \
line_buf[pos] = NUL; \
- msg((uint8_t *)line_buf); \
+ msg((char_u *)line_buf); \
pos = 0; \
continue; \
} \
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 89a170f7a2..9ec5bfb8ad 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -14,6 +14,7 @@
#include "nvim/api/vim.h"
#include "nvim/vim.h"
#include "nvim/ex_getln.h"
+#include "nvim/ex_cmds2.h"
#include "nvim/message.h"
#include "nvim/memline.h"
#include "nvim/buffer_defs.h"
@@ -284,7 +285,9 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
///
/// Crashes NeoVim if initialization fails. Should be called once per lua
/// interpreter instance.
-static lua_State *init_lua(void)
+///
+/// @return New lua interpreter instance.
+static lua_State *nlua_init(void)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT
{
lua_State *lstate = luaL_newstate();
@@ -297,7 +300,43 @@ static lua_State *init_lua(void)
return lstate;
}
-static lua_State *global_lstate = NULL;
+/// Enter lua interpreter
+///
+/// Calls nlua_init() if needed. Is responsible for pre-lua call initalization
+/// like updating `package.[c]path` with directories derived from &runtimepath.
+///
+/// @return Interprter instance to use. Will either be initialized now or taken
+/// from previous initalization.
+static lua_State *nlua_enter(void)
+ FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ static lua_State *global_lstate = NULL;
+ if (global_lstate == NULL) {
+ global_lstate = nlua_init();
+ }
+ lua_State *const lstate = global_lstate;
+ // Last used p_rtp value. Must not be dereferenced because value pointed to
+ // may already be freed. Used to check whether &runtimepath option value
+ // changed.
+ static const void *last_p_rtp = NULL;
+ if (last_p_rtp != (const void *)p_rtp) {
+ // stack: (empty)
+ lua_getglobal(lstate, "vim");
+ // stack: vim
+ lua_getfield(lstate, -1, "_update_package_paths");
+ // stack: vim, vim._update_package_paths
+ if (lua_pcall(lstate, 0, 0, 0)) {
+ // stack: vim, error
+ nlua_error(lstate, _("E5117: Error while updating package paths: %.*s"));
+ // stack: vim
+ }
+ // stack: vim
+ lua_pop(lstate, 1);
+ // stack: (empty)
+ last_p_rtp = (const void *)p_rtp;
+ }
+ return lstate;
+}
/// Execute lua string
///
@@ -308,11 +347,7 @@ static lua_State *global_lstate = NULL;
void executor_exec_lua(const String str, typval_T *const ret_tv)
FUNC_ATTR_NONNULL_ALL
{
- if (global_lstate == NULL) {
- global_lstate = init_lua();
- }
-
- NLUA_CALL_C_FUNCTION_2(global_lstate, nlua_exec_lua_string, 0,
+ NLUA_CALL_C_FUNCTION_2(nlua_enter(), nlua_exec_lua_string, 0,
(void *)&str, ret_tv);
}
@@ -551,11 +586,7 @@ void executor_eval_lua(const String str, typval_T *const arg,
typval_T *const ret_tv)
FUNC_ATTR_NONNULL_ALL
{
- if (global_lstate == NULL) {
- global_lstate = init_lua();
- }
-
- NLUA_CALL_C_FUNCTION_3(global_lstate, nlua_eval_lua_string, 0,
+ NLUA_CALL_C_FUNCTION_3(nlua_enter(), nlua_eval_lua_string, 0,
(void *)&str, arg, ret_tv);
}
@@ -570,12 +601,8 @@ void executor_eval_lua(const String str, typval_T *const arg,
/// @return Return value of the execution.
Object executor_exec_lua_api(const String str, const Array args, Error *err)
{
- if (global_lstate == NULL) {
- global_lstate = init_lua();
- }
-
Object retval = NIL;
- NLUA_CALL_C_FUNCTION_4(global_lstate, nlua_exec_lua_string_api, 0,
+ NLUA_CALL_C_FUNCTION_4(nlua_enter(), nlua_exec_lua_string_api, 0,
(void *)&str, (void *)&args, &retval, err);
return retval;
}
@@ -609,9 +636,6 @@ void ex_lua(exarg_T *const eap)
void ex_luado(exarg_T *const eap)
FUNC_ATTR_NONNULL_ALL
{
- if (global_lstate == NULL) {
- global_lstate = init_lua();
- }
if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL) {
EMSG(_("cannot save undo information"));
return;
@@ -621,7 +645,7 @@ void ex_luado(exarg_T *const eap)
.data = (char *)eap->arg,
};
const linenr_T range[] = { eap->line1, eap->line2 };
- NLUA_CALL_C_FUNCTION_2(global_lstate, nlua_exec_luado_string, 0,
+ NLUA_CALL_C_FUNCTION_2(nlua_enter(), nlua_exec_luado_string, 0,
(void *)&cmd, (void *)range);
}
@@ -633,9 +657,6 @@ void ex_luado(exarg_T *const eap)
void ex_luafile(exarg_T *const eap)
FUNC_ATTR_NONNULL_ALL
{
- if (global_lstate == NULL) {
- global_lstate = init_lua();
- }
- NLUA_CALL_C_FUNCTION_1(global_lstate, nlua_exec_lua_file, 0,
+ NLUA_CALL_C_FUNCTION_1(nlua_enter(), nlua_exec_lua_file, 0,
(void *)eap->arg);
}
diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua
index 8d1c5bdf4f..c7952520b0 100644
--- a/src/nvim/lua/vim.lua
+++ b/src/nvim/lua/vim.lua
@@ -1,2 +1,64 @@
-- TODO(ZyX-I): Create compatibility layer.
-return {}
+--{{{1 package.path updater function
+-- Last inserted paths. Used to clear out items from package.[c]path when they
+-- are no longer in &runtimepath.
+local last_nvim_paths = {}
+local function _update_package_paths()
+ local cur_nvim_paths = {}
+ local rtps = vim.api.nvim_list_runtime_paths()
+ local sep = package.config:sub(1, 1)
+ for _, key in ipairs({'path', 'cpath'}) do
+ local orig_str = package[key] .. ';'
+ local pathtrails_ordered = {}
+ local orig = {}
+ -- Note: ignores trailing item without trailing `;`. Not using something
+ -- simpler in order to preserve empty items (stand for default path).
+ for s in orig_str:gmatch('[^;]*;') do
+ s = s:sub(1, -2) -- Strip trailing semicolon
+ orig[#orig + 1] = s
+ end
+ if key == 'path' then
+ -- /?.lua and /?/init.lua
+ pathtrails_ordered = {sep .. '?.lua', sep .. '?' .. sep .. 'init.lua'}
+ else
+ local pathtrails = {}
+ for _, s in ipairs(orig) do
+ -- Find out path patterns. pathtrail should contain something like
+ -- /?.so, \?.dll. This allows not to bother determining what correct
+ -- suffixes are.
+ local pathtrail = s:match('[/\\][^/\\]*%?.*$')
+ if pathtrail and not pathtrails[pathtrail] then
+ pathtrails[pathtrail] = true
+ pathtrails_ordered[#pathtrails_ordered + 1] = pathtrail
+ end
+ end
+ end
+ local new = {}
+ for _, rtp in ipairs(rtps) do
+ if not rtp:match(';') then
+ for _, pathtrail in pairs(pathtrails_ordered) do
+ local new_path = rtp .. sep .. 'lua' .. pathtrail
+ -- Always keep paths from &runtimepath at the start:
+ -- append them here disregarding orig possibly containing one of them.
+ new[#new + 1] = new_path
+ cur_nvim_paths[new_path] = true
+ end
+ end
+ end
+ for _, orig_path in ipairs(orig) do
+ -- Handle removing obsolete paths originating from &runtimepath: such
+ -- paths either belong to cur_nvim_paths and were already added above or
+ -- to last_nvim_paths and should not be added at all if corresponding
+ -- entry was removed from &runtimepath list.
+ if not (cur_nvim_paths[orig_path] or last_nvim_paths[orig_path]) then
+ new[#new + 1] = orig_path
+ end
+ end
+ package[key] = table.concat(new, ';')
+ end
+ last_nvim_paths = cur_nvim_paths
+end
+--{{{1 Module definition
+return {
+ _update_package_paths = _update_package_paths,
+}