aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ex_docmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/ex_docmd.c')
-rw-r--r--src/nvim/ex_docmd.c974
1 files changed, 557 insertions, 417 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index a24e8458a6..0b466bbe4e 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -1,6 +1,3 @@
-// This is an open source non-commercial project. Dear PVS-Studio, please check
-// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-
// ex_docmd.c: functions for executing an Ex command line.
#include <assert.h>
@@ -12,15 +9,18 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
#include "auto/config.h"
#include "nvim/arglist.h"
-#include "nvim/ascii.h"
+#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/change.h"
#include "nvim/charset.h"
#include "nvim/cmdexpand.h"
+#include "nvim/cmdexpand_defs.h"
#include "nvim/cursor.h"
#include "nvim/debugger.h"
#include "nvim/digraph.h"
@@ -28,7 +28,6 @@
#include "nvim/edit.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
-#include "nvim/eval/typval_defs.h"
#include "nvim/eval/userfunc.h"
#include "nvim/event/loop.h"
#include "nvim/ex_cmds.h"
@@ -40,19 +39,20 @@
#include "nvim/file_search.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
+#include "nvim/func_attr.h"
#include "nvim/garray.h"
#include "nvim/getchar.h"
#include "nvim/gettext.h"
#include "nvim/globals.h"
-#include "nvim/highlight_defs.h"
+#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
#include "nvim/input.h"
#include "nvim/keycodes.h"
-#include "nvim/macros.h"
+#include "nvim/lua/executor.h"
+#include "nvim/macros_defs.h"
#include "nvim/main.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
-#include "nvim/memfile_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
@@ -61,40 +61,52 @@
#include "nvim/normal.h"
#include "nvim/ops.h"
#include "nvim/option.h"
+#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
+#include "nvim/os/fs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
#include "nvim/os/shell.h"
#include "nvim/path.h"
#include "nvim/popupmenu.h"
-#include "nvim/pos.h"
+#include "nvim/pos_defs.h"
#include "nvim/profile.h"
#include "nvim/quickfix.h"
#include "nvim/regexp.h"
#include "nvim/runtime.h"
-#include "nvim/screen.h"
#include "nvim/search.h"
#include "nvim/shada.h"
#include "nvim/state.h"
#include "nvim/statusline.h"
#include "nvim/strings.h"
#include "nvim/tag.h"
-#include "nvim/types.h"
+#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/usercmd.h"
-#include "nvim/vim.h"
+#include "nvim/vim_defs.h"
#include "nvim/window.h"
+#include "nvim/winfloat.h"
-static char e_ambiguous_use_of_user_defined_command[]
+static const char e_ambiguous_use_of_user_defined_command[]
= N_("E464: Ambiguous use of user-defined command");
-static char e_not_an_editor_command[]
+static const char e_no_call_stack_to_substitute_for_stack[]
+ = N_("E489: No call stack to substitute for \"<stack>\"");
+static const char e_not_an_editor_command[]
= N_("E492: Not an editor command");
-static char e_no_source_file_name_to_substitute_for_sfile[]
- = N_("E498: no :source file name to substitute for \"<sfile>\"");
-static char e_no_call_stack_to_substitute_for_stack[]
- = N_("E489: no call stack to substitute for \"<stack>\"");
-static char e_no_script_file_name_to_substitute_for_script[]
+static const char e_no_autocommand_file_name_to_substitute_for_afile[]
+ = N_("E495: No autocommand file name to substitute for \"<afile>\"");
+static const char e_no_autocommand_buffer_number_to_substitute_for_abuf[]
+ = N_("E496: No autocommand buffer number to substitute for \"<abuf>\"");
+static const char e_no_autocommand_match_name_to_substitute_for_amatch[]
+ = N_("E497: No autocommand match name to substitute for \"<amatch>\"");
+static const char e_no_source_file_name_to_substitute_for_sfile[]
+ = N_("E498: No :source file name to substitute for \"<sfile>\"");
+static const char e_no_line_number_to_use_for_slnum[]
+ = N_("E842: No line number to use for \"<slnum>\"");
+static const char e_no_line_number_to_use_for_sflnum[]
+ = N_("E961: No line number to use for \"<sflnum>\"");
+static const char e_no_script_file_name_to_substitute_for_script[]
= N_("E1274: No script file name to substitute for \"<script>\"");
static int quitmore = 0;
@@ -139,10 +151,6 @@ struct dbg_stuff {
# include "ex_docmd.c.generated.h"
#endif
-#ifndef HAVE_WORKING_LIBINTL
-# define ex_language ex_ni
-#endif
-
// Declare cmdnames[].
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ex_cmds_defs.generated.h"
@@ -152,19 +160,28 @@ static char dollar_command[2] = { '$', 0 };
static void save_dbg_stuff(struct dbg_stuff *dsp)
{
- dsp->trylevel = trylevel; trylevel = 0;
- dsp->force_abort = force_abort; force_abort = false;
- dsp->caught_stack = caught_stack; caught_stack = NULL;
- dsp->vv_exception = v_exception(NULL);
- dsp->vv_throwpoint = v_throwpoint(NULL);
+ dsp->trylevel = trylevel;
+ trylevel = 0;
+ dsp->force_abort = force_abort;
+ force_abort = false;
+ dsp->caught_stack = caught_stack;
+ caught_stack = NULL;
+ dsp->vv_exception = v_exception(NULL);
+ dsp->vv_throwpoint = v_throwpoint(NULL);
// Necessary for debugging an inactive ":catch", ":finally", ":endtry".
- dsp->did_emsg = did_emsg; did_emsg = false;
- dsp->got_int = got_int; got_int = false;
- dsp->did_throw = did_throw; did_throw = false;
- dsp->need_rethrow = need_rethrow; need_rethrow = false;
- dsp->check_cstack = check_cstack; check_cstack = false;
- dsp->current_exception = current_exception; current_exception = NULL;
+ dsp->did_emsg = did_emsg;
+ did_emsg = false;
+ dsp->got_int = got_int;
+ got_int = false;
+ dsp->did_throw = did_throw;
+ did_throw = false;
+ dsp->need_rethrow = need_rethrow;
+ need_rethrow = false;
+ dsp->check_cstack = check_cstack;
+ check_cstack = false;
+ dsp->current_exception = current_exception;
+ current_exception = NULL;
}
static void restore_dbg_stuff(struct dbg_stuff *dsp)
@@ -200,7 +217,7 @@ void do_exmode(void)
RedrawingDisabled++; // don't redisplay the window
no_wait_return++; // don't wait for return
- msg(_("Entering Ex mode. Type \"visual\" to go to Normal mode."));
+ msg(_("Entering Ex mode. Type \"visual\" to go to Normal mode."), 0);
while (exmode_active) {
// Check for a ":normal" command and no more characters left.
if (ex_normal_busy > 0 && typebuf.tb_len == 0) {
@@ -221,7 +238,7 @@ void do_exmode(void)
if ((prev_line != curwin->w_cursor.lnum
|| changedtick != buf_get_changedtick(curbuf)) && !ex_no_reprint) {
if (curbuf->b_ml.ml_flags & ML_EMPTY) {
- emsg(_(e_emptybuf));
+ emsg(_(e_empty_buffer));
} else {
if (ex_pressedreturn) {
// Make sure the message overwrites the right line and isn't throttled.
@@ -239,7 +256,7 @@ void do_exmode(void)
}
} else if (ex_pressedreturn && !ex_no_reprint) { // must be at EOF
if (curbuf->b_ml.ml_flags & ML_EMPTY) {
- emsg(_(e_emptybuf));
+ emsg(_(e_empty_buffer));
} else {
emsg(_("E501: At end-of-file"));
}
@@ -264,9 +281,9 @@ static void msg_verbose_cmd(linenr_T lnum, char *cmd)
verbose_enter_scroll();
if (lnum == 0) {
- smsg(_("Executing: %s"), cmd);
+ smsg(0, _("Executing: %s"), cmd);
} else {
- smsg(_("line %" PRIdLINENR ": %s"), lnum, cmd);
+ smsg(0, _("line %" PRIdLINENR ": %s"), lnum, cmd);
}
if (msg_silent == 0) {
msg_puts("\n"); // don't overwrite this
@@ -279,7 +296,7 @@ static void msg_verbose_cmd(linenr_T lnum, char *cmd)
/// Execute a simple command line. Used for translated commands like "*".
int do_cmdline_cmd(const char *cmd)
{
- return do_cmdline((char *)cmd, NULL, NULL, DOCMD_NOWAIT|DOCMD_KEYTYPED);
+ return do_cmdline((char *)cmd, NULL, NULL, DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED);
}
/// do_cmdline(): execute one Ex command line
@@ -320,16 +337,12 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
linenr_T *breakpoint = NULL; // ptr to breakpoint field in cookie
int *dbg_tick = NULL; // ptr to dbg_tick field in cookie
struct dbg_stuff debug_saved; // saved things for debug mode
- int initial_trylevel;
- msglist_T **saved_msg_list = NULL;
msglist_T *private_msg_list;
// "fgetline" and "cookie" passed to do_one_cmd()
char *(*cmd_getline)(int, void *, int, bool);
void *cmd_cookie;
struct loop_cookie cmd_loop_cookie;
- void *real_cookie;
- int getline_is_func;
static int call_depth = 0; // recursiveness
// For every pair of do_cmdline()/do_one_cmd() calls, use an extra memory
@@ -338,7 +351,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
// combine the messages stored by an earlier invocation of do_one_cmd()
// with the command name of the later one. This would happen when
// BufWritePost autocommands are executed after a write error.
- saved_msg_list = msg_list;
+ msglist_T **saved_msg_list = msg_list;
msg_list = &private_msg_list;
private_msg_list = NULL;
@@ -358,10 +371,10 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
ga_init(&lines_ga, (int)sizeof(wcmd_T), 10);
- real_cookie = getline_cookie(fgetline, cookie);
+ void *real_cookie = getline_cookie(fgetline, cookie);
// Inside a function use a higher nesting level.
- getline_is_func = getline_equal(fgetline, cookie, get_func_line);
+ bool getline_is_func = getline_equal(fgetline, cookie, get_func_line);
if (getline_is_func && ex_nesting_level == func_level(real_cookie)) {
ex_nesting_level++;
}
@@ -393,7 +406,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
CLEAR_FIELD(debug_saved);
}
- initial_trylevel = trylevel;
+ int initial_trylevel = trylevel;
// "did_throw" will be set to true when an exception is being thrown.
did_throw = false;
@@ -485,24 +498,6 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
}
}
- if (cstack.cs_looplevel > 0) {
- // Inside a while/for loop we need to store the lines and use them
- // again. Pass a different "fgetline" function to do_one_cmd()
- // below, so that it stores lines in or reads them from
- // "lines_ga". Makes it possible to define a function inside a
- // while/for loop.
- cmd_getline = get_loop_line;
- cmd_cookie = (void *)&cmd_loop_cookie;
- cmd_loop_cookie.lines_gap = &lines_ga;
- cmd_loop_cookie.current_line = current_line;
- cmd_loop_cookie.getline = fgetline;
- cmd_loop_cookie.cookie = cookie;
- cmd_loop_cookie.repeating = (current_line < lines_ga.ga_len);
- } else {
- cmd_getline = fgetline;
- cmd_cookie = cookie;
- }
-
// 2. If no line given, get an allocated line with fgetline().
if (next_cmdline == NULL) {
// Need to set msg_didout for the first line after an ":if",
@@ -541,15 +536,37 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
}
cmdline_copy = next_cmdline;
- // Save the current line when inside a ":while" or ":for", and when
- // the command looks like a ":while" or ":for", because we may need it
- // later. When there is a '|' and another command, it is stored
- // separately, because we need to be able to jump back to it from an
+ int current_line_before = 0;
+ // Inside a while/for loop, and when the command looks like a ":while"
+ // or ":for", the line is stored, because we may need it later when
+ // looping.
+ //
+ // When there is a '|' and another command, it is stored separately,
+ // because we need to be able to jump back to it from an
// :endwhile/:endfor.
- if (current_line == lines_ga.ga_len
- && (cstack.cs_looplevel || has_loop_cmd(next_cmdline))) {
- store_loop_line(&lines_ga, next_cmdline);
+ //
+ // Pass a different "fgetline" function to do_one_cmd() below,
+ // that it stores lines in or reads them from "lines_ga". Makes it
+ // possible to define a function inside a while/for loop.
+ if ((cstack.cs_looplevel > 0 || has_loop_cmd(next_cmdline))) {
+ cmd_getline = get_loop_line;
+ cmd_cookie = (void *)&cmd_loop_cookie;
+ cmd_loop_cookie.lines_gap = &lines_ga;
+ cmd_loop_cookie.current_line = current_line;
+ cmd_loop_cookie.getline = fgetline;
+ cmd_loop_cookie.cookie = cookie;
+ cmd_loop_cookie.repeating = (current_line < lines_ga.ga_len);
+
+ // Save the current line when encountering it the first time.
+ if (current_line == lines_ga.ga_len) {
+ store_loop_line(&lines_ga, next_cmdline);
+ }
+ current_line_before = current_line;
+ } else {
+ cmd_getline = fgetline;
+ cmd_cookie = cookie;
}
+
did_endif = false;
if (count++ == 0) {
@@ -652,7 +669,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
} else if (cstack.cs_lflags & CSL_HAD_LOOP) {
// For a ":while" or ":for" we need to remember the line number.
cstack.cs_lflags &= ~CSL_HAD_LOOP;
- cstack.cs_line[cstack.cs_idx] = current_line - 1;
+ cstack.cs_line[cstack.cs_idx] = current_line_before;
}
}
@@ -819,8 +836,8 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
// Cleanup if "cs_emsg_silent_list" remains.
if (cstack.cs_emsg_silent_list != NULL) {
- eslist_T *elem, *temp;
- for (elem = cstack.cs_emsg_silent_list; elem != NULL; elem = temp) {
+ eslist_T *temp;
+ for (eslist_T *elem = cstack.cs_emsg_silent_list; elem != NULL; elem = temp) {
temp = elem->next;
xfree(elem);
}
@@ -893,7 +910,7 @@ void handle_did_throw(void)
if (messages != NULL) {
do {
msglist_T *next = messages->next;
- emsg(messages->msg);
+ emsg_multiline(messages->msg, messages->multiline);
xfree(messages->msg);
xfree(messages->sfile);
xfree(messages);
@@ -919,7 +936,7 @@ static char *get_loop_line(int c, void *cookie, int indent, bool do_concat)
char *line;
// First time inside the ":while"/":for": get line normally.
if (cp->getline == NULL) {
- line = getcmdline(c, 0L, indent, do_concat);
+ line = getcmdline(c, 0, indent, do_concat);
} else {
line = cp->getline(c, cp->cookie, indent, do_concat);
}
@@ -986,10 +1003,10 @@ void *getline_cookie(LineGetter fgetline, void *cookie)
/// ":bwipeout", etc.
///
/// @return the buffer number.
-static int compute_buffer_local_count(cmd_addr_T addr_type, linenr_T lnum, long offset)
+static int compute_buffer_local_count(cmd_addr_T addr_type, linenr_T lnum, int offset)
{
buf_T *nextbuf;
- long count = offset;
+ int count = offset;
buf_T *buf = firstbuf;
while (buf->b_next != NULL && buf->b_fnum < lnum) {
@@ -1107,7 +1124,7 @@ static void get_wincmd_addr_type(const char *arg, exarg_T *eap)
case 'd':
case Ctrl_D:
// window size or any count
- eap->addr_type = ADDR_OTHER; // -V1037
+ eap->addr_type = ADDR_OTHER;
break;
case Ctrl_HAT:
@@ -1311,16 +1328,16 @@ static void parse_register(exarg_T *eap)
}
// Change line1 and line2 of Ex command to use count
-void set_cmd_count(exarg_T *eap, long count, bool validate)
+void set_cmd_count(exarg_T *eap, linenr_T count, bool validate)
{
if (eap->addr_type != ADDR_LINES) { // e.g. :buffer 2, :sleep 3
- eap->line2 = (linenr_T)count;
+ eap->line2 = count;
if (eap->addr_count == 0) {
eap->addr_count = 1;
}
} else {
eap->line1 = eap->line2;
- eap->line2 += (linenr_T)count - 1;
+ eap->line2 += count - 1;
eap->addr_count++;
// Be vi compatible: no error message for out of range.
if (validate && eap->line2 > curbuf->b_ml.ml_line_count) {
@@ -1329,7 +1346,7 @@ void set_cmd_count(exarg_T *eap, long count, bool validate)
}
}
-static int parse_count(exarg_T *eap, char **errormsg, bool validate)
+static int parse_count(exarg_T *eap, const char **errormsg, bool validate)
{
// Check for a count. When accepting a EX_BUFNAME, don't use "123foo" as a
// count, it's a buffer name.
@@ -1338,7 +1355,7 @@ static int parse_count(exarg_T *eap, char **errormsg, bool validate)
if ((eap->argt & EX_COUNT) && ascii_isdigit(*eap->arg)
&& (!(eap->argt & EX_BUFNAME) || *(p = skipdigits(eap->arg + 1)) == NUL
|| ascii_iswhite(*p))) {
- long n = getdigits_long(&eap->arg, false, -1);
+ linenr_T n = getdigits_int32(&eap->arg, false, -1);
eap->arg = skipwhite(eap->arg);
if (eap->args != NULL) {
@@ -1383,7 +1400,7 @@ bool is_cmd_ni(cmdidx_T cmdidx)
/// @param[out] errormsg Error message, if any
///
/// @return Success or failure
-bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **errormsg)
+bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, const char **errormsg)
{
char *after_modifier = NULL;
bool retval = false;
@@ -1441,7 +1458,7 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er
}
// Fail if command is invalid
if (eap->cmdidx == CMD_SIZE) {
- STRCPY(IObuff, _(e_not_an_editor_command));
+ xstrlcpy(IObuff, _(e_not_an_editor_command), IOSIZE);
// If the modifier was parsed OK the error must be in the following command
char *cmdname = after_modifier ? after_modifier : cmdline;
append_command(cmdname);
@@ -1551,7 +1568,7 @@ static void shift_cmd_args(exarg_T *eap)
xfree(oldarglens);
}
-static int execute_cmd0(int *retv, exarg_T *eap, char **errormsg, bool preview)
+static int execute_cmd0(int *retv, exarg_T *eap, const char **errormsg, bool preview)
{
// If filename expansion is enabled, expand filenames
if (eap->argt & EX_XFILE) {
@@ -1636,7 +1653,7 @@ static int execute_cmd0(int *retv, exarg_T *eap, char **errormsg, bool preview)
/// @param preview Execute command preview callback instead of actual command
int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview)
{
- char *errormsg = NULL;
+ const char *errormsg = NULL;
int retv = 0;
#undef ERROR
@@ -1677,7 +1694,7 @@ int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview)
&& !(eap->cmdidx == CMD_file && *eap->arg == NUL)
&& !IS_USER_CMDIDX(eap->cmdidx)
&& curbuf_locked()) {
- ERROR(_(e_cannot_edit_other_buf));
+ goto end;
}
correct_range(eap);
@@ -1849,7 +1866,8 @@ static bool skip_cmd(const exarg_T *eap)
/// Execute one Ex command.
///
-/// If 'sourcing' is true, the command will be included in the error message.
+/// If "flags" has DOCMD_VERBOSE, the command will be included in the error
+/// message.
///
/// 1. skip comment lines and leading space
/// 2. handle command modifiers
@@ -1867,7 +1885,7 @@ static bool skip_cmd(const exarg_T *eap)
static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter fgetline,
void *cookie)
{
- char *errormsg = NULL; // error message
+ const char *errormsg = NULL; // error message
const int save_reg_executing = reg_executing;
const bool save_pending_end_reg_executing = pending_end_reg_executing;
@@ -1882,8 +1900,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
// avoid that a function call in 'statusline' does this
&& !getline_equal(fgetline, cookie, get_func_line)
// avoid that an autocommand, e.g. QuitPre, does this
- && !getline_equal(fgetline, cookie,
- getnextac)) {
+ && !getline_equal(fgetline, cookie, getnextac)) {
quitmore--;
}
@@ -2013,7 +2030,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
while (ASCII_ISALNUM(*p)) {
p++;
}
- p = xstrnsave(ea.cmd, (size_t)(p - ea.cmd));
+ p = xmemdupz(ea.cmd, (size_t)(p - ea.cmd));
int ret = apply_autocmds(EVENT_CMDUNDEFINED, p, p, true, NULL);
xfree(p);
// If the autocommands did something and didn't cause an error, try
@@ -2031,7 +2048,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
// Check for wrong commands.
if (ea.cmdidx == CMD_SIZE) {
if (!ea.skip) {
- STRCPY(IObuff, _(e_not_an_editor_command));
+ xstrlcpy(IObuff, _(e_not_an_editor_command), IOSIZE);
// If the modifier was parsed OK the error must be in the following
// command
char *cmdname = after_modifier ? after_modifier : *cmdlinep;
@@ -2308,7 +2325,7 @@ doend:
if (errormsg != NULL && *errormsg != NUL && !did_emsg) {
if (flags & DOCMD_VERBOSE) {
if (errormsg != IObuff) {
- STRCPY(IObuff, errormsg);
+ xstrlcpy(IObuff, errormsg, IOSIZE);
errormsg = IObuff;
}
append_command(*ea.cmdlinep);
@@ -2329,6 +2346,7 @@ doend:
}
ex_nesting_level--;
+ xfree(ea.cmdline_tofree);
return ea.nextcmd;
}
@@ -2362,12 +2380,12 @@ char *ex_errmsg(const char *const msg, const char *const arg)
/// - set 'eventignore' to "all" for ":noautocmd"
///
/// @return FAIL when the command is not to be executed.
-int parse_command_modifiers(exarg_T *eap, char **errormsg, cmdmod_T *cmod, bool skip_only)
+int parse_command_modifiers(exarg_T *eap, const char **errormsg, cmdmod_T *cmod, bool skip_only)
{
CLEAR_POINTER(cmod);
// Repeat until no more command modifiers are found.
- for (;;) {
+ while (true) {
while (*eap->cmd == ' '
|| *eap->cmd == '\t'
|| *eap->cmd == ':') {
@@ -2397,7 +2415,7 @@ int parse_command_modifiers(exarg_T *eap, char **errormsg, cmdmod_T *cmod, bool
char *p = skip_range(eap->cmd, NULL);
switch (*p) {
- // When adding an entry, also modify cmd_exists().
+ // When adding an entry, also modify cmdmods[]
case 'a':
if (!checkforcmd(&eap->cmd, "aboveleft", 3)) {
break;
@@ -2543,7 +2561,10 @@ int parse_command_modifiers(exarg_T *eap, char **errormsg, cmdmod_T *cmod, bool
if (checkforcmd(&p, "tab", 3)) {
if (!skip_only) {
int tabnr = (int)get_address(eap, &eap->cmd, ADDR_TABS, eap->skip, skip_only,
- false, 1);
+ false, 1, errormsg);
+ if (eap->cmd == NULL) {
+ return false;
+ }
if (tabnr == MAXLNUM) {
cmod->cmod_tab = tabpage_index(curtab) + 1;
@@ -2687,7 +2708,7 @@ void undo_cmdmod(cmdmod_T *cmod)
/// May set the last search pattern, unless "silent" is true.
///
/// @return FAIL and set "errormsg" or return OK.
-int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent)
+int parse_cmd_address(exarg_T *eap, const char **errormsg, bool silent)
FUNC_ATTR_NONNULL_ALL
{
int address_count = 1;
@@ -2696,12 +2717,12 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent)
int ret = FAIL;
// Repeat for all ',' or ';' separated addresses.
- for (;;) {
+ while (true) {
eap->line1 = eap->line2;
eap->line2 = get_cmd_default_range(eap);
eap->cmd = skipwhite(eap->cmd);
lnum = get_address(eap, &eap->cmd, eap->addr_type, eap->skip, silent,
- eap->addr_count == 0, address_count++);
+ eap->addr_count == 0, address_count++, errormsg);
if (eap->cmd == NULL) { // error detected
goto theend;
}
@@ -2737,7 +2758,7 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent)
if (IS_USER_CMDIDX(eap->cmdidx)) {
eap->line1 = 1;
eap->line2 = eap->addr_type == ADDR_WINDOWS
- ? LAST_WIN_NR : LAST_TAB_NR;
+ ? LAST_WIN_NR : LAST_TAB_NR;
} else {
// there is no Vim command which uses '%' and
// ADDR_WINDOWS or ADDR_TABS
@@ -2780,13 +2801,13 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent)
eap->cmd++;
if (!eap->skip) {
fmark_T *fm = mark_get_visual(curbuf, '<');
- if (!mark_check(fm)) {
+ if (!mark_check(fm, errormsg)) {
goto theend;
}
assert(fm != NULL);
eap->line1 = fm->mark.lnum;
fm = mark_get_visual(curbuf, '>');
- if (!mark_check(fm)) {
+ if (!mark_check(fm, errormsg)) {
goto theend;
}
assert(fm != NULL);
@@ -2862,10 +2883,10 @@ bool checkforcmd(char **pp, const char *cmd, int len)
/// Append "cmd" to the error message in IObuff.
/// Takes care of limiting the length and handling 0xa0, which would be
/// invisible otherwise.
-static void append_command(char *cmd)
+static void append_command(const char *cmd)
{
size_t len = strlen(IObuff);
- char *s = cmd;
+ const char *s = cmd;
char *d;
if (len > IOSIZE - 100) {
@@ -2874,7 +2895,7 @@ static void append_command(char *cmd)
d -= utf_head_off(IObuff, d);
STRCPY(d, "...");
}
- STRCAT(IObuff, ": ");
+ xstrlcat(IObuff, ": ", IOSIZE);
d = IObuff + strlen(IObuff);
while (*s != NUL && d - IObuff + 5 < IOSIZE) {
if ((uint8_t)s[0] == 0xc2 && (uint8_t)s[1] == 0xa0) {
@@ -2884,7 +2905,7 @@ static void append_command(char *cmd)
} else if (d - IObuff + utfc_ptr2len(s) + 1 >= IOSIZE) {
break;
} else {
- mb_copy_char((const char **)&s, &d);
+ mb_copy_char(&s, &d);
}
}
*d = NUL;
@@ -2988,6 +3009,11 @@ char *find_ex_command(exarg_T *eap, int *full)
}
assert(eap->cmdidx >= 0);
+ if (len == 3 && strncmp("def", eap->cmd, 3) == 0) {
+ // Make :def an unknown command to avoid confusing behavior. #23149
+ eap->cmdidx = CMD_SIZE;
+ }
+
for (; (int)eap->cmdidx < CMD_SIZE;
eap->cmdidx = (cmdidx_T)((int)eap->cmdidx + 1)) {
if (strncmp(cmdnames[(int)eap->cmdidx].cmd_name, eap->cmd,
@@ -3029,6 +3055,7 @@ static struct cmdmod {
{ "confirm", 4, false },
{ "filter", 4, false },
{ "hide", 3, false },
+ { "horizontal", 3, false },
{ "keepalt", 5, false },
{ "keepjumps", 5, false },
{ "keepmarks", 3, false },
@@ -3094,7 +3121,7 @@ int cmd_exists(const char *const name)
// For ":2match" and ":3match" we need to skip the number.
exarg_T ea;
ea.cmd = (char *)((*name == '2' || *name == '3') ? name + 1 : name);
- ea.cmdidx = (cmdidx_T)0;
+ ea.cmdidx = 0;
ea.flags = 0;
int full = false;
char *p = find_ex_command(&ea, &full);
@@ -3113,13 +3140,10 @@ int cmd_exists(const char *const name)
/// "fullcommand" function
void f_fullcommand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- char *name = argvars[0].vval.v_string;
+ char *name = (char *)tv_get_string(&argvars[0]);
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
- if (name == NULL) {
- return;
- }
while (*name == ':') {
name++;
@@ -3128,7 +3152,7 @@ void f_fullcommand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
exarg_T ea;
ea.cmd = (*name == '2' || *name == '3') ? name + 1 : name;
- ea.cmdidx = (cmdidx_T)0;
+ ea.cmdidx = 0;
ea.flags = 0;
char *p = find_ex_command(&ea, NULL);
if (p == NULL || ea.cmdidx == CMD_SIZE) {
@@ -3142,10 +3166,15 @@ void f_fullcommand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
cmdidx_T excmd_get_cmdidx(const char *cmd, size_t len)
{
+ if (len == 3 && strncmp("def", cmd, 3) == 0) {
+ // Make :def an unknown command to avoid confusing behavior. #23149
+ return CMD_SIZE;
+ }
+
cmdidx_T idx;
if (!one_letter_cmd(cmd, &idx)) {
- for (idx = (cmdidx_T)0; (int)idx < CMD_SIZE; idx = (cmdidx_T)((int)idx + 1)) {
+ for (idx = 0; (int)idx < CMD_SIZE; idx = (cmdidx_T)((int)idx + 1)) {
if (strncmp(cmdnames[(int)idx].cmd_name, cmd, len) == 0) {
break;
}
@@ -3200,34 +3229,35 @@ char *skip_range(const char *cmd, int *ctx)
}
// Skip ":" and white space.
- cmd = skip_colon_white((char *)cmd, false);
+ cmd = skip_colon_white(cmd, false);
return (char *)cmd;
}
-static void addr_error(cmd_addr_T addr_type)
+static const char *addr_error(cmd_addr_T addr_type)
{
if (addr_type == ADDR_NONE) {
- emsg(_(e_norange));
+ return _(e_norange);
} else {
- emsg(_(e_invrange));
+ return _(e_invrange);
}
}
-/// Get a single EX address
+/// Gets a single EX address.
///
-/// Set ptr to the next character after the part that was interpreted.
-/// Set ptr to NULL when an error is encountered.
-/// This may set the last used search pattern.
+/// Sets ptr to the next character after the part that was interpreted.
+/// Sets ptr to NULL when an error is encountered (stored in `errormsg`).
+/// May set the last used search pattern.
///
/// @param skip only skip the address, don't use it
/// @param silent no errors or side effects
/// @param to_other_file flag: may jump to other file
/// @param address_count 1 for first, >1 after comma
+/// @param errormsg Error message, if any
///
/// @return MAXLNUM when no Ex address was found.
static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int skip, bool silent,
- int to_other_file, int address_count)
+ int to_other_file, int address_count, const char **errormsg)
FUNC_ATTR_NONNULL_ALL
{
int c;
@@ -3263,7 +3293,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
case ADDR_NONE:
case ADDR_TABS_RELATIVE:
case ADDR_UNSIGNED:
- addr_error(addr_type);
+ *errormsg = addr_error(addr_type);
cmd = NULL;
goto error;
break;
@@ -3308,7 +3338,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
case ADDR_NONE:
case ADDR_TABS_RELATIVE:
case ADDR_UNSIGNED:
- addr_error(addr_type);
+ *errormsg = addr_error(addr_type);
cmd = NULL;
goto error;
break;
@@ -3333,7 +3363,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
goto error;
}
if (addr_type != ADDR_LINES) {
- addr_error(addr_type);
+ *errormsg = addr_error(addr_type);
cmd = NULL;
goto error;
}
@@ -3346,10 +3376,11 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
fmark_T *fm = mark_get(curbuf, curwin, NULL, flag, *cmd);
cmd++;
if (fm != NULL && fm->fnum != curbuf->handle) {
+ (void)mark_move_to(fm, 0);
// Jumped to another file.
lnum = curwin->w_cursor.lnum;
} else {
- if (!mark_check(fm)) {
+ if (!mark_check(fm, errormsg)) {
cmd = NULL;
goto error;
}
@@ -3363,7 +3394,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
case '?': // '/' or '?' - search
c = (uint8_t)(*cmd++);
if (addr_type != ADDR_LINES) {
- addr_error(addr_type);
+ *errormsg = addr_error(addr_type);
cmd = NULL;
goto error;
}
@@ -3397,7 +3428,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
}
searchcmdlen = 0;
flags = silent ? 0 : SEARCH_HIS | SEARCH_MSG;
- if (!do_search(NULL, c, c, cmd, 1L, flags, NULL)) {
+ if (!do_search(NULL, c, c, cmd, 1, flags, NULL)) {
curwin->w_cursor = pos;
cmd = NULL;
goto error;
@@ -3412,7 +3443,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
case '\\': // "\?", "\/" or "\&", repeat search
cmd++;
if (addr_type != ADDR_LINES) {
- addr_error(addr_type);
+ *errormsg = addr_error(addr_type);
cmd = NULL;
goto error;
}
@@ -3421,7 +3452,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
} else if (*cmd == '?' || *cmd == '/') {
i = RE_SEARCH;
} else {
- emsg(_(e_backslash));
+ *errormsg = _(e_backslash);
cmd = NULL;
goto error;
}
@@ -3434,7 +3465,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
pos.coladd = 0;
if (searchit(curwin, curbuf, &pos, NULL,
*cmd == '?' ? BACKWARD : FORWARD,
- "", 1L, SEARCH_MSG, i, NULL) != FAIL) {
+ "", 1, SEARCH_MSG, i, NULL) != FAIL) {
lnum = pos.lnum;
} else {
cmd = NULL;
@@ -3450,7 +3481,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
}
}
- for (;;) {
+ while (true) {
cmd = skipwhite(cmd);
if (*cmd != '-' && *cmd != '+' && !ascii_isdigit(*cmd)) {
break;
@@ -3503,13 +3534,13 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
// "number", "+number" or "-number"
n = getdigits_int32(&cmd, false, MAXLNUM);
if (n == MAXLNUM) {
- emsg(_(e_line_number_out_of_range));
+ *errormsg = _(e_line_number_out_of_range);
goto error;
}
}
if (addr_type == ADDR_TABS_RELATIVE) {
- emsg(_(e_invrange));
+ *errormsg = _(e_invrange);
cmd = NULL;
goto error;
} else if (addr_type == ADDR_LOADED_BUFFERS || addr_type == ADDR_BUFFERS) {
@@ -3524,8 +3555,8 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
if (i == '-') {
lnum -= n;
} else {
- if (n >= INT32_MAX - lnum) {
- emsg(_(e_line_number_out_of_range));
+ if (lnum >= 0 && n >= INT32_MAX - lnum) {
+ *errormsg = _(e_line_number_out_of_range);
goto error;
}
lnum += n;
@@ -3738,7 +3769,7 @@ char *replace_makeprg(exarg_T *eap, char *arg, char **cmdlinep)
/// When an error is detected, "errormsgp" is set to a non-NULL pointer.
///
/// @return FAIL for failure, OK otherwise.
-int expand_filename(exarg_T *eap, char **cmdlinep, char **errormsgp)
+int expand_filename(exarg_T *eap, char **cmdlinep, const char **errormsgp)
{
// Skip a regexp pattern for ":vimgrep[add] pat file..."
char *p = skip_grep_pat(eap);
@@ -3751,7 +3782,7 @@ int expand_filename(exarg_T *eap, char **cmdlinep, char **errormsgp)
// Skip over `=expr`, wildcards in it are not expanded.
if (p[0] == '`' && p[1] == '=') {
p += 2;
- (void)skip_expr(&p);
+ (void)skip_expr(&p, NULL);
if (*p == '`') {
p++;
}
@@ -3970,7 +4001,7 @@ void separate_nextcmd(exarg_T *eap)
} else if (p[0] == '`' && p[1] == '=' && (eap->argt & EX_XFILE)) {
// Skip over `=expr` when wildcards are expanded.
p += 2;
- (void)skip_expr(&p);
+ (void)skip_expr(&p, NULL);
if (*p == NUL) { // stop at NUL after CTRL-V
break;
}
@@ -4011,7 +4042,7 @@ static char *getargcmd(char **argp)
if (*arg == '+') { // +[command]
arg++;
if (ascii_isspace(*arg) || *arg == '\0') {
- command = (char *)dollar_command;
+ command = dollar_command;
} else {
command = arg;
arg = skip_cmd_arg(command, true);
@@ -4059,6 +4090,22 @@ int get_bad_opt(const char *p, exarg_T *eap)
return OK;
}
+/// Function given to ExpandGeneric() to obtain the list of bad= names.
+static char *get_bad_name(expand_T *xp FUNC_ATTR_UNUSED, int idx)
+{
+ // Note: Keep this in sync with get_bad_opt().
+ static char *(p_bad_values[]) = {
+ "?",
+ "keep",
+ "drop",
+ };
+
+ if (idx < (int)ARRAY_SIZE(p_bad_values)) {
+ return p_bad_values[idx];
+ }
+ return NULL;
+}
+
/// Get "++opt=arg" argument.
///
/// @return FAIL or OK.
@@ -4068,6 +4115,8 @@ static int getargopt(exarg_T *eap)
int *pp = NULL;
int bad_char_idx;
+ // Note: Keep this in sync with get_argopt_name.
+
// ":edit ++[no]bin[ary] file"
if (strncmp(arg, "bin", 3) == 0 || strncmp(arg, "nobin", 5) == 0) {
if (*arg == 'n') {
@@ -4146,6 +4195,71 @@ static int getargopt(exarg_T *eap)
return OK;
}
+/// Function given to ExpandGeneric() to obtain the list of ++opt names.
+static char *get_argopt_name(expand_T *xp FUNC_ATTR_UNUSED, int idx)
+{
+ // Note: Keep this in sync with getargopt().
+ static char *(p_opt_values[]) = {
+ "fileformat=",
+ "encoding=",
+ "binary",
+ "nobinary",
+ "bad=",
+ "edit",
+ "p",
+ };
+
+ if (idx < (int)ARRAY_SIZE(p_opt_values)) {
+ return p_opt_values[idx];
+ }
+ return NULL;
+}
+
+/// Command-line expansion for ++opt=name.
+int expand_argopt(char *pat, expand_T *xp, regmatch_T *rmp, char ***matches, int *numMatches)
+{
+ if (xp->xp_pattern > xp->xp_line && *(xp->xp_pattern - 1) == '=') {
+ CompleteListItemGetter cb = NULL;
+
+ char *name_end = xp->xp_pattern - 1;
+ if (name_end - xp->xp_line >= 2
+ && strncmp(name_end - 2, "ff", 2) == 0) {
+ cb = get_fileformat_name;
+ } else if (name_end - xp->xp_line >= 10
+ && strncmp(name_end - 10, "fileformat", 10) == 0) {
+ cb = get_fileformat_name;
+ } else if (name_end - xp->xp_line >= 3
+ && strncmp(name_end - 3, "enc", 3) == 0) {
+ cb = get_encoding_name;
+ } else if (name_end - xp->xp_line >= 8
+ && strncmp(name_end - 8, "encoding", 8) == 0) {
+ cb = get_encoding_name;
+ } else if (name_end - xp->xp_line >= 3
+ && strncmp(name_end - 3, "bad", 3) == 0) {
+ cb = get_bad_name;
+ }
+
+ if (cb != NULL) {
+ ExpandGeneric(pat, xp, rmp, matches, numMatches, cb, false);
+ return OK;
+ }
+ return FAIL;
+ }
+
+ // Special handling of "ff" which acts as a short form of
+ // "fileformat", as "ff" is not a substring of it.
+ if (xp->xp_pattern_len == 2
+ && strncmp(xp->xp_pattern, "ff", xp->xp_pattern_len) == 0) {
+ *matches = xmalloc(sizeof(char *));
+ *numMatches = 1;
+ (*matches)[0] = xstrdup("fileformat=");
+ return OK;
+ }
+
+ ExpandGeneric(pat, xp, rmp, matches, numMatches, get_argopt_name, false);
+ return OK;
+}
+
/// Handle the argument for a tabpage related ex command.
/// When an error is encountered then eap->errmsg is set.
///
@@ -4401,7 +4515,7 @@ static int check_more(int message, bool forceit)
if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && curbuf->b_fname != NULL) {
char buff[DIALOG_MSG_SIZE];
- vim_snprintf((char *)buff, DIALOG_MSG_SIZE,
+ vim_snprintf(buff, DIALOG_MSG_SIZE,
NGETTEXT("%d more file to edit. Quit anyway?",
"%d more files to edit. Quit anyway?", n), n);
if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 1) == VIM_YES) {
@@ -4433,15 +4547,15 @@ static void ex_colorscheme(exarg_T *eap)
char *expr = xstrdup("g:colors_name");
emsg_off++;
- char *p = eval_to_string(expr, NULL, false);
+ char *p = eval_to_string(expr, false);
emsg_off--;
xfree(expr);
if (p != NULL) {
- msg(p);
+ msg(p, 0);
xfree(p);
} else {
- msg("default");
+ msg("default", 0);
}
} else if (load_colors(eap->arg) == FAIL) {
semsg(_("E185: Cannot find color scheme '%s'"), eap->arg);
@@ -4451,9 +4565,9 @@ static void ex_colorscheme(exarg_T *eap)
static void ex_highlight(exarg_T *eap)
{
if (*eap->arg == NUL && eap->cmd[2] == '!') {
- msg(_("Greetings, Vim user!"));
+ msg(_("Greetings, Vim user!"), 0);
}
- do_highlight((const char *)eap->arg, eap->forceit, false);
+ do_highlight(eap->arg, eap->forceit, false);
}
/// Call this function if we thought we were going to exit, but we won't
@@ -4562,11 +4676,14 @@ static void ex_cquit(exarg_T *eap)
FUNC_ATTR_NORETURN
{
// this does not always pass on the exit code to the Manx compiler. why?
- getout(eap->addr_count > 0 ? (int)eap->line2 : EXIT_FAILURE);
+ int status = eap->addr_count > 0 ? (int)eap->line2 : EXIT_FAILURE;
+ ui_call_error_exit(status);
+ getout(status);
}
-/// ":qall": try to quit all windows
-static void ex_quit_all(exarg_T *eap)
+/// Do preparations for "qall" and "wqall".
+/// Returns FAIL when quitting should be aborted.
+int before_quit_all(exarg_T *eap)
{
if (cmdwin_type != 0) {
if (eap->forceit) {
@@ -4574,19 +4691,28 @@ static void ex_quit_all(exarg_T *eap)
} else {
cmdwin_result = K_XF2;
}
- return;
+ return FAIL;
}
// Don't quit while editing the command line.
if (text_locked()) {
text_locked_msg();
- return;
+ return FAIL;
}
if (before_quit_autocmds(curwin, true, eap->forceit)) {
- return;
+ return FAIL;
}
+ return OK;
+}
+
+/// ":qall": try to quit all windows
+static void ex_quit_all(exarg_T *eap)
+{
+ if (before_quit_all(eap) == FAIL) {
+ return;
+ }
exiting = true;
if (eap->forceit || !check_changed_any(false, false)) {
getout(0);
@@ -4710,7 +4836,7 @@ static void ex_tabonly(exarg_T *eap)
}
if (first_tabpage->tp_next == NULL) {
- msg(_("Already only one tab page"));
+ msg(_("Already only one tab page"), 0);
return;
}
@@ -4769,7 +4895,7 @@ void tabpage_close_other(tabpage_T *tp, int forceit)
// Limit to 1000 windows, autocommands may add a window while we close
// one. OK, so I'm paranoid...
while (++done < 1000) {
- snprintf((char *)prev_idx, sizeof(prev_idx), "%i", tabpage_index(tp));
+ snprintf(prev_idx, sizeof(prev_idx), "%i", tabpage_index(tp));
win_T *wp = tp->tp_lastwin;
ex_win_close(forceit, wp, tp);
@@ -4836,19 +4962,9 @@ static void ex_stop(exarg_T *eap)
if (!eap->forceit) {
autowrite_all();
}
- apply_autocmds(EVENT_VIMSUSPEND, NULL, NULL, false, NULL);
-
- // TODO(bfredl): the TUI should do this on suspend
- ui_cursor_goto(Rows - 1, 0);
- ui_call_grid_scroll(1, 0, Rows, 0, Columns, 1, 0);
- ui_flush();
- ui_call_suspend(); // call machine specific function
-
+ may_trigger_vim_suspend_resume(true);
+ ui_call_suspend();
ui_flush();
- maketitle();
- resettitle(); // force updating the title
- ui_refresh(); // may have resized window
- apply_autocmds(EVENT_VIMRESUME, NULL, NULL, false, NULL);
}
/// ":exit", ":xit" and ":wq": Write file and quit the current window.
@@ -4891,7 +5007,7 @@ static void ex_exit(exarg_T *eap)
static void ex_print(exarg_T *eap)
{
if (curbuf->b_ml.ml_flags & ML_EMPTY) {
- emsg(_(e_emptybuf));
+ emsg(_(e_empty_buffer));
} else {
for (; !got_int; os_breakcheck()) {
print_line(eap->line1,
@@ -4976,8 +5092,13 @@ void ex_splitview(exarg_T *eap)
}
if (eap->cmdidx == CMD_sfind || eap->cmdidx == CMD_tabfind) {
+ char *file_to_find = NULL;
+ char *search_ctx = NULL;
fname = find_file_in_path(eap->arg, strlen(eap->arg),
- FNAME_MESS, true, curbuf->b_ffname);
+ FNAME_MESS, true, curbuf->b_ffname,
+ &file_to_find, &search_ctx);
+ xfree(file_to_find);
+ vim_findfile_cleanup(search_ctx);
if (fname == NULL) {
goto theend;
}
@@ -5091,8 +5212,8 @@ static void ex_tabs(exarg_T *eap)
msg_scroll = true;
win_T *lastused_win = valid_tabpage(lastused_tabpage)
- ? lastused_tabpage->tp_curwin
- : NULL;
+ ? lastused_tabpage->tp_curwin
+ : NULL;
FOR_ALL_TABS(tp) {
if (got_int) {
@@ -5101,7 +5222,7 @@ static void ex_tabs(exarg_T *eap)
msg_putchar('\n');
vim_snprintf(IObuff, IOSIZE, _("Tab page %d"), tabcount++);
- msg_outtrans_attr(IObuff, HL_ATTR(HLF_T));
+ msg_outtrans(IObuff, HL_ATTR(HLF_T));
os_breakcheck();
FOR_ALL_WINDOWS_IN_TAB(wp, tp) {
@@ -5119,7 +5240,7 @@ static void ex_tabs(exarg_T *eap)
} else {
home_replace(wp->w_buffer, wp->w_buffer->b_fname, IObuff, IOSIZE, true);
}
- msg_outtrans(IObuff);
+ msg_outtrans(IObuff, 0);
os_breakcheck();
}
}
@@ -5169,17 +5290,23 @@ static void ex_resize(exarg_T *eap)
/// ":find [+command] <file>" command.
static void ex_find(exarg_T *eap)
{
+ char *file_to_find = NULL;
+ char *search_ctx = NULL;
char *fname = find_file_in_path(eap->arg, strlen(eap->arg),
- FNAME_MESS, true, curbuf->b_ffname);
+ FNAME_MESS, true, curbuf->b_ffname,
+ &file_to_find, &search_ctx);
if (eap->addr_count > 0) {
- // Repeat finding the file "count" times. This matters when it
- // appears several times in the path.
+ // Repeat finding the file "count" times. This matters when it appears
+ // several times in the path.
linenr_T count = eap->line2;
while (fname != NULL && --count > 0) {
xfree(fname);
- fname = find_file_in_path(NULL, 0, FNAME_MESS, false, curbuf->b_ffname);
+ fname = find_file_in_path(NULL, 0, FNAME_MESS, false, curbuf->b_ffname,
+ &file_to_find, &search_ctx);
}
}
+ xfree(file_to_find);
+ vim_findfile_cleanup(search_ctx);
if (fname == NULL) {
return;
@@ -5201,8 +5328,6 @@ static void ex_edit(exarg_T *eap)
/// @param old_curwin curwin before doing a split or NULL
void do_exedit(exarg_T *eap, win_T *old_curwin)
{
- int n;
-
// ":vi" command ends Ex mode.
if (exmode_active && (eap->cmdidx == CMD_visual
|| eap->cmdidx == CMD_view)) {
@@ -5211,18 +5336,17 @@ void do_exedit(exarg_T *eap, win_T *old_curwin)
if (*eap->arg == NUL) {
// Special case: ":global/pat/visual\NLvi-commands"
if (global_busy) {
- int rd = RedrawingDisabled;
- int nwr = no_wait_return;
- int ms = msg_scroll;
-
if (eap->nextcmd != NULL) {
- stuffReadbuff((const char *)eap->nextcmd);
+ stuffReadbuff(eap->nextcmd);
eap->nextcmd = NULL;
}
+ const int save_rd = RedrawingDisabled;
RedrawingDisabled = 0;
+ const int save_nwr = no_wait_return;
no_wait_return = 0;
need_wait_return = false;
+ const int save_ms = msg_scroll;
msg_scroll = 0;
redraw_all_later(UPD_NOT_VALID);
pending_exmode_active = true;
@@ -5230,9 +5354,9 @@ void do_exedit(exarg_T *eap, win_T *old_curwin)
normal_enter(false, true);
pending_exmode_active = false;
- RedrawingDisabled = rd;
- no_wait_return = nwr;
- msg_scroll = ms;
+ RedrawingDisabled = save_rd;
+ no_wait_return = save_nwr;
+ msg_scroll = save_ms;
}
return;
}
@@ -5254,7 +5378,7 @@ void do_exedit(exarg_T *eap, win_T *old_curwin)
if (*eap->arg != NUL && text_or_buf_locked()) {
return;
}
- n = readonlymode;
+ int n = readonlymode;
if (eap->cmdidx == CMD_view || eap->cmdidx == CMD_sview) {
readonlymode = true;
} else if (eap->cmdidx == CMD_enew) {
@@ -5302,7 +5426,7 @@ void do_exedit(exarg_T *eap, win_T *old_curwin)
if (eap->do_ecmd_cmd != NULL) {
do_cmdline_cmd(eap->do_ecmd_cmd);
}
- n = curwin->w_arg_idx_invalid;
+ int n = curwin->w_arg_idx_invalid;
check_arg_idx(curwin);
if (n != curwin->w_arg_idx_invalid) {
maketitle();
@@ -5337,9 +5461,9 @@ static void ex_popup(exarg_T *eap)
static void ex_swapname(exarg_T *eap)
{
if (curbuf->b_ml.ml_mfp == NULL || curbuf->b_ml.ml_mfp->mf_fname == NULL) {
- msg(_("No swap file"));
+ msg(_("No swap file"), 0);
} else {
- msg(curbuf->b_ml.ml_mfp->mf_fname);
+ msg(curbuf->b_ml.ml_mfp->mf_fname, 0);
}
}
@@ -5350,8 +5474,8 @@ static void ex_syncbind(exarg_T *eap)
{
win_T *save_curwin = curwin;
buf_T *save_curbuf = curbuf;
- long topline;
- long y;
+ linenr_T topline;
+ int y;
linenr_T old_linenr = curwin->w_cursor.lnum;
setpcmark();
@@ -5425,13 +5549,13 @@ static void ex_read(exarg_T *eap)
return;
}
i = readfile(curbuf->b_ffname, curbuf->b_fname,
- eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0, false);
+ eap->line2, 0, (linenr_T)MAXLNUM, eap, 0, false);
} else {
if (vim_strchr(p_cpo, CPO_ALTREAD) != NULL) {
- (void)setaltfname(eap->arg, eap->arg, (linenr_T)1);
+ (void)setaltfname(eap->arg, eap->arg, 1);
}
i = readfile(eap->arg, NULL,
- eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0, false);
+ eap->line2, 0, (linenr_T)MAXLNUM, eap, 0, false);
}
if (i != OK) {
if (!aborting()) {
@@ -5447,13 +5571,13 @@ static void ex_read(exarg_T *eap)
} else {
lnum = 1;
}
- if (*ml_get(lnum) == NUL && u_savedel(lnum, 1L) == OK) {
+ if (*ml_get(lnum) == NUL && u_savedel(lnum, 1) == OK) {
ml_delete(lnum, false);
if (curwin->w_cursor.lnum > 1
&& curwin->w_cursor.lnum >= lnum) {
curwin->w_cursor.lnum--;
}
- deleted_lines_mark(lnum, 1L);
+ deleted_lines_mark(lnum, 1);
}
}
redraw_curbuf_later(UPD_VALID);
@@ -5651,9 +5775,9 @@ static void ex_pwd(exarg_T *eap)
} else if (curtab->tp_localdir != NULL) {
context = "tabpage";
}
- smsg("[%s] %s", context, NameBuff);
+ smsg(0, "[%s] %s", context, NameBuff);
} else {
- msg(NameBuff);
+ msg(NameBuff, 0);
}
} else {
emsg(_("E187: Unknown"));
@@ -5663,25 +5787,27 @@ static void ex_pwd(exarg_T *eap)
/// ":=".
static void ex_equal(exarg_T *eap)
{
- smsg("%" PRId64, (int64_t)eap->line2);
- ex_may_print(eap);
+ if (*eap->arg != NUL && *eap->arg != '|') {
+ // equivalent to :lua= expr
+ ex_lua(eap);
+ } else {
+ eap->nextcmd = find_nextcmd(eap->arg);
+ smsg(0, "%" PRId64, (int64_t)eap->line2);
+ }
}
static void ex_sleep(exarg_T *eap)
{
if (cursor_valid()) {
- int n = curwin->w_winrow + curwin->w_wrow - msg_scrolled;
- if (n >= 0) {
- ui_cursor_goto(n, curwin->w_wincol + curwin->w_wcol);
- }
+ setcursor_mayforce(true);
}
- long len = eap->line2;
+ int64_t len = eap->line2;
switch (*eap->arg) {
case 'm':
break;
case NUL:
- len *= 1000L; break;
+ len *= 1000; break;
default:
semsg(_(e_invarg2), eap->arg); return;
}
@@ -5689,7 +5815,7 @@ static void ex_sleep(exarg_T *eap)
}
/// Sleep for "msec" milliseconds, but return early on CTRL-C.
-void do_sleep(long msec)
+void do_sleep(int64_t msec)
{
ui_flush(); // flush before waiting
LOOP_PROCESS_EVENTS_UNTIL(&main_loop, main_loop.events, msec, got_int);
@@ -5746,7 +5872,7 @@ static void ex_wincmd(exarg_T *eap)
// Pass flags on for ":vertical wincmd ]".
postponed_split_flags = cmdmod.cmod_split;
postponed_split_tab = cmdmod.cmod_tab;
- do_window(*eap->arg, eap->addr_count > 0 ? eap->line2 : 0L, xchar);
+ do_window(*eap->arg, eap->addr_count > 0 ? eap->line2 : 0, xchar);
postponed_split_flags = 0;
postponed_split_tab = 0;
}
@@ -5816,8 +5942,12 @@ static void ex_put(exarg_T *eap)
/// Handle ":copy" and ":move".
static void ex_copymove(exarg_T *eap)
{
- long n = get_address(eap, &eap->arg, eap->addr_type, false, false, false, 1);
+ const char *errormsg = NULL;
+ linenr_T n = get_address(eap, &eap->arg, eap->addr_type, false, false, false, 1, &errormsg);
if (eap->arg == NULL) { // error detected
+ if (errormsg != NULL) {
+ emsg(errormsg);
+ }
eap->nextcmd = NULL;
return;
}
@@ -5830,13 +5960,13 @@ static void ex_copymove(exarg_T *eap)
}
if (eap->cmdidx == CMD_move) {
- if (do_move(eap->line1, eap->line2, (linenr_T)n) == FAIL) {
+ if (do_move(eap->line1, eap->line2, n) == FAIL) {
return;
}
} else {
- ex_copy(eap->line1, eap->line2, (linenr_T)n);
+ ex_copy(eap->line1, eap->line2, n);
}
- u_clearline();
+ u_clearline(curbuf);
beginline(BL_SOL | BL_FIX);
ex_may_print(eap);
}
@@ -5862,7 +5992,7 @@ static void ex_submagic(exarg_T *eap)
}
/// ":smagic" and ":snomagic" preview callback.
-static int ex_submagic_preview(exarg_T *eap, long cmdpreview_ns, handle_T cmdpreview_bufnr)
+static int ex_submagic_preview(exarg_T *eap, int cmdpreview_ns, handle_T cmdpreview_bufnr)
{
const optmagic_T saved = magic_overruled;
@@ -5944,7 +6074,7 @@ static void ex_undo(exarg_T *eap)
return;
}
- long step = eap->line2;
+ linenr_T step = eap->line2;
if (eap->forceit) { // undo! 123
// change number for "undo!" must be lesser than current change number
@@ -5995,7 +6125,7 @@ static void ex_redo(exarg_T *eap)
/// ":earlier" and ":later".
static void ex_later(exarg_T *eap)
{
- long count = 0;
+ int count = 0;
bool sec = false;
bool file = false;
char *p = eap->arg;
@@ -6003,7 +6133,7 @@ static void ex_later(exarg_T *eap)
if (*p == NUL) {
count = 1;
} else if (isdigit((uint8_t)(*p))) {
- count = getdigits_long(&p, false, 0);
+ count = getdigits_int(&p, false, 0);
switch (*p) {
case 's':
p++; sec = true; break;
@@ -6334,6 +6464,11 @@ void restore_current_state(save_state_T *sst)
ui_cursor_shape(); // may show different cursor shape
}
+bool expr_map_locked(void)
+{
+ return expr_map_lock > 0 && !(curbuf->b_flags & BF_DUMMY);
+}
+
/// ":normal[!] {commands}": Execute normal mode commands.
static void ex_normal(exarg_T *eap)
{
@@ -6343,10 +6478,11 @@ static void ex_normal(exarg_T *eap)
}
char *arg = NULL;
- if (ex_normal_lock > 0) {
+ if (expr_map_locked()) {
emsg(_(e_secure));
return;
}
+
if (ex_normal_busy >= p_mmd) {
emsg(_("E192: Recursive use of :normal too deep"));
return;
@@ -6360,8 +6496,7 @@ static void ex_normal(exarg_T *eap)
// Count the number of characters to be escaped.
int l;
- char *p;
- for (p = eap->arg; *p != NUL; p++) {
+ for (char *p = eap->arg; *p != NUL; p++) {
for (l = utfc_ptr2len(p) - 1; l > 0; l--) {
if (*++p == (char)K_SPECIAL) { // trailbyte K_SPECIAL
len += 2;
@@ -6371,7 +6506,7 @@ static void ex_normal(exarg_T *eap)
if (len > 0) {
arg = xmalloc(strlen(eap->arg) + (size_t)len + 1);
len = 0;
- for (p = eap->arg; *p != NUL; p++) {
+ for (char *p = eap->arg; *p != NUL; p++) {
arg[len++] = *p;
for (l = utfc_ptr2len(p) - 1; l > 0; l--) {
arg[len++] = *++p;
@@ -6489,9 +6624,9 @@ void exec_normal(bool was_typed)
static void ex_checkpath(exarg_T *eap)
{
- find_pattern_in_path(NULL, 0, 0, false, false, CHECK_PATH, 1L,
+ find_pattern_in_path(NULL, 0, 0, false, false, CHECK_PATH, 1,
eap->forceit ? ACTION_SHOW_ALL : ACTION_SHOW,
- (linenr_T)1, (linenr_T)MAXLNUM);
+ 1, (linenr_T)MAXLNUM);
}
/// ":psearch"
@@ -6526,9 +6661,9 @@ static void ex_findpat(exarg_T *eap)
break;
}
- long n = 1;
+ int n = 1;
if (ascii_isdigit(*eap->arg)) { // get count
- n = getdigits_long(&eap->arg, false, 0);
+ n = getdigits_int(&eap->arg, false, 0);
eap->arg = skipwhite(eap->arg);
}
if (*eap->arg == '/') { // Match regexp, not just whole words
@@ -6549,7 +6684,7 @@ static void ex_findpat(exarg_T *eap)
}
if (!eap->skip) {
find_pattern_in_path(eap->arg, 0, strlen(eap->arg), whole, !eap->forceit,
- *eap->cmd == 'd' ? FIND_DEFINE : FIND_ANY,
+ *eap->cmd == 'd' ? FIND_DEFINE : FIND_ANY,
n, action, eap->line1, eap->line2);
}
}
@@ -6725,8 +6860,8 @@ ssize_t find_cmdline_var(const char *src, size_t *usedlen)
/// @return an allocated string if a valid match was found.
/// Returns NULL if no match was found. "usedlen" then still contains the
/// number of characters to skip.
-char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnump, char **errormsg,
- int *escaped, bool empty_is_error)
+char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnump,
+ const char **errormsg, int *escaped, bool empty_is_error)
{
char *result;
char *resultbuf = NULL;
@@ -6752,7 +6887,7 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum
// Note: In "\\%" the % is also not recognized!
if (src > srcstart && src[-1] == '\\') {
*usedlen = 0;
- STRMOVE(src - 1, (char *)src); // remove backslash
+ STRMOVE(src - 1, src); // remove backslash
return NULL;
}
@@ -6845,7 +6980,7 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum
break;
case SPEC_CFILE: // file name under cursor
- result = file_name_at_cursor(FNAME_MESS|FNAME_HYP, 1L, NULL);
+ result = file_name_at_cursor(FNAME_MESS|FNAME_HYP, 1, NULL);
if (result == NULL) {
*errormsg = "";
return NULL;
@@ -6854,12 +6989,10 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum
break;
case SPEC_AFILE: // file name for autocommand
- if (autocmd_fname != NULL
- && !path_is_absolute(autocmd_fname)
- // For CmdlineEnter and related events, <afile> is not a path! #9348
- && !strequal("/", autocmd_fname)) {
+ if (autocmd_fname != NULL && !autocmd_fname_full) {
// Still need to turn the fname into a full path. It was
// postponed to avoid a delay when <afile> is not used.
+ autocmd_fname_full = true;
result = FullName_save(autocmd_fname, false);
// Copy into `autocmd_fname`, don't reassign it. #8165
xstrlcpy(autocmd_fname, result, MAXPATHL);
@@ -6867,7 +7000,7 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum
}
result = autocmd_fname;
if (result == NULL) {
- *errormsg = _("E495: no autocommand file name to substitute for \"<afile>\"");
+ *errormsg = _(e_no_autocommand_file_name_to_substitute_for_afile);
return NULL;
}
result = path_try_shorten_fname(result);
@@ -6875,7 +7008,7 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum
case SPEC_ABUF: // buffer number for autocommand
if (autocmd_bufnr <= 0) {
- *errormsg = _("E496: no autocommand buffer number to substitute for \"<abuf>\"");
+ *errormsg = _(e_no_autocommand_buffer_number_to_substitute_for_abuf);
return NULL;
}
snprintf(strbuf, sizeof(strbuf), "%d", autocmd_bufnr);
@@ -6885,7 +7018,7 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum
case SPEC_AMATCH: // match name for autocommand
result = autocmd_match;
if (result == NULL) {
- *errormsg = _("E497: no autocommand match name to substitute for \"<amatch>\"");
+ *errormsg = _(e_no_autocommand_match_name_to_substitute_for_amatch);
return NULL;
}
break;
@@ -6917,7 +7050,7 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum
case SPEC_SLNUM: // line in file for ":so" command
if (SOURCING_NAME == NULL || SOURCING_LNUM == 0) {
- *errormsg = _("E842: no line number to use for \"<slnum>\"");
+ *errormsg = _(e_no_line_number_to_use_for_slnum);
return NULL;
}
snprintf(strbuf, sizeof(strbuf), "%" PRIdLINENR, SOURCING_LNUM);
@@ -6926,10 +7059,10 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum
case SPEC_SFLNUM: // line in script file
if (current_sctx.sc_lnum + SOURCING_LNUM == 0) {
- *errormsg = _("E961: no line number to use for \"<sflnum>\"");
+ *errormsg = _(e_no_line_number_to_use_for_sflnum);
return NULL;
}
- snprintf((char *)strbuf, sizeof(strbuf), "%" PRIdLINENR,
+ snprintf(strbuf, sizeof(strbuf), "%" PRIdLINENR,
current_sctx.sc_lnum + SOURCING_LNUM);
result = strbuf;
break;
@@ -6982,7 +7115,7 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum
}
result = NULL;
} else {
- result = xstrnsave(result, resultlen);
+ result = xmemdupz(result, resultlen);
}
xfree(resultbuf);
return result;
@@ -7001,7 +7134,7 @@ char *expand_sfile(char *arg)
} else {
// replace "<sfile>" with the sourced file name, and do ":" stuff
size_t srclen;
- char *errormsg;
+ const char *errormsg;
char *repl = eval_vars(p, result, &srclen, NULL, &errormsg, NULL, true);
if (errormsg != NULL) {
if (*errormsg) {
@@ -7055,24 +7188,6 @@ void dialog_msg(char *buff, char *format, char *fname)
vim_snprintf(buff, DIALOG_MSG_SIZE, format, fname);
}
-/// ":behave {mswin,xterm}"
-static void ex_behave(exarg_T *eap)
-{
- if (strcmp(eap->arg, "mswin") == 0) {
- set_option_value_give_err("selection", 0L, "exclusive", 0);
- set_option_value_give_err("selectmode", 0L, "mouse,key", 0);
- set_option_value_give_err("mousemodel", 0L, "popup", 0);
- set_option_value_give_err("keymodel", 0L, "startsel,stopsel", 0);
- } else if (strcmp(eap->arg, "xterm") == 0) {
- set_option_value_give_err("selection", 0L, "inclusive", 0);
- set_option_value_give_err("selectmode", 0L, "", 0);
- set_option_value_give_err("mousemodel", 0L, "extend", 0);
- set_option_value_give_err("keymodel", 0L, "", 0);
- } else {
- semsg(_(e_invarg2), eap->arg);
- }
-}
-
static TriState filetype_detect = kNone;
static TriState filetype_plugin = kNone;
static TriState filetype_indent = kNone;
@@ -7088,7 +7203,7 @@ static void ex_filetype(exarg_T *eap)
{
if (*eap->arg == NUL) {
// Print current status.
- smsg("filetype detection:%s plugin:%s indent:%s",
+ smsg(0, "filetype detection:%s plugin:%s indent:%s",
filetype_detect == kTrue ? "ON" : "OFF",
filetype_plugin == kTrue ? (filetype_detect == kTrue ? "ON" : "(on)") : "OFF",
filetype_indent == kTrue ? (filetype_detect == kTrue ? "ON" : "(on)") : "OFF");
@@ -7100,7 +7215,7 @@ static void ex_filetype(exarg_T *eap)
bool indent = false;
// Accept "plugin" and "indent" in any order.
- for (;;) {
+ while (true) {
if (strncmp(arg, "plugin", 6) == 0) {
plugin = true;
arg = skipwhite(arg + 6);
@@ -7189,7 +7304,7 @@ static void ex_setfiletype(exarg_T *eap)
arg += 9;
}
- set_option_value_give_err("filetype", 0L, arg, OPT_LOCAL);
+ set_option_value_give_err("filetype", CSTR_AS_OPTVAL(arg), OPT_LOCAL);
if (arg != eap->arg) {
did_filetype = false;
}
@@ -7271,12 +7386,31 @@ void set_pressedreturn(bool val)
static void ex_terminal(exarg_T *eap)
{
char ex_cmd[1024];
+ size_t len = 0;
+
+ if (cmdmod.cmod_tab > 0 || cmdmod.cmod_split != 0) {
+ bool multi_mods = false;
+
+ // ex_cmd must be a null terminated string before passing to add_win_cmd_modifiers
+ ex_cmd[0] = '\0';
+
+ len = add_win_cmd_modifiers(ex_cmd, &cmdmod, &multi_mods);
+ assert(len < sizeof(ex_cmd));
+ int result = snprintf(ex_cmd + len, sizeof(ex_cmd) - len, " new");
+ assert(result > 0);
+ len += (size_t)result;
+ } else {
+ int result = snprintf(ex_cmd, sizeof(ex_cmd), "enew%s", eap->forceit ? "!" : "");
+ assert(result > 0);
+ len += (size_t)result;
+ }
+
+ assert(len < sizeof(ex_cmd));
if (*eap->arg != NUL) { // Run {cmd} in 'shell'.
char *name = vim_strsave_escaped(eap->arg, "\"\\");
- snprintf(ex_cmd, sizeof(ex_cmd),
- ":enew%s | call termopen(\"%s\")",
- eap->forceit ? "!" : "", name);
+ snprintf(ex_cmd + len, sizeof(ex_cmd) - len,
+ " | call termopen(\"%s\")", name);
xfree(name);
} else { // No {cmd}: run the job with tokenized 'shell'.
if (*p_sh == NUL) {
@@ -7296,302 +7430,308 @@ static void ex_terminal(exarg_T *eap)
}
shell_free_argv(argv);
- snprintf(ex_cmd, sizeof(ex_cmd),
- ":enew%s | call termopen([%s])",
- eap->forceit ? "!" : "", shell_argv + 1);
+ snprintf(ex_cmd + len, sizeof(ex_cmd) - len,
+ " | call termopen([%s])", shell_argv + 1);
}
do_cmdline_cmd(ex_cmd);
}
+/// ":fclose"
+static void ex_fclose(exarg_T *eap)
+{
+ win_float_remove(eap->forceit, eap->line1);
+}
+
void verify_command(char *cmd)
{
if (strcmp("smile", cmd) != 0) {
return; // acceptable non-existing command
}
+ int a = HL_ATTR(HLF_E);
msg(" #xxn` #xnxx` ,+x@##@Mz;` .xxx"
- "xxxxxxnz+, znnnnnnnnnnnnnnnn.");
+ "xxxxxxnz+, znnnnnnnnnnnnnnnn.", a);
msg(" n###z x####` :x##########W+` ,###"
- "##########M; W################.");
+ "##########M; W################.", a);
msg(" n####; x####` `z##############W: ,###"
- "############# W################.");
+ "############# W################.", a);
msg(" n####W. x####` ,W#################+ ,###"
- "############## W################.");
+ "############## W################.", a);
msg(" n#####n x####` @################### ,###"
- "##############i W################.");
+ "##############i W################.", a);
msg(" n######i x####` .#########@W@########* ,###"
- "##############W`W################.");
+ "##############W`W################.", a);
msg(" n######@. x####` x######W*. `;n#######: ,###"
- "#x,,,,:*M######iW###@:,,,,,,,,,,,`");
+ "#x,,,,:*M######iW###@:,,,,,,,,,,,`", a);
msg(" n#######n x####` *######+` :M#####M ,###"
- "#n `x#####xW###@`");
+ "#n `x#####xW###@`", a);
msg(" n########* x####``@####@; `x#####i ,###"
- "#n ,#####@W###@`");
+ "#n ,#####@W###@`", a);
msg(" n########@ x####`*#####i `M####M ,###"
- "#n x#########@`");
+ "#n x#########@`", a);
msg(" n######### x####`M####z :#####:,###"
- "#n z#########@`");
+ "#n z#########@`", a);
msg(" n#########* x####,#####. n####+,###"
- "#n n#########@`");
+ "#n n#########@`", a);
msg(" n####@####@, x####i####x ;####x,###"
- "#n `W#####@####+++++++++++i");
+ "#n `W#####@####+++++++++++i", a);
msg(" n####*#####M` x#########* `####@,###"
- "#n i#####MW###############W");
+ "#n i#####MW###############W", a);
msg(" n####.######+ x####z####; W####,###"
- "#n i@######W###############W");
+ "#n i@######W###############W", a);
msg(" n####.`W#####: x####n####: M####:###"
- "#@nnnnnW#######,W###############W");
+ "#@nnnnnW#######,W###############W", a);
msg(" n####. :#####M`x####z####; W####,###"
- "##############z W###############W");
+ "##############z W###############W", a);
msg(" n####. #######x#########* `####W,###"
- "#############W` W###############W");
+ "#############W` W###############W", a);
msg(" n####. `M#####W####i####x ;####x,###"
- "############W, W####+**********i");
+ "############W, W####+**********i", a);
msg(" n####. ,##########,#####. n####+,###"
- "###########n. W###@`");
+ "###########n. W###@`", a);
msg(" n####. ##########`M####z :#####:,###"
- "########Wz: W###@`");
+ "########Wz: W###@`", a);
msg(" n####. x#########`*#####i `M####M ,###"
- "#x.....` W###@`");
+ "#x.....` W###@`", a);
msg(" n####. ,@########``@####@; `x#####i ,###"
- "#n W###@`");
+ "#n W###@`", a);
msg(" n####. *########` *#####@+` ,M#####M ,###"
- "#n W###@`");
+ "#n W###@`", a);
msg(" n####. x#######` x######W*. `;n######@: ,###"
- "#n W###@,,,,,,,,,,,,`");
+ "#n W###@,,,,,,,,,,,,`", a);
msg(" n####. .@######` .#########@W@########* ,###"
- "#n W################,");
+ "#n W################,", a);
msg(" n####. i######` @################### ,###"
- "#n W################,");
+ "#n W################,", a);
msg(" n####. n#####` ,W#################+ ,###"
- "#n W################,");
+ "#n W################,", a);
msg(" n####. .@####` .n##############W; ,###"
- "#n W################,");
+ "#n W################,", a);
msg(" n####. i####` :x##########W+` ,###"
- "#n W################,");
+ "#n W################,", a);
msg(" +nnnn` +nnn` ,+x@##@Mz;` .nnn"
- "n+ zxxxxxxxxxxxxxxxx.");
- msg(" ");
+ "n+ zxxxxxxxxxxxxxxxx.", a);
+ msg(" ", a);
msg(" "
- " ,+M@#Mi");
+ " ,+M@#Mi", a);
msg(" "
- " .z########");
+ " .z########", a);
msg(" "
- " i@#########i");
+ " i@#########i", a);
msg(" "
- " `############W`");
+ " `############W`", a);
msg(" "
- " `n#############i");
+ " `n#############i", a);
msg(" "
- " `n##############n");
+ " `n##############n", a);
msg(" `` "
- " z###############@`");
+ " z###############@`", a);
msg(" `W@z, "
- " ##################,");
+ " ##################,", a);
msg(" *#####` "
- " i############@x@###i");
+ " i############@x@###i", a);
msg(" ######M. "
- " :#############n`,W##+");
+ " :#############n`,W##+", a);
msg(" +######@: "
- " .W#########M@##+ *##z");
+ " .W#########M@##+ *##z", a);
msg(" :#######@: "
- " `x########@#x###* ,##n");
+ " `x########@#x###* ,##n", a);
msg(" `@#######@; "
- " z#########M*@nW#i .##x");
+ " z#########M*@nW#i .##x", a);
msg(" z########@i "
- " *###########WM#@#, `##x");
+ " *###########WM#@#, `##x", a);
msg(" i##########+ "
- " ;###########*n###@ `##x");
+ " ;###########*n###@ `##x", a);
msg(" `@#MM#######x, "
- " ,@#########zM,`z##M `@#x");
+ " ,@#########zM,`z##M `@#x", a);
msg(" n##M#W#######n. "
- " `.:i*+#zzzz##+i:.` ,W#########Wii,`n@#@` n@##n");
+ " `.:i*+#zzzz##+i:.` ,W#########Wii,`n@#@` n@##n", a);
msg(" ;###@#x#######n `,i"
- "#nW@#####@@WWW@@####@Mzi. ,W##########@z.. ;zM#+i####z");
+ "#nW@#####@@WWW@@####@Mzi. ,W##########@z.. ;zM#+i####z", a);
msg(" x####nz######## .;#x@##"
- "@Wn#*;,.` ``,:*#x@##M+, ;@########xz@WM+#` `n@#######");
+ "@Wn#*;,.` ``,:*#x@##M+, ;@########xz@WM+#` `n@#######", a);
msg(" ,@####M########xi#@##@Mzi,"
- "` .+x###Mi:n##########Mz```.:i *@######*");
+ "` .+x###Mi:n##########Mz```.:i *@######*", a);
msg(" *#####W#########ix+:` "
- " :n#############z: `*.`M######i");
+ " :n#############z: `*.`M######i", a);
msg(" i#W##nW@+@##@#M@; "
- " ;W@@##########W, i`x@#####,");
+ " ;W@@##########W, i`x@#####,", a);
msg(" `@@n@Wn#@iMW*#*: "
- " `iz#z@######x. M######`");
+ " `iz#z@######x. M######`", a);
msg(" z##zM###x`*, .` "
- " `iW#####W;:` +#####M");
+ " `iW#####W;:` +#####M", a);
msg(" ,###nn##n` "
- " ,#####x;` ,;@######");
+ " ,#####x;` ,;@######", a);
msg(" x###xz#. "
- " in###+ `:######@.");
+ " in###+ `:######@.", a);
msg(" ;####n+ "
- " `Mnx##xi` , zM#######");
+ " `Mnx##xi` , zM#######", a);
msg(" `W####+ "
- "i. `.+x###@#. :n,z######:");
+ "i. `.+x###@#. :n,z######:", a);
msg(" z####@` ;"
- "#: .ii@###@;.*M*z####@`");
+ "#: .ii@###@;.*M*z####@`", a);
msg(" i####M ` `i@"
- "#, :: +#n##@+@##W####n");
+ "#, :: +#n##@+@##W####n", a);
msg(" :####x ,i. ##xzM###"
- "@` i. .@@, .z####x#######*");
+ "@` i. .@@, .z####x#######*", a);
msg(" ,###W; i##Wz########"
- "# :## z##n ,@########x###:");
+ "# :## z##n ,@########x###:", a);
msg(" n##n `W###########M"
- "`;n, i#x ,###@i *W########W#@`");
+ "`;n, i#x ,###@i *W########W#@`", a);
msg(" .@##+ `x###########@."
- " z#+ .M#W``x#####n` `;#######@z#x");
+ " z#+ .M#W``x#####n` `;#######@z#x", a);
msg(" n###z :W############@ "
- " z#* @##xM#######@n; `########nW+");
+ " z#* @##xM#######@n; `########nW+", a);
msg(" ;####nW##############W "
- ":@#* `@#############* :########z@i`");
+ ":@#* `@#############* :########z@i`", a);
msg(" M##################### "
- "M##: @#############@: *W########M#");
+ "M##: @#############@: *W########M#", a);
msg(" ;#####################i."
- "##x` W#############W, :n########zx");
+ "##x` W#############W, :n########zx", a);
msg(" x####################@.`"
- "x; @#############z. .@########W#");
+ "x; @#############z. .@########W#", a);
msg(" ,######################` "
- " W###############x*,` W######zM#i");
+ " W###############x*,` W######zM#i", a);
msg(" #######################: "
- " z##################@x+*#zzi `@#########.");
+ " z##################@x+*#zzi `@#########.", a);
msg(" W########W#z#M#########; "
- " *##########################z :@#######@`");
+ " *##########################z :@#######@`", a);
msg(" `@#######x`;#z ,x#######; "
- " z###########M###xnM@########* :M######@");
+ " z###########M###xnM@########* :M######@", a);
msg(" i########, x#@` z######; "
- " *##########i *#@` `+########+` n######.");
+ " *##########i *#@` `+########+` n######.", a);
msg(" n#######@` M##, `W#####. "
- " *#########z ###; z########M: :W####n");
+ " *#########z ###; z########M: :W####n", a);
msg(" M#######M n##. x####x "
- " `x########: z##+ M#########@; .n###+");
+ " `x########: z##+ M#########@; .n###+", a);
msg(" W#######@` :#W `@####: "
- " `@######W i### ;###########@. n##n");
+ " `@######W i### ;###########@. n##n", a);
msg(" W########z` ,, .x####z "
- " @######@` `W#; `W############* *###;");
+ " @######@` `W#; `W############* *###;", a);
msg(" `@#########Mi,:*n@####W` "
- " W#######* .. `n#############i i###x");
+ " W#######* .. `n#############i i###x", a);
msg(" .#####################z "
- " `@#######@*` .x############n:` ;####.");
+ " `@#######@*` .x############n:` ;####.", a);
msg(" :####################x`,,` "
- " `W#########@x#+#@#############i ,####:");
+ " `W#########@x#+#@#############i ,####:", a);
msg(" ;###################x#@###x"
- "i` *############################: `####i");
+ "i` *############################: `####i", a);
msg(" i##################+#######"
- "#M, x##########################@` W###i");
+ "#M, x##########################@` W###i", a);
msg(" *################@; @######"
- "##@, .W#########################@ x###:");
+ "##@, .W#########################@ x###:", a);
msg(" .+M#############z. M######"
- "###x ,W########################@` ####.");
+ "###x ,W########################@` ####.", a);
msg(" *M*;z@########x: :W#####"
- "##i .M########################i i###:");
+ "##i .M########################i i###:", a);
msg(" *##@z;#@####x: :z###"
- "@i `########################x .###;");
+ "@i `########################x .###;", a);
msg(" *#####n;#@## ;##"
- "* ,x#####################@` W##*");
+ "* ,x#####################@` W##*", a);
msg(" *#######n;* :M##"
- "W*, *W####################` n##z");
+ "W*, *W####################` n##z", a);
msg(" i########@. ,*n####"
- "###M*` `###################M *##M");
+ "###M*` `###################M *##M", a);
msg(" i########n `z#####@@"
- "#####Wi ,M################; ,##@`");
+ "#####Wi ,M################; ,##@`", a);
msg(" ;WMWW@###* .x##@ni.``"
- ".:+zW##z` `n##############z @##,");
+ ".:+zW##z` `n##############z @##,", a);
msg(" .*++*i;;;. .M#@+` "
- " .##n `x############x` n##i");
+ " .##n `x############x` n##i", a);
msg(" :########* x#W, "
- " *#+ *###########M` +##+");
+ " *#+ *###########M` +##+", a);
msg(" ,######### :#@: "
- " ##: #nzzzzzzzzzz. :##x");
+ " ##: #nzzzzzzzzzz. :##x", a);
msg(" .#####Wz+` ##+ "
- " `MM` .znnnnnnnnn. `@#@`");
+ " `MM` .znnnnnnnnn. `@#@`", a);
msg(" `@@ni;*nMz` @W` "
- " :#+ .x#######n x##,");
+ " :#+ .x#######n x##,", a);
msg(" i;z@#####, .#* "
- " z#: ;;;*zW##; ###i");
+ " z#: ;;;*zW##; ###i", a);
msg(" z########: :#; "
- " `Wx +###Wni;n. ;##z");
+ " `Wx +###Wni;n. ;##z", a);
msg(" n########W: .#* "
- " ,#, ;#######@+ `@#M");
+ " ,#, ;#######@+ `@#M", a);
msg(" .###########n;.MM "
- " n* ;iM#######* x#@`");
+ " n* ;iM#######* x#@`", a);
msg(" :#############@;; "
- " .n` ,#W*iW#####W` +##,");
+ " .n` ,#W*iW#####W` +##,", a);
msg(" ,##############. "
- " ix. `x###M;####### ,##i");
+ " ix. `x###M;####### ,##i", a);
msg(" .#############@` "
- " x@n**#W######z;M###@. W##");
+ " x@n**#W######z;M###@. W##", a);
msg(" .##############W: "
- " .x############@*;zW#; z#x");
+ " .x############@*;zW#; z#x", a);
msg(" ,###############@; "
- " `##############@n*;. i#@");
+ " `##############@n*;. i#@", a);
msg(" ,#################i "
- " :n##############W` .##,");
+ " :n##############W` .##,", a);
msg(" ,###################` "
- " .+W##########W, `##i");
+ " .+W##########W, `##i", a);
msg(" :###################@zi,` "
- " ;zM@@@WMn*` @#z");
+ " ;zM@@@WMn*` @#z", a);
msg(" :#######################@x+"
- "*i;;:i#M, `` M#W");
+ "*i;;:i#M, `` M#W", a);
msg(" ;##########################"
- "######@x. n##,");
+ "######@x. n##,", a);
msg(" i#####################@W@@@"
- "@Wxz*:` *##+");
+ "@Wxz*:` *##+", a);
msg(" *######################+```"
- " :##M");
+ " :##M", a);
msg(" ########################M; "
- " `@##,");
+ " `@##,", a);
msg(" z#########################x"
- ", z###");
+ ", z###", a);
msg(" n##########################"
- "#n: ;##W`");
+ "#n: ;##W`", a);
msg(" x##########################"
- "###Mz#++##* `W##i");
+ "###Mz#++##* `W##i", a);
msg(" M##########################"
- "##########@` ###x");
+ "##########@` ###x", a);
msg(" W##########################"
- "###########` .###,");
+ "###########` .###,", a);
msg(" @##########################"
- "##########M n##z");
+ "##########M n##z", a);
msg(" @##################z*i@WMMM"
- "x#x@#####,. :##@.");
+ "x#x@#####,. :##@.", a);
msg(" `#####################@xi` "
- " `::,* x##+");
+ " `::,* x##+", a);
msg(" .#####################@#M. "
- " ;##@`");
+ " ;##@`", a);
msg(" ,#####################:. "
- " M##i");
+ " M##i", a);
msg(" ;###################ni` "
- " i##M");
+ " i##M", a);
msg(" *#################W#` "
- " `W##,");
+ " `W##,", a);
msg(" z#################@Wx+. "
- " +###");
+ " +###", a);
msg(" x######################z. "
- " .@#@`");
+ " .@#@`", a);
msg(" `@#######################@; "
- " z##;");
+ " z##;", a);
msg(" :##########################: "
- " :##z");
+ " :##z", a);
msg(" +#########################W# "
- " M#W");
+ " M#W", a);
msg(" W################@n+*i;:,` "
- " +##,");
+ " +##,", a);
msg(" :##################WMxz+, "
- " ,##i");
+ " ,##i", a);
msg(" n#######################W.., "
- " W##");
+ " W##", a);
msg(" +#########################WW@+. .:. "
- " z#x");
+ " z#x", a);
msg(" `@#############################@@###: "
- " *#W");
+ " *#W", a);
msg(" #################################Wz: "
- " :#@");
+ " :#@", a);
msg(",@###############################i "
- " .##");
+ " .##", a);
msg("n@@@@@@@#########################+ "
- " `##");
+ " `##", a);
msg("` `.:.`.,:iii;;;;;;;;iii;;;:` `.`` "
- " `nW");
+ " `nW", a);
}
/// Get argt of command with id