mirror of
https://github.com/neovim/neovim.git
synced 2025-09-29 06:28:35 +00:00
Merge #6789 from ZyX-I/lua-path
lua: Add paths from &runtimepath to package.path and package.cpath
This commit is contained in:
@@ -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; \
|
||||
} \
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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,
|
||||
}
|
||||
|
Reference in New Issue
Block a user