aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZyX <kp-pav@yandex.ru>2017-11-19 22:05:22 +0300
committerZyX <kp-pav@yandex.ru>2017-11-19 22:05:22 +0300
commit03a129aacf7e4b77ceaccc71251ecb5bf41d2a8f (patch)
treea3a05c99fe20de98aafbdea9314aa0d76f71aee9 /src
parent6ea3a08fdbb276fe64dda60c5fb934360327ed39 (diff)
parentde8b1fd1dee5a91b2893fccc53cfd11631ccba38 (diff)
downloadrneovim-03a129aacf7e4b77ceaccc71251ecb5bf41d2a8f.tar.gz
rneovim-03a129aacf7e4b77ceaccc71251ecb5bf41d2a8f.tar.bz2
rneovim-03a129aacf7e4b77ceaccc71251ecb5bf41d2a8f.zip
Merge branch 'master' into expression-parser
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/vim.c3
-rw-r--r--src/nvim/buffer.c7
-rw-r--r--src/nvim/eval.c16
-rw-r--r--src/nvim/event/libuv_process.c2
-rw-r--r--src/nvim/event/process.c7
-rw-r--r--src/nvim/ex_docmd.c21
-rw-r--r--src/nvim/ex_getln.c55
-rw-r--r--src/nvim/fileio.c63
-rw-r--r--src/nvim/globals.h27
-rw-r--r--src/nvim/main.c6
-rw-r--r--src/nvim/option_defs.h21
-rw-r--r--src/nvim/options.lua4
-rw-r--r--src/nvim/os/fs.c94
-rw-r--r--src/nvim/po/af.po7118
-rw-r--r--src/nvim/po/ca.po88
-rw-r--r--src/nvim/po/de.po18
-rw-r--r--src/nvim/po/eo.po323
-rw-r--r--src/nvim/po/es.po31
-rw-r--r--src/nvim/po/fi.po57
-rw-r--r--src/nvim/po/fr.po286
-rw-r--r--src/nvim/po/ga.po179
-rw-r--r--src/nvim/po/it.po52
-rw-r--r--src/nvim/po/ja.euc-jp.po147
-rw-r--r--src/nvim/po/ja.po147
-rw-r--r--src/nvim/po/ko.UTF-8.po63
-rw-r--r--src/nvim/po/pl.UTF-8.po2
-rw-r--r--src/nvim/po/pt_BR.po12
-rw-r--r--src/nvim/po/ru.po8
-rw-r--r--src/nvim/po/sk.cp1250.po1
-rw-r--r--src/nvim/po/sk.po1
-rw-r--r--src/nvim/po/uk.po44
-rw-r--r--src/nvim/screen.c4
-rw-r--r--src/nvim/state.c24
-rw-r--r--src/nvim/syntax.c4
-rw-r--r--src/nvim/testdir/test_cmdline.vim38
-rw-r--r--src/nvim/testdir/test_fileformat.vim16
-rw-r--r--src/nvim/testdir/test_functions.vim85
-rw-r--r--src/nvim/testdir/test_mapping.vim4
-rw-r--r--src/nvim/testdir/test_unlet.vim2
-rw-r--r--src/nvim/testdir/test_usercommands.vim104
-rw-r--r--src/nvim/tui/input.c2
-rw-r--r--src/nvim/tui/tui.c26
-rw-r--r--src/nvim/ui.c2
-rw-r--r--src/nvim/version.c16
-rw-r--r--src/nvim/vim.h170
-rw-r--r--src/nvim/window.c18
46 files changed, 4739 insertions, 4679 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index ce554d351c..c6771fbc03 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -91,7 +91,8 @@ Dictionary nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Error *err)
{
Dictionary dic = ARRAY_DICT_INIT;
if (syn_get_final_id((int)hl_id) == 0) {
- api_set_error(err, kErrorTypeException, "Invalid highlight id: %d", hl_id);
+ api_set_error(err, kErrorTypeException,
+ "Invalid highlight id: %" PRId64, hl_id);
return dic;
}
int attrcode = syn_id2attr((int)hl_id);
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index f874268910..766003a021 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -64,7 +64,6 @@
#include "nvim/spell.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
-#include "nvim/terminal.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/version.h"
@@ -1464,12 +1463,6 @@ void enter_buffer(buf_T *buf)
/* mark cursor position as being invalid */
curwin->w_valid = 0;
- if (buf->terminal) {
- terminal_resize(buf->terminal,
- (uint16_t)(MAX(0, curwin->w_width - win_col_off(curwin))),
- (uint16_t)curwin->w_height);
- }
-
/* Make sure the buffer is loaded. */
if (curbuf->b_ml.ml_mfp == NULL) { /* need to load the file */
/* If there is no filetype, allow for detecting one. Esp. useful for
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index c7cb51ac29..33bea8ef87 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -334,7 +334,7 @@ static struct vimvar {
// VV_SEND_SERVER "servername"
// VV_REG "register"
// VV_OP "operator"
- VV(VV_COUNT, "count", VAR_NUMBER, VV_COMPAT+VV_RO),
+ VV(VV_COUNT, "count", VAR_NUMBER, VV_RO),
VV(VV_COUNT1, "count1", VAR_NUMBER, VV_RO),
VV(VV_PREVCOUNT, "prevcount", VAR_NUMBER, VV_RO),
VV(VV_ERRMSG, "errmsg", VAR_STRING, VV_COMPAT),
@@ -10672,6 +10672,10 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr)
n = has_nvim_version(name + 5);
} else if (STRICMP(name, "vim_starting") == 0) {
n = (starting != 0);
+ } else if (STRICMP(name, "ttyin") == 0) {
+ n = stdin_isatty;
+ } else if (STRICMP(name, "ttyout") == 0) {
+ n = stdout_isatty;
} else if (STRICMP(name, "multi_byte_encoding") == 0) {
n = has_mbyte != 0;
#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
@@ -22879,11 +22883,15 @@ void ex_checkhealth(exarg_T *eap)
const char *vimruntime_env = os_getenv("VIMRUNTIME");
if (vimruntime_env == NULL) {
EMSG(_("E5009: $VIMRUNTIME is empty or unset"));
- return;
} else {
- EMSG2(_("E5009: Invalid $VIMRUNTIME: %s"), os_getenv("VIMRUNTIME"));
- return;
+ bool rtp_ok = NULL != strstr((char *)p_rtp, vimruntime_env);
+ if (rtp_ok) {
+ EMSG2(_("E5009: Invalid $VIMRUNTIME: %s"), vimruntime_env);
+ } else {
+ EMSG(_("E5009: Invalid 'runtimepath'"));
+ }
}
+ return;
}
size_t bufsize = STRLEN(eap->arg) + sizeof("call health#check('')");
diff --git a/src/nvim/event/libuv_process.c b/src/nvim/event/libuv_process.c
index f6a567a520..758b35796e 100644
--- a/src/nvim/event/libuv_process.c
+++ b/src/nvim/event/libuv_process.c
@@ -38,7 +38,7 @@ int libuv_process_spawn(LibuvProcess *uvproc)
#endif
uvproc->uvopts.exit_cb = exit_cb;
uvproc->uvopts.cwd = proc->cwd;
- uvproc->uvopts.env = NULL;
+ uvproc->uvopts.env = NULL; // Inherits the parent (nvim) env.
uvproc->uvopts.stdio = uvproc->uvstdio;
uvproc->uvopts.stdio_count = 3;
uvproc->uvstdio[0].flags = UV_IGNORE;
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c
index 8371d3cd48..41e793500a 100644
--- a/src/nvim/event/process.c
+++ b/src/nvim/event/process.c
@@ -324,6 +324,13 @@ static void process_close(Process *proc)
}
assert(!proc->closed);
proc->closed = true;
+
+ if (proc->detach) {
+ if (proc->type == kProcessTypeUv) {
+ uv_unref((uv_handle_t *)&(((LibuvProcess *)proc)->uv));
+ }
+ }
+
switch (proc->type) {
case kProcessTypeUv:
libuv_process_close((LibuvProcess *)proc);
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 3bcea4b666..3202f8a848 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -3272,6 +3272,12 @@ const char * set_one_cmd_context(
case CMD_echoerr:
case CMD_call:
case CMD_return:
+ case CMD_cexpr:
+ case CMD_caddexpr:
+ case CMD_cgetexpr:
+ case CMD_lexpr:
+ case CMD_laddexpr:
+ case CMD_lgetexpr:
set_context_for_expression(xp, (char_u *)arg, ea.cmdidx);
break;
@@ -9351,15 +9357,18 @@ put_view (
}
}
- /*
- * Local directory.
- */
- if (wp->w_localdir != NULL) {
+ //
+ // Local directory, if the current flag is not view options or the "curdir"
+ // option is included.
+ //
+ if (wp->w_localdir != NULL
+ && (flagp != &vop_flags || (*flagp & SSOP_CURDIR))) {
if (fputs("lcd ", fd) < 0
|| ses_put_fname(fd, wp->w_localdir, flagp) == FAIL
- || put_eol(fd) == FAIL)
+ || put_eol(fd) == FAIL) {
return FAIL;
- did_lcd = TRUE;
+ }
+ did_lcd = true;
}
return OK;
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index cabdda28cf..53f6ca0d2b 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -93,6 +93,13 @@ typedef struct {
CmdlineColors colors; ///< Last colors.
} ColoredCmdline;
+/// Keeps track how much state must be sent to external ui.
+typedef enum {
+ kCmdRedrawNone,
+ kCmdRedrawPos,
+ kCmdRedrawAll,
+} CmdRedraw;
+
/*
* Variables shared between getcmdline(), redrawcmdline() and others.
* These need to be saved when using CTRL-R |, that's why they are in a
@@ -122,6 +129,7 @@ struct cmdline_info {
struct cmdline_info *prev_ccline; ///< pointer to saved cmdline state
char special_char; ///< last putcmdline char (used for redraws)
bool special_shift; ///< shift of last putcmdline char
+ CmdRedraw redraw_state; ///< needed redraw for external cmdline
};
/// Last value of prompt_id, incremented when doing new prompt
static unsigned last_prompt_id = 0;
@@ -425,6 +433,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
ccline.cmdbuff = NULL;
if (ui_is_external(kUICmdline)) {
+ ccline.redraw_state = kCmdRedrawNone;
ui_call_cmdline_hide(ccline.level);
}
ccline.level--;
@@ -1818,7 +1827,8 @@ static int command_line_changed(CommandLineState *s)
// right-left typing. Not efficient, but it works.
// Do it only when there are no characters left to read
// to avoid useless intermediate redraws.
- if (vpeekc() == NUL) {
+ // if cmdline is external the ui handles shaping, no redraw needed.
+ if (!ui_is_external(kUICmdline) && vpeekc() == NUL) {
redrawcmd();
}
}
@@ -2667,7 +2677,7 @@ static void draw_cmdline(int start, int len)
if (ui_is_external(kUICmdline)) {
ccline.special_char = NUL;
- ui_ext_cmdline_show(&ccline);
+ ccline.redraw_state = kCmdRedrawAll;
return;
}
@@ -2879,7 +2889,7 @@ void cmdline_screen_cleared(void)
if (prev_ccline->level == prev_level) {
// don't redraw a cmdline already shown in the cmdline window
if (prev_level != cmdwin_level) {
- ui_ext_cmdline_show(prev_ccline);
+ prev_ccline->redraw_state = kCmdRedrawAll;
}
prev_level--;
}
@@ -2887,6 +2897,28 @@ void cmdline_screen_cleared(void)
}
}
+/// called by ui_flush, do what redraws neccessary to keep cmdline updated.
+void cmdline_ui_flush(void)
+{
+ if (!ui_is_external(kUICmdline)) {
+ return;
+ }
+ int level = ccline.level;
+ CmdlineInfo *line = &ccline;
+ while (level > 0 && line) {
+ if (line->level == level) {
+ if (line->redraw_state == kCmdRedrawAll) {
+ ui_ext_cmdline_show(line);
+ } else if (line->redraw_state == kCmdRedrawPos) {
+ ui_call_cmdline_pos(line->cmdpos, line->level);
+ }
+ line->redraw_state = kCmdRedrawNone;
+ level--;
+ }
+ line = line->prev_ccline;
+ }
+}
+
/*
* Put a character on the command line. Shifts the following text to the
* right when "shift" is TRUE. Used for CTRL-V, CTRL-K, etc.
@@ -2907,8 +2939,10 @@ void putcmdline(int c, int shift)
} else {
ccline.special_char = c;
ccline.special_shift = shift;
- ui_call_cmdline_special_char(cchar_to_string((char)(c)), shift,
- ccline.level);
+ if (ccline.redraw_state != kCmdRedrawAll) {
+ ui_call_cmdline_special_char(cchar_to_string((char)(c)), shift,
+ ccline.level);
+ }
}
cursorcmd();
ui_cursor_shape();
@@ -3249,7 +3283,7 @@ static void redrawcmdprompt(void)
if (cmd_silent)
return;
if (ui_is_external(kUICmdline)) {
- ui_ext_cmdline_show(&ccline);
+ ccline.redraw_state = kCmdRedrawAll;
return;
}
if (ccline.cmdfirstc != NUL) {
@@ -3326,7 +3360,9 @@ static void cursorcmd(void)
return;
if (ui_is_external(kUICmdline)) {
- ui_call_cmdline_pos(ccline.cmdpos, ccline.level);
+ if (ccline.redraw_state < kCmdRedrawPos) {
+ ccline.redraw_state = kCmdRedrawPos;
+ }
return;
}
@@ -4164,7 +4200,9 @@ addstar (
|| context == EXPAND_OWNSYNTAX
|| context == EXPAND_FILETYPE
|| context == EXPAND_PACKADD
- || (context == EXPAND_TAGS && fname[0] == '/'))
+ || ((context == EXPAND_TAGS_LISTFILES
+ || context == EXPAND_TAGS)
+ && fname[0] == '/'))
retval = vim_strnsave(fname, len);
else {
new_len = len + 2; /* +2 for '^' at start, NUL at end */
@@ -5920,6 +5958,7 @@ static int ex_window(void)
changed_line_abv_curs();
invalidate_botline();
if (ui_is_external(kUICmdline)) {
+ ccline.redraw_state = kCmdRedrawNone;
ui_call_cmdline_hide(ccline.level);
}
redraw_later(SOME_VALID);
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index feb16f44d4..ae6c3f96e3 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -302,12 +302,9 @@ readfile (
linenr_T skip_count = 0;
linenr_T read_count = 0;
int msg_save = msg_scroll;
- linenr_T read_no_eol_lnum = 0; /* non-zero lnum when last line of
- * last read was missing the eol */
- int try_mac = (vim_strchr(p_ffs, 'm') != NULL);
- int try_dos = (vim_strchr(p_ffs, 'd') != NULL);
- int try_unix = (vim_strchr(p_ffs, 'x') != NULL);
- int file_rewind = FALSE;
+ linenr_T read_no_eol_lnum = 0; // non-zero lnum when last line of
+ // last read was missing the eol
+ int file_rewind = false;
int can_retry;
linenr_T conv_error = 0; /* line nr with conversion error */
linenr_T illegal_byte = 0; /* line nr with illegal byte */
@@ -639,37 +636,46 @@ readfile (
curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
curbuf->b_op_start.col = 0;
+ int try_mac = (vim_strchr(p_ffs, 'm') != NULL);
+ int try_dos = (vim_strchr(p_ffs, 'd') != NULL);
+ int try_unix = (vim_strchr(p_ffs, 'x') != NULL);
+
if (!read_buffer) {
int m = msg_scroll;
int n = msg_scrolled;
- /*
- * The file must be closed again, the autocommands may want to change
- * the file before reading it.
- */
- if (!read_stdin)
- close(fd); /* ignore errors */
+ // The file must be closed again, the autocommands may want to change
+ // the file before reading it.
+ if (!read_stdin) {
+ close(fd); // ignore errors
+ }
- /*
- * The output from the autocommands should not overwrite anything and
- * should not be overwritten: Set msg_scroll, restore its value if no
- * output was done.
- */
- msg_scroll = TRUE;
- if (filtering)
+ // The output from the autocommands should not overwrite anything and
+ // should not be overwritten: Set msg_scroll, restore its value if no
+ // output was done.
+ msg_scroll = true;
+ if (filtering) {
apply_autocmds_exarg(EVENT_FILTERREADPRE, NULL, sfname,
- FALSE, curbuf, eap);
- else if (read_stdin)
+ false, curbuf, eap);
+ } else if (read_stdin) {
apply_autocmds_exarg(EVENT_STDINREADPRE, NULL, sfname,
- FALSE, curbuf, eap);
- else if (newfile)
+ false, curbuf, eap);
+ } else if (newfile) {
apply_autocmds_exarg(EVENT_BUFREADPRE, NULL, sfname,
- FALSE, curbuf, eap);
- else
+ false, curbuf, eap);
+ } else {
apply_autocmds_exarg(EVENT_FILEREADPRE, sfname, sfname,
- FALSE, NULL, eap);
- if (msg_scrolled == n)
+ false, NULL, eap);
+ }
+
+ // autocommands may have changed it
+ try_mac = (vim_strchr(p_ffs, 'm') != NULL);
+ try_dos = (vim_strchr(p_ffs, 'd') != NULL);
+ try_unix = (vim_strchr(p_ffs, 'x') != NULL);
+
+ if (msg_scrolled == n) {
msg_scroll = m;
+ }
if (aborting()) { /* autocmds may abort script processing */
--no_wait_return;
@@ -1616,7 +1622,8 @@ rewind_retry:
*ptr = NUL; /* end of line */
len = (colnr_T)(ptr - line_start + 1);
if (fileformat == EOL_DOS) {
- if (ptr[-1] == CAR) { /* remove CR */
+ if (ptr > line_start && ptr[-1] == CAR) {
+ // remove CR before NL
ptr[-1] = NUL;
len--;
} else if (ff_error != EOL_DOS) {
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 2a041177d4..8874f0bb75 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -564,21 +564,22 @@ EXTERN int ru_col; /* column for ruler */
EXTERN int ru_wid; /* 'rulerfmt' width of ruler when non-zero */
EXTERN int sc_col; /* column for shown command */
-/*
- * When starting or exiting some things are done differently (e.g. screen
- * updating).
- */
+//
+// When starting or exiting some things are done differently (e.g. screen
+// updating).
+//
+
+// First NO_SCREEN, then NO_BUFFERS, then 0 when startup finished.
EXTERN int starting INIT(= NO_SCREEN);
-/* first NO_SCREEN, then NO_BUFFERS and then
- * set to 0 when starting up finished */
-EXTERN int exiting INIT(= FALSE);
-/* TRUE when planning to exit Vim. Might
- * still keep on running if there is a changed
- * buffer. */
-// volatile because it is used in signal handler deathtrap().
+// true when planning to exit. Might keep running if there is a changed buffer.
+EXTERN int exiting INIT(= false);
+// is stdin a terminal?
+EXTERN int stdin_isatty INIT(= true);
+// is stdout a terminal?
+EXTERN int stdout_isatty INIT(= true);
+// true when doing full-screen output, otherwise only writing some messages.
+// volatile because it is used in a signal handler.
EXTERN volatile int full_screen INIT(= false);
-// TRUE when doing full-screen output
-// otherwise only writing some messages
EXTERN int restricted INIT(= FALSE);
// TRUE when started in restricted mode (-Z)
diff --git a/src/nvim/main.c b/src/nvim/main.c
index ea7a58bda3..93afe11f3a 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -1240,8 +1240,10 @@ static void init_startuptime(mparm_T *paramp)
static void check_and_set_isatty(mparm_T *paramp)
{
- paramp->input_isatty = os_isatty(fileno(stdin));
- paramp->output_isatty = os_isatty(fileno(stdout));
+ stdin_isatty
+ = paramp->input_isatty = os_isatty(fileno(stdin));
+ stdout_isatty
+ = paramp->output_isatty = os_isatty(fileno(stdout));
paramp->err_isatty = os_isatty(fileno(stderr));
TIME_MSG("window checked");
}
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index a2fe90b3c2..1f62490ab9 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -539,7 +539,7 @@ static char *(p_ssop_values[]) = {"buffers", "winpos", "resize", "winsize",
"localoptions", "options", "help", "blank",
"globals", "slash", "unix",
"sesdir", "curdir", "folds", "cursor",
- "tabpages", NULL};
+ "tabpages", NULL };
# endif
# define SSOP_BUFFERS 0x001
# define SSOP_WINPOS 0x002
@@ -557,16 +557,17 @@ static char *(p_ssop_values[]) = {"buffers", "winpos", "resize", "winsize",
# define SSOP_FOLDS 0x2000
# define SSOP_CURSOR 0x4000
# define SSOP_TABPAGES 0x8000
-EXTERN char_u *p_sh; /* 'shell' */
-EXTERN char_u *p_shcf; /* 'shellcmdflag' */
-EXTERN char_u *p_sp; /* 'shellpipe' */
-EXTERN char_u *p_shq; /* 'shellquote' */
-EXTERN char_u *p_sxq; /* 'shellxquote' */
-EXTERN char_u *p_sxe; /* 'shellxescape' */
-EXTERN char_u *p_srr; /* 'shellredir' */
-EXTERN int p_stmp; /* 'shelltemp' */
+
+EXTERN char_u *p_sh; // 'shell'
+EXTERN char_u *p_shcf; // 'shellcmdflag'
+EXTERN char_u *p_sp; // 'shellpipe'
+EXTERN char_u *p_shq; // 'shellquote'
+EXTERN char_u *p_sxq; // 'shellxquote'
+EXTERN char_u *p_sxe; // 'shellxescape'
+EXTERN char_u *p_srr; // 'shellredir'
+EXTERN int p_stmp; // 'shelltemp'
#ifdef BACKSLASH_IN_FILENAME
-EXTERN int p_ssl; /* 'shellslash' */
+EXTERN int p_ssl; // 'shellslash'
#endif
EXTERN char_u *p_stl; // 'statusline'
EXTERN int p_sr; // 'shiftround'
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 7cecb16686..52e478e78a 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -1924,7 +1924,7 @@ return {
vi_def=true,
varname='p_scbk',
redraw={'current_buffer'},
- defaults={if_true={vi=1000}}
+ defaults={if_true={vi=10000}}
},
{
full_name='scrollbind', abbreviation='scb',
@@ -2610,7 +2610,7 @@ return {
deny_duplicates=true,
vi_def=true,
varname='p_vop',
- defaults={if_true={vi="folds,options,cursor"}}
+ defaults={if_true={vi="folds,options,cursor,curdir"}}
},
{
full_name='viminfo', abbreviation='vi',
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index 78627f8703..aa28b95c30 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -133,22 +133,12 @@ bool os_isdir(const char_u *name)
int os_nodetype(const char *name)
FUNC_ATTR_NONNULL_ALL
{
-#ifdef WIN32
- // Edge case from Vim os_win32.c:
- // We can't open a file with a name "\\.\con" or "\\.\prn", trying to read
- // from it later will cause Vim to hang. Thus return NODE_WRITABLE here.
- if (STRNCMP(name, "\\\\.\\", 4) == 0) {
- return NODE_WRITABLE;
- }
-#endif
-
+#ifndef WIN32 // Unix
uv_stat_t statbuf;
if (0 != os_stat(name, &statbuf)) {
return NODE_NORMAL; // File doesn't exist.
}
-
-#ifndef WIN32
- // libuv does not handle BLK and DIR in uv_handle_type.
+ // uv_handle_type does not distinguish BLK and DIR.
// Related: https://github.com/joyent/libuv/pull/1421
if (S_ISREG(statbuf.st_mode) || S_ISDIR(statbuf.st_mode)) {
return NODE_NORMAL;
@@ -156,48 +146,51 @@ int os_nodetype(const char *name)
if (S_ISBLK(statbuf.st_mode)) { // block device isn't writable
return NODE_OTHER;
}
-#endif
+ // Everything else is writable?
+ // buf_write() expects NODE_WRITABLE for char device /dev/stderr.
+ return NODE_WRITABLE;
+#else // Windows
+ // Edge case from Vim os_win32.c:
+ // We can't open a file with a name "\\.\con" or "\\.\prn", trying to read
+ // from it later will cause Vim to hang. Thus return NODE_WRITABLE here.
+ if (STRNCMP(name, "\\\\.\\", 4) == 0) {
+ return NODE_WRITABLE;
+ }
- // Vim os_win32.c:mch_nodetype does this (since patch 7.4.015):
- // if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) {
- // wn = enc_to_utf16(name, NULL);
- // hFile = CreatFile(wn, ...)
- // to get a HANDLE. But libuv just calls win32's _get_osfhandle() on the fd we
- // give it. uv_fs_open calls fs__capture_path which does a similar dance and
- // saves us the hassle.
+ // Vim os_win32.c:mch_nodetype does (since 7.4.015):
+ // wn = enc_to_utf16(name, NULL);
+ // hFile = CreatFile(wn, ...)
+ // to get a HANDLE. Whereas libuv just calls _get_osfhandle() on the fd we
+ // give it. But uv_fs_open later calls fs__capture_path which does a similar
+ // utf8-to-utf16 dance and saves us the hassle.
- int nodetype = NODE_WRITABLE;
+ // macOS: os_open(/dev/stderr) would return UV_EACCES.
int fd = os_open(name, O_RDONLY
-#ifdef O_NONBLOCK
+# ifdef O_NONBLOCK
| O_NONBLOCK
-#endif
+# endif
, 0);
- if (fd == -1) {
- return NODE_OTHER; // open() failed.
+ if (fd < 0) { // open() failed.
+ return NODE_NORMAL;
+ }
+ int guess = uv_guess_handle(fd);
+ if (close(fd) == -1) {
+ ELOG("close(%d) failed. name='%s'", fd, name);
}
- switch (uv_guess_handle(fd)) {
- case UV_TTY: // FILE_TYPE_CHAR
- nodetype = NODE_WRITABLE;
- break;
- case UV_FILE: // FILE_TYPE_DISK
- nodetype = NODE_NORMAL;
- break;
- case UV_NAMED_PIPE: // not handled explicitly in Vim os_win32.c
- case UV_UDP: // unix only
- case UV_TCP: // unix only
+ switch (guess) {
+ case UV_TTY: // FILE_TYPE_CHAR
+ return NODE_WRITABLE;
+ case UV_FILE: // FILE_TYPE_DISK
+ return NODE_NORMAL;
+ case UV_NAMED_PIPE: // not handled explicitly in Vim os_win32.c
+ case UV_UDP: // unix only
+ case UV_TCP: // unix only
case UV_UNKNOWN_HANDLE:
default:
-#ifdef WIN32
- nodetype = NODE_NORMAL;
-#else
- nodetype = NODE_WRITABLE; // Everything else is writable?
-#endif
- break;
+ return NODE_OTHER; // Vim os_win32.c default
}
-
- close(fd);
- return nodetype;
+#endif
}
/// Gets the absolute path of the currently running executable.
@@ -394,9 +387,11 @@ end:
/// @param mode Permissions for the newly-created file (IGNORED if 'flags' is
/// not `O_CREAT` or `O_TMPFILE`), subject to the current umask
/// @return file descriptor, or libuv error code on failure
-int os_open(const char* path, int flags, int mode)
- FUNC_ATTR_NONNULL_ALL
+int os_open(const char *path, int flags, int mode)
{
+ if (path == NULL) { // uv_fs_open asserts on NULL. #7561
+ return UV_EINVAL;
+ }
int r;
RUN_UV_FS_FUNC(r, uv_fs_open, path, flags, mode, NULL);
return r;
@@ -603,12 +598,12 @@ int os_fsync(int fd)
/// Get stat information for a file.
///
-/// @return libuv return code.
+/// @return libuv return code, or -errno
static int os_stat(const char *name, uv_stat_t *statbuf)
FUNC_ATTR_NONNULL_ARG(2)
{