mirror of
https://github.com/neovim/neovim.git
synced 2024-12-23 20:55:18 -07:00
Merge #4813 'runtime: clipboard: start daemons in /'.
This commit is contained in:
commit
a160590e40
@ -94,6 +94,7 @@ function! s:clipboard.set(lines, regtype, reg)
|
||||
let selection.data = [a:lines, a:regtype]
|
||||
let argv = split(s:copy[a:reg], " ")
|
||||
let selection.detach = s:cache_enabled
|
||||
let selection.cwd = "/"
|
||||
let jobid = jobstart(argv, selection)
|
||||
if jobid <= 0
|
||||
echohl WarningMsg
|
||||
|
@ -4309,21 +4309,24 @@ jobstart({cmd}[, {opts}]) {Nvim} *jobstart()*
|
||||
with 'shell' or 'shellcmdflag' options. The above call is
|
||||
only written to show the idea, one needs to perform unquoting
|
||||
and do split taking quotes into account.
|
||||
If passed, {opts} must be a dictionary with any of the
|
||||
following keys:
|
||||
- on_stdout: stdout event handler
|
||||
- on_stderr: stderr event handler
|
||||
- on_exit: exit event handler
|
||||
- pty: If set, the job will be connected to a new pseudo
|
||||
terminal, and the job streams are connected to the master
|
||||
file descriptor.
|
||||
- width: Width of the terminal screen(only if pty is set)
|
||||
- height: Height of the terminal screen(only if pty is set)
|
||||
- TERM: $TERM environment variable(only if pty is set)
|
||||
- detach: Detach the job process from the nvim process. The
|
||||
process won't get killed when nvim exists. If the process
|
||||
dies before nvim exits, on_exit will still be invoked.
|
||||
This option is only allowed for non-pty jobs.
|
||||
|
||||
{opts} is a dictionary with these keys:
|
||||
on_stdout: stdout event handler
|
||||
on_stderr: stderr event handler
|
||||
on_exit : exit event handler
|
||||
cwd : Working directory of the job; defaults to
|
||||
|current-directory|.
|
||||
pty : If set, the job will be connected to a new pseudo
|
||||
terminal, and the job streams are connected to
|
||||
the master file descriptor.
|
||||
width : (pty only) Width of the terminal screen
|
||||
height : (pty only) Height of the terminal screen
|
||||
TERM : (pty only) $TERM environment variable
|
||||
detach : (non-pty only) Detach the job process from the
|
||||
nvim process. The process will not get killed
|
||||
when nvim exits. If the process dies before
|
||||
nvim exits, on_exit will still be invoked.
|
||||
|
||||
Either funcrefs or function names can be passed as event
|
||||
handlers. The {opts} object is also used as the "self"
|
||||
argument for the callback, so the caller may pass arbitrary
|
||||
|
@ -11742,8 +11742,21 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv)
|
||||
|
||||
dict_T *job_opts = NULL;
|
||||
ufunc_T *on_stdout = NULL, *on_stderr = NULL, *on_exit = NULL;
|
||||
char *cwd = NULL;
|
||||
if (argvars[1].v_type == VAR_DICT) {
|
||||
job_opts = argvars[1].vval.v_dict;
|
||||
|
||||
char *new_cwd = (char *)get_dict_string(job_opts, (char_u *)"cwd", false);
|
||||
if (new_cwd && strlen(new_cwd) > 0) {
|
||||
cwd = new_cwd;
|
||||
// The new cwd must be a directory.
|
||||
if (!os_isdir((char_u *)cwd)) {
|
||||
EMSG2(_(e_invarg2), "expected valid directory");
|
||||
shell_free_argv(argv);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!common_job_callbacks(job_opts, &on_stdout, &on_stderr, &on_exit)) {
|
||||
shell_free_argv(argv);
|
||||
return;
|
||||
@ -11753,7 +11766,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv)
|
||||
bool pty = job_opts && get_dict_number(job_opts, (uint8_t *)"pty") != 0;
|
||||
bool detach = job_opts && get_dict_number(job_opts, (uint8_t *)"detach") != 0;
|
||||
TerminalJobData *data = common_job_init(argv, on_stdout, on_stderr, on_exit,
|
||||
job_opts, pty, detach);
|
||||
job_opts, pty, detach, cwd);
|
||||
Process *proc = (Process *)&data->proc;
|
||||
|
||||
if (pty) {
|
||||
@ -16468,8 +16481,21 @@ static void f_termopen(typval_T *argvars, typval_T *rettv)
|
||||
|
||||
ufunc_T *on_stdout = NULL, *on_stderr = NULL, *on_exit = NULL;
|
||||
dict_T *job_opts = NULL;
|
||||
char *cwd = ".";
|
||||
if (argvars[1].v_type == VAR_DICT) {
|
||||
job_opts = argvars[1].vval.v_dict;
|
||||
|
||||
char *new_cwd = (char *)get_dict_string(job_opts, (char_u *)"cwd", false);
|
||||
if (new_cwd && strlen(new_cwd) > 0) {
|
||||
cwd = new_cwd;
|
||||
// The new cwd must be a directory.
|
||||
if (!os_isdir((char_u *)cwd)) {
|
||||
EMSG2(_(e_invarg2), "expected valid directory");
|
||||
shell_free_argv(argv);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!common_job_callbacks(job_opts, &on_stdout, &on_stderr, &on_exit)) {
|
||||
shell_free_argv(argv);
|
||||
return;
|
||||
@ -16477,7 +16503,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv)
|
||||
}
|
||||
|
||||
TerminalJobData *data = common_job_init(argv, on_stdout, on_stderr, on_exit,
|
||||
job_opts, true, false);
|
||||
job_opts, true, false, cwd);
|
||||
data->proc.pty.width = curwin->w_width;
|
||||
data->proc.pty.height = curwin->w_height;
|
||||
data->proc.pty.term_name = xstrdup("xterm-256color");
|
||||
@ -16492,11 +16518,6 @@ static void f_termopen(typval_T *argvars, typval_T *rettv)
|
||||
topts.resize_cb = term_resize;
|
||||
topts.close_cb = term_close;
|
||||
|
||||
char *cwd = ".";
|
||||
if (argvars[1].v_type == VAR_STRING
|
||||
&& os_isdir(argvars[1].vval.v_string)) {
|
||||
cwd = (char *)argvars[1].vval.v_string;
|
||||
}
|
||||
int pid = data->proc.pty.process.pid;
|
||||
|
||||
char buf[1024];
|
||||
@ -21764,7 +21785,8 @@ static inline TerminalJobData *common_job_init(char **argv,
|
||||
ufunc_T *on_exit,
|
||||
dict_T *self,
|
||||
bool pty,
|
||||
bool detach)
|
||||
bool detach,
|
||||
char *cwd)
|
||||
{
|
||||
TerminalJobData *data = xcalloc(1, sizeof(TerminalJobData));
|
||||
data->stopped = false;
|
||||
@ -21788,6 +21810,7 @@ static inline TerminalJobData *common_job_init(char **argv,
|
||||
proc->cb = on_process_exit;
|
||||
proc->events = data->events;
|
||||
proc->detach = detach;
|
||||
proc->cwd = cwd;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ bool libuv_process_spawn(LibuvProcess *uvproc)
|
||||
uvproc->uvopts.flags |= UV_PROCESS_DETACHED;
|
||||
}
|
||||
uvproc->uvopts.exit_cb = exit_cb;
|
||||
uvproc->uvopts.cwd = NULL;
|
||||
uvproc->uvopts.cwd = proc->cwd;
|
||||
uvproc->uvopts.env = NULL;
|
||||
uvproc->uvopts.stdio = uvproc->uvstdio;
|
||||
uvproc->uvopts.stdio_count = 3;
|
||||
|
@ -21,6 +21,7 @@ struct process {
|
||||
int pid, status, refcount;
|
||||
// set to the hrtime of when process_stop was called for the process.
|
||||
uint64_t stopped_time;
|
||||
char *cwd;
|
||||
char **argv;
|
||||
Stream *in, *out, *err;
|
||||
process_exit_cb cb;
|
||||
@ -40,6 +41,7 @@ static inline Process process_init(Loop *loop, ProcessType type, void *data)
|
||||
.status = 0,
|
||||
.refcount = 0,
|
||||
.stopped_time = 0,
|
||||
.cwd = NULL,
|
||||
.argv = NULL,
|
||||
.in = NULL,
|
||||
.out = NULL,
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "nvim/event/process.h"
|
||||
#include "nvim/os/pty_process_unix.h"
|
||||
#include "nvim/log.h"
|
||||
#include "nvim/os/os.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "os/pty_process_unix.c.generated.h"
|
||||
@ -131,6 +132,12 @@ static void init_child(PtyProcess *ptyproc) FUNC_ATTR_NONNULL_ALL
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
signal(SIGALRM, SIG_DFL);
|
||||
|
||||
Process *proc = (Process *)ptyproc;
|
||||
if (proc->cwd && os_chdir(proc->cwd) != 0) {
|
||||
fprintf(stderr, "chdir failed: %s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
setenv("TERM", ptyproc->term_name ? ptyproc->term_name : "ansi", 1);
|
||||
execvp(ptyproc->process.argv[0], ptyproc->process.argv);
|
||||
fprintf(stderr, "execvp failed: %s\n", strerror(errno));
|
||||
|
@ -1,11 +1,11 @@
|
||||
|
||||
local helpers = require('test.functional.helpers')
|
||||
local clear, eq, eval, execute, feed, insert, neq, next_msg, nvim,
|
||||
nvim_dir, ok, source, write_file = helpers.clear,
|
||||
nvim_dir, ok, source, write_file, mkdir, rmdir = helpers.clear,
|
||||
helpers.eq, helpers.eval, helpers.execute, helpers.feed,
|
||||
helpers.insert, helpers.neq, helpers.next_message, helpers.nvim,
|
||||
helpers.nvim_dir, helpers.ok, helpers.source,
|
||||
helpers.write_file
|
||||
helpers.write_file, helpers.mkdir, helpers.rmdir
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
|
||||
|
||||
@ -37,6 +37,32 @@ describe('jobs', function()
|
||||
eq({'notification', 'exit', {0, 0}}, next_msg())
|
||||
end)
|
||||
|
||||
it('changes to given / directory', function()
|
||||
nvim('command', "let g:job_opts.cwd = '/'")
|
||||
nvim('command', "let j = jobstart('pwd', g:job_opts)")
|
||||
eq({'notification', 'stdout', {0, {'/', ''}}}, next_msg())
|
||||
eq({'notification', 'exit', {0, 0}}, next_msg())
|
||||
end)
|
||||
|
||||
it('changes to given `cwd` directory', function()
|
||||
local dir = eval('resolve(tempname())')
|
||||
mkdir(dir)
|
||||
nvim('command', "let g:job_opts.cwd = '" .. dir .. "'")
|
||||
nvim('command', "let j = jobstart('pwd', g:job_opts)")
|
||||
eq({'notification', 'stdout', {0, {dir, ''}}}, next_msg())
|
||||
eq({'notification', 'exit', {0, 0}}, next_msg())
|
||||
rmdir(dir)
|
||||
end)
|
||||
|
||||
it('fails to change to invalid `cwd`', function()
|
||||
local dir = eval('resolve(tempname())."-bogus"')
|
||||
local _, err = pcall(function()
|
||||
nvim('command', "let g:job_opts.cwd = '" .. dir .. "'")
|
||||
nvim('command', "let j = jobstart('pwd', g:job_opts)")
|
||||
end)
|
||||
ok(string.find(err, "E475: Invalid argument: expected valid directory$") ~= nil)
|
||||
end)
|
||||
|
||||
it('returns 0 when it fails to start', function()
|
||||
local status, rv = pcall(eval, "jobstart([])")
|
||||
eq(false, status)
|
||||
|
Loading…
Reference in New Issue
Block a user