aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/window.c4
-rw-r--r--src/nvim/buffer.c12
-rw-r--r--src/nvim/buffer_defs.h2
-rw-r--r--src/nvim/diff.c7
-rw-r--r--src/nvim/eval.c43
-rw-r--r--src/nvim/ex_cmds.c2
-rw-r--r--src/nvim/ex_cmds2.c24
-rw-r--r--src/nvim/ex_getln.c4
-rw-r--r--src/nvim/file_search.c4
-rw-r--r--src/nvim/fileio.c53
-rw-r--r--src/nvim/globals.h3
-rw-r--r--src/nvim/if_cscope.c8
-rw-r--r--src/nvim/main.c48
-rw-r--r--src/nvim/memfile.c12
-rw-r--r--src/nvim/memline.c26
-rw-r--r--src/nvim/misc1.c2
-rw-r--r--src/nvim/ops.c10
-rw-r--r--src/nvim/os/channel.c97
-rw-r--r--src/nvim/os/fs.c59
-rw-r--r--src/nvim/os/input.c22
-rw-r--r--src/nvim/os/msgpack_rpc.c18
-rw-r--r--src/nvim/os/msgpack_rpc.h7
-rw-r--r--src/nvim/os/provider.c6
-rw-r--r--src/nvim/os/signal.c5
-rw-r--r--src/nvim/os/wstream.c43
-rw-r--r--src/nvim/os_unix.c20
-rw-r--r--src/nvim/path.c18
-rw-r--r--src/nvim/quickfix.c2
-rw-r--r--src/nvim/term.c3
-rw-r--r--src/nvim/testdir/test105.in4
-rw-r--r--src/nvim/testdir/test105.ok6
-rw-r--r--src/nvim/undo.c8
-rw-r--r--src/nvim/version.c2
33 files changed, 380 insertions, 204 deletions
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index 548d8171a5..1ab441bed3 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -35,7 +35,7 @@ Buffer window_get_buffer(Window window, Error *err)
/// @return the (row, col) tuple
Position window_get_cursor(Window window, Error *err)
{
- Position rv = {.row = 0, .col = 0};
+ Position rv = POSITION_INIT;
win_T *win = find_window_by_handle(window, err);
if (win) {
@@ -245,7 +245,7 @@ void window_set_option(Window window, String name, Object value, Error *err)
/// @return The (row, col) tuple with the window position
Position window_get_position(Window window, Error *err)
{
- Position rv;
+ Position rv = POSITION_INIT;
win_T *win = find_window_by_handle(window, err);
if (win) {
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 77bed67d5f..3c7fd777bd 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -1314,7 +1314,7 @@ buflist_new (
* for hard links. */
FileID file_id;
bool file_id_valid = (sfname != NULL &&
- os_get_file_id((char *)sfname, &file_id));
+ os_fileid((char *)sfname, &file_id));
if (ffname != NULL && !(flags & BLN_DUMMY)
&& (buf = buflist_findname_file_id(ffname, &file_id,
file_id_valid)) != NULL) {
@@ -1671,7 +1671,7 @@ buf_T *buflist_findname_exp(char_u *fname)
buf_T *buflist_findname(char_u *ffname)
{
FileID file_id;
- bool file_id_valid = os_get_file_id((char *)ffname, &file_id);
+ bool file_id_valid = os_fileid((char *)ffname, &file_id);
return buflist_findname_file_id(ffname, &file_id, file_id_valid);
}
@@ -2221,7 +2221,7 @@ setfname (
* - if the buffer is loaded, fail
* - if the buffer is not loaded, delete it from the list
*/
- file_id_valid = os_get_file_id((char *)ffname, &file_id);
+ file_id_valid = os_fileid((char *)ffname, &file_id);
if (!(buf->b_flags & BF_DUMMY)) {
obuf = buflist_findname_file_id(ffname, &file_id, file_id_valid);
}
@@ -2399,7 +2399,7 @@ static int otherfile_buf(buf_T *buf, char_u *ffname,
/* If no struct stat given, get it now */
if (file_id_p == NULL) {
file_id_p = &file_id;
- file_id_valid = os_get_file_id((char *)ffname, file_id_p);
+ file_id_valid = os_fileid((char *)ffname, file_id_p);
}
if (!file_id_valid) {
// file_id not valid, assume files are different.
@@ -2429,7 +2429,7 @@ void buf_set_file_id(buf_T *buf)
{
FileID file_id;
if (buf->b_fname != NULL
- && os_get_file_id((char *)buf->b_fname, &file_id)) {
+ && os_fileid((char *)buf->b_fname, &file_id)) {
buf->file_id_valid = true;
buf->file_id = file_id;
} else {
@@ -2441,7 +2441,7 @@ void buf_set_file_id(buf_T *buf)
static bool buf_same_file_id(buf_T *buf, FileID *file_id)
{
return buf->file_id_valid
- && os_file_id_equal(&(buf->file_id), file_id);
+ && os_fileid_equal(&(buf->file_id), file_id);
}
/*
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index a2d496469e..de1b0985bb 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -512,7 +512,7 @@ struct file_buffer {
long b_mtime; /* last change time of original file */
long b_mtime_read; /* last change time when reading */
- off_t b_orig_size; /* size of original file in bytes */
+ uint64_t b_orig_size; /* size of original file in bytes */
int b_orig_mode; /* mode of original file */
pos_T b_namedm[NMARKS]; /* current named marks (mark.c) */
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index ab0c80112f..73b5731ad0 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -947,9 +947,10 @@ void ex_diffpatch(exarg_T *eap)
os_remove((char *)buf);
// Only continue if the output file was created.
- off_t file_size;
- bool file_size_success = os_get_file_size((char *)tmp_new, &file_size);
- if (!file_size_success || file_size == 0) {
+ FileInfo file_info;
+ bool info_ok = os_fileinfo((char *)tmp_new, &file_info);
+ uint64_t filesize = os_fileinfo_size(&file_info);
+ if (!info_ok || filesize == 0) {
EMSG(_("E816: Cannot read patch output"));
} else {
if (curbuf->b_fname != NULL) {
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 04d90e255d..a61f082e59 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -6494,8 +6494,8 @@ static struct fst {
{"searchpair", 3, 7, f_searchpair},
{"searchpairpos", 3, 7, f_searchpairpos},
{"searchpos", 1, 4, f_searchpos},
- {"send_call", 3, 3, f_send_call},
- {"send_event", 3, 3, f_send_event},
+ {"send_call", 2, 64, f_send_call},
+ {"send_event", 2, 64, f_send_event},
{"setbufvar", 3, 3, f_setbufvar},
{"setcmdpos", 1, 1, f_setcmdpos},
{"setline", 2, 2, f_setline},
@@ -9166,15 +9166,16 @@ static void f_getfsize(typval_T *argvars, typval_T *rettv)
rettv->v_type = VAR_NUMBER;
- off_t file_size;
- if (os_get_file_size(fname, &file_size)) {
+ FileInfo file_info;
+ if (os_fileinfo(fname, &file_info)) {
+ uint64_t filesize = os_fileinfo_size(&file_info);
if (os_isdir((char_u *)fname))
rettv->vval.v_number = 0;
else {
- rettv->vval.v_number = (varnumber_T)file_size;
+ rettv->vval.v_number = (varnumber_T)filesize;
/* non-perfect check for overflow */
- if ((off_t)rettv->vval.v_number != file_size) {
+ if ((uint64_t)rettv->vval.v_number != filesize) {
rettv->vval.v_number = -2;
}
}
@@ -9191,7 +9192,7 @@ static void f_getftime(typval_T *argvars, typval_T *rettv)
char *fname = (char *)get_tv_string(&argvars[0]);
FileInfo file_info;
- if (os_get_file_info(fname, &file_info)) {
+ if (os_fileinfo(fname, &file_info)) {
rettv->vval.v_number = (varnumber_T)file_info.stat.st_mtim.tv_sec;
} else {
rettv->vval.v_number = -1;
@@ -9211,7 +9212,7 @@ static void f_getftype(typval_T *argvars, typval_T *rettv)
rettv->v_type = VAR_STRING;
FileInfo file_info;
- if (os_get_file_info_link((char *)fname, &file_info)) {
+ if (os_fileinfo_link((char *)fname, &file_info)) {
uint64_t mode = file_info.stat.st_mode;
#ifdef S_ISREG
if (S_ISREG(mode))
@@ -12700,13 +12701,19 @@ static void f_send_call(typval_T *argvars, typval_T *rettv)
return;
}
+ Array args = ARRAY_DICT_INIT;
+
+ for (typval_T *tv = argvars + 2; tv->v_type != VAR_UNKNOWN; tv++) {
+ ADD(args, vim_to_object(tv));
+ }
+
bool errored;
Object result;
if (!channel_send_call((uint64_t)argvars[0].vval.v_number,
- (char *)argvars[1].vval.v_string,
- vim_to_object(&argvars[2]),
- &result,
- &errored)) {
+ (char *)argvars[1].vval.v_string,
+ args,
+ &result,
+ &errored)) {
EMSG2(_(e_invarg2), "Channel doesn't exist");
return;
}
@@ -12741,9 +12748,15 @@ static void f_send_event(typval_T *argvars, typval_T *rettv)
return;
}
+ Array args = ARRAY_DICT_INIT;
+
+ for (typval_T *tv = argvars + 2; tv->v_type != VAR_UNKNOWN; tv++) {
+ ADD(args, vim_to_object(tv));
+ }
+
if (!channel_send_event((uint64_t)argvars[0].vval.v_number,
(char *)argvars[1].vval.v_string,
- vim_to_object(&argvars[2]))) {
+ args)) {
EMSG2(_(e_invarg2), "Channel doesn't exist");
return;
}
@@ -19217,7 +19230,9 @@ static void apply_job_autocmds(Job *job, char *name, char *type, char *str)
static void script_host_eval(char *method, typval_T *argvars, typval_T *rettv)
{
- Object result = provider_call(method, vim_to_object(argvars));
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, vim_to_object(argvars));
+ Object result = provider_call(method, args);
if (result.type == kObjectTypeNil) {
return;
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 5b6604fc93..18216f6924 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -1533,7 +1533,7 @@ void write_viminfo(char_u *file, int forceit)
*/
FileInfo old_info; // FileInfo of existing viminfo file
- if (os_get_file_info((char *)fname, &old_info)
+ if (os_fileinfo((char *)fname, &old_info)
&& getuid() != ROOT_UID
&& !(old_info.stat.st_uid == getuid()
? (old_info.stat.st_mode & 0200)
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index e0b0b55f41..ac91b2a6ac 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -2417,13 +2417,13 @@ do_source (
*/
save_current_SID = current_SID;
FileID file_id;
- bool file_id_ok = os_get_file_id((char *)fname_exp, &file_id);
+ bool file_id_ok = os_fileid((char *)fname_exp, &file_id);
for (current_SID = script_items.ga_len; current_SID > 0; --current_SID) {
si = &SCRIPT_ITEM(current_SID);
// Compare dev/ino when possible, it catches symbolic links.
// Also compare file names, the inode may change when the file was edited.
bool file_id_equal = file_id_ok && si->file_id_valid
- && os_file_id_equal(&(si->file_id), &file_id);
+ && os_fileid_equal(&(si->file_id), &file_id);
if (si->sn_name != NULL
&& (file_id_equal || fnamecmp(si->sn_name, fname_exp) == 0)) {
break;
@@ -3251,8 +3251,9 @@ static void script_host_execute(char *method, exarg_T *eap)
char *script = (char *)script_get(eap, eap->arg);
if (!eap->skip) {
- String str = cstr_to_string(script ? script : (char *)eap->arg);
- Object result = provider_call(method, STRING_OBJ(str));
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, STRING_OBJ(cstr_to_string(script ? script : (char *)eap->arg)));
+ Object result = provider_call(method, args);
// We don't care about the result, so free it just in case a bad provider
// returned something
msgpack_rpc_free_object(result);
@@ -3266,18 +3267,19 @@ static void script_host_execute_file(char *method, exarg_T *eap)
char buffer[MAXPATHL];
vim_FullName(eap->arg, (uint8_t *)buffer, sizeof(buffer), false);
- String file = cstr_to_string(buffer);
- Object result = provider_call(method, STRING_OBJ(file));
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, STRING_OBJ(cstr_to_string(buffer)));
+ Object result = provider_call(method, args);
msgpack_rpc_free_object(result);
}
static void script_host_do_range(char *method, exarg_T *eap)
{
- Array arg = {0, 0, 0};
- ADD(arg, INTEGER_OBJ(eap->line1));
- ADD(arg, INTEGER_OBJ(eap->line2));
- ADD(arg, STRING_OBJ(cstr_to_string((char *)eap->arg)));
- Object result = provider_call(method, ARRAY_OBJ(arg));
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, INTEGER_OBJ(eap->line1));
+ ADD(args, INTEGER_OBJ(eap->line2));
+ ADD(args, STRING_OBJ(cstr_to_string((char *)eap->arg)));
+ Object result = provider_call(method, args);
msgpack_rpc_free_object(result);
}
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 74f3edc8d9..69fb1d344a 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -2011,6 +2011,10 @@ void free_cmdline_buf(void)
*/
static void draw_cmdline(int start, int len)
{
+ if (embedded_mode) {
+ return;
+ }
+
int i;
if (cmdline_star > 0)
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index c7e1f5cbbc..955b0b0a68 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -1097,7 +1097,7 @@ static int ff_check_visited(ff_visited_T **visited_list, char_u *fname, char_u *
url = true;
} else {
ff_expand_buffer[0] = NUL;
- if (!os_get_file_id((char *)fname, &file_id)) {
+ if (!os_fileid((char *)fname, &file_id)) {
return FAIL;
}
}
@@ -1106,7 +1106,7 @@ static int ff_check_visited(ff_visited_T **visited_list, char_u *fname, char_u *
for (vp = *visited_list; vp != NULL; vp = vp->ffv_next) {
if ((url && fnamecmp(vp->ffv_fname, ff_expand_buffer) == 0)
|| (!url && vp->file_id_valid
- && os_file_id_equal(&(vp->file_id), &file_id))) {
+ && os_fileid_equal(&(vp->file_id), &file_id))) {
/* are the wildcard parts equal */
if (ff_wc_equal(vp->ffv_wc_path, wc_path) == TRUE)
/* already visited */
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 2e932e9695..0a05b2a4db 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -472,7 +472,7 @@ readfile (
if (newfile && !read_stdin && !read_buffer) {
/* Remember time of file. */
FileInfo file_info;
- if (os_get_file_info((char *)fname, &file_info)) {
+ if (os_fileinfo((char *)fname, &file_info)) {
buf_store_file_info(curbuf, &file_info);
curbuf->b_mtime_read = curbuf->b_mtime;
#ifdef UNIX
@@ -2583,7 +2583,7 @@ buf_write (
#if defined(UNIX)
perm = -1;
FileInfo file_info_old;
- if (!os_get_file_info((char *)fname, &file_info_old)) {
+ if (!os_fileinfo((char *)fname, &file_info_old)) {
newfile = TRUE;
} else {
perm = file_info_old.stat.st_mode;
@@ -2629,7 +2629,7 @@ buf_write (
goto fail;
}
if (overwriting) {
- os_get_file_info((char *)fname, &file_info_old);
+ os_fileinfo((char *)fname, &file_info_old);
}
}
@@ -2712,9 +2712,9 @@ buf_write (
* - it's a symbolic link
* - we don't have write permission in the directory
*/
- if (file_info_old.stat.st_nlink > 1
- || !os_get_file_info_link((char *)fname, &file_info)
- || !os_file_info_id_equal(&file_info, &file_info_old)) {
+ if (os_fileinfo_hardlinks(&file_info_old) > 1
+ || !os_fileinfo_link((char *)fname, &file_info)
+ || !os_fileinfo_id_equal(&file_info, &file_info_old)) {
backup_copy = TRUE;
} else
# endif
@@ -2728,7 +2728,7 @@ buf_write (
STRCPY(IObuff, fname);
for (i = 4913;; i += 123) {
sprintf((char *)path_tail(IObuff), "%d", i);
- if (!os_get_file_info_link((char *)IObuff, &file_info)) {
+ if (!os_fileinfo_link((char *)IObuff, &file_info)) {
break;
}
}
@@ -2739,7 +2739,7 @@ buf_write (
else {
# ifdef UNIX
os_fchown(fd, file_info_old.stat.st_uid, file_info_old.stat.st_gid);
- if (!os_get_file_info((char *)IObuff, &file_info)
+ if (!os_fileinfo((char *)IObuff, &file_info)
|| file_info.stat.st_uid != file_info_old.stat.st_uid
|| file_info.stat.st_gid != file_info_old.stat.st_gid
|| (long)file_info.stat.st_mode != perm) {
@@ -2759,20 +2759,20 @@ buf_write (
*/
if ((bkc_flags & BKC_BREAKSYMLINK) || (bkc_flags & BKC_BREAKHARDLINK)) {
# ifdef UNIX
- bool file_info_link_ok = os_get_file_info_link((char *)fname, &file_info);
+ bool file_info_link_ok = os_fileinfo_link((char *)fname, &file_info);
/* Symlinks. */
if ((bkc_flags & BKC_BREAKSYMLINK)
&& file_info_link_ok
- && !os_file_info_id_equal(&file_info, &file_info_old)) {
+ && !os_fileinfo_id_equal(&file_info, &file_info_old)) {
backup_copy = FALSE;
}
/* Hardlinks. */
if ((bkc_flags & BKC_BREAKHARDLINK)
- && file_info_old.stat.st_nlink > 1
+ && os_fileinfo_hardlinks(&file_info_old) > 1
&& (!file_info_link_ok
- || os_file_info_id_equal(&file_info, &file_info_old))) {
+ || os_fileinfo_id_equal(&file_info, &file_info_old))) {
backup_copy = FALSE;
}
# endif
@@ -2837,14 +2837,14 @@ buf_write (
/*
* Check if backup file already exists.
*/
- if (os_get_file_info((char *)backup, &file_info_new)) {
+ if (os_fileinfo((char *)backup, &file_info_new)) {
/*
* Check if backup file is same as original file.
* May happen when modname() gave the same file back (e.g. silly
* link). If we don't check here, we either ruin the file when
* copying or erase it after writing.
*/
- if (os_file_info_id_equal(&file_info_new, &file_info_old)) {
+ if (os_fileinfo_id_equal(&file_info_new, &file_info_old)) {
free(backup);
backup = NULL; /* no backup file to delete */
}
@@ -2861,7 +2861,7 @@ buf_write (
wp = backup;
*wp = 'z';
while (*wp > 'a'
- && os_get_file_info((char *)backup, &file_info_new)) {
+ && os_fileinfo((char *)backup, &file_info_new)) {
--*wp;
}
/* They all exist??? Must be something wrong. */
@@ -3201,9 +3201,9 @@ nobackup:
FileInfo file_info;
/* Don't delete the file when it's a hard or symbolic link. */
- if ((!newfile && file_info_old.stat.st_nlink > 1)
- || (os_get_file_info_link((char *)fname, &file_info)
- && !os_file_info_id_equal(&file_info, &file_info_old))) {
+ if ((!newfile && os_fileinfo_hardlinks(&file_info) > 1)
+ || (os_fileinfo_link((char *)fname, &file_info)
+ && !os_fileinfo_id_equal(&file_info, &file_info_old))) {
errmsg = (char_u *)_("E166: Can't open linked file for writing");
} else
#endif
@@ -3416,7 +3416,7 @@ restore_backup:
/* don't change the owner when it's already OK, some systems remove
* permission or ACL stuff */
FileInfo file_info;
- if (!os_get_file_info((char *)wfname, &file_info)
+ if (!os_fileinfo((char *)wfname, &file_info)
|| file_info.stat.st_uid != file_info_old.stat.st_uid
|| file_info.stat.st_gid != file_info_old.stat.st_gid) {
os_fchown(fd, file_info_old.stat.st_uid, file_info_old.stat.st_gid);
@@ -3713,7 +3713,7 @@ nofail:
/* Update the timestamp to avoid an "overwrite changed file"
* prompt when writing again. */
- if (os_get_file_info((char *)fname, &file_info_old)) {
+ if (os_fileinfo((char *)fname, &file_info_old)) {
buf_store_file_info(buf, &file_info_old);
buf->b_mtime_read = buf->b_mtime;
}
@@ -4536,7 +4536,7 @@ int vim_rename(char_u *from, char_u *to)
// Fail if the "from" file doesn't exist. Avoids that "to" is deleted.
FileInfo from_info;
- if (!os_get_file_info((char *)from, &from_info)) {
+ if (!os_fileinfo((char *)from, &from_info)) {
return -1;
}
@@ -4544,8 +4544,8 @@ int vim_rename(char_u *from, char_u *to)
// This happens when "from" and "to" differ in case and are on a FAT32
// filesystem. In that case go through a temp file name.
FileInfo to_info;
- if (os_get_file_info((char *)to, &to_info)
- && os_file_info_id_equal(&from_info, &to_info)) {
+ if (os_fileinfo((char *)to, &to_info)
+ && os_fileinfo_id_equal(&from_info, &to_info)) {
use_tmp_file = true;
}
@@ -4790,7 +4790,7 @@ buf_check_timestamp (
int helpmesg = FALSE;
int reload = FALSE;
int can_reload = FALSE;
- off_t orig_size = buf->b_orig_size;
+ uint64_t orig_size = buf->b_orig_size;
int orig_mode = buf->b_orig_mode;
static int busy = FALSE;
int n;
@@ -4812,7 +4812,7 @@ buf_check_timestamp (
bool file_info_ok;
if (!(buf->b_flags & BF_NOTEDITED)
&& buf->b_mtime != 0
- && (!(file_info_ok = os_get_file_info((char *)buf->b_ffname, &file_info))
+ && (!(file_info_ok = os_fileinfo((char *)buf->b_ffname, &file_info))
|| time_differs((long)file_info.stat.st_mtim.tv_sec, buf->b_mtime)
|| (int)file_info.stat.st_mode != buf->b_orig_mode
)) {
@@ -5127,9 +5127,10 @@ void buf_reload(buf_T *buf, int orig_mode)
}
void buf_store_file_info(buf_T *buf, FileInfo *file_info)
+ FUNC_ATTR_NONNULL_ALL
{
buf->b_mtime = (long)file_info->stat.st_mtim.tv_sec;
- buf->b_orig_size = file_info->stat.st_size;
+ buf->b_orig_size = os_fileinfo_size(file_info);
buf->b_orig_mode = (int)file_info->stat.st_mode;
}
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index ad65f7e6fd..1ff8887598 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -1233,6 +1233,9 @@ EXTERN char *ignoredp;
* os_unix.c */
EXTERN int curr_tmode INIT(= TMODE_COOK); /* contains current terminal mode */
+// If a msgpack-rpc channel should be started over stdin/stdout
+EXTERN bool embedded_mode INIT(= false);
+
/// Used to track the status of external functions.
/// Currently only used for iconv().
typedef enum {
diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c
index 9e07a60ee1..667e6512f3 100644
--- a/src/nvim/if_cscope.c
+++ b/src/nvim/if_cscope.c
@@ -473,7 +473,7 @@ cs_add_common (
fname = (char *)vim_strnsave((char_u *)fname, len);
free(fbuf);
FileInfo file_info;
- bool file_info_ok = os_get_file_info(fname, &file_info);
+ bool file_info_ok = os_fileinfo(fname, &file_info);
if (!file_info_ok) {
staterr:
if (p_csverbose)
@@ -504,7 +504,7 @@ staterr:
else
(void)sprintf(fname2, "%s/%s", fname, CSCOPE_DBFILE);
- file_info_ok = os_get_file_info(fname2, &file_info);
+ file_info_ok = os_fileinfo(fname2, &file_info);
if (!file_info_ok) {
if (p_csverbose)
cs_stat_emsg(fname2);
@@ -1181,7 +1181,7 @@ static int cs_insert_filelist(char *fname, char *ppath, char *flags,
i = -1; /* can be set to the index of an empty item in csinfo */
for (j = 0; j < csinfo_size; j++) {
if (csinfo[j].fname != NULL
- && os_file_id_equal_file_info(&(csinfo[j].file_id), file_info)) {
+ && os_fileid_equal_fileinfo(&(csinfo[j].file_id), file_info)) {
if (p_csverbose)
(void)EMSG(_("E568: duplicate cscope database not added"));
return -1;
@@ -1224,7 +1224,7 @@ static int cs_insert_filelist(char *fname, char *ppath, char *flags,
} else
csinfo[i].flags = NULL;
- os_file_info_get_id(file_info, &(csinfo[i].file_id));
+ os_fileinfo_id(file_info, &(csinfo[i].file_id));
return i;
} /* cs_insert_filelist */
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 1de4b04a07..9ab46b1ce2 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -256,10 +256,10 @@ int main(int argc, char **argv)
TIME_MSG("shell init");
- /*
- * Print a warning if stdout is not a terminal.
- */
- check_tty(&params);
+ if (!embedded_mode) {
+ // Print a warning if stdout is not a terminal.
+ check_tty(&params);
+ }
/* This message comes before term inits, but after setting "silent_mode"
* when the input is not a tty. */
@@ -267,8 +267,16 @@ int main(int argc, char **argv)
printf(_("%d files to edit\n"), GARGCOUNT);
if (params.want_full_screen && !silent_mode) {
- termcapinit(params.term); /* set terminal name and get terminal
- capabilities (will set full_screen) */
+ if (embedded_mode) {
+ // In embedded mode don't do terminal-related initializations, assume an
+ // initial screen size of 80x20
+ full_screen = true;
+ set_shellsize(80, 20, false);
+ } else {
+ // set terminal name and get terminal capabilities (will set full_screen)
+ // Do some initialization of the screen
+ termcapinit(params.term);
+ }
screen_start(); /* don't know where cursor is now */
TIME_MSG("Termcap init");
}
@@ -405,14 +413,18 @@ int main(int argc, char **argv)
TIME_MSG("waiting for return");
}
- starttermcap(); /* start termcap if not done by wait_return() */
- TIME_MSG("start termcap");
- may_req_ambiguous_char_width();
+ if (!embedded_mode) {
+ starttermcap(); // start termcap if not done by wait_return()
+ TIME_MSG("start termcap");
+ may_req_ambiguous_char_width();
+ setmouse(); // may start using the mouse
- setmouse(); /* may start using the mouse */
- if (scroll_region)
- scroll_region_reset(); /* In case Rows changed */
- scroll_start(); /* may scroll the screen to the right position */
+ if (scroll_region) {
+ scroll_region_reset(); // In case Rows changed
+ }
+
+ scroll_start(); // may scroll the screen to the right position
+ }
/*
* Don't clear the screen when starting in Ex mode, unless using the GUI.
@@ -1015,11 +1027,13 @@ static void command_line_scan(mparm_T *parmp)
msg_putchar('\n');
msg_didout = FALSE;
mch_exit(0);
- } else if (STRICMP(argv[0] + argv_idx, "api-msgpack-metadata") == 0) {
+ } else if (STRICMP(argv[0] + argv_idx, "api-msgpack-metadata") == 0) {
for (unsigned int i = 0; i<msgpack_metadata_size; i++) {
putchar(msgpack_metadata[i]);
}
mch_exit(0);
+ } else if (STRICMP(argv[0] + argv_idx, "embedded-mode") == 0) {
+ embedded_mode = true;
} else if (STRNICMP(argv[0] + argv_idx, "literal", 7) == 0) {
#if !defined(UNIX)
parmp->literal = TRUE;
@@ -2080,9 +2094,9 @@ static int file_owned(char *fname)
{
uid_t uid = getuid();
FileInfo file_info;
- bool file_owned = os_get_file_info(fname, &file_info)
+ bool file_owned = os_fileinfo(fname, &file_info)
&& file_info.stat.st_uid == uid;
- bool link_owned = os_get_file_info_link(fname, &file_info)
+ bool link_owned = os_fileinfo_link(fname, &file_info)
&& file_info.stat.st_uid == uid;
return file_owned && link_owned;
}
@@ -2200,6 +2214,8 @@ static void usage(void)
main_msg(_("--startuptime <file>\tWrite startup timing messages to <file>"));
main_msg(_("-i <viminfo>\t\tUse <viminfo> instead of .viminfo"));
main_msg(_("--api-msgpack-metadata\tDump API metadata information and exit"));
+ main_msg(_("--embedded-mode\tUse stdin/stdout as a msgpack-rpc channel. "
+ "This can be used for embedding Neovim into other programs"));
main_msg(_("-h or --help\tPrint Help (this message) and exit"));
main_msg(_("--version\t\tPrint version information and exit"));
diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c
index 82369b739a..827cff2299 100644
--- a/src/nvim/memfile.c
+++ b/src/nvim/memfile.c
@@ -122,11 +122,11 @@ memfile_T *mf_open(char_u *fname, int flags)
* mf_blocknr_max must be rounded up.
*/
FileInfo file_info;
- if (mfp->mf_fd >= 0
- && os_get_file_info_fd(mfp->mf_fd, &file_info)
- && file_info.stat.st_blksize >= MIN_SWAP_PAGE_SIZE
- && file_info.stat.st_blksize <= MAX_SWAP_PAGE_SIZE) {
- mfp->mf_page_size = file_info.stat.st_blksize;
+ if (mfp->mf_fd >= 0 && os_fileinfo_fd(mfp->mf_fd, &file_info)) {
+ uint64_t blocksize = os_fileinfo_blocksize(&file_info);
+ if (blocksize >= MIN_SWAP_PAGE_SIZE && blocksize <= MAX_SWAP_PAGE_SIZE) {
+ mfp->mf_page_size = blocksize;
+ }
}
if (mfp->mf_fd < 0 || (flags & (O_TRUNC|O_EXCL))
@@ -1017,7 +1017,7 @@ mf_do_open (
*/
FileInfo file_info;
if ((flags & O_CREAT)
- && os_get_file_info_link((char *)mfp->mf_fname, &file_info)) {
+ && os_fileinfo_link((char *)mfp->mf_fname, &file_info)) {
mfp->mf_fd = -1;
EMSG(_("E300: Swap file already exists (symlink attack?)"));
} else {
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 229de4ae1c..04ee0d7f55 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -686,9 +686,9 @@ static void set_b0_fname(ZERO_BL *b0p, buf_T *buf)
}
}
FileInfo file_info;
- if (os_get_file_info((char *)buf->b_ffname, &file_info)) {
+ if (os_fileinfo((char *)buf->b_ffname, &file_info)) {
long_to_char((long)file_info.stat.st_mtim.tv_sec, b0p->b0_mtime);
- long_to_char((long)os_file_info_get_inode(&file_info), b0p->b0_ino);
+ long_to_char((long)os_fileinfo_inode(&file_info), b0p->b0_ino);
buf_store_file_info(buf, &file_info);
buf->b_mtime_read = buf->b_mtime;
} else {
@@ -961,8 +961,8 @@ void ml_recover(void)
FileInfo swp_file_info;
mtime = char_to_long(b0p->b0_mtime);
if (curbuf->b_ffname != NULL
- && os_get_file_info((char *)curbuf->b_ffname, &org_file_info)
- && ((os_get_file_info((char *)mfp->mf_fname, &swp_file_info)
+ && os_fileinfo((char *)curbuf->b_ffname, &org_file_info)
+ && ((os_fileinfo((char *)mfp->mf_fname, &swp_file_info)
&& org_file_info.stat.st_mtim.tv_sec
> swp_file_info.stat.st_mtim.tv_sec)
|| org_file_info.stat.st_mtim.tv_sec != mtime)) {
@@ -1494,7 +1494,7 @@ static time_t swapfile_info(char_u *fname)
/* print the swap file date */
FileInfo file_info;
- if (os_get_file_info((char *)fname, &file_info)) {
+ if (os_fileinfo((char *)fname, &file_info)) {
#ifdef UNIX
/* print name of owner of the file */
if (os_get_uname(file_info.stat.st_uid, uname, B0_UNAME_SIZE) == OK) {
@@ -1630,9 +1630,9 @@ void ml_sync_all(int check_file, int check_char)
* call ml_preserve() to get rid of all negative numbered blocks.
*/
FileInfo file_info;
- if (!os_get_file_info((char *)buf->b_ffname, &file_info)
+ if (!os_fileinfo((char *)buf->b_ffname, &file_info)
|| file_info.stat.st_mtim.tv_sec != buf->b_mtime_read
- || (off_t)file_info.stat.st_size != buf->b_orig_size) {
+ || os_fileinfo_size(&file_info) != buf->b_orig_size) {
ml_preserve(buf, FALSE);
did_check_timestamps = FALSE;
need_check_timestamps = TRUE; /* give message later */
@@ -3180,7 +3180,7 @@ attention_message (
msg_outtrans(buf->b_fname);
MSG_PUTS("\"\n");
FileInfo file_info;
- if (os_get_file_info((char *)buf->b_fname, &file_info)) {
+ if (os_fileinfo((char *)buf->b_fname, &file_info)) {
MSG_PUTS(_(" dated: "));
x = file_info.stat.st_mtim.tv_sec;
p = ctime(&x); // includes '\n'
@@ -3294,7 +3294,7 @@ findswapname (
// Extra security check: When a swap file is a symbolic link, this
// is most likely a symlink attack.
FileInfo file_info;
- bool file_or_link_found = os_get_file_info_link((char *)fname, &file_info);
+ bool file_or_link_found = os_fileinfo_link((char *)fname, &file_info);
if (!file_or_link_found) {
break;
}
@@ -3558,8 +3558,8 @@ fnamecmp_ino (
int retval_s; /* flag: buf_s valid */
FileInfo file_info;
- if (os_get_file_info((char *)fname_c, &file_info)) {
- ino_c = os_file_info_get_inode(&file_info);
+ if (os_fileinfo((char *)fname_c, &file_info)) {
+ ino_c = os_fileinfo_inode(&file_info);
}
/*
@@ -3567,8 +3567,8 @@ fnamecmp_ino (
* the swap file may be outdated. If that fails (e.g. this path is not
* valid on this machine), use the inode from block 0.
*/
- if (os_get_file_info((char *)fname_s, &file_info)) {
- ino_s = os_file_info_get_inode(&file_info);
+ if (os_fileinfo((char *)fname_s, &file_info)) {
+ ino_s = os_fileinfo_inode(&file_info);
} else {
ino_s = (uint64_t)ino_block0;
}
diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c
index 986374b352..8669977ea1 100644
--- a/src/nvim/misc1.c
+++ b/src/nvim/misc1.c
@@ -503,7 +503,7 @@ open_line (
break;
}
}
- if (lead_len) {
+ if (lead_len > 0) {
/* allocate buffer (may concatenate p_extra later) */
leader = xmalloc(lead_len + lead_repl_len + extra_space + extra_len
+ (second_line_indent > 0 ? second_line_indent : 0) + 1);
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 0b0a913a95..f1cb34577b 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -5232,7 +5232,8 @@ static void get_clipboard(int name)
struct yankreg *reg = &y_regs[CLIP_REGISTER];
free_register(reg);
- Object result = provider_call("clipboard_get", NIL);
+ Array args = ARRAY_DICT_INIT;
+ Object result = provider_call("clipboard_get", args);
if (result.type != kObjectTypeArray) {
goto err;
@@ -5278,12 +5279,15 @@ static void set_clipboard(int name)
copy_register(reg, &y_regs[0]);
}
- Array lines = {0, 0, 0};
+ Array lines = ARRAY_DICT_INIT;
for (int i = 0; i < reg->y_size; i++) {
ADD(lines, STRING_OBJ(cstr_to_string((char *)reg->y_array[i])));
}
- Object result = provider_call("clipboard_set", ARRAY_OBJ(lines));
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, ARRAY_OBJ(lines));
+
+ Object result = provider_call("clipboard_set", args);
msgpack_rpc_free_object(result);
}
diff --git a/src/nvim/os/channel.c b/src/nvim/os/channel.c
index 1a2efca513..bad82bc272 100644
--- a/src/nvim/os/channel.c
+++ b/src/nvim/os/channel.c
@@ -20,11 +20,14 @@
#include "nvim/vim.h"
#include "nvim/ascii.h"
#include "nvim/memory.h"
+#include "nvim/os_unix.h"
#include "nvim/message.h"
#include "nvim/map.h"
#include "nvim/log.h"
#include "nvim/lib/kvec.h"
+#define CHANNEL_BUFFER_SIZE 0xffff
+
typedef struct {
uint64_t request_id;
bool errored;
@@ -64,6 +67,10 @@ void channel_init(void)
channels = pmap_new(uint64_t)();
event_strings = pmap_new(cstr_t)();
msgpack_sbuffer_init(&out_buffer);
+
+ if (embedded_mode) {
+ channel_from_stdio();
+ }
}
/// Teardown the module
@@ -117,7 +124,10 @@ void channel_from_stream(uv_stream_t *stream)
stream->data = NULL;
channel->is_job = false;
// read stream
- channel->data.streams.read = rstream_new(parse_msgpack, 1024, channel, NULL);
+ channel->data.streams.read = rstream_new(parse_msgpack,
+ CHANNEL_BUFFER_SIZE,
+ channel,
+ NULL);
rstream_set_stream(channel->data.streams.read, stream);
rstream_start(channel->data.streams.read);
// write stream
@@ -133,40 +143,48 @@ bool channel_exists(uint64_t id)
&& channel->enabled;
}
-/// Sends event/data to channel
+/// Sends event/arguments to channel
///
/// @param id The channel id. If 0, the event will be sent to all
/// channels that have subscribed to the event type
/// @param name The event name, an arbitrary string
-/// @param arg The event arg
-/// @return True if the data was sent successfully, false otherwise.
-bool channel_send_event(uint64_t id, char *name, Object arg)
+/// @param args Array with event arguments
+/// @return True if the event was sent successfully, false otherwise.
+bool channel_send_event(uint64_t id, char *name, Array args)
{
Channel *channel = NULL;
if (id > 0) {
if (!(channel = pmap_get(uint64_t)(channels, id)) || !channel->enabled) {
- msgpack_rpc_free_object(arg);
+ msgpack_rpc_free_array(args);
return false;
}
- send_event(channel, name, arg);
+ send_event(channel, name, args);
} else {
- broadcast_event(name, arg);
+ broadcast_event(name, args);
}
return true;
}
+/// Sends a method call to a channel
+///
+/// @param id The channel id
+/// @param name The method name, an arbitrary string
+/// @param args Array with method arguments
+/// @param[out] result Pointer to return value received from the channel
+/// @param[out] error True if the return value is an error
+/// @return True if the call was sent successfully, false otherwise.
bool channel_send_call(uint64_t id,
char *name,
- Object arg,
+ Array args,
Object *result,
bool *errored)
{
Channel *channel = NULL;
if (!(channel = pmap_get(uint64_t)(channels, id)) || !channel->enabled) {
- msgpack_rpc_free_object(arg);
+ msgpack_rpc_free_array(args);
return false;
}
@@ -176,17 +194,16 @@ bool channel_send_call(uint64_t id,
char buf[256];
snprintf(buf,
sizeof(buf),
- "Channel %" PRIu64 " was closed due to a high stack depth "
- "while processing a RPC call",
+ "Channel %" PRIu64 " crossed maximum stack depth",
channel->id);
*result = STRING_OBJ(cstr_to_string(buf));
- msgpack_rpc_free_object(arg);
+ msgpack_rpc_free_array(args);
return false;
}
uint64_t request_id = channel->next_request_id++;
// Send the msgpack-rpc request
- send_request(channel, request_id, name, arg);
+ send_request(channel, request_id, name, args);
EventSource channel_source = channel->is_job
? job_event_source(channel->data.job)
@@ -205,14 +222,6 @@ bool channel_send_call(uint64_t id,
channel->enabled && // the channel is still enabled
kv_size(channel->call_stack) >= size); // the call didn't return
- if (!(kv_size(channel->call_stack)
- || channel->enabled
- || channel->rpc_call_level)) {
- // Close the channel if it has been disabled and we have not been called
- // by `parse_msgpack`(It would be unsafe to close the channel otherwise)
- close_channel(channel);
- }
-
*errored = frame.errored;
*result = frame.result;
@@ -256,6 +265,25 @@ void channel_unsubscribe(uint64_t id, char *event)
unsubscribe(channel, event);
}
+/// Creates an API channel from stdin/stdout. This is used when embedding
+/// Neovim
+static void channel_from_stdio(void)
+{
+ Channel *channel = register_channel();
+ channel->is_job = false;
+ // read stream
+ channel->data.streams.read = rstream_new(parse_msgpack,
+ CHANNEL_BUFFER_SIZE,
+ channel,
+ NULL);
+ rstream_set_file(channel->data.streams.read, 0);
+ rstream_start(channel->data.streams.read);
+ // write stream
+ channel->data.streams.write = wstream_new(0);
+ wstream_set_file(channel->data.streams.write, 1);
+ channel->data.streams.uv = NULL;
+}
+
static void job_out(RStream *rstream, void *data, bool eof)
{
Job *job = data;
@@ -278,6 +306,7 @@ static void job_err(RStream *rstream, void *data, bool eof)
static void parse_msgpack(RStream *rstream, void *data, bool eof)
{
Channel *channel = data;
+ channel->rpc_call_level++;
if (eof) {
char buf[256];
@@ -287,10 +316,9 @@ static void parse_msgpack(RStream *rstream, void *data, bool eof)
"closed by the client",
channel->id);
call_set_error(channel, buf);
- return;
+ goto end;
}
- channel->rpc_call_level++;
uint32_t count = rstream_available(rstream);
DLOG("Feeding the msgpack parser with %u bytes of data from RStream(%p)",
count,
@@ -386,21 +414,21 @@ static void send_error(Channel *channel, uint64_t id, char *err)
static void send_request(Channel *channel,
uint64_t id,
char *name,
- Object arg)
+ Array args)
{
String method = {.size = strlen(name), .data = name};
- channel_write(channel, serialize_request(id, method, arg, &out_buffer, 1));
+ channel_write(channel, serialize_request(id, method, args, &out_buffer, 1));
}
static void send_event(Channel *channel,
char *name,
- Object arg)
+ Array args)
{
String method = {.size = strlen(name), .data = name};
- channel_write(channel, serialize_request(0, method, arg, &out_buffer, 1));
+ channel_write(channel, serialize_request(0, method, args, &out_buffer, 1));
}
-static void broadcast_event(char *name, Object arg)
+static void broadcast_event(char *name, Array args)
{
kvec_t(Channel *) subscribed;
kv_init(subscribed);
@@ -413,14 +441,14 @@ static void broadcast_event(char *name, Object arg)
});
if (!kv_size(subscribed)) {
- msgpack_rpc_free_object(arg);
+ msgpack_rpc_free_array(args);
goto end;
}
String method = {.size = strlen(name), .data = name};
WBuffer *buffer = serialize_request(0,
method,
- arg,
+ args,
&out_buffer,
kv_size(subscribed));
@@ -469,7 +497,12 @@ static void close_channel(Channel *channel)
} else {
rstream_free(channel->data.streams.read);
wstream_free(channel->data.streams.write);
- uv_close((uv_handle_t *)channel->data.streams.uv, close_cb);
+ if (channel->data.streams.uv) {
+ uv_close((uv_handle_t *)channel->data.streams.uv, close_cb);
+ } else {
+ // When the stdin channel closes, it's time to go
+ mch_exit(0);
+ }
}
free(channel);
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index aca7005064..bb4e897887 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -258,20 +258,6 @@ int os_file_is_writable(const char *name)
return 0;
}
-/// Get the size of a file in bytes.
-///
-/// @param[out] size pointer to an off_t to put the size into.
-/// @return `true` for success, `false` for failure.
-bool os_get_file_size(const char *name, off_t *size)
-{
- uv_stat_t statbuf;
- if (os_stat(name, &statbuf)) {
- *size = statbuf.st_size;
- return true;
- }
- return false;
-}
-
/// Rename a file or directory.
///
/// @return `OK` for success, `FAIL` for failure.
@@ -345,7 +331,7 @@ int os_remove(const char *path)
/// @param path Path to the file.
/// @param[out] file_info Pointer to a FileInfo to put the information in.
/// @return `true` on success, `false` for failure.
-bool os_get_file_info(const char *path, FileInfo *file_info)
+bool os_fileinfo(const char *path, FileInfo *file_info)
{
return os_stat(path, &(file_info->stat));
}
@@ -355,7 +341,7 @@ bool os_get_file_info(const char *path, FileInfo *file_info)
/// @param path Path to the file.
/// @param[out] file_info Pointer to a FileInfo to put the information in.
/// @return `true` on success, `false` for failure.
-bool os_get_file_info_link(const char *path, FileInfo *file_info)
+bool os_fileinfo_link(const char *path, FileInfo *file_info)
{
uv_fs_t request;
int result = uv_fs_lstat(uv_default_loop(), &request, path, NULL);
@@ -369,7 +355,7 @@ bool os_get_file_info_link(const char *path, FileInfo *file_info)
/// @param file_descriptor File descriptor of the file.
/// @param[out] file_info Pointer to a FileInfo to put the information in.
/// @return `true` on success, `false` for failure.
-bool os_get_file_info_fd(int file_descriptor, FileInfo *file_info)
+bool os_fileinfo_fd(int file_descriptor, FileInfo *file_info)
{
uv_fs_t request;
int result = uv_fs_fstat(uv_default_loop(), &request, file_descriptor, NULL);
@@ -381,7 +367,7 @@ bool os_get_file_info_fd(int file_descriptor, FileInfo *file_info)
/// Compare the inodes of two FileInfos
///
/// @return `true` if the two FileInfos represent the same file.
-bool os_file_info_id_equal(const FileInfo *file_info_1,
+bool os_fileinfo_id_equal(const FileInfo *file_info_1,
const FileInfo *file_info_2)
{
return file_info_1->stat.st_ino == file_info_2->stat.st_ino
@@ -392,7 +378,7 @@ bool os_file_info_id_equal(const FileInfo *file_info_1,
///
/// @param file_info Pointer to the `FileInfo`
/// @param[out] file_id Pointer to a `FileID`
-void os_file_info_get_id(const FileInfo *file_info, FileID *file_id)
+void os_fileinfo_id(const FileInfo *file_info, FileID *file_id)
{
file_id->inode = file_info->stat.st_ino;
file_id->device_id = file_info->stat.st_dev;
@@ -403,17 +389,44 @@ void os_file_info_get_id(const FileInfo *file_info, FileID *file_id)
/// @deprecated Use `FileID` instead, this function is only needed in memline.c
/// @param file_info Pointer to the `FileInfo`
/// @return the inode number
-uint64_t os_file_info_get_inode(const FileInfo *file_info)
+uint64_t os_fileinfo_inode(const FileInfo *file_info)
{
return file_info->stat.st_ino;
}
+/// Get the size of a file from a `FileInfo`.
+///
+/// @return filesize in bytes.
+uint64_t os_fileinfo_size(const FileInfo *file_info)
+ FUNC_ATTR_NONNULL_ALL
+{
+ return file_info->stat.st_size;
+}
+
+/// Get the number of hardlinks from a `FileInfo`.
+///
+/// @return number of hardlinks.
+uint64_t os_fileinfo_hardlinks(const FileInfo *file_info)
+ FUNC_ATTR_NONNULL_ALL
+{
+ return file_info->stat.st_nlink;
+}
+
+/// Get the blocksize from a `FileInfo`.
+///
+/// @return blocksize in bytes.
+uint64_t os_fileinfo_blocksize(const FileInfo *file_info)
+ FUNC_ATTR_NONNULL_ALL
+{
+ return file_info->stat.st_blksize;
+}
+
/// Get the `FileID` for a given path
///
/// @param path Path to the file.
/// @param[out] file_info Pointer to a `FileID` to fill in.
/// @return `true` on sucess, `false` for failure.
-bool os_get_file_id(const char *path, FileID *file_id)
+bool os_fileid(const char *path, FileID *file_id)
{
uv_stat_t statbuf;
if (os_stat(path, &statbuf)) {
@@ -429,7 +442,7 @@ bool os_get_file_id(const char *path, FileID *file_id)
/// @param file_id_1 Pointer to first `FileID`
/// @param file_id_2 Pointer to second `FileID`
/// @return `true` if the two `FileID`s represent te same file.
-bool os_file_id_equal(const FileID *file_id_1, const FileID *file_id_2)
+bool os_fileid_equal(const FileID *file_id_1, const FileID *file_id_2)
{
return file_id_1->inode == file_id_2->inode
&& file_id_1->device_id == file_id_2->device_id;
@@ -440,7 +453,7 @@ bool os_file_id_equal(const FileID *file_id_1, const FileID *file_id_2)
/// @param file_id Pointer to a `FileID`
/// @param file_info Pointer to a `FileInfo`
/// @return `true` if the `FileID` and the `FileInfo` represent te same file.
-bool os_file_id_equal_file_info(const FileID *file_id,
+bool os_fileid_equal_fileinfo(const FileID *file_id,
const FileInfo *file_info)
{
return file_id->inode == file_info->stat.st_ino
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index 15aebdbf3d..53024d1389 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -6,6 +6,7 @@
#include "nvim/os/input.h"
#include "nvim/os/event.h"
+#include "nvim/os/signal.h"
#include "nvim/os/rstream_defs.h"
#include "nvim/os/rstream.h"
#include "nvim/ascii.h"
@@ -34,6 +35,10 @@ static bool eof = false, started_reading = false;
void input_init(void)
{
+ if (embedded_mode) {
+ return;
+ }
+
read_stream = rstream_new(read_cb, READ_BUFFER_SIZE, NULL, NULL);
rstream_set_file(read_stream, read_cmd_fd);
}
@@ -41,18 +46,30 @@ void input_init(void)
// Listen for input
void input_start(void)
{
+ if (embedded_mode) {
+ return;
+ }
+
rstream_start(read_stream);
}
// Stop listening for input
void input_stop(void)
{
+ if (embedded_mode) {
+ return;
+ }
+
rstream_stop(read_stream);
}
// Copies (at most `count`) of was read from `read_cmd_fd` into `buf`
uint32_t input_read(char *buf, uint32_t count)
{
+ if (embedded_mode) {
+ return 0;
+ }
+
return rstream_read(read_stream, buf, count);
}
@@ -129,6 +146,11 @@ bool os_isatty(int fd)
static bool input_poll(int32_t ms)
{
+ if (embedded_mode) {
+ EventSource input_sources[] = { signal_event_source(), NULL };
+ return event_poll(ms, input_sources);
+ }
+
EventSource input_sources[] = {
rstream_event_source(read_stream),
NULL
diff --git a/src/nvim/os/msgpack_rpc.c b/src/nvim/os/msgpack_rpc.c
index c03d8dccca..c6e2af2f1c 100644
--- a/src/nvim/os/msgpack_rpc.c
+++ b/src/nvim/os/msgpack_rpc.c
@@ -39,15 +39,14 @@ WBuffer *msgpack_rpc_call(uint64_t channel_id,
return serialize_response(response_id, err, NIL, sbuffer);
}
- uint64_t method_id = req->via.array.ptr[2].via.u64;
-
- if (method_id == 0) {
+ if (req->via.array.ptr[2].type == MSGPACK_OBJECT_POSITIVE_INTEGER
+ && req->via.array.ptr[2].via.u64 == 0) {
return serialize_metadata(response_id, channel_id, sbuffer);
}
// dispatch the call
Error error = { .set = false };
- Object rv = msgpack_rpc_dispatch(channel_id, method_id, req, &error);
+ Object rv = msgpack_rpc_dispatch(channel_id, req, &error);
// send the response
msgpack_packer response;
msgpack_packer_init(&response, sbuffer, msgpack_sbuffer_write);
@@ -119,7 +118,7 @@ void msgpack_rpc_error(char *msg, msgpack_packer *res)
/// Serializes a msgpack-rpc request or notification(id == 0)
WBuffer *serialize_request(uint64_t request_id,
String method,
- Object arg,
+ Array args,
msgpack_sbuffer *sbuffer,
size_t refcount)
FUNC_ATTR_NONNULL_ARG(4)
@@ -135,12 +134,12 @@ WBuffer *serialize_request(uint64_t request_id,
msgpack_pack_raw(&pac, method.size);
msgpack_pack_raw_body(&pac, method.data, method.size);
- msgpack_rpc_from_object(arg, &pac);
+ msgpack_rpc_from_array(args, &pac);
WBuffer *rv = wstream_new_buffer(xmemdup(sbuffer->data, sbuffer->size),
sbuffer->size,
refcount,
free);
- msgpack_rpc_free_object(arg);
+ msgpack_rpc_free_array(args);
msgpack_sbuffer_clear(sbuffer);
return rv;
}
@@ -235,8 +234,9 @@ static char *msgpack_rpc_validate(uint64_t *response_id, msgpack_object *req)
return "Message type must be 0";
}
- if (req->via.array.ptr[2].type != MSGPACK_OBJECT_POSITIVE_INTEGER) {
- return "Method id must be a positive integer";
+ if (req->via.array.ptr[2].type != MSGPACK_OBJECT_POSITIVE_INTEGER
+ && req->via.array.ptr[2].type != MSGPACK_OBJECT_RAW) {
+ return "Method must be a positive integer or a string";
}
if (req->via.array.ptr[3].type != MSGPACK_OBJECT_ARRAY) {
diff --git a/src/nvim/os/msgpack_rpc.h b/src/nvim/os/msgpack_rpc.h
index 5aca900d2e..35f175d2a0 100644
--- a/src/nvim/os/msgpack_rpc.h
+++ b/src/nvim/os/msgpack_rpc.h
@@ -21,6 +21,11 @@ typedef Object (*rpc_method_handler_fn)(uint64_t channel_id,
msgpack_object *req,
Error *error);
+
+/// Initializes the msgpack-rpc method table
+void msgpack_rpc_init(void);
+
+
/// Dispatches to the actual API function after basic payload validation by
/// `msgpack_rpc_call`. It is responsible for validating/converting arguments
/// to C types, and converting the return value back to msgpack types.
@@ -33,11 +38,11 @@ typedef Object (*rpc_method_handler_fn)(uint64_t channel_id,
/// @param error Pointer to error structure
/// @return Some object
Object msgpack_rpc_dispatch(uint64_t channel_id,
- uint64_t method_id,
msgpack_object *req,
Error *error)
FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_NONNULL_ARG(3);
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/msgpack_rpc.h.generated.h"
#endif
diff --git a/src/nvim/os/provider.c b/src/nvim/os/provider.c
index d94203f683..07e757fe0e 100644
--- a/src/nvim/os/provider.c
+++ b/src/nvim/os/provider.c
@@ -98,7 +98,7 @@ bool provider_register(char *method, uint64_t channel_id)
return true;
}
-Object provider_call(char *method, Object arg)
+Object provider_call(char *method, Array args)
{
uint64_t channel_id = get_provider_for(method);
@@ -109,13 +109,13 @@ Object provider_call(char *method, Object arg)
"Provider for \"%s\" is not available",
method);
report_error(buf);
- msgpack_rpc_free_object(arg);
+ msgpack_rpc_free_array(args);
return NIL;
}
bool error = false;
Object result = NIL;
- channel_send_call(channel_id, method, arg, &result, &error);
+ channel_send_call(channel_id, method, args, &result, &error);
if (error) {
report_error(result.data.string.data);
diff --git a/src/nvim/os/signal.c b/src/nvim/os/signal.c
index 17f270a5cc..2f93cfb08a 100644
--- a/src/nvim/os/signal.c
+++ b/src/nvim/os/signal.c
@@ -39,7 +39,10 @@ void signal_init(void)
uv_signal_start(&shup, signal_cb, SIGHUP);
uv_signal_start(&squit, signal_cb, SIGQUIT);
uv_signal_start(&sterm, signal_cb, SIGTERM);
- uv_signal_start(&swinch, signal_cb, SIGWINCH);
+ if (!embedded_mode) {
+ // TODO(tarruda): There must be an API function for resizing window
+ uv_signal_start(&swinch, signal_cb, SIGWINCH);
+ }
#ifdef SIGPWR
uv_signal_init(uv_default_loop(), &spwr);
uv_signal_start(&spwr, signal_cb, SIGPWR);
diff --git a/src/nvim/os/wstream.c b/src/nvim/os/wstream.c
index 194bf757e4..44463c7c88 100644
--- a/src/nvim/os/wstream.c
+++ b/src/nvim/os/wstream.c
@@ -1,6 +1,7 @@
#include <assert.h>
#include <stdint.h>
#include <stdbool.h>
+#include <stdlib.h>
#include <uv.h>
@@ -20,7 +21,7 @@ struct wstream {
size_t maxmem;
// Number of pending requests
size_t pending_reqs;
- bool freed;
+ bool freed, free_handle;
// (optional) Write callback and data
wstream_cb cb;
void *data;
@@ -60,6 +61,7 @@ WStream * wstream_new(size_t maxmem)
rv->curmem = 0;
rv->pending_reqs = 0;
rv->freed = false;
+ rv->free_handle = false;
rv->cb = NULL;
return rv;
@@ -68,9 +70,13 @@ WStream * wstream_new(size_t maxmem)
/// Frees all memory allocated for a WStream instance
///
/// @param wstream The `WStream` instance
-void wstream_free(WStream *wstream)
-{
+void wstream_free(WStream *wstream) {
if (!wstream->pending_reqs) {
+ handle_set_wstream((uv_handle_t *)wstream->stream, NULL);
+ if (wstream->free_handle) {
+ uv_close((uv_handle_t *)wstream->stream, close_cb);
+ }
+
free(wstream);
} else {
wstream->freed = true;
@@ -87,6 +93,24 @@ void wstream_set_stream(WStream *wstream, uv_stream_t *stream)
wstream->stream = stream;
}
+/// Sets the underlying file descriptor that will be written to. Only pipes
+/// are supported for now.
+///
+/// @param wstream The `WStream` instance
+/// @param file The file descriptor
+void wstream_set_file(WStream *wstream, uv_file file)
+{
+ uv_handle_type type = uv_guess_handle(file);
+
+ assert(type == UV_NAMED_PIPE || type == UV_TTY);
+ wstream->stream = xmalloc(sizeof(uv_pipe_t));
+ uv_pipe_init(uv_default_loop(), (uv_pipe_t *)wstream->stream, 0);
+ uv_pipe_open((uv_pipe_t *)wstream->stream, file);
+ wstream->stream->data = NULL;
+ handle_set_wstream((uv_handle_t *)wstream->stream, wstream);
+ wstream->free_handle = true;
+}
+
/// Sets a callback that will be called on completion of a write request,
/// indicating failure/success.
///
@@ -211,3 +235,16 @@ static void release_wbuffer(WBuffer *buffer)
free(buffer);
}
}
+
+static void close_cb(uv_handle_t *handle)
+{
+ WStream *wstream = handle_get_wstream(handle);
+
+ if (wstream) {
+ free(wstream);
+ }
+
+ free(handle->data);
+ free(handle);
+}
+
diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c
index af17676ebf..3fa8b803b2 100644
--- a/src/nvim/os_unix.c
+++ b/src/nvim/os_unix.c
@@ -54,6 +54,7 @@
#include "nvim/os/shell.h"
#include "nvim/os/signal.h"
#include "nvim/os/job.h"
+#include "nvim/os/msgpack_rpc.h"
#if defined(HAVE_SYS_IOCTL_H)
# include <sys/ioctl.h>
@@ -88,6 +89,18 @@ static int did_set_icon = FALSE;
*/
void mch_write(char_u *s, int len)
{
+ if (embedded_mode) {
+ // TODO(tarruda): This is a temporary hack to stop Neovim from writing
+ // messages to stdout in embedded mode. In the future, embedded mode will
+ // be the only possibility(GUIs will always start neovim with a msgpack-rpc
+ // over stdio) and this function won't exist.
+ //
+ // The reason for this is because before Neovim fully migrates to a
+ // msgpack-rpc-driven architecture, we must have a fully functional
+ // UI working
+ return;
+ }
+
ignored = (int)write(1, (char *)s, len);
if (p_wd) /* Unix is too fast, slow down a bit more */
os_microdelay(p_wd, false);
@@ -152,6 +165,7 @@ void mch_init(void)
mac_conv_init();
#endif
+ msgpack_rpc_init();
event_init();
}
@@ -314,7 +328,7 @@ int len /* buffer size, only used when name gets longer */
struct dirent *dp;
FileInfo file_info;
- if (os_get_file_info_link((char *)name, &file_info)) {
+ if (os_fileinfo_link((char *)name, &file_info)) {
/* Open the directory where the file is located. */
slash = vim_strrchr(name, '/');
if (slash == NULL) {
@@ -340,8 +354,8 @@ int len /* buffer size, only used when name gets longer */
STRLCPY(newname + (tail - name), dp->d_name,
MAXPATHL - (tail - name) + 1);
FileInfo file_info_new;
- if (os_get_file_info_link((char *)newname, &file_info_new)
- && os_file_info_id_equal(&file_info, &file_info_new)) {
+ if (os_fileinfo_link((char *)newname, &file_info_new)
+ && os_fileinfo_id_equal(&file_info, &file_info_new)) {
STRCPY(tail, dp->d_name);
break;
}
diff --git a/src/nvim/path.c b/src/nvim/path.c
index 0c18ab7bd4..4e05c506f8 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -61,10 +61,10 @@ FileComparison path_full_compare(char_u *s1, char_u *s2, int checkname)
FileID file_id_1, file_id_2;
expand_env(s1, exp1, MAXPATHL);
- bool id_ok_1 = os_get_file_id((char *)exp1, &file_id_1);
- bool id_ok_2 = os_get_file_id((char *)s2, &file_id_2);
+ bool id_ok_1 = os_fileid((char *)exp1, &file_id_1);
+ bool id_ok_2 = os_fileid((char *)s2, &file_id_2);
if (!id_ok_1 && !id_ok_2) {
- // If os_get_file_id() doesn't work, may compare the names.
+ // If os_fileid() doesn't work, may compare the names.
if (checkname) {
vim_FullName(exp1, full1, MAXPATHL, FALSE);
vim_FullName(s2, full2, MAXPATHL, FALSE);
@@ -77,7 +77,7 @@ FileComparison path_full_compare(char_u *s1, char_u *s2, int checkname)
if (!id_ok_1 || !id_ok_2) {
return kOneFileMissing;
}
- if (os_file_id_equal(&file_id_1, &file_id_2)) {
+ if (os_fileid_equal(&file_id_1, &file_id_2)) {
return kEqualFiles;
}
return kDifferentFiles;
@@ -1304,7 +1304,7 @@ void simplify_filename(char_u *filename)
saved_char = p[-1];
p[-1] = NUL;
FileInfo file_info;
- if (!os_get_file_info_link((char *)filename, &file_info)) {
+ if (!os_fileinfo_link((char *)filename, &file_info)) {
do_strip = TRUE;
}
p[-1] = saved_char;
@@ -1327,7 +1327,7 @@ void simplify_filename(char_u *filename)
* components. */
saved_char = *tail;
*tail = NUL;
- if (os_get_file_info((char *)filename, &file_info)) {
+ if (os_fileinfo((char *)filename, &file_info)) {
do_strip = TRUE;
}
else
@@ -1343,15 +1343,15 @@ void simplify_filename(char_u *filename)
* component's parent directory.) */
FileInfo new_file_info;
if (p == start && relative) {
- os_get_file_info(".", &new_file_info);
+ os_fileinfo(".", &new_file_info);
} else {
saved_char = *p;
*p = NUL;
- os_get_file_info((char *)filename, &new_file_info);
+ os_fileinfo((char *)filename, &new_file_info);
*p = saved_char;
}
- if (!os_file_info_id_equal(&file_info, &new_file_info)) {
+ if (!os_fileinfo_id_equal(&file_info, &new_file_info)) {
do_strip = FALSE;
/* We don't disable stripping of later
* components since the unstripped path name is
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 2415858e0f..876d4e73d1 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -2564,7 +2564,7 @@ static char_u *get_mef_name(void)
STRCAT(name, p + 2);
// Don't accept a symbolic link, its a security risk.
FileInfo file_info;
- bool file_or_link_found = os_get_file_info_link((char *)name, &file_info);
+ bool file_or_link_found = os_fileinfo_link((char *)name, &file_info);
if (!file_or_link_found) {
break;
}
diff --git a/src/nvim/term.c b/src/nvim/term.c
index 36e433d624..d2c524e2e8 100644
--- a/src/nvim/term.c
+++ b/src/nvim/term.c
@@ -2360,6 +2360,9 @@ void set_shellsize(int width, int height, int mustset)
*/
void settmode(int tmode)
{
+ if (embedded_mode) {
+ return;
+ }
if (full_screen) {
/*
diff --git a/src/nvim/testdir/test105.in b/src/nvim/testdir/test105.in
index 73d92e899d..bfb4b65fbb 100644
--- a/src/nvim/testdir/test105.in
+++ b/src/nvim/testdir/test105.in
@@ -7,7 +7,7 @@ STARTTEST
:set shellslash
:let tab="\t"
:command -nargs=1 Put :let expr=<q-args> | $put =expr.tab.strtrans(string(eval(expr)))
-:let $HOME=fnamemodify('.', ':p:h:h:h:h')
+:let $HOME=fnamemodify('.', ':p:h:h:h')
:Put fnamemodify('.', ':p' )[-1:]
:Put fnamemodify('.', ':p:h' )[-1:]
:Put fnamemodify('test.out', ':p' )[-1:]
@@ -23,7 +23,7 @@ STARTTEST
:Put fnamemodify('abc.fb2.tar.gz', ':r' )
:Put fnamemodify('abc.fb2.tar.gz', ':r:r' )
:Put fnamemodify('abc.fb2.tar.gz', ':r:r:r' )
-:Put substitute(fnamemodify('abc.fb2.tar.gz', ':p:r:r'), '.*\(src/nvim/testdir/.*\)', '\1', '')
+:Put substitute(fnamemodify('abc.fb2.tar.gz', ':p:r:r'), '.*\(nvim/testdir/.*\)', '\1', '')
:Put fnamemodify('abc.fb2.tar.gz', ':e' )
:Put fnamemodify('abc.fb2.tar.gz', ':e:e' )
:Put fnamemodify('abc.fb2.tar.gz', ':e:e:e' )
diff --git a/src/nvim/testdir/test105.ok b/src/nvim/testdir/test105.ok
index be1eca8f8f..0b30ee4281 100644
--- a/src/nvim/testdir/test105.ok
+++ b/src/nvim/testdir/test105.ok
@@ -3,8 +3,8 @@ fnamemodify('.', ':p:h' )[-1:] 'r'
fnamemodify('test.out', ':p' )[-1:] 't'
fnamemodify('test.out', ':.' ) 'test.out'
fnamemodify('../testdir/a', ':.' ) 'a'
-fnamemodify('test.out', ':~' ) '~/src/nvim/testdir/test.out'
-fnamemodify('../testdir/a', ':~' ) '~/src/nvim/testdir/a'
+fnamemodify('test.out', ':~' ) '~/nvim/testdir/test.out'
+fnamemodify('../testdir/a', ':~' ) '~/nvim/testdir/a'
fnamemodify('../testdir/a', ':t' ) 'a'
fnamemodify('.', ':p:t' ) ''
fnamemodify('test.out', ':p:t' ) 'test.out'
@@ -13,7 +13,7 @@ fnamemodify('test.out', ':p:t:e' ) 'out'
fnamemodify('abc.fb2.tar.gz', ':r' ) 'abc.fb2.tar'
fnamemodify('abc.fb2.tar.gz', ':r:r' ) 'abc.fb2'
fnamemodify('abc.fb2.tar.gz', ':r:r:r' ) 'abc'
-substitute(fnamemodify('abc.fb2.tar.gz', ':p:r:r'), '.*\(src/nvim/testdir/.*\)', '\1', '') 'src/nvim/testdir/abc.fb2'
+substitute(fnamemodify('abc.fb2.tar.gz', ':p:r:r'), '.*\(nvim/testdir/.*\)', '\1', '') 'nvim/testdir/abc.fb2'
fnamemodify('abc.fb2.tar.gz', ':e' ) 'gz'
fnamemodify('abc.fb2.tar.gz', ':e:e' ) 'tar.gz'
fnamemodify('abc.fb2.tar.gz', ':e:e:e' ) 'fb2.tar.gz'
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 8c7b5b38e9..d7a691aa83 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -1116,8 +1116,8 @@ void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash)
*/
FileInfo file_info_old;
FileInfo file_info_new;
- if (os_get_file_info((char *)buf->b_ffname, &file_info_old)
- && os_get_file_info((char *)file_name, &file_info_new)
+ if (os_fileinfo((char *)buf->b_ffname, &file_info_old)
+ && os_fileinfo((char *)file_name, &file_info_new)
&& file_info_old.stat.st_gid != file_info_new.stat.st_gid
&& os_fchown(fd, -1, file_info_old.stat.st_gid) != 0) {
os_setperm(file_name, (perm & 0707) | ((perm & 07) << 3));
@@ -1249,8 +1249,8 @@ void u_read_undo(char_u *name, char_u *hash, char_u *orig_name)
* owner of the text file or equal to the current user. */
FileInfo file_info_orig;
FileInfo file_info_undo;
- if (os_get_file_info((char *)orig_name, &file_info_orig)
- && os_get_file_info((char *)file_name, &file_info_undo)
+ if (os_fileinfo((char *)orig_name, &file_info_orig)
+ && os_fileinfo((char *)file_name, &file_info_undo)
&& file_info_orig.stat.st_uid != file_info_undo.stat.st_uid
&& file_info_undo.stat.st_uid != getuid()) {
if (p_verbose > 0) {
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 8132d5dfcc..75b4ac4b4d 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -375,7 +375,7 @@ static int included_patches[] = {
//223 NA
//222 NA
221,
- //220,
+ 220,
219,
218,
//217 NA