2019-01-17 16:44:35 -07:00
|
|
|
-- Nvim-Lua stdlib: the `vim` module (:help lua-stdlib)
|
|
|
|
--
|
|
|
|
-- Lua code lives in one of three places:
|
2019-05-19 08:58:54 -07:00
|
|
|
-- 1. runtime/lua/vim/ (the runtime): For "nice to have" features, e.g. the
|
|
|
|
-- `inspect` and `lpeg` modules.
|
|
|
|
-- 2. runtime/lua/vim/shared.lua: Code shared between Nvim and tests.
|
|
|
|
-- 3. src/nvim/lua/: Compiled-into Nvim itself.
|
2019-01-17 16:44:35 -07:00
|
|
|
--
|
|
|
|
-- Guideline: "If in doubt, put it in the runtime".
|
|
|
|
--
|
2019-08-18 13:25:03 -07:00
|
|
|
-- Most functions should live directly in `vim.`, not in submodules.
|
|
|
|
-- The only "forbidden" names are those claimed by legacy `if_lua`:
|
2019-01-17 16:44:35 -07:00
|
|
|
-- $ vim
|
|
|
|
-- :lua for k,v in pairs(vim) do print(k) end
|
|
|
|
-- buffer
|
|
|
|
-- open
|
|
|
|
-- window
|
|
|
|
-- lastline
|
|
|
|
-- firstline
|
|
|
|
-- type
|
|
|
|
-- line
|
|
|
|
-- eval
|
|
|
|
-- dict
|
|
|
|
-- beep
|
|
|
|
-- list
|
|
|
|
-- command
|
|
|
|
--
|
|
|
|
-- Reference (#6580):
|
|
|
|
-- - https://github.com/luafun/luafun
|
|
|
|
-- - https://github.com/rxi/lume
|
|
|
|
-- - http://leafo.net/lapis/reference/utilities.html
|
|
|
|
-- - https://github.com/torch/paths
|
|
|
|
-- - https://github.com/bakpakin/Fennel (pretty print, repl)
|
|
|
|
-- - https://github.com/howl-editor/howl/tree/master/lib/howl/util
|
|
|
|
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
local vim = vim
|
|
|
|
assert(vim)
|
2019-01-17 16:44:35 -07:00
|
|
|
|
2020-11-04 02:41:22 -07:00
|
|
|
vim.inspect = package.loaded['vim.inspect']
|
|
|
|
assert(vim.inspect)
|
|
|
|
|
API: nvim_get_proc()
TODO: "exepath" field (win32: QueryFullProcessImageName())
On unix-likes `ps` is used because the platform-specific APIs are
a nightmare. For reference, below is a (incomplete) attempt:
diff --git a/src/nvim/os/process.c b/src/nvim/os/process.c
index 09769925aca5..99afbbf290c1 100644
--- a/src/nvim/os/process.c
+++ b/src/nvim/os/process.c
@@ -208,3 +210,60 @@ int os_proc_children(int ppid, int **proc_list, size_t *proc_count)
return 0;
}
+/// Gets various properties of the process identified by `pid`.
+///
+/// @param pid Process to inspect.
+/// @return Map of process properties, empty on error.
+Dictionary os_proc_info(int pid)
+{
+ Dictionary pinfo = ARRAY_DICT_INIT;
+#ifdef WIN32
+
+#elif defined(__APPLE__)
+ char buf[PROC_PIDPATHINFO_MAXSIZE];
+ if (proc_pidpath(pid, buf, sizeof(buf))) {
+ name = getName(buf);
+ PUT(pinfo, "exepath", STRING_OBJ(cstr_to_string(buf)));
+ return name;
+ } else {
+ ILOG("proc_pidpath() failed for pid: %d", pid);
+ }
+#elif defined(BSD)
+# if defined(__FreeBSD__)
+# define KP_COMM(o) o.ki_comm
+# else
+# define KP_COMM(o) o.p_comm
+# endif
+ struct kinfo_proc *proc = kinfo_getproc(pid);
+ if (proc) {
+ PUT(pinfo, "name", cstr_to_string(KP_COMM(proc)));
+ xfree(proc);
+ } else {
+ ILOG("kinfo_getproc() failed for pid: %d", pid);
+ }
+
+#elif defined(__linux__)
+ char fname[256] = { 0 };
+ char buf[MAXPATHL];
+ snprintf(fname, sizeof(fname), "/proc/%d/comm", pid);
+ FILE *fp = fopen(fname, "r");
+ // FileDescriptor *f = file_open_new(&error, fname, kFileReadOnly, 0);
+ // ptrdiff_t file_read(FileDescriptor *const fp, char *const ret_buf,
+ // const size_t size)
+ if (fp == NULL) {
+ ILOG("fopen() of /proc/%d/comm failed", pid);
+ } else {
+ size_t n = fread(buf, sizeof(char), sizeof(buf) - 1, fp);
+ if (n == 0) {
+ WLOG("fread() of /proc/%d/comm failed", pid);
+ } else {
+ size_t end = MIN(sizeof(buf) - 1, n);
+ end = (end > 0 && buf[end - 1] == '\n') ? end - 1 : end;
+ buf[end] = '\0';
+ PUT(pinfo, "name", STRING_OBJ(cstr_to_string(buf)));
+ }
+ }
+ fclose(fp);
+#endif
+ return pinfo;
+}
2018-03-15 21:13:38 -07:00
|
|
|
-- Internal-only until comments in #8107 are addressed.
|
|
|
|
-- Returns:
|
|
|
|
-- {errcode}, {output}
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
function vim._system(cmd)
|
|
|
|
local out = vim.fn.system(cmd)
|
|
|
|
local err = vim.v.shell_error
|
API: nvim_get_proc()
TODO: "exepath" field (win32: QueryFullProcessImageName())
On unix-likes `ps` is used because the platform-specific APIs are
a nightmare. For reference, below is a (incomplete) attempt:
diff --git a/src/nvim/os/process.c b/src/nvim/os/process.c
index 09769925aca5..99afbbf290c1 100644
--- a/src/nvim/os/process.c
+++ b/src/nvim/os/process.c
@@ -208,3 +210,60 @@ int os_proc_children(int ppid, int **proc_list, size_t *proc_count)
return 0;
}
+/// Gets various properties of the process identified by `pid`.
+///
+/// @param pid Process to inspect.
+/// @return Map of process properties, empty on error.
+Dictionary os_proc_info(int pid)
+{
+ Dictionary pinfo = ARRAY_DICT_INIT;
+#ifdef WIN32
+
+#elif defined(__APPLE__)
+ char buf[PROC_PIDPATHINFO_MAXSIZE];
+ if (proc_pidpath(pid, buf, sizeof(buf))) {
+ name = getName(buf);
+ PUT(pinfo, "exepath", STRING_OBJ(cstr_to_string(buf)));
+ return name;
+ } else {
+ ILOG("proc_pidpath() failed for pid: %d", pid);
+ }
+#elif defined(BSD)
+# if defined(__FreeBSD__)
+# define KP_COMM(o) o.ki_comm
+# else
+# define KP_COMM(o) o.p_comm
+# endif
+ struct kinfo_proc *proc = kinfo_getproc(pid);
+ if (proc) {
+ PUT(pinfo, "name", cstr_to_string(KP_COMM(proc)));
+ xfree(proc);
+ } else {
+ ILOG("kinfo_getproc() failed for pid: %d", pid);
+ }
+
+#elif defined(__linux__)
+ char fname[256] = { 0 };
+ char buf[MAXPATHL];
+ snprintf(fname, sizeof(fname), "/proc/%d/comm", pid);
+ FILE *fp = fopen(fname, "r");
+ // FileDescriptor *f = file_open_new(&error, fname, kFileReadOnly, 0);
+ // ptrdiff_t file_read(FileDescriptor *const fp, char *const ret_buf,
+ // const size_t size)
+ if (fp == NULL) {
+ ILOG("fopen() of /proc/%d/comm failed", pid);
+ } else {
+ size_t n = fread(buf, sizeof(char), sizeof(buf) - 1, fp);
+ if (n == 0) {
+ WLOG("fread() of /proc/%d/comm failed", pid);
+ } else {
+ size_t end = MIN(sizeof(buf) - 1, n);
+ end = (end > 0 && buf[end - 1] == '\n') ? end - 1 : end;
+ buf[end] = '\0';
+ PUT(pinfo, "name", STRING_OBJ(cstr_to_string(buf)));
+ }
+ }
+ fclose(fp);
+#endif
+ return pinfo;
+}
2018-03-15 21:13:38 -07:00
|
|
|
return err, out
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Gets process info from the `ps` command.
|
|
|
|
-- Used by nvim_get_proc() as a fallback.
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
function vim._os_proc_info(pid)
|
API: nvim_get_proc()
TODO: "exepath" field (win32: QueryFullProcessImageName())
On unix-likes `ps` is used because the platform-specific APIs are
a nightmare. For reference, below is a (incomplete) attempt:
diff --git a/src/nvim/os/process.c b/src/nvim/os/process.c
index 09769925aca5..99afbbf290c1 100644
--- a/src/nvim/os/process.c
+++ b/src/nvim/os/process.c
@@ -208,3 +210,60 @@ int os_proc_children(int ppid, int **proc_list, size_t *proc_count)
return 0;
}
+/// Gets various properties of the process identified by `pid`.
+///
+/// @param pid Process to inspect.
+/// @return Map of process properties, empty on error.
+Dictionary os_proc_info(int pid)
+{
+ Dictionary pinfo = ARRAY_DICT_INIT;
+#ifdef WIN32
+
+#elif defined(__APPLE__)
+ char buf[PROC_PIDPATHINFO_MAXSIZE];
+ if (proc_pidpath(pid, buf, sizeof(buf))) {
+ name = getName(buf);
+ PUT(pinfo, "exepath", STRING_OBJ(cstr_to_string(buf)));
+ return name;
+ } else {
+ ILOG("proc_pidpath() failed for pid: %d", pid);
+ }
+#elif defined(BSD)
+# if defined(__FreeBSD__)
+# define KP_COMM(o) o.ki_comm
+# else
+# define KP_COMM(o) o.p_comm
+# endif
+ struct kinfo_proc *proc = kinfo_getproc(pid);
+ if (proc) {
+ PUT(pinfo, "name", cstr_to_string(KP_COMM(proc)));
+ xfree(proc);
+ } else {
+ ILOG("kinfo_getproc() failed for pid: %d", pid);
+ }
+
+#elif defined(__linux__)
+ char fname[256] = { 0 };
+ char buf[MAXPATHL];
+ snprintf(fname, sizeof(fname), "/proc/%d/comm", pid);
+ FILE *fp = fopen(fname, "r");
+ // FileDescriptor *f = file_open_new(&error, fname, kFileReadOnly, 0);
+ // ptrdiff_t file_read(FileDescriptor *const fp, char *const ret_buf,
+ // const size_t size)
+ if (fp == NULL) {
+ ILOG("fopen() of /proc/%d/comm failed", pid);
+ } else {
+ size_t n = fread(buf, sizeof(char), sizeof(buf) - 1, fp);
+ if (n == 0) {
+ WLOG("fread() of /proc/%d/comm failed", pid);
+ } else {
+ size_t end = MIN(sizeof(buf) - 1, n);
+ end = (end > 0 && buf[end - 1] == '\n') ? end - 1 : end;
+ buf[end] = '\0';
+ PUT(pinfo, "name", STRING_OBJ(cstr_to_string(buf)));
+ }
+ }
+ fclose(fp);
+#endif
+ return pinfo;
+}
2018-03-15 21:13:38 -07:00
|
|
|
if pid == nil or pid <= 0 or type(pid) ~= 'number' then
|
|
|
|
error('invalid pid')
|
|
|
|
end
|
2018-08-15 03:39:10 -07:00
|
|
|
local cmd = { 'ps', '-p', pid, '-o', 'comm=', }
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
local err, name = vim._system(cmd)
|
|
|
|
if 1 == err and vim.trim(name) == '' then
|
API: nvim_get_proc()
TODO: "exepath" field (win32: QueryFullProcessImageName())
On unix-likes `ps` is used because the platform-specific APIs are
a nightmare. For reference, below is a (incomplete) attempt:
diff --git a/src/nvim/os/process.c b/src/nvim/os/process.c
index 09769925aca5..99afbbf290c1 100644
--- a/src/nvim/os/process.c
+++ b/src/nvim/os/process.c
@@ -208,3 +210,60 @@ int os_proc_children(int ppid, int **proc_list, size_t *proc_count)
return 0;
}
+/// Gets various properties of the process identified by `pid`.
+///
+/// @param pid Process to inspect.
+/// @return Map of process properties, empty on error.
+Dictionary os_proc_info(int pid)
+{
+ Dictionary pinfo = ARRAY_DICT_INIT;
+#ifdef WIN32
+
+#elif defined(__APPLE__)
+ char buf[PROC_PIDPATHINFO_MAXSIZE];
+ if (proc_pidpath(pid, buf, sizeof(buf))) {
+ name = getName(buf);
+ PUT(pinfo, "exepath", STRING_OBJ(cstr_to_string(buf)));
+ return name;
+ } else {
+ ILOG("proc_pidpath() failed for pid: %d", pid);
+ }
+#elif defined(BSD)
+# if defined(__FreeBSD__)
+# define KP_COMM(o) o.ki_comm
+# else
+# define KP_COMM(o) o.p_comm
+# endif
+ struct kinfo_proc *proc = kinfo_getproc(pid);
+ if (proc) {
+ PUT(pinfo, "name", cstr_to_string(KP_COMM(proc)));
+ xfree(proc);
+ } else {
+ ILOG("kinfo_getproc() failed for pid: %d", pid);
+ }
+
+#elif defined(__linux__)
+ char fname[256] = { 0 };
+ char buf[MAXPATHL];
+ snprintf(fname, sizeof(fname), "/proc/%d/comm", pid);
+ FILE *fp = fopen(fname, "r");
+ // FileDescriptor *f = file_open_new(&error, fname, kFileReadOnly, 0);
+ // ptrdiff_t file_read(FileDescriptor *const fp, char *const ret_buf,
+ // const size_t size)
+ if (fp == NULL) {
+ ILOG("fopen() of /proc/%d/comm failed", pid);
+ } else {
+ size_t n = fread(buf, sizeof(char), sizeof(buf) - 1, fp);
+ if (n == 0) {
+ WLOG("fread() of /proc/%d/comm failed", pid);
+ } else {
+ size_t end = MIN(sizeof(buf) - 1, n);
+ end = (end > 0 && buf[end - 1] == '\n') ? end - 1 : end;
+ buf[end] = '\0';
+ PUT(pinfo, "name", STRING_OBJ(cstr_to_string(buf)));
+ }
+ }
+ fclose(fp);
+#endif
+ return pinfo;
+}
2018-03-15 21:13:38 -07:00
|
|
|
return {} -- Process not found.
|
|
|
|
elseif 0 ~= err then
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
error('command failed: '..vim.fn.string(cmd))
|
API: nvim_get_proc()
TODO: "exepath" field (win32: QueryFullProcessImageName())
On unix-likes `ps` is used because the platform-specific APIs are
a nightmare. For reference, below is a (incomplete) attempt:
diff --git a/src/nvim/os/process.c b/src/nvim/os/process.c
index 09769925aca5..99afbbf290c1 100644
--- a/src/nvim/os/process.c
+++ b/src/nvim/os/process.c
@@ -208,3 +210,60 @@ int os_proc_children(int ppid, int **proc_list, size_t *proc_count)
return 0;
}
+/// Gets various properties of the process identified by `pid`.
+///
+/// @param pid Process to inspect.
+/// @return Map of process properties, empty on error.
+Dictionary os_proc_info(int pid)
+{
+ Dictionary pinfo = ARRAY_DICT_INIT;
+#ifdef WIN32
+
+#elif defined(__APPLE__)
+ char buf[PROC_PIDPATHINFO_MAXSIZE];
+ if (proc_pidpath(pid, buf, sizeof(buf))) {
+ name = getName(buf);
+ PUT(pinfo, "exepath", STRING_OBJ(cstr_to_string(buf)));
+ return name;
+ } else {
+ ILOG("proc_pidpath() failed for pid: %d", pid);
+ }
+#elif defined(BSD)
+# if defined(__FreeBSD__)
+# define KP_COMM(o) o.ki_comm
+# else
+# define KP_COMM(o) o.p_comm
+# endif
+ struct kinfo_proc *proc = kinfo_getproc(pid);
+ if (proc) {
+ PUT(pinfo, "name", cstr_to_string(KP_COMM(proc)));
+ xfree(proc);
+ } else {
+ ILOG("kinfo_getproc() failed for pid: %d", pid);
+ }
+
+#elif defined(__linux__)
+ char fname[256] = { 0 };
+ char buf[MAXPATHL];
+ snprintf(fname, sizeof(fname), "/proc/%d/comm", pid);
+ FILE *fp = fopen(fname, "r");
+ // FileDescriptor *f = file_open_new(&error, fname, kFileReadOnly, 0);
+ // ptrdiff_t file_read(FileDescriptor *const fp, char *const ret_buf,
+ // const size_t size)
+ if (fp == NULL) {
+ ILOG("fopen() of /proc/%d/comm failed", pid);
+ } else {
+ size_t n = fread(buf, sizeof(char), sizeof(buf) - 1, fp);
+ if (n == 0) {
+ WLOG("fread() of /proc/%d/comm failed", pid);
+ } else {
+ size_t end = MIN(sizeof(buf) - 1, n);
+ end = (end > 0 && buf[end - 1] == '\n') ? end - 1 : end;
+ buf[end] = '\0';
+ PUT(pinfo, "name", STRING_OBJ(cstr_to_string(buf)));
+ }
+ }
+ fclose(fp);
+#endif
+ return pinfo;
+}
2018-03-15 21:13:38 -07:00
|
|
|
end
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
local _, ppid = vim._system({ 'ps', '-p', pid, '-o', 'ppid=', })
|
API: nvim_get_proc()
TODO: "exepath" field (win32: QueryFullProcessImageName())
On unix-likes `ps` is used because the platform-specific APIs are
a nightmare. For reference, below is a (incomplete) attempt:
diff --git a/src/nvim/os/process.c b/src/nvim/os/process.c
index 09769925aca5..99afbbf290c1 100644
--- a/src/nvim/os/process.c
+++ b/src/nvim/os/process.c
@@ -208,3 +210,60 @@ int os_proc_children(int ppid, int **proc_list, size_t *proc_count)
return 0;
}
+/// Gets various properties of the process identified by `pid`.
+///
+/// @param pid Process to inspect.
+/// @return Map of process properties, empty on error.
+Dictionary os_proc_info(int pid)
+{
+ Dictionary pinfo = ARRAY_DICT_INIT;
+#ifdef WIN32
+
+#elif defined(__APPLE__)
+ char buf[PROC_PIDPATHINFO_MAXSIZE];
+ if (proc_pidpath(pid, buf, sizeof(buf))) {
+ name = getName(buf);
+ PUT(pinfo, "exepath", STRING_OBJ(cstr_to_string(buf)));
+ return name;
+ } else {
+ ILOG("proc_pidpath() failed for pid: %d", pid);
+ }
+#elif defined(BSD)
+# if defined(__FreeBSD__)
+# define KP_COMM(o) o.ki_comm
+# else
+# define KP_COMM(o) o.p_comm
+# endif
+ struct kinfo_proc *proc = kinfo_getproc(pid);
+ if (proc) {
+ PUT(pinfo, "name", cstr_to_string(KP_COMM(proc)));
+ xfree(proc);
+ } else {
+ ILOG("kinfo_getproc() failed for pid: %d", pid);
+ }
+
+#elif defined(__linux__)
+ char fname[256] = { 0 };
+ char buf[MAXPATHL];
+ snprintf(fname, sizeof(fname), "/proc/%d/comm", pid);
+ FILE *fp = fopen(fname, "r");
+ // FileDescriptor *f = file_open_new(&error, fname, kFileReadOnly, 0);
+ // ptrdiff_t file_read(FileDescriptor *const fp, char *const ret_buf,
+ // const size_t size)
+ if (fp == NULL) {
+ ILOG("fopen() of /proc/%d/comm failed", pid);
+ } else {
+ size_t n = fread(buf, sizeof(char), sizeof(buf) - 1, fp);
+ if (n == 0) {
+ WLOG("fread() of /proc/%d/comm failed", pid);
+ } else {
+ size_t end = MIN(sizeof(buf) - 1, n);
+ end = (end > 0 && buf[end - 1] == '\n') ? end - 1 : end;
+ buf[end] = '\0';
+ PUT(pinfo, "name", STRING_OBJ(cstr_to_string(buf)));
+ }
+ }
+ fclose(fp);
+#endif
+ return pinfo;
+}
2018-03-15 21:13:38 -07:00
|
|
|
-- Remove trailing whitespace.
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
name = vim.trim(name):gsub('^.*/', '')
|
|
|
|
ppid = tonumber(ppid) or -1
|
API: nvim_get_proc()
TODO: "exepath" field (win32: QueryFullProcessImageName())
On unix-likes `ps` is used because the platform-specific APIs are
a nightmare. For reference, below is a (incomplete) attempt:
diff --git a/src/nvim/os/process.c b/src/nvim/os/process.c
index 09769925aca5..99afbbf290c1 100644
--- a/src/nvim/os/process.c
+++ b/src/nvim/os/process.c
@@ -208,3 +210,60 @@ int os_proc_children(int ppid, int **proc_list, size_t *proc_count)
return 0;
}
+/// Gets various properties of the process identified by `pid`.
+///
+/// @param pid Process to inspect.
+/// @return Map of process properties, empty on error.
+Dictionary os_proc_info(int pid)
+{
+ Dictionary pinfo = ARRAY_DICT_INIT;
+#ifdef WIN32
+
+#elif defined(__APPLE__)
+ char buf[PROC_PIDPATHINFO_MAXSIZE];
+ if (proc_pidpath(pid, buf, sizeof(buf))) {
+ name = getName(buf);
+ PUT(pinfo, "exepath", STRING_OBJ(cstr_to_string(buf)));
+ return name;
+ } else {
+ ILOG("proc_pidpath() failed for pid: %d", pid);
+ }
+#elif defined(BSD)
+# if defined(__FreeBSD__)
+# define KP_COMM(o) o.ki_comm
+# else
+# define KP_COMM(o) o.p_comm
+# endif
+ struct kinfo_proc *proc = kinfo_getproc(pid);
+ if (proc) {
+ PUT(pinfo, "name", cstr_to_string(KP_COMM(proc)));
+ xfree(proc);
+ } else {
+ ILOG("kinfo_getproc() failed for pid: %d", pid);
+ }
+
+#elif defined(__linux__)
+ char fname[256] = { 0 };
+ char buf[MAXPATHL];
+ snprintf(fname, sizeof(fname), "/proc/%d/comm", pid);
+ FILE *fp = fopen(fname, "r");
+ // FileDescriptor *f = file_open_new(&error, fname, kFileReadOnly, 0);
+ // ptrdiff_t file_read(FileDescriptor *const fp, char *const ret_buf,
+ // const size_t size)
+ if (fp == NULL) {
+ ILOG("fopen() of /proc/%d/comm failed", pid);
+ } else {
+ size_t n = fread(buf, sizeof(char), sizeof(buf) - 1, fp);
+ if (n == 0) {
+ WLOG("fread() of /proc/%d/comm failed", pid);
+ } else {
+ size_t end = MIN(sizeof(buf) - 1, n);
+ end = (end > 0 && buf[end - 1] == '\n') ? end - 1 : end;
+ buf[end] = '\0';
+ PUT(pinfo, "name", STRING_OBJ(cstr_to_string(buf)));
+ }
+ }
+ fclose(fp);
+#endif
+ return pinfo;
+}
2018-03-15 21:13:38 -07:00
|
|
|
return {
|
|
|
|
name = name,
|
|
|
|
pid = pid,
|
|
|
|
ppid = ppid,
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Gets process children from the `pgrep` command.
|
2018-03-14 15:26:37 -07:00
|
|
|
-- Used by nvim_get_proc_children() as a fallback.
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
function vim._os_proc_children(ppid)
|
2018-03-14 15:26:37 -07:00
|
|
|
if ppid == nil or ppid <= 0 or type(ppid) ~= 'number' then
|
|
|
|
error('invalid ppid')
|
|
|
|
end
|
API: nvim_get_proc()
TODO: "exepath" field (win32: QueryFullProcessImageName())
On unix-likes `ps` is used because the platform-specific APIs are
a nightmare. For reference, below is a (incomplete) attempt:
diff --git a/src/nvim/os/process.c b/src/nvim/os/process.c
index 09769925aca5..99afbbf290c1 100644
--- a/src/nvim/os/process.c
+++ b/src/nvim/os/process.c
@@ -208,3 +210,60 @@ int os_proc_children(int ppid, int **proc_list, size_t *proc_count)
return 0;
}
+/// Gets various properties of the process identified by `pid`.
+///
+/// @param pid Process to inspect.
+/// @return Map of process properties, empty on error.
+Dictionary os_proc_info(int pid)
+{
+ Dictionary pinfo = ARRAY_DICT_INIT;
+#ifdef WIN32
+
+#elif defined(__APPLE__)
+ char buf[PROC_PIDPATHINFO_MAXSIZE];
+ if (proc_pidpath(pid, buf, sizeof(buf))) {
+ name = getName(buf);
+ PUT(pinfo, "exepath", STRING_OBJ(cstr_to_string(buf)));
+ return name;
+ } else {
+ ILOG("proc_pidpath() failed for pid: %d", pid);
+ }
+#elif defined(BSD)
+# if defined(__FreeBSD__)
+# define KP_COMM(o) o.ki_comm
+# else
+# define KP_COMM(o) o.p_comm
+# endif
+ struct kinfo_proc *proc = kinfo_getproc(pid);
+ if (proc) {
+ PUT(pinfo, "name", cstr_to_string(KP_COMM(proc)));
+ xfree(proc);
+ } else {
+ ILOG("kinfo_getproc() failed for pid: %d", pid);
+ }
+
+#elif defined(__linux__)
+ char fname[256] = { 0 };
+ char buf[MAXPATHL];
+ snprintf(fname, sizeof(fname), "/proc/%d/comm", pid);
+ FILE *fp = fopen(fname, "r");
+ // FileDescriptor *f = file_open_new(&error, fname, kFileReadOnly, 0);
+ // ptrdiff_t file_read(FileDescriptor *const fp, char *const ret_buf,
+ // const size_t size)
+ if (fp == NULL) {
+ ILOG("fopen() of /proc/%d/comm failed", pid);
+ } else {
+ size_t n = fread(buf, sizeof(char), sizeof(buf) - 1, fp);
+ if (n == 0) {
+ WLOG("fread() of /proc/%d/comm failed", pid);
+ } else {
+ size_t end = MIN(sizeof(buf) - 1, n);
+ end = (end > 0 && buf[end - 1] == '\n') ? end - 1 : end;
+ buf[end] = '\0';
+ PUT(pinfo, "name", STRING_OBJ(cstr_to_string(buf)));
+ }
+ }
+ fclose(fp);
+#endif
+ return pinfo;
+}
2018-03-15 21:13:38 -07:00
|
|
|
local cmd = { 'pgrep', '-P', ppid, }
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
local err, rv = vim._system(cmd)
|
|
|
|
if 1 == err and vim.trim(rv) == '' then
|
2018-03-14 15:26:37 -07:00
|
|
|
return {} -- Process not found.
|
|
|
|
elseif 0 ~= err then
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
error('command failed: '..vim.fn.string(cmd))
|
2018-03-14 15:26:37 -07:00
|
|
|
end
|
|
|
|
local children = {}
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
for s in rv:gmatch('%S+') do
|
2018-03-14 15:26:37 -07:00
|
|
|
local i = tonumber(s)
|
|
|
|
if i ~= nil then
|
|
|
|
table.insert(children, i)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return children
|
|
|
|
end
|
|
|
|
|
2020-10-19 11:05:54 -07:00
|
|
|
local pathtrails = {}
|
|
|
|
vim._so_trails = {}
|
|
|
|
for s in (package.cpath..';'):gmatch('[^;]*;') do
|
|
|
|
s = s:sub(1, -2) -- Strip trailing semicolon
|
|
|
|
-- 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
|
|
|
|
table.insert(vim._so_trails, pathtrail)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function vim._load_package(name)
|
|
|
|
local basename = name:gsub('%.', '/')
|
|
|
|
local paths = {"lua/"..basename..".lua", "lua/"..basename.."/init.lua"}
|
|
|
|
for _,path in ipairs(paths) do
|
|
|
|
local found = vim.api.nvim_get_runtime_file(path, false)
|
|
|
|
if #found > 0 then
|
2020-12-07 15:47:28 -07:00
|
|
|
local f, err = loadfile(found[1])
|
|
|
|
return f or error(err)
|
2017-05-22 14:46:57 -07:00
|
|
|
end
|
2020-10-19 11:05:54 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
for _,trail in ipairs(vim._so_trails) do
|
2020-12-25 03:23:57 -07:00
|
|
|
local path = "lua"..trail:gsub('?', basename) -- so_trails contains a leading slash
|
2020-10-19 11:05:54 -07:00
|
|
|
local found = vim.api.nvim_get_runtime_file(path, false)
|
|
|
|
if #found > 0 then
|
2020-12-25 03:23:57 -07:00
|
|
|
-- Making function name in Lua 5.1 (see src/loadlib.c:mkfuncname) is
|
|
|
|
-- a) strip prefix up to and including the first dash, if any
|
|
|
|
-- b) replace all dots by underscores
|
|
|
|
-- c) prepend "luaopen_"
|
|
|
|
-- So "foo-bar.baz" should result in "luaopen_bar_baz"
|
|
|
|
local dash = name:find("-", 1, true)
|
|
|
|
local modname = dash and name:sub(dash + 1) or name
|
|
|
|
local f, err = package.loadlib(found[1], "luaopen_"..modname:gsub("%.", "_"))
|
2020-12-07 15:47:28 -07:00
|
|
|
return f or error(err)
|
2017-05-22 14:46:57 -07:00
|
|
|
end
|
|
|
|
end
|
2020-10-19 11:05:54 -07:00
|
|
|
return nil
|
2017-05-22 14:46:57 -07:00
|
|
|
end
|
API: nvim_get_proc()
TODO: "exepath" field (win32: QueryFullProcessImageName())
On unix-likes `ps` is used because the platform-specific APIs are
a nightmare. For reference, below is a (incomplete) attempt:
diff --git a/src/nvim/os/process.c b/src/nvim/os/process.c
index 09769925aca5..99afbbf290c1 100644
--- a/src/nvim/os/process.c
+++ b/src/nvim/os/process.c
@@ -208,3 +210,60 @@ int os_proc_children(int ppid, int **proc_list, size_t *proc_count)
return 0;
}
+/// Gets various properties of the process identified by `pid`.
+///
+/// @param pid Process to inspect.
+/// @return Map of process properties, empty on error.
+Dictionary os_proc_info(int pid)
+{
+ Dictionary pinfo = ARRAY_DICT_INIT;
+#ifdef WIN32
+
+#elif defined(__APPLE__)
+ char buf[PROC_PIDPATHINFO_MAXSIZE];
+ if (proc_pidpath(pid, buf, sizeof(buf))) {
+ name = getName(buf);
+ PUT(pinfo, "exepath", STRING_OBJ(cstr_to_string(buf)));
+ return name;
+ } else {
+ ILOG("proc_pidpath() failed for pid: %d", pid);
+ }
+#elif defined(BSD)
+# if defined(__FreeBSD__)
+# define KP_COMM(o) o.ki_comm
+# else
+# define KP_COMM(o) o.p_comm
+# endif
+ struct kinfo_proc *proc = kinfo_getproc(pid);
+ if (proc) {
+ PUT(pinfo, "name", cstr_to_string(KP_COMM(proc)));
+ xfree(proc);
+ } else {
+ ILOG("kinfo_getproc() failed for pid: %d", pid);
+ }
+
+#elif defined(__linux__)
+ char fname[256] = { 0 };
+ char buf[MAXPATHL];
+ snprintf(fname, sizeof(fname), "/proc/%d/comm", pid);
+ FILE *fp = fopen(fname, "r");
+ // FileDescriptor *f = file_open_new(&error, fname, kFileReadOnly, 0);
+ // ptrdiff_t file_read(FileDescriptor *const fp, char *const ret_buf,
+ // const size_t size)
+ if (fp == NULL) {
+ ILOG("fopen() of /proc/%d/comm failed", pid);
+ } else {
+ size_t n = fread(buf, sizeof(char), sizeof(buf) - 1, fp);
+ if (n == 0) {
+ WLOG("fread() of /proc/%d/comm failed", pid);
+ } else {
+ size_t end = MIN(sizeof(buf) - 1, n);
+ end = (end > 0 && buf[end - 1] == '\n') ? end - 1 : end;
+ buf[end] = '\0';
+ PUT(pinfo, "name", STRING_OBJ(cstr_to_string(buf)));
+ }
+ }
+ fclose(fp);
+#endif
+ return pinfo;
+}
2018-03-15 21:13:38 -07:00
|
|
|
|
2020-10-19 11:05:54 -07:00
|
|
|
table.insert(package.loaders, 1, vim._load_package)
|
|
|
|
|
|
|
|
-- TODO(ZyX-I): Create compatibility layer.
|
|
|
|
|
2019-05-20 14:06:14 -07:00
|
|
|
--- Return a human-readable representation of the given object.
|
2019-03-29 13:56:38 -07:00
|
|
|
---
|
2019-05-20 14:06:14 -07:00
|
|
|
--@see https://github.com/kikito/inspect.lua
|
2019-09-09 15:35:30 -07:00
|
|
|
--@see https://github.com/mpeterv/vinspect
|
2019-05-20 14:06:14 -07:00
|
|
|
local function inspect(object, options) -- luacheck: no unused
|
|
|
|
error(object, options) -- Stub for gen_vimdoc.py
|
2019-01-07 07:42:20 -07:00
|
|
|
end
|
|
|
|
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
do
|
2019-08-31 03:44:42 -07:00
|
|
|
local tdots, tick, got_line1 = 0, 0, false
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
|
|
|
|
--- Paste handler, invoked by |nvim_paste()| when a conforming UI
|
|
|
|
--- (such as the |TUI|) pastes text into the editor.
|
|
|
|
---
|
|
|
|
--- Example: To remove ANSI color codes when pasting:
|
|
|
|
--- <pre>
|
|
|
|
--- vim.paste = (function(overridden)
|
|
|
|
--- return function(lines, phase)
|
|
|
|
--- for i,line in ipairs(lines) do
|
|
|
|
--- -- Scrub ANSI color codes from paste input.
|
|
|
|
--- lines[i] = line:gsub('\27%[[0-9;mK]+', '')
|
|
|
|
--- end
|
|
|
|
--- overridden(lines, phase)
|
|
|
|
--- end
|
|
|
|
--- end)(vim.paste)
|
|
|
|
--- </pre>
|
|
|
|
---
|
|
|
|
--@see |paste|
|
|
|
|
---
|
|
|
|
--@param lines |readfile()|-style list of lines to paste. |channel-lines|
|
|
|
|
--@param phase -1: "non-streaming" paste: the call contains all lines.
|
|
|
|
--- If paste is "streamed", `phase` indicates the stream state:
|
|
|
|
--- - 1: starts the paste (exactly once)
|
|
|
|
--- - 2: continues the paste (zero or more times)
|
|
|
|
--- - 3: ends the paste (exactly once)
|
|
|
|
--@returns false if client should cancel the paste.
|
|
|
|
function vim.paste(lines, phase)
|
2019-08-26 20:19:25 -07:00
|
|
|
local call = vim.api.nvim_call_function
|
|
|
|
local now = vim.loop.now()
|
|
|
|
local mode = call('mode', {}):sub(1,1)
|
|
|
|
if phase < 2 then -- Reset flags.
|
2019-08-31 03:44:42 -07:00
|
|
|
tdots, tick, got_line1 = now, 0, false
|
|
|
|
elseif mode ~= 'c' then
|
|
|
|
vim.api.nvim_command('undojoin')
|
2019-08-26 20:19:25 -07:00
|
|
|
end
|
|
|
|
if mode == 'c' and not got_line1 then -- cmdline-mode: paste only 1 line.
|
|
|
|
got_line1 = (#lines > 1)
|
|
|
|
vim.api.nvim_set_option('paste', true) -- For nvim_input().
|
2019-09-25 00:15:33 -07:00
|
|
|
local line1 = lines[1]:gsub('<', '<lt>'):gsub('[\r\n\012\027]', ' ') -- Scrub.
|
2019-09-08 14:58:47 -07:00
|
|
|
vim.api.nvim_input(line1)
|
|
|
|
vim.api.nvim_set_option('paste', false)
|
2019-11-09 22:18:51 -07:00
|
|
|
elseif mode ~= 'c' then
|
|
|
|
if phase < 2 and mode:find('^[vV\22sS\19]') then
|
|
|
|
vim.api.nvim_command([[exe "normal! \<Del>"]])
|
|
|
|
vim.api.nvim_put(lines, 'c', false, true)
|
|
|
|
elseif phase < 2 and not mode:find('^[iRt]') then
|
2019-09-09 08:29:49 -07:00
|
|
|
vim.api.nvim_put(lines, 'c', true, true)
|
|
|
|
-- XXX: Normal-mode: workaround bad cursor-placement after first chunk.
|
|
|
|
vim.api.nvim_command('normal! a')
|
2020-05-05 04:18:41 -07:00
|
|
|
elseif phase < 2 and mode == 'R' then
|
|
|
|
local nchars = 0
|
|
|
|
for _, line in ipairs(lines) do
|
|
|
|
nchars = nchars + line:len()
|
|
|
|
end
|
|
|
|
local row, col = unpack(vim.api.nvim_win_get_cursor(0))
|
|
|
|
local bufline = vim.api.nvim_buf_get_lines(0, row-1, row, true)[1]
|
|
|
|
local firstline = lines[1]
|
|
|
|
firstline = bufline:sub(1, col)..firstline
|
|
|
|
lines[1] = firstline
|
|
|
|
lines[#lines] = lines[#lines]..bufline:sub(col + nchars + 1, bufline:len())
|
|
|
|
vim.api.nvim_buf_set_lines(0, row-1, row, false, lines)
|
2019-09-09 08:29:49 -07:00
|
|
|
else
|
|
|
|
vim.api.nvim_put(lines, 'c', false, true)
|
|
|
|
end
|
2019-08-26 20:19:25 -07:00
|
|
|
end
|
|
|
|
if phase ~= -1 and (now - tdots >= 100) then
|
|
|
|
local dots = ('.'):rep(tick % 4)
|
|
|
|
tdots = now
|
|
|
|
tick = tick + 1
|
|
|
|
-- Use :echo because Lua print('') is a no-op, and we want to clear the
|
|
|
|
-- message when there are zero dots.
|
|
|
|
vim.api.nvim_command(('echo "%s"'):format(dots))
|
|
|
|
end
|
|
|
|
if phase == -1 or phase == 3 then
|
2019-09-08 15:37:24 -07:00
|
|
|
vim.api.nvim_command('redraw'..(tick > 1 and '|echo ""' or ''))
|
2019-08-26 20:19:25 -07:00
|
|
|
end
|
|
|
|
return true -- Paste will not continue if not returning `true`.
|
|
|
|
end
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
end
|
2019-08-26 20:19:25 -07:00
|
|
|
|
2019-08-25 16:01:01 -07:00
|
|
|
--- Defers callback `cb` until the Nvim API is safe to call.
|
2019-08-18 13:25:03 -07:00
|
|
|
---
|
2019-08-25 16:01:01 -07:00
|
|
|
---@see |lua-loop-callbacks|
|
|
|
|
---@see |vim.schedule()|
|
|
|
|
---@see |vim.in_fast_event()|
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
function vim.schedule_wrap(cb)
|
2019-08-18 13:25:03 -07:00
|
|
|
return (function (...)
|
|
|
|
local args = {...}
|
|
|
|
vim.schedule(function() cb(unpack(args)) end)
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
2020-07-02 04:09:17 -07:00
|
|
|
--- <Docs described in |vim.empty_dict()| >
|
|
|
|
--@private
|
2019-11-27 12:45:41 -07:00
|
|
|
function vim.empty_dict()
|
|
|
|
return setmetatable({}, vim._empty_dict_mt)
|
|
|
|
end
|
|
|
|
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
-- vim.fn.{func}(...)
|
|
|
|
vim.fn = setmetatable({}, {
|
|
|
|
__index = function(t, key)
|
|
|
|
local function _fn(...)
|
|
|
|
return vim.call(key, ...)
|
|
|
|
end
|
|
|
|
t[key] = _fn
|
|
|
|
return _fn
|
|
|
|
end
|
|
|
|
})
|
|
|
|
|
2020-06-18 21:23:30 -07:00
|
|
|
vim.funcref = function(viml_func_name)
|
|
|
|
return vim.fn[viml_func_name]
|
|
|
|
end
|
|
|
|
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
-- These are for loading runtime modules lazily since they aren't available in
|
|
|
|
-- the nvim binary as specified in executor.c
|
2019-01-17 16:44:35 -07:00
|
|
|
local function __index(t, key)
|
2020-11-04 02:41:22 -07:00
|
|
|
if key == 'treesitter' then
|
2019-06-15 03:10:12 -07:00
|
|
|
t.treesitter = require('vim.treesitter')
|
|
|
|
return t.treesitter
|
2019-11-13 13:55:26 -07:00
|
|
|
elseif require('vim.uri')[key] ~= nil then
|
|
|
|
-- Expose all `vim.uri` functions on the `vim` module.
|
|
|
|
t[key] = require('vim.uri')[key]
|
|
|
|
return t[key]
|
|
|
|
elseif key == 'lsp' then
|
|
|
|
t.lsp = require('vim.lsp')
|
|
|
|
return t.lsp
|
2020-07-05 18:30:12 -07:00
|
|
|
elseif key == 'highlight' then
|
|
|
|
t.highlight = require('vim.highlight')
|
|
|
|
return t.highlight
|
lsp: vim.lsp.diagnostic (#12655)
Breaking Changes:
- Deprecated all `vim.lsp.util.{*diagnostics*}()` functions.
- Instead, all functions must be found in vim.lsp.diagnostic
- For now, they issue a warning ONCE per neovim session. In a
"little while" we will remove them completely.
- `vim.lsp.callbacks` has moved to `vim.lsp.handlers`.
- For a "little while" we will just redirect `vim.lsp.callbacks` to
`vim.lsp.handlers`. However, we will remove this at some point, so
it is recommended that you change all of your references to
`callbacks` into `handlers`.
- This also means that for functions like |vim.lsp.start_client()|
and similar, keyword style arguments have moved from "callbacks"
to "handlers". Once again, these are currently being forward, but
will cease to be forwarded in a "little while".
- Changed the highlight groups for LspDiagnostic highlight as they were
inconsistently named.
- For more information, see |lsp-highlight-diagnostics|
- Changed the sign group names as well, to be consistent with
|lsp-highlight-diagnostics|
General Enhancements:
- Rewrote much of the getting started help document for lsp. It also
provides a much nicer configuration strategy, so as to not recommend
globally overwriting builtin neovim mappings.
LSP Enhancements:
- Introduced the concept of |lsp-handlers| which will allow much better
customization for users without having to copy & paste entire files /
functions / etc.
Diagnostic Enhancements:
- "goto next diagnostic" |vim.lsp.diagnostic.goto_next()|
- "goto prev diagnostic" |vim.lsp.diagnostic.goto_prev()|
- For each of the gotos, auto open diagnostics is available as a
configuration option
- Configurable diagnostic handling:
- See |vim.lsp.diagnostic.on_publish_diagnostics()|
- Delay display until after insert mode
- Configure signs
- Configure virtual text
- Configure underline
- Set the location list with the buffers diagnostics.
- See |vim.lsp.diagnostic.set_loclist()|
- Better performance for getting counts and line diagnostics
- They are now cached on save, to enhance lookups.
- Particularly useful for checking in statusline, etc.
- Actual testing :)
- See ./test/functional/plugin/lsp/diagnostic_spec.lua
- Added `guisp` for underline highlighting
NOTE: "a little while" means enough time to feel like most plugins and
plugin authors have had a chance to refactor their code to use the
updated calls. Then we will remove them completely. There is no need to
keep them, because we don't have any released version of neovim that
exposes these APIs. I'm trying to be nice to people following HEAD :)
Co-authored: [Twitch Chat 2020](https://twitch.tv/teej_dv)
2020-11-12 20:21:34 -07:00
|
|
|
elseif key == 'F' then
|
|
|
|
t.F = require('vim.F')
|
|
|
|
return t.F
|
2019-01-14 10:08:17 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
setmetatable(vim, {
|
|
|
|
__index = __index
|
|
|
|
})
|
2019-08-25 13:01:35 -07:00
|
|
|
|
2019-12-01 06:28:53 -07:00
|
|
|
-- An easier alias for commands.
|
|
|
|
vim.cmd = vim.api.nvim_command
|
|
|
|
|
|
|
|
-- These are the vim.env/v/g/o/bo/wo variable magic accessors.
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
do
|
|
|
|
local a = vim.api
|
|
|
|
local validate = vim.validate
|
|
|
|
local function make_meta_accessor(get, set, del)
|
|
|
|
validate {
|
|
|
|
get = {get, 'f'};
|
|
|
|
set = {set, 'f'};
|
|
|
|
del = {del, 'f', true};
|
|
|
|
}
|
|
|
|
local mt = {}
|
|
|
|
if del then
|
|
|
|
function mt:__newindex(k, v)
|
|
|
|
if v == nil then
|
|
|
|
return del(k)
|
|
|
|
end
|
|
|
|
return set(k, v)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
function mt:__newindex(k, v)
|
|
|
|
return set(k, v)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
function mt:__index(k)
|
|
|
|
return get(k)
|
|
|
|
end
|
|
|
|
return setmetatable({}, mt)
|
|
|
|
end
|
|
|
|
local function pcall_ret(status, ...)
|
|
|
|
if status then return ... end
|
|
|
|
end
|
|
|
|
local function nil_wrap(fn)
|
|
|
|
return function(...)
|
|
|
|
return pcall_ret(pcall(fn, ...))
|
|
|
|
end
|
|
|
|
end
|
2020-05-07 12:22:24 -07:00
|
|
|
|
|
|
|
vim.b = make_meta_accessor(
|
|
|
|
nil_wrap(function(v) return a.nvim_buf_get_var(0, v) end),
|
|
|
|
function(v, k) return a.nvim_buf_set_var(0, v, k) end,
|
|
|
|
function(v) return a.nvim_buf_del_var(0, v) end
|
|
|
|
)
|
|
|
|
vim.w = make_meta_accessor(
|
|
|
|
nil_wrap(function(v) return a.nvim_win_get_var(0, v) end),
|
|
|
|
function(v, k) return a.nvim_win_set_var(0, v, k) end,
|
|
|
|
function(v) return a.nvim_win_del_var(0, v) end
|
|
|
|
)
|
|
|
|
vim.t = make_meta_accessor(
|
|
|
|
nil_wrap(function(v) return a.nvim_tabpage_get_var(0, v) end),
|
|
|
|
function(v, k) return a.nvim_tabpage_set_var(0, v, k) end,
|
|
|
|
function(v) return a.nvim_tabpage_del_var(0, v) end
|
|
|
|
)
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
vim.g = make_meta_accessor(nil_wrap(a.nvim_get_var), a.nvim_set_var, a.nvim_del_var)
|
|
|
|
vim.v = make_meta_accessor(nil_wrap(a.nvim_get_vvar), a.nvim_set_vvar)
|
2019-11-26 09:57:53 -07:00
|
|
|
vim.o = make_meta_accessor(a.nvim_get_option, a.nvim_set_option)
|
2020-05-07 12:22:24 -07:00
|
|
|
|
2019-12-01 06:04:57 -07:00
|
|
|
local function getenv(k)
|
|
|
|
local v = vim.fn.getenv(k)
|
|
|
|
if v == vim.NIL then
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
return v
|
|
|
|
end
|
|
|
|
vim.env = make_meta_accessor(getenv, vim.fn.setenv)
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
-- TODO(ashkan) if/when these are available from an API, generate them
|
|
|
|
-- instead of hardcoding.
|
|
|
|
local window_options = {
|
|
|
|
arab = true; arabic = true; breakindent = true; breakindentopt = true;
|
|
|
|
bri = true; briopt = true; cc = true; cocu = true;
|
|
|
|
cole = true; colorcolumn = true; concealcursor = true; conceallevel = true;
|
|
|
|
crb = true; cuc = true; cul = true; cursorbind = true;
|
|
|
|
cursorcolumn = true; cursorline = true; diff = true; fcs = true;
|
|
|
|
fdc = true; fde = true; fdi = true; fdl = true;
|
|
|
|
fdm = true; fdn = true; fdt = true; fen = true;
|
|
|
|
fillchars = true; fml = true; fmr = true; foldcolumn = true;
|
|
|
|
foldenable = true; foldexpr = true; foldignore = true; foldlevel = true;
|
|
|
|
foldmarker = true; foldmethod = true; foldminlines = true; foldnestmax = true;
|
|
|
|
foldtext = true; lbr = true; lcs = true; linebreak = true;
|
|
|
|
list = true; listchars = true; nu = true; number = true;
|
|
|
|
numberwidth = true; nuw = true; previewwindow = true; pvw = true;
|
|
|
|
relativenumber = true; rightleft = true; rightleftcmd = true; rl = true;
|
|
|
|
rlc = true; rnu = true; scb = true; scl = true;
|
|
|
|
scr = true; scroll = true; scrollbind = true; signcolumn = true;
|
|
|
|
spell = true; statusline = true; stl = true; wfh = true;
|
|
|
|
wfw = true; winbl = true; winblend = true; winfixheight = true;
|
|
|
|
winfixwidth = true; winhighlight = true; winhl = true; wrap = true;
|
|
|
|
}
|
|
|
|
local function new_buf_opt_accessor(bufnr)
|
|
|
|
local function get(k)
|
|
|
|
if window_options[k] then
|
|
|
|
return a.nvim_err_writeln(k.." is a window option, not a buffer option")
|
|
|
|
end
|
2019-11-26 09:57:53 -07:00
|
|
|
if bufnr == nil and type(k) == "number" then
|
|
|
|
return new_buf_opt_accessor(k)
|
|
|
|
end
|
|
|
|
return a.nvim_buf_get_option(bufnr or 0, k)
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
end
|
|
|
|
local function set(k, v)
|
|
|
|
if window_options[k] then
|
|
|
|
return a.nvim_err_writeln(k.." is a window option, not a buffer option")
|
|
|
|
end
|
2019-11-26 09:57:53 -07:00
|
|
|
return a.nvim_buf_set_option(bufnr or 0, k, v)
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
end
|
2019-11-26 09:57:53 -07:00
|
|
|
return make_meta_accessor(get, set)
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
end
|
2019-11-26 09:57:53 -07:00
|
|
|
vim.bo = new_buf_opt_accessor(nil)
|
Lua: vim.env, vim.{g,v,w,bo,wo} #11442
- Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo}
- Redo gen_char_blob to generate multiple blobs instead of just one
so that multiple Lua modules can be inlined.
- Reorder vim.lua inclusion so that it can use previously defined C
functions and utility functions like vim.shared and vim.inspect things.
- Inline shared.lua into nvim, but also keep it available in runtime.
2019-11-24 03:28:48 -07:00
|
|
|
local function new_win_opt_accessor(winnr)
|
2019-11-26 09:57:53 -07:00
|
|
|
local function get(k)
|
|
|
|
if winnr == nil and type(k) == "number" then
|
|
|
|
return new_win_opt_accessor(k)
|
|
|
|
end
|
2019-12-07 04:34:02 -07:00
|
|
|
return a.nvim_win_get_option(winnr or 0, k)
|
2019-11-26 09:57:53 -07:00
|
|
|
end
|
2019-12-07 04:34:02 -07:00
|
|
|
local function set(k, v) return a.nvim_win_set_option(winnr or 0, k, v) end
|
2019-11-26 09:57:53 -07:00
|
|
|
return make_meta_accessor(get, set)
|
2019-08-25 13:01:35 -07:00
|
|
|
end
|
2019-11-26 09:57:53 -07:00
|
|
|
vim.wo = new_win_opt_accessor(nil)
|
2019-08-25 13:01:35 -07:00
|
|
|
end
|
2019-01-14 10:08:17 -07:00
|
|
|
|
2020-05-18 06:49:50 -07:00
|
|
|
--- Get a table of lines with start, end columns for a region marked by two points
|
|
|
|
---
|
|
|
|
--@param bufnr number of buffer
|
|
|
|
--@param pos1 (line, column) tuple marking beginning of region
|
|
|
|
--@param pos2 (line, column) tuple marking end of region
|
|
|
|
--@param regtype type of selection (:help setreg)
|
|
|
|
--@param inclusive boolean indicating whether the selection is end-inclusive
|
|
|
|
--@return region lua table of the form {linenr = {startcol,endcol}}
|
|
|
|
function vim.region(bufnr, pos1, pos2, regtype, inclusive)
|
|
|
|
if not vim.api.nvim_buf_is_loaded(bufnr) then
|
|
|
|
vim.fn.bufload(bufnr)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- in case of block selection, columns need to be adjusted for non-ASCII characters
|
|
|
|
-- TODO: handle double-width characters
|
|
|
|
local bufline
|
|
|
|
if regtype:byte() == 22 then
|
|
|
|
bufline = vim.api.nvim_buf_get_lines(bufnr, pos1[1], pos1[1] + 1, true)[1]
|
|
|
|
pos1[2] = vim.str_utfindex(bufline, pos1[2])
|
|
|
|
end
|
|
|
|
|
|
|
|
local region = {}
|
|
|
|
for l = pos1[1], pos2[1] do
|
|
|
|
local c1, c2
|
|
|
|
if regtype:byte() == 22 then -- block selection: take width from regtype
|
|
|
|
c1 = pos1[2]
|
|
|
|
c2 = c1 + regtype:sub(2)
|
|
|
|
-- and adjust for non-ASCII characters
|
|
|
|
bufline = vim.api.nvim_buf_get_lines(bufnr, l, l + 1, true)[1]
|
|
|
|
if c1 < #bufline then
|
|
|
|
c1 = vim.str_byteindex(bufline, c1)
|
|
|
|
end
|
|
|
|
if c2 < #bufline then
|
|
|
|
c2 = vim.str_byteindex(bufline, c2)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
c1 = (l == pos1[1]) and (pos1[2]) or 0
|
|
|
|
c2 = (l == pos2[1]) and (pos2[2] + (inclusive and 1 or 0)) or -1
|
|
|
|
end
|
|
|
|
table.insert(region, l, {c1, c2})
|
|
|
|
end
|
|
|
|
return region
|
|
|
|
end
|
|
|
|
|
|
|
|
--- Defers calling `fn` until `timeout` ms passes.
|
|
|
|
---
|
|
|
|
--- Use to do a one-shot timer that calls `fn`
|
2020-07-07 01:55:40 -07:00
|
|
|
--- Note: The {fn} is |schedule_wrap|ped automatically, so API functions are
|
|
|
|
--- safe to call.
|
2020-05-18 06:49:50 -07:00
|
|
|
--@param fn Callback to call once `timeout` expires
|
|
|
|
--@param timeout Number of milliseconds to wait before calling `fn`
|
|
|
|
--@return timer luv timer object
|
|
|
|
function vim.defer_fn(fn, timeout)
|
|
|
|
vim.validate { fn = { fn, 'c', true}; }
|
|
|
|
local timer = vim.loop.new_timer()
|
|
|
|
timer:start(timeout, 0, vim.schedule_wrap(function()
|
|
|
|
timer:stop()
|
|
|
|
timer:close()
|
|
|
|
|
|
|
|
fn()
|
|
|
|
end))
|
|
|
|
|
|
|
|
return timer
|
|
|
|
end
|
|
|
|
|
2020-08-14 07:03:17 -07:00
|
|
|
local on_keystroke_callbacks = {}
|
|
|
|
|
|
|
|
--- Register a lua {fn} with an {id} to be run after every keystroke.
|
|
|
|
---
|
|
|
|
--@param fn function: Function to call. It should take one argument, which is a string.
|
|
|
|
--- The string will contain the literal keys typed.
|
|
|
|
--- See |i_CTRL-V|
|
|
|
|
---
|
|
|
|
--- If {fn} is nil, it removes the callback for the associated {ns_id}
|
|
|
|
--@param ns_id number? Namespace ID. If not passed or 0, will generate and return a new
|
|
|
|
--- namespace ID from |nvim_create_namesapce()|
|
|
|
|
---
|
|
|
|
--@return number Namespace ID associated with {fn}
|
|
|
|
---
|
|
|
|
--@note {fn} will be automatically removed if an error occurs while calling.
|
|
|
|
--- This is to prevent the annoying situation of every keystroke erroring
|
|
|
|
--- while trying to remove a broken callback.
|
|
|
|
--@note {fn} will not be cleared from |nvim_buf_clear_namespace()|
|
|
|
|
--@note {fn} will receive the keystrokes after mappings have been evaluated
|
|
|
|
function vim.register_keystroke_callback(fn, ns_id)
|
|
|
|
vim.validate {
|
|
|
|
fn = { fn, 'c', true},
|
|
|
|
ns_id = { ns_id, 'n', true }
|
|
|
|
}
|
|
|
|
|
|
|
|
if ns_id == nil or ns_id == 0 then
|
|
|
|
ns_id = vim.api.nvim_create_namespace('')
|
|
|
|
end
|
|
|
|
|
|
|
|
on_keystroke_callbacks[ns_id] = fn
|
|
|
|
return ns_id
|
|
|
|
end
|
|
|
|
|
|
|
|
--- Function that executes the keystroke callbacks.
|
|
|
|
--@private
|
|
|
|
function vim._log_keystroke(char)
|
|
|
|
local failed_ns_ids = {}
|
|
|
|
local failed_messages = {}
|
|
|
|
for k, v in pairs(on_keystroke_callbacks) do
|
|
|
|
local ok, err_msg = pcall(v, char)
|
|
|
|
if not ok then
|
|
|
|
vim.register_keystroke_callback(nil, k)
|
|
|
|
|
|
|
|
table.insert(failed_ns_ids, k)
|
|
|
|
table.insert(failed_messages, err_msg)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if failed_ns_ids[1] then
|
|
|
|
error(string.format(
|
|
|
|
"Error executing 'on_keystroke' with ns_ids of '%s'\n With messages: %s",
|
|
|
|
table.concat(failed_ns_ids, ", "),
|
|
|
|
table.concat(failed_messages, "\n")))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-11-24 21:24:52 -07:00
|
|
|
--- Generate a list of possible completions for the string.
|
|
|
|
--- String starts with ^ and then has the pattern.
|
|
|
|
---
|
|
|
|
--- 1. Can we get it to just return things in the global namespace with that name prefix
|
|
|
|
--- 2. Can we get it to return things from global namespace even with `print(` in front.
|
|
|
|
function vim._expand_pat(pat, env)
|
|
|
|
env = env or _G
|
|
|
|
|
|
|
|
pat = string.sub(pat, 2, #pat)
|
|
|
|
|
|
|
|
if pat == '' then
|
|
|
|
local result = vim.tbl_keys(env)
|
|
|
|
table.sort(result)
|
|
|
|
return result
|
|
|
|
end
|
|
|
|
|
|
|
|
-- TODO: We can handle spaces in [] ONLY.
|
|
|
|
-- We should probably do that at some point, just for cooler completion.
|
|
|
|
-- TODO: We can suggest the variable names to go in []
|
|
|
|
-- This would be difficult as well.
|
|
|
|
-- Probably just need to do a smarter match than just `:match`
|
|
|
|
|
|
|
|
-- Get the last part of the pattern
|
|
|
|
local last_part = pat:match("[%w.:_%[%]'\"]+$")
|
|
|
|
if not last_part then return {} end
|
|
|
|
|
|
|
|
local parts, search_index = vim._expand_pat_get_parts(last_part)
|
|
|
|
|
|
|
|
local match_pat = '^' .. string.sub(last_part, search_index, #last_part)
|
|
|
|
local prefix_match_pat = string.sub(pat, 1, #pat - #match_pat + 1) or ''
|
|
|
|
|
|
|
|
local final_env = env
|
|
|
|
for _, part in ipairs(parts) do
|
|
|
|
if type(final_env) ~= 'table' then
|
|
|
|
return {}
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Normally, we just have a string
|
|
|
|
-- Just attempt to get the string directly from the environment
|
|
|
|
if type(part) == "string" then
|
|
|
|
final_env = rawget(final_env, part)
|
|
|
|
else
|
|
|
|
-- However, sometimes you want to use a variable, and complete on it
|
|
|
|
-- With this, you have the power.
|
|
|
|
|
|
|
|
-- MY_VAR = "api"
|
|
|
|
-- vim[MY_VAR]
|
|
|
|
-- -> _G[MY_VAR] -> "api"
|
|
|
|
local result_key = part[1]
|
|
|
|
if not result_key then
|
|
|
|
return {}
|
|
|
|
end
|
|
|
|
|
|
|
|
local result = rawget(env, result_key)
|
|
|
|
|
|
|
|
if result == nil then
|
|
|
|
return {}
|
|
|
|
end
|
|
|
|
|
|
|
|
final_env = rawget(final_env, result)
|
|
|
|
end
|
|
|
|
|
|
|
|
if not final_env then
|
|
|
|
return {}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local result = vim.tbl_map(function(v)
|
|
|
|
return prefix_match_pat .. v
|
|
|
|
end, vim.tbl_filter(function(name)
|
|
|
|
return string.find(name, match_pat) ~= nil
|
|
|
|
end, vim.tbl_keys(final_env)))
|
|
|
|
|
|
|
|
table.sort(result)
|
|
|
|
|
|
|
|
return result
|
|
|
|
end
|
|
|
|
|
|
|
|
vim._expand_pat_get_parts = function(lua_string)
|
|
|
|
local parts = {}
|
|
|
|
|
|
|
|
local accumulator, search_index = '', 1
|
|
|
|
local in_brackets, bracket_end = false, -1
|
|
|
|
local string_char = nil
|
|
|
|
for idx = 1, #lua_string do
|
|
|
|
local s = lua_string:sub(idx, idx)
|
|
|
|
|
|
|
|
if not in_brackets and (s == "." or s == ":") then
|
|
|
|
table.insert(parts, accumulator)
|
|
|
|
accumulator = ''
|
|
|
|
|
|
|
|
search_index = idx + 1
|
|
|
|
elseif s == "[" then
|
|
|
|
in_brackets = true
|
|
|
|
|
|
|
|
table.insert(parts, accumulator)
|
|
|
|
accumulator = ''
|
|
|
|
|
|
|
|
search_index = idx + 1
|
|
|
|
elseif in_brackets then
|
|
|
|
if idx == bracket_end then
|
|
|
|
in_brackets = false
|
|
|
|
search_index = idx + 1
|
|
|
|
|
|
|
|
if string_char == "VAR" then
|
|
|
|
table.insert(parts, { accumulator })
|
|
|
|
accumulator = ''
|
|
|
|
|
|
|
|
string_char = nil
|
|
|
|
end
|
|
|
|
elseif not string_char then
|
|
|
|
bracket_end = string.find(lua_string, ']', idx, true)
|
|
|
|
|
|
|
|
if s == '"' or s == "'" then
|
|
|
|
string_char = s
|
|
|
|
elseif s ~= ' ' then
|
|
|
|
string_char = "VAR"
|
|
|
|
accumulator = s
|
|
|
|
end
|
|
|
|
elseif string_char then
|
|
|
|
if string_char ~= s then
|
|
|
|
accumulator = accumulator .. s
|
|
|
|
else
|
|
|
|
table.insert(parts, accumulator)
|
|
|
|
accumulator = ''
|
|
|
|
|
|
|
|
string_char = nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
accumulator = accumulator .. s
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
parts = vim.tbl_filter(function(val) return #val > 0 end, parts)
|
|
|
|
|
|
|
|
return parts, search_index
|
|
|
|
end
|
|
|
|
|
API: nvim_get_proc()
TODO: "exepath" field (win32: QueryFullProcessImageName())
On unix-likes `ps` is used because the platform-specific APIs are
a nightmare. For reference, below is a (incomplete) attempt:
diff --git a/src/nvim/os/process.c b/src/nvim/os/process.c
index 09769925aca5..99afbbf290c1 100644
--- a/src/nvim/os/process.c
+++ b/src/nvim/os/process.c
@@ -208,3 +210,60 @@ int os_proc_children(int ppid, int **proc_list, size_t *proc_count)
return 0;
}
+/// Gets various properties of the process identified by `pid`.
+///
+/// @param pid Process to inspect.
+/// @return Map of process properties, empty on error.
+Dictionary os_proc_info(int pid)
+{
+ Dictionary pinfo = ARRAY_DICT_INIT;
+#ifdef WIN32
+
+#elif defined(__APPLE__)
+ char buf[PROC_PIDPATHINFO_MAXSIZE];
+ if (proc_pidpath(pid, buf, sizeof(buf))) {
+ name = getName(buf);
+ PUT(pinfo, "exepath", STRING_OBJ(cstr_to_string(buf)));
+ return name;
+ } else {
+ ILOG("proc_pidpath() failed for pid: %d", pid);
+ }
+#elif defined(BSD)
+# if defined(__FreeBSD__)
+# define KP_COMM(o) o.ki_comm
+# else
+# define KP_COMM(o) o.p_comm
+# endif
+ struct kinfo_proc *proc = kinfo_getproc(pid);
+ if (proc) {
+ PUT(pinfo, "name", cstr_to_string(KP_COMM(proc)));
+ xfree(proc);
+ } else {
+ ILOG("kinfo_getproc() failed for pid: %d", pid);
+ }
+
+#elif defined(__linux__)
+ char fname[256] = { 0 };
+ char buf[MAXPATHL];
+ snprintf(fname, sizeof(fname), "/proc/%d/comm", pid);
+ FILE *fp = fopen(fname, "r");
+ // FileDescriptor *f = file_open_new(&error, fname, kFileReadOnly, 0);
+ // ptrdiff_t file_read(FileDescriptor *const fp, char *const ret_buf,
+ // const size_t size)
+ if (fp == NULL) {
+ ILOG("fopen() of /proc/%d/comm failed", pid);
+ } else {
+ size_t n = fread(buf, sizeof(char), sizeof(buf) - 1, fp);
+ if (n == 0) {
+ WLOG("fread() of /proc/%d/comm failed", pid);
+ } else {
+ size_t end = MIN(sizeof(buf) - 1, n);
+ end = (end > 0 && buf[end - 1] == '\n') ? end - 1 : end;
+ buf[end] = '\0';
+ PUT(pinfo, "name", STRING_OBJ(cstr_to_string(buf)));
+ }
+ }
+ fclose(fp);
+#endif
+ return pinfo;
+}
2018-03-15 21:13:38 -07:00
|
|
|
return module
|