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.
|
2023-06-22 03:44:51 -07:00
|
|
|
-- 2. runtime/lua/vim/shared.lua: pure Lua functions which always
|
2022-03-06 05:13:10 -07:00
|
|
|
-- are available. Used in the test runner, as well as worker threads
|
|
|
|
-- and processes launched from Nvim.
|
|
|
|
-- 3. runtime/lua/vim/_editor.lua: Code which directly interacts with
|
|
|
|
-- the Nvim editor state. Only available in the main thread.
|
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.
|
2022-10-09 05:21:52 -07:00
|
|
|
--
|
|
|
|
-- Compatibility with Vim's `if_lua` is explicitly a non-goal.
|
2019-01-17 16:44:35 -07:00
|
|
|
--
|
|
|
|
-- 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
|
|
|
|
|
2021-05-28 08:24:48 -07:00
|
|
|
-- These are for loading runtime modules lazily since they aren't available in
|
|
|
|
-- the nvim binary as specified in executor.c
|
2022-03-06 05:13:10 -07:00
|
|
|
for k, v in pairs({
|
|
|
|
treesitter = true,
|
|
|
|
filetype = true,
|
2023-03-26 03:42:15 -07:00
|
|
|
loader = true,
|
2023-09-16 15:10:30 -07:00
|
|
|
func = true,
|
2022-03-06 05:13:10 -07:00
|
|
|
F = true,
|
|
|
|
lsp = true,
|
|
|
|
highlight = true,
|
|
|
|
diagnostic = true,
|
|
|
|
keymap = true,
|
|
|
|
ui = true,
|
2022-05-31 11:10:18 -07:00
|
|
|
health = true,
|
2022-11-05 12:37:05 -07:00
|
|
|
secure = true,
|
2023-10-20 23:51:26 -07:00
|
|
|
snippet = true,
|
2023-03-04 23:52:27 -07:00
|
|
|
_watch = true,
|
2022-03-06 05:13:10 -07:00
|
|
|
}) do
|
|
|
|
vim._submodules[k] = v
|
|
|
|
end
|
2021-05-28 08:24:48 -07:00
|
|
|
|
2021-01-27 01:00:28 -07:00
|
|
|
-- There are things which have special rules in vim._init_packages
|
|
|
|
-- for legacy reasons (uri) or for performance (_inspector).
|
|
|
|
-- most new things should go into a submodule namespace ( vim.foobar.do_thing() )
|
|
|
|
vim._extra = {
|
|
|
|
uri_from_fname = true,
|
|
|
|
uri_from_bufnr = true,
|
|
|
|
uri_to_fname = true,
|
|
|
|
uri_to_bufnr = true,
|
|
|
|
show_pos = true,
|
|
|
|
inspect_pos = true,
|
|
|
|
}
|
|
|
|
|
2023-07-18 07:42:30 -07:00
|
|
|
--- @private
|
2021-01-27 07:09:02 -07:00
|
|
|
vim.log = {
|
|
|
|
levels = {
|
|
|
|
TRACE = 0,
|
|
|
|
DEBUG = 1,
|
|
|
|
INFO = 2,
|
|
|
|
WARN = 3,
|
|
|
|
ERROR = 4,
|
2022-05-03 07:49:23 -07:00
|
|
|
OFF = 5,
|
2021-01-27 07:09:02 -07:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2023-06-07 05:52:23 -07:00
|
|
|
-- TODO(lewis6991): document that the signature is system({cmd}, [{opts},] {on_exit})
|
2023-11-02 16:22:02 -07:00
|
|
|
--- Runs a system command or throws an error if {cmd} cannot be run.
|
2023-06-07 05:52:23 -07:00
|
|
|
---
|
|
|
|
--- Examples:
|
|
|
|
---
|
2023-09-14 06:23:01 -07:00
|
|
|
--- ```lua
|
|
|
|
--- local on_exit = function(obj)
|
|
|
|
--- print(obj.code)
|
|
|
|
--- print(obj.signal)
|
|
|
|
--- print(obj.stdout)
|
|
|
|
--- print(obj.stderr)
|
|
|
|
--- end
|
2023-06-07 05:52:23 -07:00
|
|
|
---
|
2023-11-02 16:22:02 -07:00
|
|
|
--- -- Runs asynchronously:
|
2023-09-14 06:23:01 -07:00
|
|
|
--- vim.system({'echo', 'hello'}, { text = true }, on_exit)
|
2023-06-07 05:52:23 -07:00
|
|
|
---
|
2023-11-02 16:22:02 -07:00
|
|
|
--- -- Runs synchronously:
|
2023-09-14 06:23:01 -07:00
|
|
|
--- local obj = vim.system({'echo', 'hello'}, { text = true }):wait()
|
|
|
|
--- -- { code = 0, signal = 0, stdout = 'hello', stderr = '' }
|
|
|
|
---
|
|
|
|
--- ```
|
2023-06-07 05:52:23 -07:00
|
|
|
---
|
2023-11-02 16:22:02 -07:00
|
|
|
--- See |uv.spawn()| for more details. Note: unlike |uv.spawn()|, vim.system
|
|
|
|
--- throws an error if {cmd} cannot be run.
|
2023-06-07 05:52:23 -07:00
|
|
|
---
|
|
|
|
--- @param cmd (string[]) Command to execute
|
2024-01-09 10:36:46 -07:00
|
|
|
--- @param opts vim.SystemOpts? Options:
|
2023-06-07 05:52:23 -07:00
|
|
|
--- - cwd: (string) Set the current working directory for the sub-process.
|
|
|
|
--- - env: table<string,string> Set environment variables for the new process. Inherits the
|
|
|
|
--- current environment with `NVIM` set to |v:servername|.
|
|
|
|
--- - clear_env: (boolean) `env` defines the job environment exactly, instead of merging current
|
|
|
|
--- environment.
|
|
|
|
--- - stdin: (string|string[]|boolean) If `true`, then a pipe to stdin is opened and can be written
|
|
|
|
--- to via the `write()` method to SystemObj. If string or string[] then will be written to stdin
|
|
|
|
--- and closed. Defaults to `false`.
|
|
|
|
--- - stdout: (boolean|function)
|
|
|
|
--- Handle output from stdout. When passed as a function must have the signature `fun(err: string, data: string)`.
|
|
|
|
--- Defaults to `true`
|
|
|
|
--- - stderr: (boolean|function)
|
2023-09-13 21:05:27 -07:00
|
|
|
--- Handle output from stderr. When passed as a function must have the signature `fun(err: string, data: string)`.
|
2023-06-07 05:52:23 -07:00
|
|
|
--- Defaults to `true`.
|
|
|
|
--- - text: (boolean) Handle stdout and stderr as text. Replaces `\r\n` with `\n`.
|
2023-09-04 03:30:16 -07:00
|
|
|
--- - timeout: (integer) Run the command with a time limit. Upon timeout the process is sent the
|
|
|
|
--- TERM signal (15) and the exit code is set to 124.
|
2023-06-07 05:52:23 -07:00
|
|
|
--- - detach: (boolean) If true, spawn the child process in a detached state - this will make it
|
|
|
|
--- a process group leader, and will effectively enable the child to keep running after the
|
|
|
|
--- parent exits. Note that the child process will still keep the parent's event loop alive
|
|
|
|
--- unless the parent process calls |uv.unref()| on the child's process handle.
|
|
|
|
---
|
2024-01-09 10:36:46 -07:00
|
|
|
--- @param on_exit? fun(out: vim.SystemCompleted) Called when subprocess exits. When provided, the command runs
|
2023-06-07 05:52:23 -07:00
|
|
|
--- asynchronously. Receives SystemCompleted object, see return of SystemObj:wait().
|
|
|
|
---
|
2023-09-04 04:03:03 -07:00
|
|
|
--- @return vim.SystemObj Object with the fields:
|
2024-04-15 04:33:09 -07:00
|
|
|
--- - cmd (string[]) Command name and args
|
2023-06-07 05:52:23 -07:00
|
|
|
--- - pid (integer) Process ID
|
2023-09-04 03:30:16 -07:00
|
|
|
--- - wait (fun(timeout: integer|nil): SystemCompleted) Wait for the process to complete. Upon
|
2023-11-21 04:24:30 -07:00
|
|
|
--- timeout the process is sent the KILL signal (9) and the exit code is set to 124. Cannot
|
|
|
|
--- be called in |api-fast|.
|
2023-06-07 05:52:23 -07:00
|
|
|
--- - SystemCompleted is an object with the fields:
|
2024-02-15 10:16:04 -07:00
|
|
|
--- - code: (integer)
|
|
|
|
--- - signal: (integer)
|
|
|
|
--- - stdout: (string), nil if stdout argument is passed
|
|
|
|
--- - stderr: (string), nil if stderr argument is passed
|
2023-09-04 03:30:16 -07:00
|
|
|
--- - kill (fun(signal: integer|string))
|
2023-06-07 05:52:23 -07:00
|
|
|
--- - write (fun(data: string|nil)) Requires `stdin=true`. Pass `nil` to close the stream.
|
|
|
|
--- - is_closing (fun(): boolean)
|
|
|
|
function vim.system(cmd, opts, on_exit)
|
|
|
|
if type(opts) == 'function' then
|
|
|
|
on_exit = opts
|
|
|
|
opts = nil
|
|
|
|
end
|
|
|
|
return require('vim._system').run(cmd, opts, on_exit)
|
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
|
|
|
|
|
|
|
|
-- 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=' }
|
2023-06-07 05:52:23 -07:00
|
|
|
local r = vim.system(cmd):wait()
|
|
|
|
local name = assert(r.stdout)
|
|
|
|
if r.code == 1 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.
|
2023-06-07 05:52:23 -07:00
|
|
|
elseif r.code ~= 0 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
|
2023-12-13 06:04:24 -07:00
|
|
|
local ppid_string = assert(vim.system({ 'ps', '-p', pid, '-o', 'ppid=' }):wait().stdout)
|
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('^.*/', '')
|
2023-12-13 06:04:24 -07:00
|
|
|
local ppid = tonumber(ppid_string) 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 }
|
2023-06-07 05:52:23 -07:00
|
|
|
local r = vim.system(cmd):wait()
|
|
|
|
if r.code == 1 and vim.trim(r.stdout) == '' then
|
2018-03-14 15:26:37 -07:00
|
|
|
return {} -- Process not found.
|
2023-06-07 05:52:23 -07:00
|
|
|
elseif r.code ~= 0 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 = {}
|
2023-06-07 05:52:23 -07:00
|
|
|
for s in r.stdout: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
|
|
|
|
|
2024-02-27 08:20:32 -07:00
|
|
|
--- @nodoc
|
2024-01-16 03:30:08 -07:00
|
|
|
--- @class vim.inspect.Opts
|
|
|
|
--- @field depth? integer
|
|
|
|
--- @field newline? string
|
|
|
|
--- @field process? fun(item:any, path: string[]): any
|
|
|
|
|
2022-10-09 05:21:52 -07:00
|
|
|
--- Gets a human-readable representation of the given object.
|
2019-03-29 13:56:38 -07:00
|
|
|
---
|
2023-06-23 03:16:55 -07:00
|
|
|
---@see |vim.print()|
|
2021-08-22 13:55:28 -07:00
|
|
|
---@see https://github.com/kikito/inspect.lua
|
|
|
|
---@see https://github.com/mpeterv/vinspect
|
2023-08-27 01:41:32 -07:00
|
|
|
---@return string
|
2024-01-16 03:30:08 -07:00
|
|
|
---@overload fun(x: any, opts?: vim.inspect.Opts): string
|
2023-07-18 07:42:30 -07:00
|
|
|
vim.inspect = vim.inspect
|
2019-01-07 07:42:20 -07:00
|
|
|
|
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
|
2022-03-05 15:56:24 -07:00
|
|
|
local tdots, tick, got_line1, undo_started, trailing_nl = 0, 0, false, false, 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:
|
2023-09-14 06:23:01 -07:00
|
|
|
---
|
|
|
|
--- ```lua
|
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.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)
|
2023-09-14 06:23:01 -07:00
|
|
|
--- ```
|
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
|
|
|
---
|
2021-08-22 13:55:28 -07:00
|
|
|
---@see |paste|
|
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
|
|
|
---
|
2022-10-05 04:21:45 -07:00
|
|
|
---@param lines string[] # |readfile()|-style list of lines to paste. |channel-lines|
|
2024-01-09 10:36:46 -07:00
|
|
|
---@param phase (-1|1|2|3) -1: "non-streaming" paste: the call contains all lines.
|
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
|
|
|
--- 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)
|
2023-07-10 04:38:15 -07:00
|
|
|
---@return boolean result false if client should cancel the paste.
|
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.paste(lines, phase)
|
2023-06-03 03:06:00 -07:00
|
|
|
local now = vim.uv.now()
|
2022-03-05 15:56:24 -07:00
|
|
|
local is_first_chunk = phase < 2
|
2022-03-05 15:56:24 -07:00
|
|
|
local is_last_chunk = phase == -1 or phase == 3
|
2022-03-05 15:56:24 -07:00
|
|
|
if is_first_chunk then -- Reset flags.
|
2022-03-05 15:56:24 -07:00
|
|
|
tdots, tick, got_line1, undo_started, trailing_nl = now, 0, false, false, false
|
2022-03-05 15:56:24 -07:00
|
|
|
end
|
|
|
|
if #lines == 0 then
|
|
|
|
lines = { '' }
|
|
|
|
end
|
|
|
|
if #lines == 1 and lines[1] == '' and not is_last_chunk then
|
|
|
|
-- An empty chunk can cause some edge cases in streamed pasting,
|
|
|
|
-- so don't do anything unless it is the last chunk.
|
|
|
|
return true
|
2022-03-05 15:56:24 -07:00
|
|
|
end
|
|
|
|
-- Note: mode doesn't always start with "c" in cmdline mode, so use getcmdtype() instead.
|
|
|
|
if vim.fn.getcmdtype() ~= '' then -- cmdline-mode: paste only 1 line.
|
|
|
|
if not got_line1 then
|
|
|
|
got_line1 = (#lines > 1)
|
2022-04-16 17:11:53 -07:00
|
|
|
-- Escape control characters
|
|
|
|
local line1 = lines[1]:gsub('(%c)', '\022%1')
|
|
|
|
-- nvim_input() is affected by mappings,
|
|
|
|
-- so use nvim_feedkeys() with "n" flag to ignore mappings.
|
2022-11-05 21:43:05 -07:00
|
|
|
-- "t" flag is also needed so the pasted text is saved in cmdline history.
|
|
|
|
vim.api.nvim_feedkeys(line1, 'nt', true)
|
2022-03-05 15:56:24 -07:00
|
|
|
end
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
local mode = vim.api.nvim_get_mode().mode
|
2022-03-05 15:56:24 -07:00
|
|
|
if undo_started then
|
2019-08-31 03:44:42 -07:00
|
|
|
vim.api.nvim_command('undojoin')
|
2019-08-26 20:19:25 -07:00
|
|
|
end
|
2022-03-05 15:56:24 -07:00
|
|
|
if mode:find('^i') or mode:find('^n?t') then -- Insert mode or Terminal buffer
|
|
|
|
vim.api.nvim_put(lines, 'c', false, true)
|
|
|
|
elseif phase < 2 and mode:find('^R') and not mode:find('^Rv') then -- Replace mode
|
|
|
|
-- TODO: implement Replace mode streamed pasting
|
|
|
|
-- TODO: support Virtual Replace mode
|
|
|
|
local nchars = 0
|
|
|
|
for _, line in ipairs(lines) do
|
|
|
|
nchars = nchars + line:len()
|
|
|
|
end
|
2024-03-06 03:03:55 -07:00
|
|
|
--- @type integer, integer
|
2022-03-05 15:56:24 -07:00
|
|
|
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)
|
|
|
|
elseif mode:find('^[nvV\22sS\19]') then -- Normal or Visual or Select mode
|
|
|
|
if mode:find('^n') then -- Normal mode
|
2022-03-05 15:56:24 -07:00
|
|
|
-- When there was a trailing new line in the previous chunk,
|
|
|
|
-- the cursor is on the first character of the next line,
|
|
|
|
-- so paste before the cursor instead of after it.
|
|
|
|
vim.api.nvim_put(lines, 'c', not trailing_nl, false)
|
2022-03-05 15:56:24 -07:00
|
|
|
else -- Visual or Select mode
|
|
|
|
vim.api.nvim_command([[exe "silent normal! \<Del>"]])
|
|
|
|
local del_start = vim.fn.getpos("'[")
|
|
|
|
local cursor_pos = vim.fn.getpos('.')
|
|
|
|
if mode:find('^[VS]') then -- linewise
|
|
|
|
if cursor_pos[2] < del_start[2] then -- replacing lines at eof
|
|
|
|
-- create a new line
|
|
|
|
vim.api.nvim_put({ '' }, 'l', true, true)
|
2022-03-05 15:56:24 -07:00
|
|
|
end
|
2022-03-05 15:56:24 -07:00
|
|
|
vim.api.nvim_put(lines, 'c', false, false)
|
|
|
|
else
|
|
|
|
-- paste after cursor when replacing text at eol, otherwise paste before cursor
|
|
|
|
vim.api.nvim_put(lines, 'c', cursor_pos[3] < del_start[3], false)
|
2022-03-05 15:56:24 -07:00
|
|
|
end
|
2019-09-09 08:29:49 -07:00
|
|
|
end
|
2022-03-05 15:56:24 -07:00
|
|
|
-- put cursor at the end of the text instead of one character after it
|
|
|
|
vim.fn.setpos('.', vim.fn.getpos("']"))
|
2022-03-05 15:56:24 -07:00
|
|
|
trailing_nl = lines[#lines] == ''
|
2022-03-05 15:56:24 -07:00
|
|
|
else -- Don't know what to do in other modes
|
|
|
|
return false
|
2019-08-26 20:19:25 -07:00
|
|
|
end
|
2022-03-05 15:56:24 -07:00
|
|
|
undo_started = true
|
2019-08-26 20:19:25 -07:00
|
|
|
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
|
2022-03-05 15:56:24 -07:00
|
|
|
if is_last_chunk 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
|
|
|
|
2023-09-20 22:53:05 -07:00
|
|
|
--- Returns a function which calls {fn} via |vim.schedule()|.
|
|
|
|
---
|
|
|
|
--- The returned function passes all arguments to {fn}.
|
|
|
|
---
|
|
|
|
--- Example:
|
|
|
|
---
|
|
|
|
--- ```lua
|
|
|
|
--- function notify_readable(_err, readable)
|
|
|
|
--- vim.notify("readable? " .. tostring(readable))
|
|
|
|
--- end
|
|
|
|
--- vim.uv.fs_access(vim.fn.stdpath("config"), "R", vim.schedule_wrap(notify_readable))
|
|
|
|
--- ```
|
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()|
|
2023-09-20 22:53:05 -07:00
|
|
|
---@param fn function
|
2022-10-05 04:21:45 -07:00
|
|
|
---@return function
|
2023-09-20 22:53:05 -07:00
|
|
|
function vim.schedule_wrap(fn)
|
2019-08-18 13:25:03 -07:00
|
|
|
return function(...)
|
2021-08-07 12:17:45 -07:00
|
|
|
local args = vim.F.pack_len(...)
|
|
|
|
vim.schedule(function()
|
2023-09-20 22:53:05 -07:00
|
|
|
fn(vim.F.unpack_len(args))
|
2019-08-18 13:25:03 -07:00
|
|
|
end)
|
2022-05-09 02:23:51 -07:00
|
|
|
end
|
2019-08-18 13:25:03 -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
|
|
|
-- vim.fn.{func}(...)
|
2024-01-22 17:53:15 -07:00
|
|
|
---@nodoc
|
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 = setmetatable({}, {
|
2024-03-06 03:03:55 -07:00
|
|
|
--- @param t table<string,function>
|
|
|
|
--- @param key string
|
|
|
|
--- @return function
|
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
|
|
|
__index = function(t, key)
|
2024-03-06 03:03:55 -07:00
|
|
|
local _fn --- @type function
|
2021-02-03 17:13:04 -07:00
|
|
|
if vim.api[key] ~= nil then
|
2021-02-06 10:06:33 -07:00
|
|
|
_fn = function()
|
2021-02-04 07:27:38 -07:00
|
|
|
error(string.format('Tried to call API function with vim.fn: use vim.api.%s instead', key))
|
2021-02-03 17:13:04 -07:00
|
|
|
end
|
|
|
|
else
|
|
|
|
_fn = function(...)
|
|
|
|
return vim.call(key, ...)
|
|
|
|
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
|
|
|
|
t[key] = _fn
|
|
|
|
return _fn
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
|
2023-07-18 07:42:30 -07:00
|
|
|
--- @private
|
2020-06-18 21:23:30 -07:00
|
|
|
vim.funcref = function(viml_func_name)
|
|
|
|
return vim.fn[viml_func_name]
|
|
|
|
end
|
|
|
|
|
2023-07-18 07:42:30 -07:00
|
|
|
local VIM_CMD_ARG_MAX = 20
|
|
|
|
|
2023-11-02 16:22:02 -07:00
|
|
|
--- Executes Vim script commands.
|
2022-05-12 06:34:38 -07:00
|
|
|
---
|
2022-07-20 04:29:24 -07:00
|
|
|
--- Note that `vim.cmd` can be indexed with a command name to return a callable function to the
|
|
|
|
--- command.
|
|
|
|
---
|
2022-05-12 06:34:38 -07:00
|
|
|
--- Example:
|
2023-09-14 06:23:01 -07:00
|
|
|
---
|
|
|
|
--- ```lua
|
|
|
|
--- vim.cmd('echo 42')
|
|
|
|
--- vim.cmd([[
|
|
|
|
--- augroup My_group
|
|
|
|
--- autocmd!
|
|
|
|
--- autocmd FileType c setlocal cindent
|
|
|
|
--- augroup END
|
|
|
|
--- ]])
|
|
|
|
---
|
|
|
|
--- -- Ex command :echo "foo"
|
|
|
|
--- -- Note string literals need to be double quoted.
|
|
|
|
--- vim.cmd('echo "foo"')
|
|
|
|
--- vim.cmd { cmd = 'echo', args = { '"foo"' } }
|
|
|
|
--- vim.cmd.echo({ args = { '"foo"' } })
|
|
|
|
--- vim.cmd.echo('"foo"')
|
|
|
|
---
|
|
|
|
--- -- Ex command :write! myfile.txt
|
|
|
|
--- vim.cmd('write! myfile.txt')
|
|
|
|
--- vim.cmd { cmd = 'write', args = { "myfile.txt" }, bang = true }
|
|
|
|
--- vim.cmd.write { args = { "myfile.txt" }, bang = true }
|
|
|
|
--- vim.cmd.write { "myfile.txt", bang = true }
|
|
|
|
---
|
|
|
|
--- -- Ex command :colorscheme blue
|
|
|
|
--- vim.cmd('colorscheme blue')
|
|
|
|
--- vim.cmd.colorscheme('blue')
|
|
|
|
--- ```
|
2022-05-12 06:34:38 -07:00
|
|
|
---
|
|
|
|
---@param command string|table Command(s) to execute.
|
|
|
|
--- If a string, executes multiple lines of Vim script at once. In this
|
2023-03-25 09:58:48 -07:00
|
|
|
--- case, it is an alias to |nvim_exec2()|, where `opts.output` is set
|
|
|
|
--- to false. Thus it works identical to |:source|.
|
2022-05-12 06:34:38 -07:00
|
|
|
--- If a table, executes a single command. In this case, it is an alias
|
|
|
|
--- to |nvim_cmd()| where `opts` is empty.
|
|
|
|
---@see |ex-cmd-index|
|
2022-07-20 04:29:24 -07:00
|
|
|
vim.cmd = setmetatable({}, {
|
|
|
|
__call = function(_, command)
|
|
|
|
if type(command) == 'table' then
|
|
|
|
return vim.api.nvim_cmd(command, {})
|
|
|
|
else
|
2023-03-25 19:49:32 -07:00
|
|
|
vim.api.nvim_exec2(command, {})
|
|
|
|
return ''
|
2022-07-20 04:29:24 -07:00
|
|
|
end
|
|
|
|
end,
|
|
|
|
__index = function(t, command)
|
|
|
|
t[command] = function(...)
|
|
|
|
local opts
|
|
|
|
if select('#', ...) == 1 and type(select(1, ...)) == 'table' then
|
|
|
|
opts = select(1, ...)
|
|
|
|
|
|
|
|
-- Move indexed positions in opts to opt.args
|
|
|
|
if opts[1] and not opts.args then
|
|
|
|
opts.args = {}
|
|
|
|
for i = 1, VIM_CMD_ARG_MAX do
|
|
|
|
if not opts[i] then
|
|
|
|
break
|
|
|
|
end
|
|
|
|
opts.args[i] = opts[i]
|
|
|
|
opts[i] = nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
opts = { args = { ... } }
|
|
|
|
end
|
|
|
|
opts.cmd = command
|
|
|
|
return vim.api.nvim_cmd(opts, {})
|
|
|
|
end
|
|
|
|
return t[command]
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
|
2024-02-27 08:20:32 -07:00
|
|
|
--- @class (private) vim.var_accessor
|
2023-08-08 08:36:06 -07:00
|
|
|
--- @field [string] any
|
|
|
|
--- @field [integer] vim.var_accessor
|
|
|
|
|
2019-12-01 06:28:53 -07:00
|
|
|
-- 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 validate = vim.validate
|
2021-05-28 08:24:48 -07:00
|
|
|
|
2023-08-08 08:36:06 -07:00
|
|
|
--- @param scope string
|
|
|
|
--- @param handle? false|integer
|
|
|
|
--- @return vim.var_accessor
|
2021-09-23 07:00:25 -07:00
|
|
|
local function make_dict_accessor(scope, handle)
|
2020-03-31 12:44:21 -07:00
|
|
|
validate({
|
|
|
|
scope = { scope, 's' },
|
|
|
|
})
|
|
|
|
local mt = {}
|
|
|
|
function mt:__newindex(k, v)
|
2021-09-23 07:00:25 -07:00
|
|
|
return vim._setvar(scope, handle 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
|
2020-03-31 12:44:21 -07:00
|
|
|
function mt:__index(k)
|
2021-09-23 07:00:25 -07:00
|
|
|
if handle == nil and type(k) == 'number' then
|
|
|
|
return make_dict_accessor(scope, k)
|
|
|
|
end
|
|
|
|
return vim._getvar(scope, handle or 0, k)
|
2020-03-31 12:44:21 -07:00
|
|
|
end
|
|
|
|
return setmetatable({}, mt)
|
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
|
2021-05-28 08:24:48 -07:00
|
|
|
|
2021-09-23 07:00:25 -07:00
|
|
|
vim.g = make_dict_accessor('g', false)
|
2023-12-13 05:00:11 -07:00
|
|
|
vim.v = make_dict_accessor('v', false) --[[@as vim.v]]
|
2020-03-31 12:44:21 -07:00
|
|
|
vim.b = make_dict_accessor('b')
|
|
|
|
vim.w = make_dict_accessor('w')
|
|
|
|
vim.t = make_dict_accessor('t')
|
2019-08-25 13:01:35 -07:00
|
|
|
end
|
2019-01-14 10:08:17 -07:00
|
|
|
|
2024-05-28 03:07:13 -07:00
|
|
|
--- @deprecated
|
2023-07-04 10:22:04 -07:00
|
|
|
--- Gets a dict of line segment ("chunk") positions for the region from `pos1` to `pos2`.
|
2020-05-18 06:49:50 -07:00
|
|
|
---
|
2023-07-04 10:22:04 -07:00
|
|
|
--- Input and output positions are byte positions, (0,0)-indexed. "End of line" column
|
|
|
|
--- position (for example, |linewise| visual selection) is returned as |v:maxcol| (big number).
|
|
|
|
---
|
|
|
|
---@param bufnr integer Buffer number, or 0 for current buffer
|
|
|
|
---@param pos1 integer[]|string Start of region as a (line, column) tuple or |getpos()|-compatible string
|
|
|
|
---@param pos2 integer[]|string End of region as a (line, column) tuple or |getpos()|-compatible string
|
2024-03-08 05:25:18 -07:00
|
|
|
---@param regtype string [setreg()]-style selection type
|
2023-11-20 23:25:45 -07:00
|
|
|
---@param inclusive boolean Controls whether the ending column is inclusive (see also 'selection').
|
2023-07-04 10:22:04 -07:00
|
|
|
---@return table region Dict of the form `{linenr = {startcol,endcol}}`. `endcol` is exclusive, and
|
|
|
|
---whole lines are returned as `{startcol,endcol} = {0,-1}`.
|
2020-05-18 06:49:50 -07:00
|
|
|
function vim.region(bufnr, pos1, pos2, regtype, inclusive)
|
2024-05-28 03:07:13 -07:00
|
|
|
vim.deprecate('vim.region', 'vim.fn.getregionpos()', '0.13')
|
|
|
|
|
2020-05-18 06:49:50 -07:00
|
|
|
if not vim.api.nvim_buf_is_loaded(bufnr) then
|
|
|
|
vim.fn.bufload(bufnr)
|
|
|
|
end
|
|
|
|
|
2023-04-11 07:28:46 -07:00
|
|
|
if type(pos1) == 'string' then
|
|
|
|
local pos = vim.fn.getpos(pos1)
|
2023-11-20 23:25:45 -07:00
|
|
|
pos1 = { pos[2] - 1, pos[3] - 1 }
|
2023-04-11 07:28:46 -07:00
|
|
|
end
|
|
|
|
if type(pos2) == 'string' then
|
|
|
|
local pos = vim.fn.getpos(pos2)
|
2023-11-20 23:25:45 -07:00
|
|
|
pos2 = { pos[2] - 1, pos[3] - 1 }
|
2023-04-11 07:28:46 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
if pos1[1] > pos2[1] or (pos1[1] == pos2[1] and pos1[2] > pos2[2]) then
|
|
|
|
pos1, pos2 = pos2, pos1
|
|
|
|
end
|
|
|
|
|
|
|
|
-- getpos() may return {0,0,0,0}
|
|
|
|
if pos1[1] < 0 or pos1[2] < 0 then
|
|
|
|
return {}
|
|
|
|
end
|
|
|
|
|
2021-06-11 01:09:56 -07:00
|
|
|
-- check that region falls within current buffer
|
|
|
|
local buf_line_count = vim.api.nvim_buf_line_count(bufnr)
|
|
|
|
pos1[1] = math.min(pos1[1], buf_line_count - 1)
|
|
|
|
pos2[1] = math.min(pos2[1], buf_line_count - 1)
|
|
|
|
|
2020-05-18 06:49:50 -07:00
|
|
|
-- in case of block selection, columns need to be adjusted for non-ASCII characters
|
|
|
|
-- TODO: handle double-width characters
|
|
|
|
if regtype:byte() == 22 then
|
2023-11-20 23:25:45 -07:00
|
|
|
local bufline = vim.api.nvim_buf_get_lines(bufnr, pos1[1], pos1[1] + 1, true)[1]
|
2020-05-18 06:49:50 -07:00
|
|
|
pos1[2] = vim.str_utfindex(bufline, pos1[2])
|
|
|
|
end
|
|
|
|
|
|
|
|
local region = {}
|
|
|
|
for l = pos1[1], pos2[1] do
|
2023-12-13 06:04:24 -07:00
|
|
|
local c1 --- @type number
|
|
|
|
local c2 --- @type number
|
2020-05-18 06:49:50 -07:00
|
|
|
if regtype:byte() == 22 then -- block selection: take width from regtype
|
|
|
|
c1 = pos1[2]
|
2023-12-13 06:04:24 -07:00
|
|
|
c2 = c1 + tonumber(regtype:sub(2))
|
2020-05-18 06:49:50 -07:00
|
|
|
-- and adjust for non-ASCII characters
|
2023-11-20 23:25:45 -07:00
|
|
|
local bufline = vim.api.nvim_buf_get_lines(bufnr, l, l + 1, true)[1]
|
2022-10-14 02:12:46 -07:00
|
|
|
local utflen = vim.str_utfindex(bufline, #bufline)
|
|
|
|
if c1 <= utflen then
|
2023-12-13 06:04:24 -07:00
|
|
|
c1 = assert(tonumber(vim.str_byteindex(bufline, c1)))
|
2022-10-14 02:12:46 -07:00
|
|
|
else
|
|
|
|
c1 = #bufline + 1
|
2020-05-18 06:49:50 -07:00
|
|
|
end
|
2022-10-14 02:12:46 -07:00
|
|
|
if c2 <= utflen then
|
2023-12-13 06:04:24 -07:00
|
|
|
c2 = assert(tonumber(vim.str_byteindex(bufline, c2)))
|
2022-10-14 02:12:46 -07:00
|
|
|
else
|
|
|
|
c2 = #bufline + 1
|
2020-05-18 06:49:50 -07:00
|
|
|
end
|
2023-10-06 05:44:50 -07:00
|
|
|
elseif regtype == 'V' then -- linewise selection, always return whole line
|
|
|
|
c1 = 0
|
|
|
|
c2 = -1
|
2020-05-18 06:49:50 -07:00
|
|
|
else
|
|
|
|
c1 = (l == pos1[1]) and pos1[2] or 0
|
2023-11-20 23:25:45 -07:00
|
|
|
if inclusive and l == pos2[1] then
|
|
|
|
local bufline = vim.api.nvim_buf_get_lines(bufnr, pos2[1], pos2[1] + 1, true)[1]
|
|
|
|
pos2[2] = vim.fn.byteidx(bufline, vim.fn.charidx(bufline, pos2[2]) + 1)
|
|
|
|
end
|
|
|
|
c2 = (l == pos2[1]) and pos2[2] or -1
|
2020-05-18 06:49:50 -07:00
|
|
|
end
|
|
|
|
table.insert(region, l, { c1, c2 })
|
|
|
|
end
|
|
|
|
return region
|
|
|
|
end
|
|
|
|
|
2023-06-12 05:08:08 -07:00
|
|
|
--- Defers calling {fn} until {timeout} ms passes.
|
2020-05-18 06:49:50 -07:00
|
|
|
---
|
2023-06-12 05:08:08 -07:00
|
|
|
--- Use to do a one-shot timer that calls {fn}
|
2022-09-25 16:58:27 -07:00
|
|
|
--- Note: The {fn} is |vim.schedule_wrap()|ped automatically, so API functions are
|
2020-07-07 01:55:40 -07:00
|
|
|
--- safe to call.
|
2022-10-05 04:21:45 -07:00
|
|
|
---@param fn function Callback to call once `timeout` expires
|
|
|
|
---@param timeout integer Number of milliseconds to wait before calling `fn`
|
|
|
|
---@return table timer luv timer object
|
2020-05-18 06:49:50 -07:00
|
|
|
function vim.defer_fn(fn, timeout)
|
|
|
|
vim.validate({ fn = { fn, 'c', true } })
|
2023-12-13 06:04:24 -07:00
|
|
|
local timer = assert(vim.uv.new_timer())
|
2020-05-18 06:49:50 -07:00
|
|
|
timer:start(
|
|
|
|
timeout,
|
|
|
|
0,
|
|
|
|
vim.schedule_wrap(function()
|
2022-06-15 19:39:55 -07:00
|
|
|
if not timer:is_closing() then
|
|
|
|
timer:close()
|
|
|
|
end
|
2020-05-18 06:49:50 -07:00
|
|
|
|
|
|
|
fn()
|
|
|
|
end)
|
2022-05-09 02:23:51 -07:00
|
|
|
)
|
2020-05-18 06:49:50 -07:00
|
|
|
|
|
|
|
return timer
|
|
|
|
end
|
|
|
|
|
2023-11-02 16:22:02 -07:00
|
|
|
--- Displays a notification to the user.
|
2021-08-22 13:55:28 -07:00
|
|
|
---
|
2022-01-06 11:10:56 -07:00
|
|
|
--- This function can be overridden by plugins to display notifications using a
|
|
|
|
--- custom provider (such as the system notification provider). By default,
|
|
|
|
--- writes to |:messages|.
|
|
|
|
---
|
|
|
|
---@param msg string Content of the notification to show to the user.
|
2023-03-04 06:07:39 -07:00
|
|
|
---@param level integer|nil One of the values from |vim.log.levels|.
|
2022-01-06 11:10:56 -07:00
|
|
|
---@param opts table|nil Optional parameters. Unused by default.
|
2023-12-13 06:04:24 -07:00
|
|
|
---@diagnostic disable-next-line: unused-local
|
2022-01-06 11:10:56 -07:00
|
|
|
function vim.notify(msg, level, opts) -- luacheck: no unused args
|
|
|
|
if level == vim.log.levels.ERROR then
|
2021-01-27 07:09:02 -07:00
|
|
|
vim.api.nvim_err_writeln(msg)
|
2022-01-06 11:10:56 -07:00
|
|
|
elseif level == vim.log.levels.WARN then
|
2021-05-10 05:26:39 -07:00
|
|
|
vim.api.nvim_echo({ { msg, 'WarningMsg' } }, true, {})
|
2021-01-27 07:09:02 -07:00
|
|
|
else
|
2021-02-09 03:41:02 -07:00
|
|
|
vim.api.nvim_echo({ { msg } }, true, {})
|
2021-01-27 07:09:02 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-01-06 11:10:56 -07:00
|
|
|
do
|
2024-03-06 03:03:55 -07:00
|
|
|
local notified = {} --- @type table<string,true>
|
2022-01-06 11:10:56 -07:00
|
|
|
|
2023-11-02 16:22:02 -07:00
|
|
|
--- Displays a notification only one time.
|
2022-01-06 11:10:56 -07:00
|
|
|
---
|
|
|
|
--- Like |vim.notify()|, but subsequent calls with the same message will not
|
|
|
|
--- display a notification.
|
|
|
|
---
|
|
|
|
---@param msg string Content of the notification to show to the user.
|
2023-03-04 06:07:39 -07:00
|
|
|
---@param level integer|nil One of the values from |vim.log.levels|.
|
2022-01-06 11:10:56 -07:00
|
|
|
---@param opts table|nil Optional parameters. Unused by default.
|
2022-05-15 18:07:36 -07:00
|
|
|
---@return boolean true if message was displayed, else false
|
|
|
|
function vim.notify_once(msg, level, opts)
|
2022-01-06 11:10:56 -07:00
|
|
|
if not notified[msg] then
|
|
|
|
vim.notify(msg, level, opts)
|
|
|
|
notified[msg] = true
|
2022-05-15 18:07:36 -07:00
|
|
|
return true
|
2022-01-06 11:10:56 -07:00
|
|
|
end
|
2022-05-15 18:07:36 -07:00
|
|
|
return false
|
2022-01-06 11:10:56 -07:00
|
|
|
end
|
|
|
|
end
|
2021-01-27 07:09:02 -07:00
|
|
|
|
2024-03-06 03:03:55 -07:00
|
|
|
local on_key_cbs = {} --- @type table<integer,function>
|
2020-08-14 07:03:17 -07:00
|
|
|
|
2021-08-22 18:26:35 -07:00
|
|
|
--- Adds Lua function {fn} with namespace id {ns_id} as a listener to every,
|
|
|
|
--- yes every, input key.
|
2020-08-14 07:03:17 -07:00
|
|
|
---
|
2021-08-22 18:26:35 -07:00
|
|
|
--- The Nvim command-line option |-w| is related but does not support callbacks
|
|
|
|
--- and cannot be toggled dynamically.
|
2020-08-14 07:03:17 -07:00
|
|
|
---
|
2023-07-04 10:22:04 -07:00
|
|
|
---@note {fn} will be removed on error.
|
|
|
|
---@note {fn} will not be cleared by |nvim_buf_clear_namespace()|
|
|
|
|
---
|
2024-03-30 20:20:05 -07:00
|
|
|
---@param fn fun(key: string, typed: string)?
|
|
|
|
--- Function invoked on every key press. |i_CTRL-V|
|
|
|
|
--- {key} is the key after mappings have been applied, and
|
|
|
|
--- {typed} is the key(s) before mappings are applied, which
|
|
|
|
--- may be empty if {key} is produced by non-typed keys.
|
|
|
|
--- When {fn} is nil and {ns_id} is specified, the callback
|
|
|
|
--- associated with namespace {ns_id} is removed.
|
2023-08-09 02:06:13 -07:00
|
|
|
---@param ns_id integer? Namespace ID. If nil or 0, generates and returns a
|
|
|
|
--- new |nvim_create_namespace()| id.
|
2020-08-14 07:03:17 -07:00
|
|
|
---
|
2023-03-04 06:07:39 -07:00
|
|
|
---@return integer Namespace id associated with {fn}. Or count of all callbacks
|
2021-08-22 18:26:35 -07:00
|
|
|
---if on_key() is called without arguments.
|
|
|
|
function vim.on_key(fn, ns_id)
|
|
|
|
if fn == nil and ns_id == nil then
|
2023-11-06 17:33:38 -07:00
|
|
|
return vim.tbl_count(on_key_cbs)
|
2021-08-22 18:26:35 -07:00
|
|
|
end
|
|
|
|
|
2020-08-14 07:03:17 -07:00
|
|
|
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
|
|
|
|
|
2021-08-22 18:26:35 -07:00
|
|
|
on_key_cbs[ns_id] = fn
|
2020-08-14 07:03:17 -07:00
|
|
|
return ns_id
|
|
|
|
end
|
|
|
|
|
2021-08-22 18:26:35 -07:00
|
|
|
--- Executes the on_key callbacks.
|
2021-08-22 13:55:28 -07:00
|
|
|
---@private
|
2024-03-30 20:20:05 -07:00
|
|
|
function vim._on_key(buf, typed_buf)
|
2020-08-14 07:03:17 -07:00
|
|
|
local failed_ns_ids = {}
|
|
|
|
local failed_messages = {}
|
2021-08-22 18:26:35 -07:00
|
|
|
for k, v in pairs(on_key_cbs) do
|
2024-03-30 20:20:05 -07:00
|
|
|
local ok, err_msg = pcall(v, buf, typed_buf)
|
2020-08-14 07:03:17 -07:00
|
|
|
if not ok then
|
2021-08-22 18:26:35 -07:00
|
|
|
vim.on_key(nil, k)
|
2020-08-14 07:03:17 -07:00
|
|
|
table.insert(failed_ns_ids, k)
|
|
|
|
table.insert(failed_messages, err_msg)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if failed_ns_ids[1] then
|
|
|
|
error(
|
|
|
|
string.format(
|
2021-08-22 18:26:35 -07:00
|
|
|
"Error executing 'on_key' with ns_ids '%s'\n Messages: %s",
|
2020-08-14 07:03:17 -07:00
|
|
|
table.concat(failed_ns_ids, ', '),
|
|
|
|
table.concat(failed_messages, '\n')
|
2022-05-09 02:23:51 -07:00
|
|
|
)
|
|
|
|
)
|
2020-08-14 07:03:17 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-11-02 16:22:02 -07:00
|
|
|
--- Generates a list of possible completions for the string.
|
2021-01-27 01:00:28 -07:00
|
|
|
--- String has the pattern.
|
2020-11-24 21:24:52 -07:00
|
|
|
---
|
2024-02-15 10:16:04 -07:00
|
|
|
--- 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.
|
2023-12-13 06:04:24 -07:00
|
|
|
---
|
|
|
|
--- @param pat string
|
2024-03-06 03:03:55 -07:00
|
|
|
--- @return any[], integer
|
2020-11-24 21:24:52 -07:00
|
|
|
function vim._expand_pat(pat, env)
|
|
|
|
env = env or _G
|
|
|
|
|
|
|
|
if pat == '' then
|
|
|
|
local result = vim.tbl_keys(env)
|
|
|
|
table.sort(result)
|
2020-11-30 06:33:52 -07:00
|
|
|
return result, 0
|
2020-11-24 21:24:52 -07:00
|
|
|
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.:_%[%]\'"]+$')
|
2020-11-30 06:33:52 -07:00
|
|
|
if not last_part then
|
|
|
|
return {}, 0
|
|
|
|
end
|
2020-11-24 21:24:52 -07:00
|
|
|
|
|
|
|
local parts, search_index = vim._expand_pat_get_parts(last_part)
|
|
|
|
|
2021-01-23 03:22:34 -07:00
|
|
|
local match_part = string.sub(last_part, search_index, #last_part)
|
|
|
|
local prefix_match_pat = string.sub(pat, 1, #pat - #match_part) or ''
|
2020-11-24 21:24:52 -07:00
|
|
|
|
|
|
|
local final_env = env
|
2021-01-23 03:22:34 -07:00
|
|
|
|
2020-11-24 21:24:52 -07:00
|
|
|
for _, part in ipairs(parts) do
|
|
|
|
if type(final_env) ~= 'table' then
|
2020-11-30 06:33:52 -07:00
|
|
|
return {}, 0
|
2020-11-24 21:24:52 -07:00
|
|
|
end
|
2024-03-06 03:03:55 -07:00
|
|
|
local key --- @type any
|
2020-11-24 21:24:52 -07:00
|
|
|
|
|
|
|
-- Normally, we just have a string
|
2020-11-30 06:33:52 -07:00
|
|
|
-- Just attempt to get the string directly from the environment
|
2020-11-24 21:24:52 -07:00
|
|
|
if type(part) == 'string' then
|
2021-01-23 03:22:34 -07:00
|
|
|
key = part
|
2020-11-24 21:24:52 -07:00
|
|
|
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
|
2020-11-30 06:33:52 -07:00
|
|
|
return {}, 0
|
2020-11-24 21:24:52 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
local result = rawget(env, result_key)
|
|
|
|
|
|
|
|
if result == nil then
|
2020-11-30 06:33:52 -07:00
|
|
|
return {}, 0
|
2020-11-24 21:24:52 -07:00
|
|
|
end
|
|
|
|
|
2021-01-23 03:22:34 -07:00
|
|
|
key = result
|
|
|
|
end
|
|
|
|
local field = rawget(final_env, key)
|
|
|
|
if field == nil then
|
|
|
|
local mt = getmetatable(final_env)
|
|
|
|
if mt and type(mt.__index) == 'table' then
|
|
|
|
field = rawget(mt.__index, key)
|
2021-01-27 01:00:28 -07:00
|
|
|
elseif final_env == vim and (vim._submodules[key] or vim._extra[key]) then
|
2022-03-09 06:26:01 -07:00
|
|
|
field = vim[key]
|
2021-01-23 03:22:34 -07:00
|
|
|
end
|
2020-11-24 21:24:52 -07:00
|
|
|
end
|
2021-01-23 03:22:34 -07:00
|
|
|
final_env = field
|
2020-11-24 21:24:52 -07:00
|
|
|
|
|
|
|
if not final_env then
|
2020-11-30 06:33:52 -07:00
|
|
|
return {}, 0
|
2020-11-24 21:24:52 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-03-06 03:03:55 -07:00
|
|
|
local keys = {} --- @type table<string,true>
|
|
|
|
--- @param obj table<any,any>
|
2021-01-23 03:22:34 -07:00
|
|
|
local function insert_keys(obj)
|
|
|
|
for k, _ in pairs(obj) do
|
|
|
|
if type(k) == 'string' and string.sub(k, 1, string.len(match_part)) == match_part then
|
2022-07-17 15:40:18 -07:00
|
|
|
keys[k] = true
|
2021-01-23 03:22:34 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if type(final_env) == 'table' then
|
|
|
|
insert_keys(final_env)
|
|
|
|
end
|
|
|
|
local mt = getmetatable(final_env)
|
|
|
|
if mt and type(mt.__index) == 'table' then
|
|
|
|
insert_keys(mt.__index)
|
|
|
|
end
|
2022-03-09 06:26:01 -07:00
|
|
|
if final_env == vim then
|
|
|
|
insert_keys(vim._submodules)
|
2021-01-27 01:00:28 -07:00
|
|
|
insert_keys(vim._extra)
|
2022-03-09 06:26:01 -07:00
|
|
|
end
|
2020-11-24 21:24:52 -07:00
|
|
|
|
2022-07-17 15:40:18 -07:00
|
|
|
keys = vim.tbl_keys(keys)
|
2021-01-23 03:22:34 -07:00
|
|
|
table.sort(keys)
|
2020-11-24 21:24:52 -07:00
|
|
|
|
2021-01-23 03:22:34 -07:00
|
|
|
return keys, #prefix_match_pat
|
2020-11-24 21:24:52 -07:00
|
|
|
end
|
|
|
|
|
2023-12-13 06:04:24 -07:00
|
|
|
--- @param lua_string string
|
2024-03-06 03:03:55 -07:00
|
|
|
--- @return (string|string[])[], integer
|
2020-11-24 21:24:52 -07:00
|
|
|
vim._expand_pat_get_parts = function(lua_string)
|
|
|
|
local parts = {}
|
|
|
|
|
|
|
|
local accumulator, search_index = '', 1
|
2023-12-13 06:04:24 -07:00
|
|
|
local in_brackets = false
|
|
|
|
local bracket_end = -1 --- @type integer?
|
2020-11-24 21:24:52 -07:00
|
|
|
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
|
|
|
|
|
2024-03-06 03:03:55 -07:00
|
|
|
--- @param val any[]
|
2020-11-24 21:24:52 -07:00
|
|
|
parts = vim.tbl_filter(function(val)
|
|
|
|
return #val > 0
|
|
|
|
end, parts)
|
|
|
|
|
|
|
|
return parts, search_index
|
|
|
|
end
|
|
|
|
|
2021-01-27 01:00:28 -07:00
|
|
|
do
|
|
|
|
-- Ideally we should just call complete() inside omnifunc, though there are
|
|
|
|
-- some bugs, so fake the two-step dance for now.
|
2024-03-06 03:03:55 -07:00
|
|
|
local matches --- @type any[]
|
2021-01-27 01:00:28 -07:00
|
|
|
|
2023-06-22 03:44:51 -07:00
|
|
|
--- Omnifunc for completing Lua values from the runtime Lua interpreter,
|
2021-01-27 01:00:28 -07:00
|
|
|
--- similar to the builtin completion for the `:lua` command.
|
|
|
|
---
|
2023-06-22 03:44:51 -07:00
|
|
|
--- Activate using `set omnifunc=v:lua.vim.lua_omnifunc` in a Lua buffer.
|
2024-02-15 10:16:04 -07:00
|
|
|
--- @param find_start 1|0
|
2021-01-27 01:00:28 -07:00
|
|
|
function vim.lua_omnifunc(find_start, _)
|
|
|
|
if find_start == 1 then
|
|
|
|
local line = vim.api.nvim_get_current_line()
|
|
|
|
local prefix = string.sub(line, 1, vim.api.nvim_win_get_cursor(0)[2])
|
|
|
|
local pos
|
|
|
|
matches, pos = vim._expand_pat(prefix)
|
|
|
|
return (#matches > 0 and pos) or -1
|
|
|
|
else
|
|
|
|
return matches
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
refactor!: rename vim.pretty_print => vim.print
Problem:
The function name `vim.pretty_print`:
1. is verbose, which partially defeats its purpose as sugar
2. does not draw from existing precedent or any sort of convention
(except external projects like penlight or python?), which reduces
discoverability, and degrades signaling about best practices.
Solution:
- Rename to `vim.print`.
- Change the behavior so that
1. strings are printed without quotes
2. each arg is printed on its own line
3. tables are indented with 2 instead of 4 spaces
- Example:
:lua ='a', 'b', 42, {a=3}
a
b
42
{
a = 3
}
Comparison of alternatives:
- `vim.print`:
- pro: consistent with Lua's `print()`
- pro: aligns with potential `nvim_print` API function which will
replace nvim_echo, nvim_notify, etc.
- con: behaves differently than Lua's `print()`, slightly misleading?
- `vim.echo`:
- pro: `:echo` has similar "pretty print" behavior.
- con: inconsistent with Lua idioms.
- `vim.p`:
- pro: very short, fits with `vim.o`, etc.
- con: not as discoverable as "echo"
- con: less opportunity for `local p = vim.p` because of potential shadowing.
2023-03-07 08:04:57 -07:00
|
|
|
--- "Pretty prints" the given arguments and returns them unmodified.
|
|
|
|
---
|
|
|
|
--- Example:
|
2023-09-14 06:23:01 -07:00
|
|
|
---
|
|
|
|
--- ```lua
|
2023-09-24 21:39:59 -07:00
|
|
|
--- local hl_normal = vim.print(vim.api.nvim_get_hl(0, { name = 'Normal' }))
|
2023-09-14 06:23:01 -07:00
|
|
|
--- ```
|
refactor!: rename vim.pretty_print => vim.print
Problem:
The function name `vim.pretty_print`:
1. is verbose, which partially defeats its purpose as sugar
2. does not draw from existing precedent or any sort of convention
(except external projects like penlight or python?), which reduces
discoverability, and degrades signaling about best practices.
Solution:
- Rename to `vim.print`.
- Change the behavior so that
1. strings are printed without quotes
2. each arg is printed on its own line
3. tables are indented with 2 instead of 4 spaces
- Example:
:lua ='a', 'b', 42, {a=3}
a
b
42
{
a = 3
}
Comparison of alternatives:
- `vim.print`:
- pro: consistent with Lua's `print()`
- pro: aligns with potential `nvim_print` API function which will
replace nvim_echo, nvim_notify, etc.
- con: behaves differently than Lua's `print()`, slightly misleading?
- `vim.echo`:
- pro: `:echo` has similar "pretty print" behavior.
- con: inconsistent with Lua idioms.
- `vim.p`:
- pro: very short, fits with `vim.o`, etc.
- con: not as discoverable as "echo"
- con: less opportunity for `local p = vim.p` because of potential shadowing.
2023-03-07 08:04:57 -07:00
|
|
|
---
|
|
|
|
--- @see |vim.inspect()|
|
2023-06-23 03:16:55 -07:00
|
|
|
--- @see |:=|
|
2024-02-15 10:16:04 -07:00
|
|
|
--- @param ... any
|
refactor!: rename vim.pretty_print => vim.print
Problem:
The function name `vim.pretty_print`:
1. is verbose, which partially defeats its purpose as sugar
2. does not draw from existing precedent or any sort of convention
(except external projects like penlight or python?), which reduces
discoverability, and degrades signaling about best practices.
Solution:
- Rename to `vim.print`.
- Change the behavior so that
1. strings are printed without quotes
2. each arg is printed on its own line
3. tables are indented with 2 instead of 4 spaces
- Example:
:lua ='a', 'b', 42, {a=3}
a
b
42
{
a = 3
}
Comparison of alternatives:
- `vim.print`:
- pro: consistent with Lua's `print()`
- pro: aligns with potential `nvim_print` API function which will
replace nvim_echo, nvim_notify, etc.
- con: behaves differently than Lua's `print()`, slightly misleading?
- `vim.echo`:
- pro: `:echo` has similar "pretty print" behavior.
- con: inconsistent with Lua idioms.
- `vim.p`:
- pro: very short, fits with `vim.o`, etc.
- con: not as discoverable as "echo"
- con: less opportunity for `local p = vim.p` because of potential shadowing.
2023-03-07 08:04:57 -07:00
|
|
|
--- @return any # given arguments.
|
|
|
|
function vim.print(...)
|
|
|
|
if vim.in_fast_event() then
|
|
|
|
print(...)
|
|
|
|
return ...
|
|
|
|
end
|
|
|
|
|
2022-01-06 11:42:31 -07:00
|
|
|
for i = 1, select('#', ...) do
|
refactor!: rename vim.pretty_print => vim.print
Problem:
The function name `vim.pretty_print`:
1. is verbose, which partially defeats its purpose as sugar
2. does not draw from existing precedent or any sort of convention
(except external projects like penlight or python?), which reduces
discoverability, and degrades signaling about best practices.
Solution:
- Rename to `vim.print`.
- Change the behavior so that
1. strings are printed without quotes
2. each arg is printed on its own line
3. tables are indented with 2 instead of 4 spaces
- Example:
:lua ='a', 'b', 42, {a=3}
a
b
42
{
a = 3
}
Comparison of alternatives:
- `vim.print`:
- pro: consistent with Lua's `print()`
- pro: aligns with potential `nvim_print` API function which will
replace nvim_echo, nvim_notify, etc.
- con: behaves differently than Lua's `print()`, slightly misleading?
- `vim.echo`:
- pro: `:echo` has similar "pretty print" behavior.
- con: inconsistent with Lua idioms.
- `vim.p`:
- pro: very short, fits with `vim.o`, etc.
- con: not as discoverable as "echo"
- con: less opportunity for `local p = vim.p` because of potential shadowing.
2023-03-07 08:04:57 -07:00
|
|
|
local o = select(i, ...)
|
|
|
|
if type(o) == 'string' then
|
|
|
|
vim.api.nvim_out_write(o)
|
|
|
|
else
|
|
|
|
vim.api.nvim_out_write(vim.inspect(o, { newline = '\n', indent = ' ' }))
|
|
|
|
end
|
|
|
|
vim.api.nvim_out_write('\n')
|
2022-01-06 11:42:31 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
return ...
|
|
|
|
end
|
|
|
|
|
2023-11-02 16:22:02 -07:00
|
|
|
--- Translates keycodes.
|
2023-04-25 07:52:44 -07:00
|
|
|
---
|
|
|
|
--- Example:
|
2023-09-14 06:23:01 -07:00
|
|
|
---
|
|
|
|
--- ```lua
|
|
|
|
--- local k = vim.keycode
|
|
|
|
--- vim.g.mapleader = k'<bs>'
|
|
|
|
--- ```
|
|
|
|
---
|
2023-04-25 07:52:44 -07:00
|
|
|
--- @param str string String to be converted.
|
|
|
|
--- @return string
|
|
|
|
--- @see |nvim_replace_termcodes()|
|
|
|
|
function vim.keycode(str)
|
|
|
|
return vim.api.nvim_replace_termcodes(str, true, true, true)
|
|
|
|
end
|
|
|
|
|
2023-12-13 06:04:24 -07:00
|
|
|
--- @param server_addr string
|
|
|
|
--- @param connect_error string
|
2022-03-11 09:16:34 -07:00
|
|
|
function vim._cs_remote(rcid, server_addr, connect_error, args)
|
2023-12-13 06:04:24 -07:00
|
|
|
--- @return string
|
2022-03-11 09:16:34 -07:00
|
|
|
local function connection_failure_errmsg(consequence)
|
2023-12-13 06:04:24 -07:00
|
|
|
local explanation --- @type string
|
2022-03-11 09:16:34 -07:00
|
|
|
if server_addr == '' then
|
|
|
|
explanation = 'No server specified with --server'
|
|
|
|
else
|
|
|
|
explanation = "Failed to connect to '" .. server_addr .. "'"
|
|
|
|
if connect_error ~= '' then
|
|
|
|
explanation = explanation .. ': ' .. connect_error
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return 'E247: ' .. explanation .. '. ' .. consequence
|
|
|
|
end
|
|
|
|
|
2022-02-16 15:11:50 -07:00
|
|
|
local f_silent = false
|
|
|
|
local f_tab = false
|
|
|
|
|
|
|
|
local subcmd = string.sub(args[1], 10)
|
2022-03-03 14:33:27 -07:00
|
|
|
if subcmd == 'tab' then
|
2022-02-16 15:11:50 -07:00
|
|
|
f_tab = true
|
|
|
|
elseif subcmd == 'silent' then
|
|
|
|
f_silent = true
|
2022-03-03 14:33:27 -07:00
|
|
|
elseif
|
|
|
|
subcmd == 'wait'
|
|
|
|
or subcmd == 'wait-silent'
|
|
|
|
or subcmd == 'tab-wait'
|
|
|
|
or subcmd == 'tab-wait-silent'
|
|
|
|
then
|
2023-06-11 00:29:51 -07:00
|
|
|
return { errmsg = 'E5600: Wait commands not yet implemented in Nvim' }
|
2022-02-16 15:11:50 -07:00
|
|
|
elseif subcmd == 'tab-silent' then
|
|
|
|
f_tab = true
|
|
|
|
f_silent = true
|
|
|
|
elseif subcmd == 'send' then
|
2022-02-24 08:47:41 -07:00
|
|
|
if rcid == 0 then
|
2022-03-11 09:16:34 -07:00
|
|
|
return { errmsg = connection_failure_errmsg('Send failed.') }
|
2022-02-24 08:47:41 -07:00
|
|
|
end
|
2023-06-11 07:12:32 -07:00
|
|
|
vim.rpcrequest(rcid, 'nvim_input', args[2])
|
2022-02-24 08:47:41 -07:00
|
|
|
return { should_exit = true, tabbed = false }
|
2022-02-16 15:11:50 -07:00
|
|
|
elseif subcmd == 'expr' then
|
2022-02-24 08:47:41 -07:00
|
|
|
if rcid == 0 then
|
2022-03-11 09:16:34 -07:00
|
|
|
return { errmsg = connection_failure_errmsg('Send expression failed.') }
|
2022-02-24 08:47:41 -07:00
|
|
|
end
|
2023-06-11 07:12:32 -07:00
|
|
|
local res = tostring(vim.rpcrequest(rcid, 'nvim_eval', args[2]))
|
2023-06-11 00:29:51 -07:00
|
|
|
return { result = res, should_exit = true, tabbed = false }
|
2022-03-03 14:33:27 -07:00
|
|
|
elseif subcmd ~= '' then
|
2023-12-13 06:04:24 -07:00
|
|
|
return { errmsg = 'Unknown option argument: ' .. tostring(args[1]) }
|
2022-02-16 15:11:50 -07:00
|
|
|
end
|
|
|
|
|
2022-02-24 08:47:41 -07:00
|
|
|
if rcid == 0 then
|
|
|
|
if not f_silent then
|
2022-03-11 09:16:34 -07:00
|
|
|
vim.notify(connection_failure_errmsg('Editing locally'), vim.log.levels.WARN)
|
2022-02-24 08:47:41 -07:00
|
|
|
end
|
|
|
|
else
|
|
|
|
local command = {}
|
|
|
|
if f_tab then
|
|
|
|
table.insert(command, 'tab')
|
|
|
|
end
|
|
|
|
table.insert(command, 'drop')
|
|
|
|
for i = 2, #args do
|
|
|
|
table.insert(command, vim.fn.fnameescape(args[i]))
|
2022-02-16 15:11:50 -07:00
|
|
|
end
|
2022-02-24 08:47:41 -07:00
|
|
|
vim.fn.rpcrequest(rcid, 'nvim_command', table.concat(command, ' '))
|
2022-02-16 15:11:50 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
return {
|
2022-02-24 08:47:41 -07:00
|
|
|
should_exit = rcid ~= 0,
|
2022-02-16 15:11:50 -07:00
|
|
|
tabbed = f_tab,
|
|
|
|
}
|
|
|
|
end
|
2022-03-01 06:27:19 -07:00
|
|
|
|
2024-05-16 09:33:09 -07:00
|
|
|
do
|
|
|
|
local function truncated_echo(msg)
|
|
|
|
-- Truncate message to avoid hit-enter-prompt
|
|
|
|
local max_width = vim.o.columns * math.max(vim.o.cmdheight - 1, 0) + vim.v.echospace
|
|
|
|
local msg_truncated = string.sub(msg, 1, max_width)
|
|
|
|
vim.api.nvim_echo({ { msg_truncated, 'WarningMsg' } }, true, {})
|
|
|
|
end
|
|
|
|
|
|
|
|
local notified = false
|
|
|
|
|
|
|
|
function vim._truncated_echo_once(msg)
|
|
|
|
if not notified then
|
|
|
|
truncated_echo(msg)
|
|
|
|
notified = true
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
--- This is basically the same as debug.traceback(), except the full paths are shown.
|
|
|
|
local function traceback()
|
|
|
|
local level = 4
|
|
|
|
local backtrace = { 'stack traceback:' }
|
|
|
|
while true do
|
|
|
|
local info = debug.getinfo(level, 'Sl')
|
|
|
|
if not info then
|
|
|
|
break
|
|
|
|
end
|
|
|
|
local msg = (' %s:%s'):format(info.source:sub(2), info.currentline)
|
|
|
|
table.insert(backtrace, msg)
|
|
|
|
level = level + 1
|
|
|
|
end
|
|
|
|
return table.concat(backtrace, '\n')
|
|
|
|
end
|
|
|
|
|
2023-03-15 05:56:13 -07:00
|
|
|
--- Shows a deprecation message to the user.
|
2022-05-03 06:42:41 -07:00
|
|
|
---
|
2023-03-15 05:56:13 -07:00
|
|
|
---@param name string Deprecated feature (function, API, etc.).
|
|
|
|
---@param alternative string|nil Suggested alternative feature.
|
|
|
|
---@param version string Version when the deprecated function will be removed.
|
|
|
|
---@param plugin string|nil Name of the plugin that owns the deprecated feature.
|
|
|
|
--- Defaults to "Nvim".
|
2022-05-15 18:07:36 -07:00
|
|
|
---@param backtrace boolean|nil Prints backtrace. Defaults to true.
|
2023-03-15 05:56:13 -07:00
|
|
|
---
|
2023-07-05 10:47:43 -07:00
|
|
|
---@return string|nil # Deprecated message, or nil if no message was shown.
|
2022-05-15 18:07:36 -07:00
|
|
|
function vim.deprecate(name, alternative, version, plugin, backtrace)
|
2024-01-15 12:19:34 -07:00
|
|
|
plugin = plugin or 'Nvim'
|
|
|
|
if plugin == 'Nvim' then
|
2024-05-16 09:33:09 -07:00
|
|
|
require('vim.deprecated.health').add(name, version, traceback(), alternative)
|
|
|
|
|
|
|
|
-- Only issue warning if feature is hard-deprecated as specified by MAINTAIN.md.
|
|
|
|
-- Example: if removal_version is 0.12 (soft-deprecated since 0.10-dev), show warnings starting at
|
|
|
|
-- 0.11, including 0.11-dev
|
perf(lua): faster vim.deprecate() #28470
Problem: `vim.deprecate()` can be relatively significantly slower than
the deprecated function in "Nvim" plugin.
Solution: Optimize checks for "Nvim" plugin. This also results into not
distinguishing "xxx-dev" and "xxx" versions when doing checks, which
is essentially covered by the deprecation logic itself.
With this rewrite I get the times from #28459: `{ 0.024827, 0.003797, 0.002024, 0.001774, 0.001703 }`.
For quicker reference:
- On current Nightly it is something like `{ 3.72243, 0.918169, 0.968143, 0.763256, 0.783424 }`.
- On 0.9.5: `{ 0.002955, 0.000361, 0.000281, 0.000251, 0.00019 }`.
2024-04-23 08:23:45 -07:00
|
|
|
local major, minor = version:match('(%d+)%.(%d+)')
|
|
|
|
major, minor = tonumber(major), tonumber(minor)
|
2024-01-15 12:19:34 -07:00
|
|
|
|
perf(lua): faster vim.deprecate() #28470
Problem: `vim.deprecate()` can be relatively significantly slower than
the deprecated function in "Nvim" plugin.
Solution: Optimize checks for "Nvim" plugin. This also results into not
distinguishing "xxx-dev" and "xxx" versions when doing checks, which
is essentially covered by the deprecation logic itself.
With this rewrite I get the times from #28459: `{ 0.024827, 0.003797, 0.002024, 0.001774, 0.001703 }`.
For quicker reference:
- On current Nightly it is something like `{ 3.72243, 0.918169, 0.968143, 0.763256, 0.783424 }`.
- On 0.9.5: `{ 0.002955, 0.000361, 0.000281, 0.000251, 0.00019 }`.
2024-04-23 08:23:45 -07:00
|
|
|
local hard_deprecated_since = string.format('nvim-%d.%d', major, minor - 1)
|
|
|
|
-- Assume there will be no next minor version before bumping up the major version
|
|
|
|
local is_hard_deprecated = minor == 0 or vim.fn.has(hard_deprecated_since) == 1
|
2024-01-15 12:19:34 -07:00
|
|
|
if not is_hard_deprecated then
|
2023-12-25 08:31:38 -07:00
|
|
|
return
|
|
|
|
end
|
perf(lua): faster vim.deprecate() #28470
Problem: `vim.deprecate()` can be relatively significantly slower than
the deprecated function in "Nvim" plugin.
Solution: Optimize checks for "Nvim" plugin. This also results into not
distinguishing "xxx-dev" and "xxx" versions when doing checks, which
is essentially covered by the deprecation logic itself.
With this rewrite I get the times from #28459: `{ 0.024827, 0.003797, 0.002024, 0.001774, 0.001703 }`.
For quicker reference:
- On current Nightly it is something like `{ 3.72243, 0.918169, 0.968143, 0.763256, 0.783424 }`.
- On 0.9.5: `{ 0.002955, 0.000361, 0.000281, 0.000251, 0.00019 }`.
2024-04-23 08:23:45 -07:00
|
|
|
|
2024-05-16 09:33:09 -07:00
|
|
|
local msg = ('%s is deprecated. Run ":checkhealth vim.deprecated" for more information'):format(
|
|
|
|
name
|
|
|
|
)
|
|
|
|
|
|
|
|
local displayed = vim._truncated_echo_once(msg)
|
|
|
|
return displayed and msg or nil
|
perf(lua): faster vim.deprecate() #28470
Problem: `vim.deprecate()` can be relatively significantly slower than
the deprecated function in "Nvim" plugin.
Solution: Optimize checks for "Nvim" plugin. This also results into not
distinguishing "xxx-dev" and "xxx" versions when doing checks, which
is essentially covered by the deprecation logic itself.
With this rewrite I get the times from #28459: `{ 0.024827, 0.003797, 0.002024, 0.001774, 0.001703 }`.
For quicker reference:
- On current Nightly it is something like `{ 3.72243, 0.918169, 0.968143, 0.763256, 0.783424 }`.
- On 0.9.5: `{ 0.002955, 0.000361, 0.000281, 0.000251, 0.00019 }`.
2024-04-23 08:23:45 -07:00
|
|
|
else
|
|
|
|
vim.validate {
|
|
|
|
name = { name, 'string' },
|
|
|
|
alternative = { alternative, 'string', true },
|
|
|
|
version = { version, 'string', true },
|
|
|
|
plugin = { plugin, 'string', true },
|
|
|
|
}
|
2023-12-25 08:31:38 -07:00
|
|
|
|
2024-05-16 09:33:09 -07:00
|
|
|
local msg = ('%s is deprecated'):format(name)
|
|
|
|
msg = alternative and ('%s, use %s instead.'):format(msg, alternative) or (msg .. '.')
|
|
|
|
msg = ('%s\nFeature will be removed in %s %s'):format(msg, plugin, version)
|
|
|
|
local displayed = vim.notify_once(msg, vim.log.levels.WARN)
|
|
|
|
if displayed and backtrace ~= false then
|
|
|
|
vim.notify(debug.traceback('', 2):sub(2), vim.log.levels.WARN)
|
|
|
|
end
|
|
|
|
return displayed and msg or nil
|
2022-05-15 18:07:36 -07:00
|
|
|
end
|
2022-05-03 06:42:41 -07:00
|
|
|
end
|
|
|
|
|
2023-07-16 01:27:39 -07:00
|
|
|
require('vim._options')
|
2022-03-01 06:27:19 -07:00
|
|
|
|
2023-06-07 05:52:23 -07:00
|
|
|
-- Remove at Nvim 1.0
|
|
|
|
---@deprecated
|
|
|
|
vim.loop = vim.uv
|
|
|
|
|
2022-03-01 06:27:19 -07:00
|
|
|
return vim
|