aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2018-06-10 15:10:59 +0200
committerGitHub <noreply@github.com>2018-06-10 15:10:59 +0200
commitb8363283faac5e02cd9961119da7accb3d35d420 (patch)
tree7c7007656dd04dcc8b950c5fb00d98c2c060b39f
parent23d172a948e77c4e1d03db3b06efac6e9edd3695 (diff)
parentd8c7ff13352d7182826b5716ff3b6a66df241231 (diff)
downloadrneovim-b8363283faac5e02cd9961119da7accb3d35d420.tar.gz
rneovim-b8363283faac5e02cd9961119da7accb3d35d420.tar.bz2
rneovim-b8363283faac5e02cd9961119da7accb3d35d420.zip
Merge #7679 'startup: treat stdin as text instead of commands'
-rw-r--r--man/nvim.195
-rw-r--r--runtime/doc/starting.txt11
-rw-r--r--runtime/doc/vim_diff.txt4
-rw-r--r--src/nvim/event/rstream.c2
-rw-r--r--src/nvim/globals.h235
-rw-r--r--src/nvim/main.c639
-rw-r--r--src/nvim/message.c5
-rw-r--r--src/nvim/os/input.c20
-rw-r--r--test/functional/core/startup_spec.lua94
-rw-r--r--test/functional/helpers.lua8
10 files changed, 549 insertions, 564 deletions
diff --git a/man/nvim.1 b/man/nvim.1
index 12f342247e..75c037946a 100644
--- a/man/nvim.1
+++ b/man/nvim.1
@@ -1,4 +1,4 @@
-.Dd January 28, 2016
+.Dd December 17, 2017
.Dt NVIM 1
.Os
.Sh NAME
@@ -25,7 +25,7 @@ To enter commands in
type a colon
.Pq Sq \&:
which is also used in this manual to denote commands.
-For more information, consult the online help system with the
+For more information, consult the online help with the
.Ic :help
command.
.Bl -tag -width Fl
@@ -73,24 +73,18 @@ See
Interpret all further arguments as files.
Can be used to edit files starting with a hyphen
.Pq Sq - .
-.It Fl -literal
-Interpret filenames literally, that is, do not expand wildcards.
-Has no effect on Unix-like systems, where the shell expands wildcards.
.It Fl e
-Ex mode.
+Ex mode. Reads stdin as Ex commands.
See
.Ic :help Ex-mode .
.It Fl E
-Improved Ex mode.
+Ex mode, improved. Reads stdin as text.
See
.Ic :help gQ .
-.It Fl s
-Silent mode.
-Only takes effect if
-.Fl e
-or
-.Fl E
-is specified before it.
+.It Fl es
+Silent (batch) mode. Reads stdin as Ex commands.
+.It Fl Es
+Silent (batch) mode. Reads stdin as text.
.It Fl d
Diff mode.
Show the difference between two to four files, similar to
@@ -99,12 +93,12 @@ See
.Ic :help diff .
.It Fl R
Read-only mode.
-Sets the option 'readonly'.
+Sets the 'readonly' option.
Implies
.Fl n .
Buffers can still be edited, but cannot be written to disk if already
associated with a file.
-To overwrite a file, add an exclamation mark to the needed Ex command, such as
+To overwrite a file, add an exclamation mark to the relevant Ex command, such as
.Ic :w! .
See
.Ic :help 'readonly' .
@@ -112,37 +106,31 @@ See
Restricted mode.
Disable commands that make use of an external shell.
.It Fl m
-Disable file modifications.
-Unsets the option 'write'.
+Resets the 'write' option, to disable file modifications.
Writing to a file is disabled, but buffers can still be modified.
.It Fl M
-Disable file and buffer modifications.
-Unsets the options 'write' and 'modifiable'.
-Note that these options can be set to re-enable making modifications.
+Resets the 'write' and 'modifiable' options, to disable file and buffer
+modifications.
.It Fl b
Binary mode.
See
.Ic :help edit-binary .
.It Fl l
Lisp mode.
-Sets the options 'lisp' and 'showmatch'.
+Sets the 'lisp' and 'showmatch' options.
.It Fl A
Arabic mode.
-Sets the option 'arabic'.
-.It Fl F
-Farsi mode.
-Sets the options 'fkmap' and 'rightleft'.
+Sets the 'arabic' option.
.It Fl H
Hebrew mode.
-Sets the options 'hkmap' and 'rightleft'.
+Sets the 'hkmap' and 'rightleft' options.
.It Fl V Ns Oo Ar N Oc Ns Op Ar file
Verbose mode.
Print messages about which files are being sourced and for reading and
writing a ShaDa file.
.Ar N
-is the value for the 'verbose' option; defaults to
-.Cm 10
-if omitted.
+is the 'verbose' level; defaults to
+.Cm 10.
If
.Ar file
is specified, append messages to
@@ -153,9 +141,9 @@ Debugging mode.
Started when executing the first command from a script.
.It Fl n
Disable the use of swap files.
-Sets the option 'updatecount' to
+Sets the 'updatecount' option to
.Cm 0 .
-Can be useful for editing file(s) on a slow medium.
+Can be useful for editing files on a slow medium.
.It Fl r Op Ar file
Recovery mode.
If
@@ -176,13 +164,13 @@ Alias for
.It Fl u Ar vimrc
Use
.Ar vimrc
-instead of the default of
+instead of the default
.Pa ~/.config/nvim/init.vim .
If
.Ar vimrc
is
.Cm NORC ,
-do not load any initialization files (excluding plugins),
+do not load any initialization files (except plugins),
and do not attempt to parse environment variables.
If
.Ar vimrc
@@ -194,7 +182,7 @@ See
.It Fl i Ar shada
Use
.Ar shada
-instead of the default of
+instead of the default
.Pa ~/.local/share/nvim/shada/main.shada .
If
.Ar shada
@@ -233,7 +221,6 @@ For the first file, position the cursor on line
If
.Ar linenum
is omitted, position the cursor on the last line of the file.
-Note that
.Cm +5
and
.Cm -c 5
@@ -246,8 +233,7 @@ For the first file, position the cursor on the first occurrence of
.Ar pattern .
If
.Ar pattern
-is omitted, the most recently used search pattern is used (if there is one).
-Note that
+is omitted, the most recent search pattern is used (if any).
.Cm +/foo
and
.Cm -c /foo
@@ -268,10 +254,9 @@ Up to 10 instances of
or
.Cm +
can be used.
-Note that
-.Qq Cm +set si
+.Qq Cm +foo
and
-.Cm -c \(dqset si\(dq
+.Cm -c \(dqfoo\(dq
are equivalent.
.It Fl -cmd Ar command
Like
@@ -292,9 +277,9 @@ cannot start with a hyphen
.Pq Sq - .
If
.Ar session
-is omitted, then
-.Pa Session.vim ,
-if found, is used.
+is omitted then
+.Pa Session.vim
+is used, if found.
See
.Ic :help session-file .
.It Fl s Ar scriptin
@@ -339,24 +324,24 @@ Print version information and exit.
.Sh ENVIRONMENT
.Bl -tag -width Fl
.It Ev VIM
-Used to locate various user files, such as init.vim.
+Used to locate user files, such as init.vim.
+System-dependent, see :help $VIM.
.It Ev VIMRUNTIME
-Used to locate runtime files, such as online documentation and
-syntax highlighting definitions.
+Used to locate runtime files (documentation, syntax highlighting, etc.).
.It Ev XDG_CONFIG_HOME
Path to the user-local configuration directory, see
.Sx FILES .
Defaults to
-.Pa ~/.config
-if not set.
+.Pa ~/.config .
+See :help xdg.
.It Ev XDG_DATA_HOME
Like
.Ev XDG_CONFIG_HOME ,
but used to store data not generally edited by the user,
namely swap, backup, and ShaDa files.
Defaults to
-.Pa ~/.local/share
-if not set.
+.Pa ~/.local/share .
+See :help xdg.
.It Ev VIMINIT
Ex commands to be executed at startup.
For example, the command to quit is
@@ -370,9 +355,11 @@ to
See
.Ic :help VIMINIT .
.It Ev SHELL
-Used to set the 'shell' option, which determines the shell used by the
-.Ic :terminal
-command.
+Used to initialize the 'shell' option, which decides the default shell used by
+features like
+.Ic :terminal ,
+.Ic :! , and
+.Ic system() .
.El
.Sh FILES
.Bl -tag -width "~/.config/nvim/init.vim"
diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt
index db3eb757c0..5ff9e0b5dc 100644
--- a/runtime/doc/starting.txt
+++ b/runtime/doc/starting.txt
@@ -22,8 +22,7 @@ More generally, Vim is started with:
Option arguments and file name arguments can be mixed, and any number of them
can be given. However, watch out for options that take an argument.
-Exactly one out of the following five items may be used to choose how to
-start editing:
+The following items may be used to choose how to start editing:
*-file* *---*
filename One or more file names. The first one will be the current
@@ -34,7 +33,6 @@ filename One or more file names. The first one will be the current
nvim -- -filename
< All arguments after the "--" will be interpreted as file names,
no other options or "+command" argument can follow.
- For behavior of quotes on MS-Windows, see |win32-quotes|.
*--*
- This argument can mean two things, depending on whether Ex
@@ -104,13 +102,6 @@ argument.
(Only available when compiled with the |+startuptime|
feature).
- *--literal*
---literal Take file names literally, don't expand wildcards. Not needed
- for Unix, because Vim always takes file names literally (the
- shell expands wildcards).
- Applies to all the names, also the ones that come before this
- argument.
-
*-+*
+[num] The cursor will be positioned on line "num" for the first
file being edited. If "num" is missing, the cursor will be
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index 04d78da45a..ceae8eba8c 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -440,6 +440,10 @@ Other compile-time features:
Emacs tags support
X11 integration (see |x11-selection|)
+Startup:
+ --literal (file args are always literal; to expand wildcards on Windows, use
+ |:n| e.g. `nvim +"n *"`)
+
Nvim does not have a built-in GUI and hence the following aliases have been
removed: gvim, gex, gview, rgvim, rgview
diff --git a/src/nvim/event/rstream.c b/src/nvim/event/rstream.c
index 2fbe7f6773..6812b342bf 100644
--- a/src/nvim/event/rstream.c
+++ b/src/nvim/event/rstream.c
@@ -115,7 +115,7 @@ static void read_cb(uv_stream_t *uvstream, ssize_t cnt, const uv_buf_t *buf)
if (cnt == UV_ENOBUFS || cnt == 0) {
return;
} else if (cnt == UV_EOF && uvstream->type == UV_TTY) {
- // The TTY driver might signal TTY without closing the stream
+ // The TTY driver might signal EOF without closing the stream
invoke_read_cb(stream, 0, true);
} else {
DLOG("Closing Stream (%p): %s (%s)", stream,
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 2860817f79..51bc3f1289 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -290,13 +290,11 @@ EXTERN int vgetc_busy INIT(= 0); /* when inside vgetc() then > 0 */
EXTERN int didset_vim INIT(= FALSE); /* did set $VIM ourselves */
EXTERN int didset_vimruntime INIT(= FALSE); /* idem for $VIMRUNTIME */
-/*
- * Lines left before a "more" message. Ex mode needs to be able to reset this
- * after you type something.
- */
-EXTERN int lines_left INIT(= -1); /* lines left for listing */
-EXTERN int msg_no_more INIT(= FALSE); /* don't use more prompt, truncate
- messages */
+/// Lines left before a "more" message. Ex mode needs to be able to reset this
+/// after you type something.
+EXTERN int lines_left INIT(= -1); // lines left for listing
+EXTERN int msg_no_more INIT(= false); // don't use more prompt, truncate
+ // messages
EXTERN char_u *sourcing_name INIT( = NULL); /* name of error message source */
EXTERN linenr_T sourcing_lnum INIT(= 0); /* line number of the source file */
@@ -307,88 +305,71 @@ EXTERN int debug_did_msg INIT(= false); // did "debug mode" message
EXTERN int debug_tick INIT(= 0); // breakpoint change count
EXTERN int debug_backtrace_level INIT(= 0); // breakpoint backtrace level
-/* Values for "do_profiling". */
-#define PROF_NONE 0 /* profiling not started */
-#define PROF_YES 1 /* profiling busy */
-#define PROF_PAUSED 2 /* profiling paused */
-EXTERN int do_profiling INIT(= PROF_NONE); /* PROF_ values */
+// Values for "do_profiling".
+#define PROF_NONE 0 ///< profiling not started
+#define PROF_YES 1 ///< profiling busy
+#define PROF_PAUSED 2 ///< profiling paused
+EXTERN int do_profiling INIT(= PROF_NONE); ///< PROF_ values
-/*
- * The exception currently being thrown. Used to pass an exception to
- * a different cstack. Also used for discarding an exception before it is
- * caught or made pending.
- */
+/// Exception currently being thrown. Used to pass an exception to a different
+/// cstack. Also used for discarding an exception before it is caught or made
+/// pending.
EXTERN except_T *current_exception;
-/*
- * need_rethrow: set to TRUE when a throw that cannot be handled in do_cmdline()
- * must be propagated to the cstack of the previously called do_cmdline().
- */
-EXTERN int need_rethrow INIT(= FALSE);
+/// Set when a throw that cannot be handled in do_cmdline() must be propagated
+/// to the cstack of the previously called do_cmdline().
+EXTERN int need_rethrow INIT(= false);
-/*
- * check_cstack: set to TRUE when a ":finish" or ":return" that cannot be
- * handled in do_cmdline() must be propagated to the cstack of the previously
- * called do_cmdline().
- */
-EXTERN int check_cstack INIT(= FALSE);
+/// Set when a ":finish" or ":return" that cannot be handled in do_cmdline()
+/// must be propagated to the cstack of the previously called do_cmdline().
+EXTERN int check_cstack INIT(= false);
-/*
- * Number of nested try conditionals (across function calls and ":source"
- * commands).
- */
+/// Number of nested try conditionals (across function calls and ":source"
+/// commands).
EXTERN int trylevel INIT(= 0);
-/*
- * When "force_abort" is TRUE, always skip commands after an error message,
- * even after the outermost ":endif", ":endwhile" or ":endfor" or for a
- * function without the "abort" flag. It is set to TRUE when "trylevel" is
- * non-zero (and ":silent!" was not used) or an exception is being thrown at
- * the time an error is detected. It is set to FALSE when "trylevel" gets
- * zero again and there was no error or interrupt or throw.
- */
-EXTERN int force_abort INIT(= FALSE);
-
-/*
- * "msg_list" points to a variable in the stack of do_cmdline() which keeps
- * the list of arguments of several emsg() calls, one of which is to be
- * converted to an error exception immediately after the failing command
- * returns. The message to be used for the exception value is pointed to by
- * the "throw_msg" field of the first element in the list. It is usually the
- * same as the "msg" field of that element, but can be identical to the "msg"
- * field of a later list element, when the "emsg_severe" flag was set when the
- * emsg() call was made.
- */
+/// When "force_abort" is TRUE, always skip commands after an error message,
+/// even after the outermost ":endif", ":endwhile" or ":endfor" or for a
+/// function without the "abort" flag. It is set to TRUE when "trylevel" is
+/// non-zero (and ":silent!" was not used) or an exception is being thrown at
+/// the time an error is detected. It is set to FALSE when "trylevel" gets
+/// zero again and there was no error or interrupt or throw.
+EXTERN int force_abort INIT(= false);
+
+/// "msg_list" points to a variable in the stack of do_cmdline() which keeps
+/// the list of arguments of several emsg() calls, one of which is to be
+/// converted to an error exception immediately after the failing command
+/// returns. The message to be used for the exception value is pointed to by
+/// the "throw_msg" field of the first element in the list. It is usually the
+/// same as the "msg" field of that element, but can be identical to the "msg"
+/// field of a later list element, when the "emsg_severe" flag was set when the
+/// emsg() call was made.
EXTERN struct msglist **msg_list INIT(= NULL);
-/*
- * suppress_errthrow: When TRUE, don't convert an error to an exception. Used
- * when displaying the interrupt message or reporting an exception that is still
- * uncaught at the top level (which has already been discarded then). Also used
- * for the error message when no exception can be thrown.
- */
-EXTERN int suppress_errthrow INIT(= FALSE);
+/// When set, don't convert an error to an exception. Used when displaying the
+/// interrupt message or reporting an exception that is still uncaught at the
+/// top level (which has already been discarded then). Also used for the error
+/// message when no exception can be thrown.
+EXTERN int suppress_errthrow INIT(= false);
-/*
- * The stack of all caught and not finished exceptions. The exception on the
- * top of the stack is the one got by evaluation of v:exception. The complete
- * stack of all caught and pending exceptions is embedded in the various
- * cstacks; the pending exceptions, however, are not on the caught stack.
- */
+/// The stack of all caught and not finished exceptions. The exception on the
+/// top of the stack is the one got by evaluation of v:exception. The complete
+/// stack of all caught and pending exceptions is embedded in the various
+/// cstacks; the pending exceptions, however, are not on the caught stack.
EXTERN except_T *caught_stack INIT(= NULL);
-/*
- * Garbage collection can only take place when we are sure there are no Lists
- * or Dictionaries being used internally. This is flagged with
- * "may_garbage_collect" when we are at the toplevel.
- * "want_garbage_collect" is set by the garbagecollect() function, which means
- * we do garbage collection before waiting for a char at the toplevel.
- * "garbage_collect_at_exit" indicates garbagecollect(1) was called.
- */
-EXTERN int may_garbage_collect INIT(= FALSE);
-EXTERN int want_garbage_collect INIT(= FALSE);
-EXTERN int garbage_collect_at_exit INIT(= FALSE);
+///
+/// Garbage collection can only take place when we are sure there are no Lists
+/// or Dictionaries being used internally. This is flagged with
+/// "may_garbage_collect" when we are at the toplevel.
+/// "want_garbage_collect" is set by the garbagecollect() function, which means
+/// we do garbage collection before waiting for a char at the toplevel.
+/// "garbage_collect_at_exit" indicates garbagecollect(1) was called.
+///
+EXTERN int may_garbage_collect INIT(= false);
+EXTERN int want_garbage_collect INIT(= false);
+EXTERN int garbage_collect_at_exit INIT(= false);
// Special values for current_SID.
#define SID_MODELINE -1 // when using a modeline
@@ -574,57 +555,46 @@ EXTERN int stdout_isatty INIT(= true);
// volatile because it is used in a signal handler.
EXTERN volatile int full_screen INIT(= false);
-EXTERN int restricted INIT(= FALSE);
-// TRUE when started in restricted mode (-Z)
-EXTERN int secure INIT(= FALSE);
-/* non-zero when only "safe" commands are
- * allowed, e.g. when sourcing .exrc or .vimrc
- * in current directory */
+// When started in restricted mode (-Z).
+EXTERN int restricted INIT(= false);
+
+/// Non-zero when only "safe" commands are allowed, e.g. when sourcing .exrc or
+/// .vimrc in current directory.
+EXTERN int secure INIT(= false);
+/// Non-zero when changing text and jumping to another window/buffer is not
+/// allowed.
EXTERN int textlock INIT(= 0);
-/* non-zero when changing text and jumping to
- * another window or buffer is not allowed */
+/// Non-zero when the current buffer can't be changed. Used for FileChangedRO.
EXTERN int curbuf_lock INIT(= 0);
-/* non-zero when the current buffer can't be
- * changed. Used for FileChangedRO. */
+
+/// Non-zero when no buffer name can be changed, no buffer can be deleted and
+/// current directory can't be changed. Used for SwapExists et al.
EXTERN int allbuf_lock INIT(= 0);
-/* non-zero when no buffer name can be
- * changed, no buffer can be deleted and
- * current directory can't be changed.
- * Used for SwapExists et al. */
+
+/// Non-zero when evaluating an expression in a "sandbox". Several things are
+/// not allowed then.
EXTERN int sandbox INIT(= 0);
-/* Non-zero when evaluating an expression in a
- * "sandbox". Several things are not allowed
- * then. */
-
-EXTERN int silent_mode INIT(= FALSE);
-/* set to TRUE when "-s" commandline argument
- * used for ex */
-
-// Set to true when sourcing of startup scripts (init.vim) is done.
-// Used for options that cannot be changed after startup scripts.
-EXTERN bool did_source_startup_scripts INIT(= false);
-
-EXTERN pos_T VIsual; /* start position of active Visual selection */
-EXTERN int VIsual_active INIT(= FALSE);
-/* whether Visual mode is active */
-EXTERN int VIsual_select INIT(= FALSE);
-/* whether Select mode is active */
-EXTERN int VIsual_reselect;
-/* whether to restart the selection after a
- * Select mode mapping or menu */
-EXTERN int VIsual_mode INIT(= 'v');
-/* type of Visual mode */
+/// Batch-mode: "-es" or "-Es" commandline argument was given.
+EXTERN int silent_mode INIT(= false);
-EXTERN int redo_VIsual_busy INIT(= FALSE);
-/* TRUE when redoing Visual */
+/// Start position of active Visual selection.
+EXTERN pos_T VIsual;
+/// Whether Visual mode is active.
+EXTERN int VIsual_active INIT(= false);
+/// Whether Select mode is active.
+EXTERN int VIsual_select INIT(= false);
+/// Whether to restart the selection after a Select-mode mapping or menu.
+EXTERN int VIsual_reselect;
+/// Type of Visual mode.
+EXTERN int VIsual_mode INIT(= 'v');
+/// TRUE when redoing Visual.
+EXTERN int redo_VIsual_busy INIT(= false);
-/*
- * When pasting text with the middle mouse button in visual mode with
- * restart_edit set, remember where it started so we can set Insstart.
- */
+/// When pasting text with the middle mouse button in visual mode with
+/// restart_edit set, remember where it started so we can set Insstart.
EXTERN pos_T where_paste_started;
/*
@@ -732,25 +702,23 @@ EXTERN int (*iconvctl)(iconv_t cd, int request, void *argument);
EXTERN int* (*iconv_errno)(void);
# endif
-/*
- * "State" is the main state of Vim.
- * There are other variables that modify the state:
- * "Visual_mode" When State is NORMAL or INSERT.
- * "finish_op" When State is NORMAL, after typing the operator and before
- * typing the motion command.
- */
-EXTERN int State INIT(= NORMAL); /* This is the current state of the
- * command interpreter. */
+/// "State" is the main state of Vim.
+/// There are other variables that modify the state:
+/// Visual_mode: When State is NORMAL or INSERT.
+/// finish_op : When State is NORMAL, after typing the operator and
+/// before typing the motion command.
+EXTERN int State INIT(= NORMAL); // This is the current state of the
+ // command interpreter.
EXTERN bool finish_op INIT(= false); // true while an operator is pending
EXTERN long opcount INIT(= 0); // count for pending operator
// Ex Mode (Q) state
-EXTERN int exmode_active INIT(= 0); // zero, EXMODE_NORMAL or EXMODE_VIM
-EXTERN int ex_no_reprint INIT(= false); // no need to print after z or p
+EXTERN int exmode_active INIT(= 0); // Zero, EXMODE_NORMAL or EXMODE_VIM.
+EXTERN int ex_no_reprint INIT(=false); // No need to print after z or p.
-EXTERN int Recording INIT(= FALSE); /* TRUE when recording into a reg. */
-EXTERN int Exec_reg INIT(= FALSE); /* TRUE when executing a register */
+EXTERN int Recording INIT(= false); // TRUE when recording into a reg.
+EXTERN int Exec_reg INIT(= false); // TRUE when executing a register.
EXTERN int no_mapping INIT(= false); // currently no mapping allowed
EXTERN int no_zero_mapping INIT(= 0); // mapping zero not allowed
@@ -1164,10 +1132,9 @@ EXTERN FILE *time_fd INIT(= NULL); /* where to write startup timing */
EXTERN int ignored;
EXTERN char *ignoredp;
-// If a msgpack-rpc channel should be started over stdin/stdout
+// Start a msgpack-rpc channel over stdin/stdout.
EXTERN bool embedded_mode INIT(= false);
-// Dont try to start an user interface
-// or read/write to stdio (unless embedding)
+// Do not start a UI nor read/write to stdio (unless embedding).
EXTERN bool headless_mode INIT(= false);
/// Used to track the status of external functions.
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 8b0d3bb2cc..e1a01fdba6 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -97,7 +97,6 @@ typedef struct {
char_u *tagname; // tag from -t argument
char_u *use_ef; // 'errorfile' from -q argument
- int want_full_screen;
bool input_isatty; // stdin is a terminal
bool output_isatty; // stdout is a terminal
bool err_isatty; // stderr is a terminal
@@ -106,9 +105,6 @@ typedef struct {
int window_count; // number of windows to use
int window_layout; // 0, WIN_HOR, WIN_VER or WIN_TABS
-#if !defined(UNIX)
- int literal; // don't expand file names
-#endif
int diff_mode; // start with 'diff' set
char *listen_addr; // --listen {address}
@@ -159,6 +155,7 @@ void event_init(void)
bool event_teardown(void)
{
if (!main_loop.events) {
+ input_stop();
return true;
}
@@ -271,25 +268,17 @@ int main(int argc, char **argv)
/* Don't redraw until much later. */
++RedrawingDisabled;
- /*
- * When listing swap file names, don't do cursor positioning et. al.
- */
- if (recoverymode && fname == NULL)
- params.want_full_screen = FALSE;
-
setbuf(stdout, NULL);
- full_screen = true;
- check_tty(&params);
+ full_screen = !silent_mode;
- /*
- * Set the default values for the options that use Rows and Columns.
- */
+ // Set the default values for the options that use Rows and Columns.
win_init_size();
// Set the 'diff' option now, so that it can be checked for in a vimrc
// file. There is no buffer yet though.
- if (params.diff_mode)
- diff_win_options(firstwin, FALSE);
+ if (params.diff_mode) {
+ diff_win_options(firstwin, false);
+ }
assert(p_ch >= 0 && Rows >= p_ch && Rows - p_ch <= INT_MAX);
cmdline_row = (int)(Rows - p_ch);
@@ -298,26 +287,31 @@ int main(int argc, char **argv)
set_init_2(headless_mode);
TIME_MSG("inits 2");
- msg_scroll = TRUE;
- no_wait_return = TRUE;
+ msg_scroll = true;
+ no_wait_return = true;
- init_highlight(TRUE, FALSE); /* set the default highlight groups */
+ init_highlight(true, false); // Default highlight groups.
TIME_MSG("init highlight");
- /* Set the break level after the terminal is initialized. */
+ // Set the break level after the terminal is initialized.
debug_break_level = params.use_debug_break_level;
- bool reading_input = !headless_mode
- && (params.input_isatty || params.output_isatty
- || params.err_isatty);
-
- if (reading_input) {
+ //
+ // Read user-input if any TTY is connected.
+ // Read ex-commands if invoked with "-es".
+ //
+ bool reading_tty = !headless_mode
+ && (params.input_isatty || params.output_isatty
+ || params.err_isatty);
+ bool reading_excmds = !params.input_isatty && silent_mode
+ && exmode_active == EXMODE_NORMAL;
+ if (reading_tty || reading_excmds) {
// One of the startup commands (arguments, sourced scripts or plugins) may
// prompt the user, so start reading from a tty now.
- int fd = fileno(stdin);
- if (!params.input_isatty || params.edit_type == EDIT_STDIN) {
- // Use stderr or stdout since stdin is not a tty and/or could be used to
- // read the "-" file (eg: cat file | nvim -)
+ int fd = STDIN_FILENO;
+ if (!silent_mode
+ && (!params.input_isatty || params.edit_type == EDIT_STDIN)) {
+ // Use stderr or stdout since stdin is being used to read commands.
fd = params.err_isatty ? fileno(stderr) : fileno(stdout);
}
input_start(fd);
@@ -341,18 +335,18 @@ int main(int argc, char **argv)
// Reset 'loadplugins' for "-u NONE" before "--cmd" arguments.
// Allows for setting 'loadplugins' there.
- if (params.use_vimrc != NULL && strcmp(params.use_vimrc, "NONE") == 0) {
+ if (params.use_vimrc != NULL && strequal(params.use_vimrc, "NONE")) {
p_lpl = false;
}
- /* Execute --cmd arguments. */
+ // Execute --cmd arguments.
exe_pre_commands(&params);
- /* Source startup scripts. */
+ // Source startup scripts.
source_startup_scripts(&params);
// If using the runtime (-u is not NONE), enable syntax & filetype plugins.
- if (params.use_vimrc == NULL || strcmp(params.use_vimrc, "NONE") != 0) {
+ if (params.use_vimrc == NULL || !strequal(params.use_vimrc, "NONE")) {
// Does ":filetype plugin indent on".
filetype_maybe_enable();
// Sources syntax/syntax.vim, which calls `:filetype on`.
@@ -378,17 +372,21 @@ int main(int argc, char **argv)
mch_exit(0);
}
- // Set a few option defaults after reading vimrc files:
- // 'title' and 'icon', Unix: 'shellpipe' and 'shellredir'.
+ // Set a few option defaults after reading vimrc files: 'title', 'icon',
+ // 'shellpipe', 'shellredir'.
set_init_3();
TIME_MSG("inits 3");
- /*
- * "-n" argument: Disable swap file by setting 'updatecount' to 0.
- * Note that this overrides anything from a vimrc file.
- */
- if (params.no_swap_file)
+ // "-n" argument: Disable swap file by setting 'updatecount' to 0.
+ // Note that this overrides anything from a vimrc file.
+ if (params.no_swap_file) {
p_uc = 0;
+ }
+
+ // XXX: Minimize 'updatetime' for -es/-Es. #7679
+ if (silent_mode) {
+ p_ut = 1;
+ }
if (curwin->w_p_rl && p_altkeymap) {
p_hkmap = FALSE; /* Reset the Hebrew keymap mode */
@@ -421,48 +419,47 @@ int main(int argc, char **argv)
* Clear screen now, so file message will not be cleared.
*/
starting = NO_BUFFERS;
- no_wait_return = FALSE;
- if (!exmode_active)
- msg_scroll = FALSE;
+ no_wait_return = false;
+ if (!exmode_active) {
+ msg_scroll = false;
+ }
- /*
- * If "-" argument given: Read file from stdin.
- * Do this before starting Raw mode, because it may change things that the
- * 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 && !recoverymode)
+ // Read file (text, not commands) from stdin if:
+ // - stdin is not a tty
+ // - and -e/-es was not given
+ //
+ // Do this before starting Raw mode, because it may change things that the
+ // 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 && !recoverymode) {
read_stdin();
+ }
-
- if (reading_input && (need_wait_return || msg_didany)) {
- // Since at this point there's no UI instance running yet, error messages
- // would have been printed to stdout. Before starting (which can result in
- // a alternate screen buffer being shown) we need confirmation that the
- // user has seen the messages and that is done with a call to wait_return.
+ if (reading_tty && (need_wait_return || msg_didany)) {
+ // Because there's no UI yet, error messages would have been printed to
+ // stdout. Before starting we need confirmation that the user has seen the
+ // messages and that is done with a call to wait_return.
TIME_MSG("waiting for return");
- wait_return(TRUE);
+ wait_return(true);
}
- if (!headless_mode) {
- // Stop reading from input stream, the UI layer will take over now.
- input_stop();
+ if (!headless_mode && !silent_mode) {
+ input_stop(); // Stop reading input, let the UI take over.
ui_builtin_start();
}
setmouse(); // may start using the mouse
ui_reset_scroll_region(); // In case Rows changed
- // Don't clear the screen when starting in Ex mode, unless using the GUI.
- if (exmode_active)
- must_redraw = CLEAR;
- else {
- screenclear(); /* clear screen */
+ if (exmode_active) {
+ must_redraw = CLEAR; // Don't clear the screen when starting in Ex mode.
+ } else {
+ screenclear(); // clear screen
TIME_MSG("clearing screen");
}
- no_wait_return = TRUE;
+ no_wait_return = true;
/*
* Create the requested number of windows and edit buffers in them.
@@ -691,9 +688,7 @@ static int get_number_arg(const char *p, int *idx, int def)
}
#if defined(HAVE_LOCALE_H)
-/*
- * Setup to use the current locale (for ctype() and many other things).
- */
+/// Setup to use the current locale (for ctype() and many other things).
static void init_locale(void)
{
setlocale(LC_ALL, "");
@@ -724,61 +719,73 @@ static void init_locale(void)
}
#endif
+/// Decides whether text (as opposed to commands) will be read from stdin.
+/// @see EDIT_STDIN
+static bool edit_stdin(bool explicit, mparm_T *parmp)
+{
+ bool implicit = !headless_mode
+ && !embedded_mode
+ && exmode_active != EXMODE_NORMAL // -E/-Es but not -e/-es.
+ && !parmp->input_isatty
+ && scriptin[0] == NULL; // `-s -` was not given.
+ return explicit || implicit;
+}
/// Scan the command line arguments.
static void command_line_scan(mparm_T *parmp)
{
int argc = parmp->argc;
- char **argv = parmp->argv;
- int argv_idx; /* index in argv[n][] */
- int had_minmin = FALSE; /* found "--" argument */
- int want_argument; /* option argument with argument */
+ char **argv = parmp->argv;
+ int argv_idx; // index in argv[n][]
+ bool had_stdin_file = false; // found explicit "-" argument
+ bool had_minmin = false; // found "--" argument
+ int want_argument; // option argument with argument
int c;
- char_u *p = NULL;
+ char_u *p = NULL;
long n;
- --argc;
- ++argv;
- argv_idx = 1; /* active option letter is argv[0][argv_idx] */
+ argc--;
+ argv++;
+ argv_idx = 1; // active option letter is argv[0][argv_idx]
while (argc > 0) {
- /*
- * "+" or "+{number}" or "+/{pat}" or "+{command}" argument.
- */
+ // "+" or "+{number}" or "+/{pat}" or "+{command}" argument.
if (argv[0][0] == '+' && !had_minmin) {
- if (parmp->n_commands >= MAX_ARG_CMDS)
+ if (parmp->n_commands >= MAX_ARG_CMDS) {
mainerr(err_extra_cmd, NULL);
- argv_idx = -1; /* skip to next argument */
- if (argv[0][1] == NUL)
+ }
+ argv_idx = -1; // skip to next argument
+ if (argv[0][1] == NUL) {
parmp->commands[parmp->n_commands++] = "$";
- else
+ } else {
parmp->commands[parmp->n_commands++] = &(argv[0][1]);
- }
- /*
- * Optional argument.
- */
- else if (argv[0][0] == '-' && !had_minmin) {
- want_argument = FALSE;
+ }
+
+ // Optional argument.
+ } else if (argv[0][0] == '-' && !had_minmin) {
+ want_argument = false;
c = argv[0][argv_idx++];
switch (c) {
- case NUL: /* "vim -" read from stdin */
+ case NUL: { // "nvim -" read from stdin
if (exmode_active) {
- // "ex -" silent mode
- silent_mode = TRUE;
+ // "nvim -e -" silent mode
+ silent_mode = true;
} else {
- if (parmp->edit_type != EDIT_NONE) {
+ if (parmp->edit_type != EDIT_NONE
+ && parmp->edit_type != EDIT_FILE
+ && parmp->edit_type != EDIT_STDIN) {
mainerr(err_too_many_args, argv[0]);
}
+ had_stdin_file = true;
parmp->edit_type = EDIT_STDIN;
}
- argv_idx = -1; /* skip to next argument */
+ argv_idx = -1; // skip to next argument
break;
-
- case '-': /* "--" don't take any more option arguments */
- /* "--help" give help message */
- /* "--version" give version message */
- /* "--literal" take files literally */
- /* "--noplugin[s]" skip plugins */
- /* "--cmd <cmd>" execute cmd before vimrc */
+ }
+ case '-': { // "--" don't take any more option arguments
+ // "--help" give help message
+ // "--version" give version message
+ // "--noplugin[s]" skip plugins
+ // "--cmd <cmd>" execute cmd before vimrc
if (STRICMP(argv[0] + argv_idx, "help") == 0) {
usage();
mch_exit(0);
@@ -821,26 +828,25 @@ static void command_line_scan(mparm_T *parmp)
want_argument = true;
argv_idx += 6;
} else if (STRNICMP(argv[0] + argv_idx, "literal", 7) == 0) {
-#if !defined(UNIX)
- parmp->literal = TRUE;
-#endif
- } else if (STRNICMP(argv[0] + argv_idx, "noplugin", 8) == 0)
- p_lpl = FALSE;
- else if (STRNICMP(argv[0] + argv_idx, "cmd", 3) == 0) {
- want_argument = TRUE;
+ // Do nothing: file args are always literal. #7679
+ } else if (STRNICMP(argv[0] + argv_idx, "noplugin", 8) == 0) {
+ p_lpl = false;
+ } else if (STRNICMP(argv[0] + argv_idx, "cmd", 3) == 0) {
+ want_argument = true;
argv_idx += 3;
} else if (STRNICMP(argv[0] + argv_idx, "startuptime", 11) == 0) {
- want_argument = TRUE;
+ want_argument = true;
argv_idx += 11;
} else {
if (argv[0][argv_idx])
mainerr(err_opt_unknown, argv[0]);
- had_minmin = TRUE;
+ had_minmin = true;
+ }
+ if (!want_argument) {
+ argv_idx = -1; // skip to next argument
}
- if (!want_argument)
- argv_idx = -1; /* skip to next argument */
break;
-
+ }
case 'A': { // "-A" start in Arabic mode.
set_option_value("arabic", 1L, NULL, 0);
break;
@@ -854,168 +860,176 @@ static void command_line_scan(mparm_T *parmp)
break;
}
- case 'e': /* "-e" Ex mode */
+ case 'D': { // "-D" Debugging
+ parmp->use_debug_break_level = 9999;
+ break;
+ }
+ case 'd': { // "-d" 'diff'
+ parmp->diff_mode = true;
+ break;
+ }
+ case 'e': { // "-e" Ex mode
exmode_active = EXMODE_NORMAL;
break;
-
- case 'E': /* "-E" Improved Ex mode */
+ }
+ case 'E': { // "-E" Improved Ex mode
exmode_active = EXMODE_VIM;
break;
-
- case 'f': /* "-f" GUI: run in foreground. */
+ }
+ case 'f': { // "-f" GUI: run in foreground.
break;
-
+ }
case 'F': { // "-F" start in Farsi mode: rl + fkmap set.
p_fkmap = true;
set_option_value("rl", 1L, NULL, 0);
break;
}
-
- case 'h': /* "-h" give help message */
+ case 'h': { // "-h" give help message
usage();
mch_exit(0);
-
+ }
case 'H': { // "-H" start in Hebrew mode: rl + hkmap set.
p_hkmap = true;
set_option_value("rl", 1L, NULL, 0);
break;
}
-
case 'l': { // "-l" lisp mode, 'lisp' and 'showmatch' on.
set_option_value("lisp", 1L, NULL, 0);
p_sm = true;
break;
}
-
- case 'M': /* "-M" no changes or writing of files */
+ case 'M': { // "-M" no changes or writing of files
reset_modifiable();
- /* FALLTHROUGH */
-
- case 'm': /* "-m" no writing of files */
- p_write = FALSE;
+ // FALLTHROUGH
+ }
+ case 'm': { // "-m" no writing of files
+ p_write = false;
break;
+ }
- case 'N': // "-N" Nocompatible
- case 'X': // "-X" Do not connect to X server
+ case 'N': // "-N" Nocompatible
+ case 'X': // "-X" Do not connect to X server
// No-op
break;
- case 'n': /* "-n" no swap file */
- parmp->no_swap_file = TRUE;
+ case 'n': { // "-n" no swap file
+ parmp->no_swap_file = true;
break;
-
- case 'p': // "-p[N]" open N tab pages
+ }
+ case 'p': { // "-p[N]" open N tab pages
// default is 0: open window for each file
parmp->window_count = get_number_arg(argv[0], &argv_idx, 0);
parmp->window_layout = WIN_TABS;
break;
-
- case 'o': /* "-o[N]" open N horizontal split windows */
- /* default is 0: open window for each file */
+ }
+ case 'o': { // "-o[N]" open N horizontal split windows
+ // default is 0: open window for each file
parmp->window_count = get_number_arg(argv[0], &argv_idx, 0);
parmp->window_layout = WIN_HOR;
break;
-
- case 'O': /* "-O[N]" open N vertical split windows */
- /* default is 0: open window for each file */
+ }
+ case 'O': { // "-O[N]" open N vertical split windows
+ // default is 0: open window for each file
parmp->window_count = get_number_arg(argv[0], &argv_idx, 0);
parmp->window_layout = WIN_VER;
break;
-
- case 'q': /* "-q" QuickFix mode */
- if (parmp->edit_type != EDIT_NONE)
+ }
+ case 'q': { // "-q" QuickFix mode
+ if (parmp->edit_type != EDIT_NONE) {
mainerr(err_too_many_args, argv[0]);
+ }
parmp->edit_type = EDIT_QF;
- if (argv[0][argv_idx]) { /* "-q{errorfile}" */
+ if (argv[0][argv_idx]) { // "-q{errorfile}"
parmp->use_ef = (char_u *)argv[0] + argv_idx;
argv_idx = -1;
- } else if (argc > 1) /* "-q {errorfile}" */
- want_argument = TRUE;
+ } else if (argc > 1) { // "-q {errorfile}"
+ want_argument = true;
+ }
break;
-
- case 'R': /* "-R" readonly mode */
- readonlymode = TRUE;
- curbuf->b_p_ro = TRUE;
- p_uc = 10000; /* don't update very often */
+ }
+ case 'R': { // "-R" readonly mode
+ readonlymode = true;
+ curbuf->b_p_ro = true;
+ p_uc = 10000; // don't update very often
break;
-
- case 'r': /* "-r" recovery mode */
- case 'L': /* "-L" recovery mode */
+ }
+ case 'r': // "-r" recovery mode
+ case 'L': { // "-L" recovery mode
recoverymode = 1;
break;
-
- case 's':
- if (exmode_active) { // "-es" silent (batch) mode
+ }
+ case 's': {
+ if (exmode_active) { // "-es" silent (batch) Ex-mode
silent_mode = true;
} else { // "-s {scriptin}" read from script file
want_argument = true;
}
break;
-
- case 't': /* "-t {tag}" or "-t{tag}" jump to tag */
- if (parmp->edit_type != EDIT_NONE)
+ }
+ case 't': { // "-t {tag}" or "-t{tag}" jump to tag
+ if (parmp->edit_type != EDIT_NONE) {
mainerr(err_too_many_args, argv[0]);
+ }
parmp->edit_type = EDIT_TAG;
- if (argv[0][argv_idx]) { /* "-t{tag}" */
+ if (argv[0][argv_idx]) { // "-t{tag}"
parmp->tagname = (char_u *)argv[0] + argv_idx;
argv_idx = -1;
- } else /* "-t {tag}" */
- want_argument = TRUE;
- break;
-
- case 'D': /* "-D" Debugging */
- parmp->use_debug_break_level = 9999;
- break;
- case 'd': /* "-d" 'diff' */
- parmp->diff_mode = TRUE;
+ } else { // "-t {tag}"
+ want_argument = true;
+ }
break;
- case 'v':
+ }
+ case 'v': {
version();
mch_exit(0);
- case 'V': /* "-V{N}" Verbose level */
- /* default is 10: a little bit verbose */
+ }
+ case 'V': { // "-V{N}" Verbose level
+ // default is 10: a little bit verbose
p_verbose = get_number_arg(argv[0], &argv_idx, 10);
if (argv[0][argv_idx] != NUL) {
set_option_value("verbosefile", 0L, argv[0] + argv_idx, 0);
argv_idx = (int)STRLEN(argv[0]);
}
break;
-
- case 'w': /* "-w{number}" set window height */
- /* "-w {scriptout}" write to script */
+ }
+ case 'w': { // "-w{number}" set window height
+ // "-w {scriptout}" write to script
if (ascii_isdigit(((char_u *)argv[0])[argv_idx])) {
n = get_number_arg(argv[0], &argv_idx, 10);
set_option_value("window", n, NULL, 0);
break;
}
- want_argument = TRUE;
+ want_argument = true;
break;
-
- case 'Z': /* "-Z" restricted mode */
- restricted = TRUE;
+ }
+ case 'Z': { // "-Z" restricted mode
+ restricted = true;
break;
+ }
- case 'c': /* "-c{command}" or "-c {command}" execute
- command */
+ case 'c': { // "-c{command}" or "-c {command}" exec command
if (argv[0][argv_idx] != NUL) {
- if (parmp->n_commands >= MAX_ARG_CMDS)
+ if (parmp->n_commands >= MAX_ARG_CMDS) {
mainerr(err_extra_cmd, NULL);
- parmp->commands[parmp->n_commands++] = argv[0]
- + argv_idx;
+ }
+ parmp->commands[parmp->n_commands++] = argv[0] + argv_idx;
argv_idx = -1;
break;
}
- /*FALLTHROUGH*/
- case 'S': /* "-S {file}" execute Vim script */
- case 'i': /* "-i {shada}" use for ShaDa file */
- case 'u': /* "-u {vimrc}" vim inits file */
- case 'U': /* "-U {gvimrc}" gvim inits file */
- case 'W': /* "-W {scriptout}" overwrite */
- want_argument = TRUE;
+ // FALLTHROUGH
+ }
+ case 'S': // "-S {file}" execute Vim script
+ case 'i': // "-i {shada}" use for ShaDa file
+ case 'u': // "-u {vimrc}" vim inits file
+ case 'U': // "-U {gvimrc}" gvim inits file
+ case 'W': { // "-W {scriptout}" overwrite
+ want_argument = true;
break;
+ }
- default:
+ default: {
mainerr(err_opt_unknown, argv[0]);
+ }
}
// Handle option arguments with argument.
@@ -1025,43 +1039,45 @@ static void command_line_scan(mparm_T *parmp)
mainerr(err_opt_garbage, argv[0]);
}
- --argc;
- if (argc < 1 && c != 'S') /* -S has an optional argument */
+ argc--;
+ if (argc < 1 && c != 'S') { // -S has an optional argument
mainerr(err_arg_missing, argv[0]);
- ++argv;
+ }
+ argv++;
argv_idx = -1;
switch (c) {
- case 'c': /* "-c {command}" execute command */
- case 'S': /* "-S {file}" execute Vim script */
- if (parmp->n_commands >= MAX_ARG_CMDS)
+ case 'c': // "-c {command}" execute command
+ case 'S': { // "-S {file}" execute Vim script
+ if (parmp->n_commands >= MAX_ARG_CMDS) {
mainerr(err_extra_cmd, NULL);
+ }
if (c == 'S') {
- char *a;
+ char *a;
- if (argc < 1)
- /* "-S" without argument: use default session file
- * name. */
+ if (argc < 1) {
+ // "-S" without argument: use default session file name.
a = SESSION_FILE;
- else if (argv[0][0] == '-') {
- /* "-S" followed by another option: use default
- * session file name. */
+ } else if (argv[0][0] == '-') {
+ // "-S" followed by another option: use default session file.
a = SESSION_FILE;
++argc;
--argv;
} else {
a = argv[0];
}
- char *s = xmalloc(STRLEN(a) + 4);
- sprintf(s, "so %s", a);
- parmp->cmds_tofree[parmp->n_commands] = TRUE;
+ size_t s_size = STRLEN(a) + 4;
+ char *s = xmalloc(s_size);
+ snprintf(s, s_size, "so %s", a);
+ parmp->cmds_tofree[parmp->n_commands] = true;
parmp->commands[parmp->n_commands++] = s;
} else {
parmp->commands[parmp->n_commands++] = argv[0];
}
break;
+ }
- case '-':
+ case '-': {
if (strequal(argv[-1], "--cmd")) {
// "--cmd {command}" execute command
if (parmp->n_pre_commands >= MAX_ARG_CMDS) {
@@ -1074,16 +1090,19 @@ static void command_line_scan(mparm_T *parmp)
}
// "--startuptime <file>" already handled
break;
+ }
- case 'q': /* "-q {errorfile}" QuickFix mode */
+ case 'q': { // "-q {errorfile}" QuickFix mode
parmp->use_ef = (char_u *)argv[0];
break;
+ }
- case 'i': /* "-i {shada}" use for shada */
+ case 'i': { // "-i {shada}" use for shada
used_shada_file = argv[0];
break;
+ }
- case 's': /* "-s {scriptin}" read from script file */
+ case 's': { // "-s {scriptin}" read from script file
if (scriptin[0] != NULL) {
scripterror:
vim_snprintf((char *)IObuff, IOSIZE,
@@ -1093,11 +1112,10 @@ scripterror:
mch_exit(2);
}
int error;
- if (STRCMP(argv[0], "-") == 0) {
+ if (strequal(argv[0], "-")) {
const int stdin_dup_fd = os_dup(STDIN_FILENO);
#ifdef WIN32
- // On Windows, replace the original stdin with the
- // console input handle.
+ // Replace the original stdin with the console input handle.
close(STDIN_FILENO);
const HANDLE conin_handle =
CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
@@ -1120,20 +1138,22 @@ scripterror:
}
save_typebuf();
break;
+ }
- case 't': /* "-t {tag}" */
+ case 't': { // "-t {tag}"
parmp->tagname = (char_u *)argv[0];
break;
-
- case 'u': /* "-u {vimrc}" vim inits file */
+ }
+ case 'u': { // "-u {vimrc}" vim inits file
parmp->use_vimrc = argv[0];
break;
-
- case 'U': /* "-U {gvimrc}" gvim inits file */
+ }
+ case 'U': { // "-U {gvimrc}" gvim inits file
break;
+ }
- case 'w': /* "-w {nr}" 'window' value */
- /* "-w {scriptout}" append to script file */
+ case 'w': { // "-w {nr}" 'window' value
+ // "-w {scriptout}" append to script file
if (ascii_isdigit(*((char_u *)argv[0]))) {
argv_idx = 0;
n = get_number_arg(argv[0], &argv_idx, 10);
@@ -1141,10 +1161,12 @@ scripterror:
argv_idx = -1;
break;
}
- /*FALLTHROUGH*/
- case 'W': /* "-W {scriptout}" overwrite script file */
- if (scriptout != NULL)
+ // FALLTHROUGH
+ }
+ case 'W': { // "-W {scriptout}" overwrite script file
+ if (scriptout != NULL) {
goto scripterror;
+ }
if ((scriptout = mch_fopen(argv[0],
c == 'w' ? APPENDBIN : WRITEBIN)) == NULL) {
mch_errmsg(_("Cannot open for script output: \""));
@@ -1153,30 +1175,28 @@ scripterror:
mch_exit(2);
}
break;
-
+ }
}
}
- }
- /*
- * File name argument.
- */
- else {
- argv_idx = -1; /* skip to next argument */
-
- /* Check for only one type of editing. */
- if (parmp->edit_type != EDIT_NONE && parmp->edit_type != EDIT_FILE)
+ } else { // File name argument.
+ argv_idx = -1; // skip to next argument
+
+ // Check for only one type of editing.
+ if (parmp->edit_type != EDIT_NONE
+ && parmp->edit_type != EDIT_FILE
+ && parmp->edit_type != EDIT_STDIN) {
mainerr(err_too_many_args, argv[0]);
+ }
parmp->edit_type = EDIT_FILE;
- /* Add the file to the global argument list. */
+ // Add the file to the global argument list.
ga_grow(&global_alist.al_ga, 1);
p = vim_strsave((char_u *)argv[0]);
if (parmp->diff_mode && os_isdir(p) && GARGCOUNT > 0
&& !os_isdir(alist_name(&GARGLIST[0]))) {
- char_u *r;
-
- r = (char_u *)concat_fnames((char *)p, (char *)path_tail(alist_name(&GARGLIST[0])), TRUE);
+ char_u *r = (char_u *)concat_fnames((char *)p,
+ (char *)path_tail(alist_name(&GARGLIST[0])), true);
xfree(p);
p = r;
}
@@ -1186,30 +1206,22 @@ scripterror:
path_fix_case(p);
#endif
- alist_add(&global_alist, p,
-#if !defined(UNIX)
- parmp->literal ? 2 : 0 /* add buffer nr after exp. */
-#else
- 2 /* add buffer number now and use curbuf */
-#endif
- );
-
+ int alist_fnum_flag = edit_stdin(had_stdin_file, parmp)
+ ? 1 // add buffer nr after exp.
+ : 2; // add buffer number now and use curbuf
+ alist_add(&global_alist, p, alist_fnum_flag);
}
- /*
- * If there are no more letters after the current "-", go to next
- * argument. argv_idx is set to -1 when the current argument is to be
- * skipped.
- */
+ // If there are no more letters after the current "-", go to next argument.
+ // argv_idx is set to -1 when the current argument is to be skipped.
if (argv_idx <= 0 || argv[0][argv_idx] == NUL) {
- --argc;
- ++argv;
+ argc--;
+ argv++;
argv_idx = 1;
}
}
- /* If there is a "+123" or "-c" command, set v:swapcommand to the first
- * one. */
+ // If there is a "+123" or "-c" command, set v:swapcommand to the first one.
if (parmp->n_commands > 0) {
const size_t swcmd_len = STRLEN(parmp->commands[0]) + 3;
char *const swcmd = xmalloc(swcmd_len);
@@ -1217,6 +1229,12 @@ scripterror:
set_vim_var_string(VV_SWAPCOMMAND, swcmd, -1);
xfree(swcmd);
}
+
+ // Handle "foo | nvim". EDIT_FILE may be overwritten now. #6299
+ if (edit_stdin(had_stdin_file, parmp)) {
+ parmp->edit_type = EDIT_STDIN;
+ }
+
TIME_MSG("parsing arguments");
}
@@ -1229,7 +1247,6 @@ static void init_params(mparm_T *paramp, int argc, char **argv)
memset(paramp, 0, sizeof(*paramp));
paramp->argc = argc;
paramp->argv = argv;
- paramp->want_full_screen = true;
paramp->use_debug_break_level = -1;
paramp->window_count = -1;
paramp->listen_addr = NULL;
@@ -1252,10 +1269,10 @@ static void init_startuptime(mparm_T *paramp)
static void check_and_set_isatty(mparm_T *paramp)
{
stdin_isatty
- = paramp->input_isatty = os_isatty(fileno(stdin));
+ = paramp->input_isatty = os_isatty(STDIN_FILENO);
stdout_isatty
- = paramp->output_isatty = os_isatty(fileno(stdout));
- paramp->err_isatty = os_isatty(fileno(stderr));
+ = paramp->output_isatty = os_isatty(STDOUT_FILENO);
+ paramp->err_isatty = os_isatty(STDERR_FILENO);
#ifndef WIN32
int tty_fd = paramp->input_isatty
? STDIN_FILENO
@@ -1291,26 +1308,6 @@ static void init_path(const char *exename)
/// Get filename from command line, if any.
static char_u *get_fname(mparm_T *parmp, char_u *cwd)
{
-#if !defined(UNIX)
- /*
- * Expand wildcards in file names.
- */
- if (!parmp->literal) {
- cwd = xmalloc(MAXPATHL);
- if (cwd != NULL) {
- os_dirname(cwd, MAXPATHL);
- }
- // Temporarily add '(' and ')' to 'isfname'. These are valid
- // filename characters but are excluded from 'isfname' to make
- // "gf" work on a file name in parenthesis (e.g.: see vim.h).
- do_cmdline_cmd(":set isf+=(,)");
- alist_expand(NULL, 0);
- do_cmdline_cmd(":set isf&");
- if (cwd != NULL) {
- os_chdir((char *)cwd);
- }
- }
-#endif
return alist_name(&GARGLIST[0]);
}
@@ -1402,55 +1399,17 @@ static void handle_tag(char_u *tagname)
}
}
-// Print a warning if stdout is not a terminal.
-// When starting in Ex mode and commands come from a file, set Silent mode.
-static void check_tty(mparm_T *parmp)
-{
- if (headless_mode) {
- return;
- }
-
- // is active input a terminal?
- if (exmode_active) {
- if (!parmp->input_isatty) {
- silent_mode = true;
- }
- } else if (parmp->want_full_screen && (!parmp->err_isatty
- && (!parmp->output_isatty || !parmp->input_isatty))) {
-
- if (!parmp->output_isatty) {
- mch_errmsg(_("Vim: Warning: Output is not to a terminal\n"));
- }
-
- if (!parmp->input_isatty) {
- mch_errmsg(_("Vim: Warning: Input is not from a terminal\n"));
- }
-
- ui_flush();
-
- if (scriptin[0] == NULL) {
- os_delay(2000L, true);
- }
-
- TIME_MSG("Warning delay");
- }
-}
-
-/*
- * Read text from stdin.
- */
+/// Read text from stdin.
static void read_stdin(void)
{
- int i;
-
- /* When getting the ATTENTION prompt here, use a dialog */
+ // When getting the ATTENTION prompt here, use a dialog.
swap_exists_action = SEA_DIALOG;
- no_wait_return = TRUE;
- i = msg_didany;
- set_buflisted(TRUE);
- (void)open_buffer(TRUE, NULL, 0); /* create memfile and read file */
- no_wait_return = FALSE;
- msg_didany = i;
+ no_wait_return = true;
+ int save_msg_didany = msg_didany;
+ set_buflisted(true);
+ (void)open_buffer(true, NULL, 0); // create memfile and read file
+ no_wait_return = false;
+ msg_didany = save_msg_didany;
TIME_MSG("reading stdin");
check_swap_exists_action();
}
@@ -1791,14 +1750,15 @@ static bool do_user_initialization(void)
static void source_startup_scripts(const mparm_T *const parmp)
FUNC_ATTR_NONNULL_ALL
{
- // If -u argument given, use only the initializations from that file and
- // nothing else.
+ // If -u given, use only the initializations from that file and nothing else.
if (parmp->use_vimrc != NULL) {
- if (strcmp(parmp->use_vimrc, "NONE") == 0
- || strcmp(parmp->use_vimrc, "NORC") == 0) {
+ if (strequal(parmp->use_vimrc, "NONE")
+ || strequal(parmp->use_vimrc, "NORC")) {
+ // Do nothing.
} else {
- if (do_source((char_u *)parmp->use_vimrc, FALSE, DOSO_NONE) != OK)
+ if (do_source((char_u *)parmp->use_vimrc, false, DOSO_NONE) != OK) {
EMSG2(_("E282: Cannot read from \"%s\""), parmp->use_vimrc);
+ }
}
} else if (!silent_mode) {
#ifdef SYS_VIMRC_FILE
@@ -1837,7 +1797,6 @@ static void source_startup_scripts(const mparm_T *const parmp)
}
secure = 0;
}
- did_source_startup_scripts = true;
TIME_MSG("sourcing vimrc file(s)");
}
@@ -1927,7 +1886,6 @@ static void usage(void)
mch_msg(_("Usage:\n"));
mch_msg(_(" nvim [options] [file ...] Edit file(s)\n"));
- mch_msg(_(" nvim [options] - Read text from stdin\n"));
mch_msg(_(" nvim [options] -t <tag> Edit file where tag is defined\n"));
mch_msg(_(" nvim [options] -q [errorfile] Edit file with first error\n"));
mch_msg(_("\nOptions:\n"));
@@ -1961,10 +1919,7 @@ static void usage(void)
mch_msg(_(" --api-info Write msgpack-encoded API metadata to stdout\n"));
mch_msg(_(" --embed Use stdin/stdout as a msgpack-rpc channel\n"));
mch_msg(_(" --headless Don't start a user interface\n"));
- mch_msg(_(" --listen <address> Start RPC server at this address\n"));
-#if !defined(UNIX)
- mch_msg(_(" --literal Don't expand wildcards\n"));
-#endif
+ mch_msg(_(" --listen <address> Serve RPC API from this address\n"));
mch_msg(_(" --noplugin Don't load plugins\n"));
mch_msg(_(" --startuptime <file> Write startup timing messages to <file>\n"));
mch_msg(_("\nSee \":help startup-options\" for all options.\n"));
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 188e3544e6..7935bcbc2f 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -2076,8 +2076,9 @@ static void t_puts(int *t_col, const char_u *t_s, const char_u *s, int attr)
}
}
-// Returns TRUE when messages should be printed to stdout/stderr, which
-// happens when no UIs are attached and nvim is not being embedded
+// Returns TRUE when messages should be printed to stdout/stderr:
+// - "batch mode" ("silent mode", -es/-Es)
+// - no UI and not embedded
int msg_use_printf(void)
{
return !embedded_mode && !ui_active();
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index 405500767d..599487c345 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -34,7 +34,7 @@ typedef enum {
kInputEof
} InbufPollResult;
-static Stream read_stream = {.closed = true};
+static Stream read_stream = { .closed = true }; // Input before UI starts.
static RBuffer *input_buffer = NULL;
static bool input_eof = false;
static int global_fd = -1;
@@ -50,7 +50,7 @@ void input_init(void)
input_buffer = rbuffer_new(INPUT_BUFFER_SIZE + MAX_KEY_CODE_LEN);
}
-/// Gets the file from which input was gathered at startup.
+/// Global TTY (or pipe for "-es") input stream, before UI starts.
int input_global_fd(void)
{
return global_fd;
@@ -64,7 +64,7 @@ void input_start(int fd)
global_fd = fd;
rstream_init_fd(&main_loop, &read_stream, fd, READ_BUFFER_SIZE);
- rstream_start(&read_stream, read_cb, NULL);
+ rstream_start(&read_stream, input_read_cb, NULL);
}
void input_stop(void)
@@ -108,6 +108,11 @@ int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt)
}
} else {
if ((result = inbuf_poll((int)p_ut)) == kInputNone) {
+ if (read_stream.closed && silent_mode) {
+ // Drained eventloop & initial input; exit silent/batch-mode (-es/-Es).
+ read_error_exit();
+ }
+
if (trigger_cursorhold() && !typebuf_changed(tb_change_cnt)) {
create_cursorhold_event();
} else {
@@ -376,11 +381,11 @@ static InbufPollResult inbuf_poll(int ms)
return input_eof ? kInputEof : kInputNone;
}
-static void read_cb(Stream *stream, RBuffer *buf, size_t c, void *data,
- bool at_eof)
+static void input_read_cb(Stream *stream, RBuffer *buf, size_t c, void *data,
+ bool at_eof)
{
if (at_eof) {
- input_eof = true;
+ input_done();
}
assert(rbuffer_space(input_buffer) >= rbuffer_size(buf));
@@ -438,8 +443,9 @@ static bool input_ready(void)
// Exit because of an input read error.
static void read_error_exit(void)
{
- if (silent_mode) /* Normal way to exit for "ex -s" */
+ if (silent_mode) { // Normal way to exit for "nvim -es".
getout(0);
+ }
STRCPY(IObuff, _("Vim: Error reading input, exiting...\n"));
preserve_exit();
}
diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua
index ae7f949e52..f1f96ba626 100644
--- a/test/functional/core/startup_spec.lua
+++ b/test/functional/core/startup_spec.lua
@@ -4,16 +4,19 @@ local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
local command = helpers.command
local eq = helpers.eq
+local feed = helpers.feed
local funcs = helpers.funcs
local nvim_prog = helpers.nvim_prog
local nvim_set = helpers.nvim_set
local read_file = helpers.read_file
local retry = helpers.retry
+local sleep = helpers.sleep
local iswin = helpers.iswin
describe('startup', function()
before_each(function()
clear()
+ os.remove('Xtest_startup_ttyout')
end)
after_each(function()
os.remove('Xtest_startup_ttyout')
@@ -46,8 +49,8 @@ describe('startup', function()
end
-- Running in :terminal
command([[exe printf("terminal %s -u NONE -i NONE --cmd \"]]
- ..nvim_set..[[\" ]]
- ..[[-c \"echo has('ttyin') has('ttyout')\""]]
+ ..nvim_set..[[\"]]
+ ..[[ -c \"echo has('ttyin') has('ttyout')\""]]
..[[, shellescape(v:progpath))]])
screen:expect([[
^ |
@@ -56,41 +59,104 @@ describe('startup', function()
]])
end)
it('output to pipe: has("ttyin")==1 has("ttyout")==0', function()
- local screen = Screen.new(25, 5)
- screen:attach()
if iswin() then
command([[set shellcmdflag=/s\ /c shellxquote=\"]])
end
-- Running in :terminal
command([[exe printf("terminal %s -u NONE -i NONE --cmd \"]]
- ..nvim_set..[[\" ]]
- ..[[-c \"call writefile([has('ttyin'), has('ttyout')], 'Xtest_startup_ttyout')\"]]
- ..[[-c q | cat -v"]] -- Output to a pipe.
+ ..nvim_set..[[\"]]
+ ..[[ -c \"call writefile([has('ttyin'), has('ttyout')], 'Xtest_startup_ttyout')\"]]
+ ..[[ -c q | cat -v"]] -- Output to a pipe.
..[[, shellescape(v:progpath))]])
retry(nil, 3000, function()
- screen:sleep(1)
+ sleep(1)
eq('1\n0\n', -- stdin is a TTY, stdout is a pipe
read_file('Xtest_startup_ttyout'))
end)
end)
it('input from pipe: has("ttyin")==0 has("ttyout")==1', function()
- local screen = Screen.new(25, 5)
- screen:attach()
if iswin() then
command([[set shellcmdflag=/s\ /c shellxquote=\"]])
end
-- Running in :terminal
command([[exe printf("terminal echo foo | ]] -- Input from a pipe.
..[[%s -u NONE -i NONE --cmd \"]]
- ..nvim_set..[[\" ]]
- ..[[-c \"call writefile([has('ttyin'), has('ttyout')], 'Xtest_startup_ttyout')\"]]
- ..[[-c q -- -"]]
+ ..nvim_set..[[\"]]
+ ..[[ -c \"call writefile([has('ttyin'), has('ttyout')], 'Xtest_startup_ttyout')\"]]
+ ..[[ -c q -- -"]]
..[[, shellescape(v:progpath))]])
retry(nil, 3000, function()
- screen:sleep(1)
+ sleep(1)
eq('0\n1\n', -- stdin is a pipe, stdout is a TTY
read_file('Xtest_startup_ttyout'))
end)
end)
+ it('input from pipe (implicit) #7679', function()
+ local screen = Screen.new(25, 3)
+ screen:attach()
+ if iswin() then
+ command([[set shellcmdflag=/s\ /c shellxquote=\"]])
+ end
+ -- Running in :terminal
+ command([[exe printf("terminal echo foo | ]] -- Input from a pipe.
+ ..[[%s -u NONE -i NONE --cmd \"]]
+ ..nvim_set..[[\"]]
+ ..[[ -c \"echo has('ttyin') has('ttyout')\""]]
+ ..[[, shellescape(v:progpath))]])
+ screen:expect([[
+ ^foo |
+ 0 1 |
+ |
+ ]])
+ end)
+ it('input from pipe + file args #7679', function()
+ eq('ohyeah\r\n0 0 bufs=3',
+ funcs.system({nvim_prog, '-n', '-u', 'NONE', '-i', 'NONE', '--headless',
+ '+.print',
+ "+echo has('ttyin') has('ttyout') 'bufs='.bufnr('$')",
+ '+qall!',
+ '-',
+ 'test/functional/fixtures/tty-test.c',
+ 'test/functional/fixtures/shell-test.c',
+ },
+ { 'ohyeah', '' }))
+ end)
+
+ it('-e/-E interactive #7679', function()
+ clear('-E')
+ local screen = Screen.new(25, 3)
+ screen:attach()
+ feed("put ='from -E'<CR>")
+ screen:expect([[
+ |
+ from -E |
+ :^ |
+ ]])
+ end)
+
+ it('stdin with -es/-Es #7679', function()
+ local input = { 'append', 'line1', 'line2', '.', '%print', '' }
+ local inputstr = table.concat(input, '\n')
+
+ --
+ -- -Es: read stdin as text
+ --
+ eq('partylikeits1999\n',
+ funcs.system({nvim_prog, '-n', '-u', 'NONE', '-i', 'NONE', '-Es', '+.print', 'test/functional/fixtures/tty-test.c' },
+ { 'partylikeits1999', '' }))
+ eq(inputstr,
+ funcs.system({nvim_prog, '-i', 'NONE', '-Es', '+%print', '-' },
+ input))
+
+ --
+ -- -es: read stdin as ex-commands
+ --
+ eq(' encoding=utf-8\n',
+ funcs.system({nvim_prog, '-n', '-u', 'NONE', '-i', 'NONE', '-es', 'test/functional/fixtures/tty-test.c' },
+ { 'set encoding', '' }))
+ eq('line1\nline2\n',
+ funcs.system({nvim_prog, '-i', 'NONE', '-es', '-' },
+ input))
+ end)
end)
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index 9895281773..a6d2764187 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -316,6 +316,14 @@ local function retry(max, max_ms, fn)
end
end
+-- Starts a new global Nvim session.
+-- Parameters are interpreted as startup args, OR a map with these keys:
+-- args: Merged with the default `nvim_argv` set.
+-- env : Defines the environment of the new session.
+--
+-- Example:
+-- clear('-e')
+-- clear({args={'-e'}, env={TERM=term}})
local function clear(...)
local args = {unpack(nvim_argv)}
local new_args