refactor(ui): simplify stdin handling

This commit is contained in:
bfredl
2022-04-22 20:56:31 +02:00
parent 619c8f4b91
commit ad63b94b03
9 changed files with 106 additions and 53 deletions

View File

@@ -283,6 +283,22 @@ static void ui_set_option(UI *ui, bool init, String name, Object value, Error *e
return;
}
if (strequal(name.data, "stdin_fd")) {
if (value.type != kObjectTypeInteger || value.data.integer < 0) {
api_set_error(error, kErrorTypeValidation, "stdin_fd must be a non-negative Integer");
return;
}
if (starting != NO_SCREEN) {
api_set_error(error, kErrorTypeValidation,
"stdin_fd can only be used with first attached ui");
return;
}
stdin_fd = (int)value.data.integer;
return;
}
// LEGACY: Deprecated option, use `ext_cmdline` instead.
bool is_popupmenu = strequal(name.data, "popupmenu_external");

View File

@@ -2661,35 +2661,3 @@ end:
xfree(cmdline);
return result;
}
/// Invokes the nvim server to read from stdin when it is not a tty
///
/// It enables functionalities like:
/// - echo "1f u c4n r34d th1s u r34lly n33d t0 g37 r357"| nvim -
/// - cat path/to/a/file | nvim -
/// It has to be called before |nvim_ui_attach()| is called in order
/// to ensure proper functioning.
///
/// @param channel_id: The channel id of the GUI-client
/// @param filedesc: The file descriptor of the GUI-client process' stdin
/// @param implicit: Tells if read_stdin call is implicit.
/// i.e for cases like `echo xxx | nvim`
/// @param[out] err Error details, if any
void nvim_read_stdin(uint64_t channel_id, Integer filedesc, Error *err)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY
{
if (starting != NO_SCREEN) {
api_set_error(err, kErrorTypeValidation,
"nvim_read_stdin must be called before nvim_ui_attach");
return;
}
if (filedesc < 0) {
api_set_error(err, kErrorTypeValidation,
"file descriptor must be non-negative");
return;
}
stdin_filedesc = (int)filedesc;
implicit_readstdin = implicit;
return;
}

View File

@@ -176,7 +176,7 @@ void filemess(buf_T *buf, char_u *name, char_u *s, int attr)
int readfile(char_u *fname, char_u *sfname, linenr_T from, linenr_T lines_to_skip,
linenr_T lines_to_read, exarg_T *eap, int flags, bool silent)
{
int fd = 0;
int fd = stdin_fd >= 0 ? stdin_fd : 0;
int newfile = (flags & READ_NEW);
int check_readonly;
int filtering = (flags & READ_FILTER);
@@ -1722,17 +1722,19 @@ failed:
xfree(buffer);
if (read_stdin) {
close(0);
close(fd);
if (stdin_fd < 0) {
#ifndef WIN32
// On Unix, use stderr for stdin, makes shell commands work.
vim_ignored = dup(2);
// On Unix, use stderr for stdin, makes shell commands work.
vim_ignored = dup(2);
#else
// On Windows, use the console input handle for stdin.
HANDLE conin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING, 0, (HANDLE)NULL);
vim_ignored = _open_osfhandle(conin, _O_RDONLY);
// On Windows, use the console input handle for stdin.
HANDLE conin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING, 0, (HANDLE)NULL);
vim_ignored = _open_osfhandle(conin, _O_RDONLY);
#endif
}
}
if (tmpname != NULL) {

View File

@@ -507,6 +507,9 @@ EXTERN int v_dying INIT(= 0);
EXTERN int stdin_isatty INIT(= true);
// is stdout a terminal?
EXTERN int stdout_isatty INIT(= true);
/// filedesc set by embedder for reading first buffer like `cmd | nvim -`
EXTERN int stdin_fd INIT(= -1);
// 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);
@@ -704,7 +707,6 @@ EXTERN int RedrawingDisabled INIT(= 0);
EXTERN int readonlymode INIT(= false); // Set to true for "view"
EXTERN int recoverymode INIT(= false); // Set to true for "-r" option
EXTERN int stdin_filedesc INIT(= -1); // stdin filedesc set by embedder
// typeahead buffer
EXTERN typebuf_T typebuf INIT(= { NULL, NULL, 0, 0, 0, 0, 0, 0, 0 });
@@ -848,10 +850,6 @@ EXTERN linenr_T printer_page_num;
EXTERN bool typebuf_was_filled INIT(= false); // received text from client
// or from feedkeys()
EXTERN bool implicit_readstdin INIT(= false); // Used in embed job created
// by TUI process only in
// builtin tui
#ifdef BACKSLASH_IN_FILENAME
EXTERN char psepc INIT(= '\\'); // normal path separator character
EXTERN char psepcN INIT(= '/'); // abnormal path separator character

View File

@@ -454,7 +454,7 @@ int main(int argc, char **argv)
// writing end of the pipe doesn't like, e.g., in case stdin and stderr
// are the same terminal: "cat | vim -".
// Using autocommands here may cause trouble...
if ((params.edit_type == EDIT_STDIN || implicit_readstdin) && !recoverymode) {
if ((params.edit_type == EDIT_STDIN || stdin_fd >= 0) && !recoverymode) {
read_stdin();
}