aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ex_cmds.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/ex_cmds.c')
-rw-r--r--src/nvim/ex_cmds.c570
1 files changed, 226 insertions, 344 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index ea51cac163..437a05f61d 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -4,20 +4,27 @@
// ex_cmds.c: some functions for command line commands
#include <assert.h>
+#include <ctype.h>
#include <float.h>
#include <inttypes.h>
#include <math.h>
#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
-#include "nvim/api/buffer.h"
-#include "nvim/api/private/defs.h"
+#include "auto/config.h"
+#include "klib/kvec.h"
#include "nvim/arglist.h"
#include "nvim/ascii.h"
+#include "nvim/autocmd.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/buffer_updates.h"
#include "nvim/change.h"
+#include "nvim/channel.h"
#include "nvim/charset.h"
#include "nvim/cmdhist.h"
#include "nvim/cursor.h"
@@ -27,22 +34,27 @@
#include "nvim/drawscreen.h"
#include "nvim/edit.h"
#include "nvim/eval.h"
+#include "nvim/eval/typval.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds2.h"
+#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
#include "nvim/ex_getln.h"
#include "nvim/extmark.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
-#include "nvim/garray.h"
#include "nvim/getchar.h"
+#include "nvim/gettext.h"
+#include "nvim/globals.h"
+#include "nvim/grid_defs.h"
#include "nvim/help.h"
-#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/indent.h"
#include "nvim/input.h"
-#include "nvim/log.h"
+#include "nvim/lua/executor.h"
+#include "nvim/macros.h"
#include "nvim/main.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
@@ -55,21 +67,22 @@
#include "nvim/ops.h"
#include "nvim/option.h"
#include "nvim/optionstr.h"
+#include "nvim/os/fs_defs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
#include "nvim/os/shell.h"
#include "nvim/os/time.h"
-#include "nvim/os_unix.h"
#include "nvim/path.h"
#include "nvim/plines.h"
#include "nvim/profile.h"
#include "nvim/quickfix.h"
#include "nvim/regexp.h"
+#include "nvim/screen.h"
#include "nvim/search.h"
#include "nvim/spell.h"
#include "nvim/strings.h"
-#include "nvim/syntax.h"
-#include "nvim/tag.h"
+#include "nvim/terminal.h"
+#include "nvim/types.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/vim.h"
@@ -145,14 +158,14 @@ void do_ascii(const exarg_T *const eap)
char buf2[20];
buf2[0] = NUL;
- dig = (char *)get_digraph_for_char(cval);
+ dig = get_digraph_for_char(cval);
if (dig != NULL) {
- iobuff_len += (size_t)vim_snprintf((char *)IObuff + iobuff_len,
+ iobuff_len += (size_t)vim_snprintf(IObuff + iobuff_len,
sizeof(IObuff) - iobuff_len,
_("<%s>%s%s %d, Hex %02x, Oct %03o, Digr %s"),
transchar(c), buf1, buf2, cval, cval, cval, dig);
} else {
- iobuff_len += (size_t)vim_snprintf((char *)IObuff + iobuff_len,
+ iobuff_len += (size_t)vim_snprintf(IObuff + iobuff_len,
sizeof(IObuff) - iobuff_len,
_("<%s>%s%s %d, Hex %02x, Octal %03o"),
transchar(c), buf1, buf2, cval, cval, cval);
@@ -191,18 +204,18 @@ void do_ascii(const exarg_T *const eap)
if (utf_iscomposing(c)) {
IObuff[iobuff_len++] = ' '; // Draw composing char on top of a space.
}
- iobuff_len += (size_t)utf_char2bytes(c, (char *)IObuff + iobuff_len);
+ iobuff_len += (size_t)utf_char2bytes(c, IObuff + iobuff_len);
- dig = (char *)get_digraph_for_char(c);
+ dig = get_digraph_for_char(c);
if (dig != NULL) {
- iobuff_len += (size_t)vim_snprintf((char *)IObuff + iobuff_len,
+ iobuff_len += (size_t)vim_snprintf(IObuff + iobuff_len,
sizeof(IObuff) - iobuff_len,
(c < 0x10000
? _("> %d, Hex %04x, Oct %o, Digr %s")
: _("> %d, Hex %08x, Oct %o, Digr %s")),
c, c, c, dig);
} else {
- iobuff_len += (size_t)vim_snprintf((char *)IObuff + iobuff_len,
+ iobuff_len += (size_t)vim_snprintf(IObuff + iobuff_len,
sizeof(IObuff) - iobuff_len,
(c < 0x10000
? _("> %d, Hex %04x, Octal %o")
@@ -215,10 +228,10 @@ void do_ascii(const exarg_T *const eap)
c = cc[ci++];
}
if (ci != MAX_MCO && c != 0) {
- xstrlcpy((char *)IObuff + iobuff_len, " ...", sizeof(IObuff) - iobuff_len);
+ xstrlcpy(IObuff + iobuff_len, " ...", sizeof(IObuff) - iobuff_len);
}
- msg((char *)IObuff);
+ msg(IObuff);
}
/// ":left", ":center" and ":right": align text.
@@ -266,13 +279,12 @@ void ex_align(exarg_T *eap)
}
for (curwin->w_cursor.lnum = eap->line1;
- curwin->w_cursor.lnum <= eap->line2; ++curwin->w_cursor.lnum) {
+ curwin->w_cursor.lnum <= eap->line2; curwin->w_cursor.lnum++) {
if (eap->cmdidx == CMD_left) { // left align
new_indent = indent;
} else {
has_tab = false; // avoid uninit warnings
- len = linelen(eap->cmdidx == CMD_right ? &has_tab
- : NULL) - get_indent();
+ len = linelen(eap->cmdidx == CMD_right ? &has_tab : NULL) - get_indent();
if (len <= 0) { // skip blank lines
continue;
@@ -335,7 +347,7 @@ static int linelen(int *has_tab)
char save = *last;
*last = NUL;
// Get line length.
- len = linetabsize((char_u *)line);
+ len = linetabsize(line);
// Check for embedded TAB.
if (has_tab != NULL) {
*has_tab = vim_strchr(first, TAB) != NULL;
@@ -505,9 +517,8 @@ void ex_sort(exarg_T *eap)
eap->nextcmd = check_nextcmd(p);
break;
} else if (!ASCII_ISALPHA(*p) && regmatch.regprog == NULL) {
- s = skip_regexp(p + 1, *p, true, NULL);
- if (*s != *p) {
- emsg(_(e_invalpat));
+ s = skip_regexp_err(p + 1, *p, true);
+ if (s == NULL) {
goto sortend;
}
*s = NUL;
@@ -517,7 +528,7 @@ void ex_sort(exarg_T *eap)
emsg(_(e_noprevre));
goto sortend;
}
- regmatch.regprog = vim_regcomp((char *)last_search_pat(), RE_MAGIC);
+ regmatch.regprog = vim_regcomp(last_search_pat(), RE_MAGIC);
} else {
regmatch.regprog = vim_regcomp(p + 1, RE_MAGIC);
}
@@ -708,187 +719,6 @@ sortend:
}
}
-/// ":retab".
-void ex_retab(exarg_T *eap)
-{
- linenr_T lnum;
- bool got_tab = false;
- long num_spaces = 0;
- long num_tabs;
- long len;
- long col;
- long vcol;
- long start_col = 0; // For start of white-space string
- long start_vcol = 0; // For start of white-space string
- long old_len;
- char *ptr;
- char *new_line = (char *)1; // init to non-NULL
- bool did_undo; // called u_save for current line
- long *new_vts_array = NULL;
- char *new_ts_str; // string value of tab argument
-
- int save_list;
- linenr_T first_line = 0; // first changed line
- linenr_T last_line = 0; // last changed line
-
- save_list = curwin->w_p_list;
- curwin->w_p_list = 0; // don't want list mode here
-
- new_ts_str = eap->arg;
- if (!tabstop_set(eap->arg, &new_vts_array)) {
- return;
- }
- while (ascii_isdigit(*(eap->arg)) || *(eap->arg) == ',') {
- (eap->arg)++;
- }
-
- // This ensures that either new_vts_array and new_ts_str are freshly
- // allocated, or new_vts_array points to an existing array and new_ts_str
- // is null.
- if (new_vts_array == NULL) {
- new_vts_array = curbuf->b_p_vts_array;
- new_ts_str = NULL;
- } else {
- new_ts_str = xstrnsave(new_ts_str, (size_t)(eap->arg - new_ts_str));
- }
- for (lnum = eap->line1; !got_int && lnum <= eap->line2; lnum++) {
- ptr = ml_get(lnum);
- col = 0;
- vcol = 0;
- did_undo = false;
- for (;;) {
- if (ascii_iswhite(ptr[col])) {
- if (!got_tab && num_spaces == 0) {
- // First consecutive white-space
- start_vcol = vcol;
- start_col = col;
- }
- if (ptr[col] == ' ') {
- num_spaces++;
- } else {
- got_tab = true;
- }
- } else {
- if (got_tab || (eap->forceit && num_spaces > 1)) {
- // Retabulate this string of white-space
-
- // len is virtual length of white string
- len = num_spaces = vcol - start_vcol;
- num_tabs = 0;
- if (!curbuf->b_p_et) {
- int t, s;
-
- tabstop_fromto((colnr_T)start_vcol, (colnr_T)vcol,
- curbuf->b_p_ts, new_vts_array, &t, &s);
- num_tabs = t;
- num_spaces = s;
- }
- if (curbuf->b_p_et || got_tab
- || (num_spaces + num_tabs < len)) {
- if (did_undo == false) {
- did_undo = true;
- if (u_save((linenr_T)(lnum - 1),
- (linenr_T)(lnum + 1)) == FAIL) {
- new_line = NULL; // flag out-of-memory
- break;
- }
- }
-
- // len is actual number of white characters used
- len = num_spaces + num_tabs;
- old_len = (long)strlen(ptr);
- const long new_len = old_len - col + start_col + len + 1;
- if (new_len <= 0 || new_len >= MAXCOL) {
- emsg(_(e_resulting_text_too_long));
- break;
- }
- new_line = xmalloc((size_t)new_len);
-
- if (start_col > 0) {
- memmove(new_line, ptr, (size_t)start_col);
- }
- memmove(new_line + start_col + len,
- ptr + col, (size_t)(old_len - col + 1));
- ptr = new_line + start_col;
- for (col = 0; col < len; col++) {
- ptr[col] = (col < num_tabs) ? '\t' : ' ';
- }
- if (ml_replace(lnum, new_line, false) == OK) {
- // "new_line" may have been copied
- new_line = (char *)curbuf->b_ml.ml_line_ptr;
- extmark_splice_cols(curbuf, lnum - 1, 0, (colnr_T)old_len,
- (colnr_T)new_len - 1, kExtmarkUndo);
- }
- if (first_line == 0) {
- first_line = lnum;
- }
- last_line = lnum;
- ptr = new_line;
- col = start_col + len;
- }
- }
- got_tab = false;
- num_spaces = 0;
- }
- if (ptr[col] == NUL) {
- break;
- }
- vcol += win_chartabsize(curwin, ptr + col, (colnr_T)vcol);
- if (vcol >= MAXCOL) {
- emsg(_(e_resulting_text_too_long));
- break;
- }
- col += utfc_ptr2len(ptr + col);
- }
- if (new_line == NULL) { // out of memory
- break;
- }
- line_breakcheck();
- }
- if (got_int) {
- emsg(_(e_interr));
- }
-
- // If a single value was given then it can be considered equal to
- // either the value of 'tabstop' or the value of 'vartabstop'.
- if (tabstop_count(curbuf->b_p_vts_array) == 0
- && tabstop_count(new_vts_array) == 1
- && curbuf->b_p_ts == tabstop_first(new_vts_array)) {
- // not changed
- } else if (tabstop_count(curbuf->b_p_vts_array) > 0
- && tabstop_eq(curbuf->b_p_vts_array, new_vts_array)) {
- // not changed
- } else {
- redraw_curbuf_later(UPD_NOT_VALID);
- }
- if (first_line != 0) {
- changed_lines(first_line, 0, last_line + 1, 0L, true);
- }
-
- curwin->w_p_list = save_list; // restore 'list'
-
- if (new_ts_str != NULL) { // set the new tabstop
- // If 'vartabstop' is in use or if the value given to retab has more
- // than one tabstop then update 'vartabstop'.
- long *old_vts_ary = curbuf->b_p_vts_array;
-
- if (tabstop_count(old_vts_ary) > 0 || tabstop_count(new_vts_array) > 1) {
- set_string_option_direct("vts", -1, new_ts_str, OPT_FREE | OPT_LOCAL, 0);
- curbuf->b_p_vts_array = new_vts_array;
- xfree(old_vts_ary);
- } else {
- // 'vartabstop' wasn't in use and a single value was given to
- // retab then update 'tabstop'.
- curbuf->b_p_ts = tabstop_first(new_vts_array);
- xfree(new_vts_array);
- }
- xfree(new_ts_str);
- }
- coladvance(curwin->w_curswant);
-
- u_clearline();
-}
-
/// :move command - move lines line1-line2 to line dest
///
/// @return FAIL for failure, OK otherwise
@@ -1008,7 +838,9 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
ml_delete(line1 + extra, true);
}
if (!global_busy && num_lines > p_report) {
- smsg(NGETTEXT("1 line moved", "%" PRId64 " lines moved", num_lines), (int64_t)num_lines);
+ smsg(NGETTEXT("%" PRId64 " line moved",
+ "%" PRId64 " lines moved", num_lines),
+ (int64_t)num_lines);
}
extmark_move_region(curbuf, line1 - 1, 0, start_byte,
@@ -1124,8 +956,7 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
int scroll_save = msg_scroll;
//
- // Disallow shell commands from .exrc and .vimrc in current directory for
- // security reasons.
+ // Disallow shell commands in secure mode
//
if (check_secure()) {
return;
@@ -1137,10 +968,12 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
msg_scroll = scroll_save;
}
- // Try to find an embedded bang, like in :!<cmd> ! [args]
- // (:!! is indicated by the 'forceit' variable)
+ // Try to find an embedded bang, like in ":!<cmd> ! [args]"
+ // ":!!" is indicated by the 'forceit' variable.
bool ins_prevcmd = forceit;
- trailarg = arg;
+
+ // Skip leading white space to avoid a strange error with some shells.
+ trailarg = skipwhite(arg);
do {
len = strlen(trailarg) + 1;
if (newcmd != NULL) {
@@ -1192,7 +1025,7 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
// If % or # appears in the command, it must have been escaped.
// Reescape them, so that redoing them does not substitute them by the
// buffername.
- char *cmd = (char *)vim_strsave_escaped((char_u *)prevcmd, (char_u *)"%#");
+ char *cmd = vim_strsave_escaped(prevcmd, "%#");
AppendToRedobuffLit(cmd, -1);
xfree(cmd);
@@ -1201,7 +1034,7 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
}
// Add quotes around the command, for shells that need them.
if (*p_shq != NUL) {
- newcmd = xmalloc(strlen(prevcmd) + 2 * STRLEN(p_shq) + 1);
+ newcmd = xmalloc(strlen(prevcmd) + 2 * strlen(p_shq) + 1);
STRCPY(newcmd, p_shq);
STRCAT(newcmd, prevcmd);
STRCAT(newcmd, p_shq);
@@ -1346,7 +1179,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
read_linecount = curbuf->b_ml.ml_line_count;
// Pass on the kShellOptDoOut flag when the output is being redirected.
- call_shell((char_u *)cmd_buf, (ShellOpts)(kShellOptFilter | shell_flags), NULL);
+ call_shell(cmd_buf, (ShellOpts)(kShellOptFilter | shell_flags), NULL);
xfree(cmd_buf);
did_check_timestamps = false;
@@ -1465,8 +1298,7 @@ filterend:
/// @param flags may be SHELL_DOOUT when output is redirected
void do_shell(char *cmd, int flags)
{
- // Disallow shell commands from .exrc and .vimrc in current directory for
- // security reasons.
+ // Disallow shell commands in secure mode
if (check_secure()) {
msg_end();
return;
@@ -1492,7 +1324,7 @@ void do_shell(char *cmd, int flags)
// This ui_cursor_goto is required for when the '\n' resulted in a "delete line
// 1" command to the terminal.
ui_cursor_goto(msg_row, msg_col);
- (void)call_shell((char_u *)cmd, (ShellOpts)flags, NULL);
+ (void)call_shell(cmd, (ShellOpts)flags, NULL);
msg_didout = true;
did_check_timestamps = false;
need_check_timestamps = true;
@@ -1512,11 +1344,11 @@ static char *find_pipe(const char *cmd)
for (const char *p = cmd; *p != NUL; p++) {
if (!inquote && *p == '|') {
- return p;
+ return (char *)p;
}
if (*p == '"') {
inquote = !inquote;
- } else if (rem_backslash((const char_u *)p)) {
+ } else if (rem_backslash(p)) {
p++;
}
}
@@ -1535,12 +1367,13 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
{
bool is_fish_shell =
#if defined(UNIX)
- STRNCMP(invocation_path_tail((char_u *)p_sh, NULL), "fish", 4) == 0;
+ strncmp((char *)invocation_path_tail(p_sh, NULL), "fish", 4) == 0;
#else
false;
#endif
- bool is_pwsh = STRNCMP(invocation_path_tail((char_u *)p_sh, NULL), "pwsh", 4) == 0
- || STRNCMP(invocation_path_tail((char_u *)p_sh, NULL), "powershell", 10) == 0;
+ bool is_pwsh = strncmp((char *)invocation_path_tail(p_sh, NULL), "pwsh", 4) == 0
+ || strncmp((char *)invocation_path_tail(p_sh, NULL), "powershell",
+ 10) == 0;
size_t len = strlen(cmd) + 1; // At least enough space for cmd + NULL.
@@ -1549,7 +1382,7 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
: 0;
if (itmp != NULL) {
- len += is_pwsh ? strlen(itmp) + sizeof("& { Get-Content " " | & " " }") - 1
+ len += is_pwsh ? strlen(itmp) + sizeof("& { Get-Content " " | & " " }") - 1 + 6 // +6: #20530
: strlen(itmp) + sizeof(" { " " < " " } ") - 1;
}
if (otmp != NULL) {
@@ -1587,7 +1420,7 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
#else
// For shells that don't understand braces around commands, at least allow
// the use of commands in a pipe.
- xstrlcpy(buf, (char *)cmd, len);
+ xstrlcpy(buf, cmd, len);
if (itmp != NULL) {
// If there is a pipe, we have to put the '<' in front of it.
// Don't do this when 'shellquote' is not empty, otherwise the
@@ -1670,7 +1503,7 @@ void print_line(linenr_T lnum, int use_number, int list)
msg_start();
silent_mode = false;
- info_message = true; // use mch_msg(), not mch_errmsg()
+ info_message = true; // use os_msg(), not os_errmsg()
print_line_no_prefix(lnum, use_number, list);
if (save_silent) {
msg_putchar('\n');
@@ -1774,12 +1607,23 @@ void ex_write(exarg_T *eap)
}
}
-/// write current buffer to file 'eap->arg'
-/// if 'eap->append' is true, append to the file
+#ifdef UNIX
+static int check_writable(const char *fname)
+{
+ if (os_nodetype(fname) == NODE_OTHER) {
+ semsg(_("E503: \"%s\" is not a file or writable device"), fname);
+ return FAIL;
+ }
+ return OK;
+}
+#endif
+
+/// Write current buffer to file "eap->arg".
+/// If "eap->append" is true, append to the file.
///
-/// if *eap->arg == NUL write to current file
+/// If "*eap->arg == NUL" write to current file.
///
-/// @return FAIL for failure, OK otherwise
+/// @return FAIL for failure, OK otherwise.
int do_write(exarg_T *eap)
{
int other;
@@ -1831,7 +1675,11 @@ int do_write(exarg_T *eap)
// Writing to the current file is not allowed in readonly mode
// and a file name is required.
// "nofile" and "nowrite" buffers cannot be written implicitly either.
- if (!other && (bt_dontwrite_msg(curbuf) || check_fname() == FAIL
+ if (!other && (bt_dontwrite_msg(curbuf)
+ || check_fname() == FAIL
+#ifdef UNIX
+ || check_writable(curbuf->b_ffname) == FAIL
+#endif
|| check_readonly(&eap->forceit, curbuf))) {
goto theend;
}
@@ -1909,6 +1757,13 @@ int do_write(exarg_T *eap)
fname = curbuf->b_sfname;
}
+ if (eap->mkdir_p) {
+ if (os_file_mkdir(fname, 0755) < 0) {
+ retval = FAIL;
+ goto theend;
+ }
+ }
+
name_was_missing = curbuf->b_ffname == NULL;
retval = buf_write(curbuf, ffname, fname, eap->line1, eap->line2,
eap, eap->append, eap->forceit, true, false);
@@ -1999,7 +1854,7 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char *fname, char *ffname, int oth
p = p_dir;
copy_option_part(&p, dir, MAXPATHL, ",");
}
- swapname = (char *)makeswapname((char_u *)fname, (char_u *)ffname, curbuf, (char_u *)dir);
+ swapname = makeswapname(fname, ffname, curbuf, dir);
xfree(dir);
if (os_path_exists(swapname)) {
if (p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) {
@@ -2139,9 +1994,8 @@ static int check_readonly(int *forceit, buf_T *buf)
// Set forceit, to force the writing of a readonly file
*forceit = true;
return false;
- } else {
- return true;
}
+ return true;
} else if (buf->b_p_ro) {
emsg(_(e_readonly));
} else {
@@ -3182,8 +3036,7 @@ void ex_z(exarg_T *eap)
ex_no_reprint = true;
}
-/// @return true if the secure flag is set (.exrc or .vimrc in current directory)
-/// and also give an error message.
+/// @return true if the secure flag is set and also give an error message.
/// Otherwise, return false.
bool check_secure(void)
{
@@ -3240,7 +3093,7 @@ void sub_set_replacement(SubReplacementString sub)
/// @param[in] save Save pattern to options, history
///
/// @returns true if :substitute can be replaced with a join command
-static bool sub_joining_lines(exarg_T *eap, char *pat, char *sub, char *cmd, bool save)
+static bool sub_joining_lines(exarg_T *eap, char *pat, const char *sub, const char *cmd, bool save)
FUNC_ATTR_NONNULL_ARG(1, 3, 4)
{
// TODO(vim): find a generic solution to make line-joining operations more
@@ -3279,7 +3132,7 @@ static bool sub_joining_lines(exarg_T *eap, char *pat, char *sub, char *cmd, boo
if (save) {
if ((cmdmod.cmod_flags & CMOD_KEEPPATTERNS) == 0) {
- save_re_pat(RE_SUBST, pat, p_magic);
+ save_re_pat(RE_SUBST, pat, magic_isset());
}
// put pattern in history
add_to_history(HIST_SEARCH, pat, true, NUL);
@@ -3410,6 +3263,30 @@ static int check_regexp_delim(int c)
/// @return 0, 1 or 2. See show_cmdpreview() for more information on what the return value means.
static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T cmdpreview_bufnr)
{
+#define ADJUST_SUB_FIRSTLNUM() \
+ do { \
+ /* For a multi-line match, make a copy of the last matched */ \
+ /* line and continue in that one. */ \
+ if (nmatch > 1) { \
+ sub_firstlnum += (linenr_T)nmatch - 1; \
+ xfree(sub_firstline); \
+ sub_firstline = xstrdup(ml_get(sub_firstlnum)); \
+ /* When going beyond the last line, stop substituting. */ \
+ if (sub_firstlnum <= line2) { \
+ do_again = true; \
+ } else { \
+ subflags.do_all = false; \
+ } \
+ } \
+ if (skip_match) { \
+ /* Already hit end of the buffer, sub_firstlnum is one */ \
+ /* less than what it ought to be. */ \
+ xfree(sub_firstline); \
+ sub_firstline = xstrdup(""); \
+ copycol = 0; \
+ } \
+ } while (0)
+
long i = 0;
regmmatch_T regmatch;
static subflags_T subflags = {
@@ -3455,7 +3332,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
}
// new pattern and substitution
if (eap->cmd[0] == 's' && *cmd != NUL && !ascii_iswhite(*cmd)
- && vim_strchr("0123456789cegriIp|\"", *cmd) == NULL) {
+ && vim_strchr("0123456789cegriIp|\"", (uint8_t)(*cmd)) == NULL) {
// don't accept alphanumeric for separator
if (check_regexp_delim(*cmd) == FAIL) {
return 0;
@@ -3466,7 +3343,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
// //sub/r). "\&sub&" use last substitute pattern (like //sub/).
if (*cmd == '\\') {
cmd++;
- if (vim_strchr("/?&", *cmd) == NULL) {
+ if (vim_strchr("/?&", (uint8_t)(*cmd)) == NULL) {
emsg(_(e_backslash));
return 0;
}
@@ -3474,13 +3351,13 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
which_pat = RE_SEARCH; // use last '/' pattern
}
pat = ""; // empty search pattern
- delimiter = (char_u)(*cmd++); // remember delimiter character
+ delimiter = (uint8_t)(*cmd++); // remember delimiter character
has_second_delim = true;
} else { // find the end of the regexp
which_pat = RE_LAST; // use last used regexp
- delimiter = (char_u)(*cmd++); // remember delimiter character
+ delimiter = (uint8_t)(*cmd++); // remember delimiter character
pat = cmd; // remember start of search pat
- cmd = skip_regexp(cmd, delimiter, p_magic, &eap->arg);
+ cmd = skip_regexp_ex(cmd, delimiter, magic_isset(), &eap->arg, NULL, NULL);
if (cmd[0] == delimiter) { // end delimiter found
*cmd++ = NUL; // replace it with a NUL
has_second_delim = true;
@@ -3566,8 +3443,8 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
return 0;
}
- if (search_regcomp((char_u *)pat, RE_SUBST, which_pat, (cmdpreview ? 0 : SEARCH_HIS),
- &regmatch) == FAIL) {
+ if (search_regcomp(pat, NULL, RE_SUBST, which_pat,
+ (cmdpreview ? 0 : SEARCH_HIS), &regmatch) == FAIL) {
if (subflags.do_error) {
emsg(_(e_invcmd));
}
@@ -3596,7 +3473,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
sub = xstrdup(sub);
sub_copy = sub;
} else {
- char *newsub = regtilde(sub, p_magic, cmdpreview);
+ char *newsub = regtilde(sub, magic_isset(), cmdpreview);
if (newsub != sub) {
// newsub was allocated, free it later.
sub_copy = newsub;
@@ -3820,7 +3697,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
msg_putchar('\n');
xfree(prompt);
if (resp != NULL) {
- typed = (char_u)(*resp);
+ typed = (uint8_t)(*resp);
xfree(resp);
} else {
// getcmdline_prompt() returns NULL if there is no command line to return.
@@ -3981,30 +3858,6 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
skip_match = true;
}
-#define ADJUST_SUB_FIRSTLNUM() \
- do { \
- /* For a multi-line match, make a copy of the last matched */ \
- /* line and continue in that one. */ \
- if (nmatch > 1) { \
- sub_firstlnum += (linenr_T)nmatch - 1; \
- xfree(sub_firstline); \
- sub_firstline = xstrdup(ml_get(sub_firstlnum)); \
- /* When going beyond the last line, stop substituting. */ \
- if (sub_firstlnum <= line2) { \
- do_again = true; \
- } else { \
- subflags.do_all = false; \
- } \
- } \
- if (skip_match) { \
- /* Already hit end of the buffer, sub_firstlnum is one */ \
- /* less than what it ought to be. */ \
- xfree(sub_firstline); \
- sub_firstline = xstrdup(""); \
- copycol = 0; \
- } \
- } while (0)
-
// Save the line numbers for the preview buffer
// NOTE: If the pattern matches a final newline, the next line will
// be shown also, but should not be highlighted. Intentional for now.
@@ -4042,8 +3895,9 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
// When it fails sublen is zero.
sublen = vim_regsub_multi(&regmatch,
sub_firstlnum - regmatch.startpos[0].lnum,
- (char_u *)sub, (char_u *)sub_firstline, 0,
- REGSUB_BACKSLASH | (p_magic ? REGSUB_MAGIC : 0));
+ sub, sub_firstline, 0,
+ REGSUB_BACKSLASH
+ | (magic_isset() ? REGSUB_MAGIC : 0));
textlock--;
// If getting the substitute string caused an error, don't do
@@ -4084,8 +3938,9 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
textlock++;
(void)vim_regsub_multi(&regmatch,
sub_firstlnum - regmatch.startpos[0].lnum,
- (char_u *)sub, (char_u *)new_end, sublen,
- REGSUB_COPY | REGSUB_BACKSLASH | (p_magic ? REGSUB_MAGIC : 0));
+ sub, new_end, sublen,
+ REGSUB_COPY | REGSUB_BACKSLASH
+ | (magic_isset() ? REGSUB_MAGIC : 0));
textlock--;
sub_nsubs++;
did_sub = true;
@@ -4517,7 +4372,7 @@ void ex_global(exarg_T *eap)
// "\&": use previous substitute pattern.
if (*cmd == '\\') {
cmd++;
- if (vim_strchr("/?&", *cmd) == NULL) {
+ if (vim_strchr("/?&", (uint8_t)(*cmd)) == NULL) {
emsg(_(e_backslash));
return;
}
@@ -4537,13 +4392,15 @@ void ex_global(exarg_T *eap)
delim = *cmd; // get the delimiter
cmd++; // skip delimiter if there is one
pat = cmd; // remember start of pattern
- cmd = skip_regexp(cmd, delim, p_magic, &eap->arg);
+ cmd = skip_regexp_ex(cmd, delim, magic_isset(), &eap->arg, NULL, NULL);
if (cmd[0] == delim) { // end delimiter found
*cmd++ = NUL; // replace it with a NUL
}
}
- if (search_regcomp((char_u *)pat, RE_BOTH, which_pat, SEARCH_HIS, &regmatch) == FAIL) {
+ char *used_pat;
+ if (search_regcomp(pat, &used_pat, RE_BOTH, which_pat,
+ SEARCH_HIS, &regmatch) == FAIL) {
emsg(_(e_invcmd));
return;
}
@@ -4574,9 +4431,9 @@ void ex_global(exarg_T *eap)
msg(_(e_interr));
} else if (ndone == 0) {
if (type == 'v') {
- smsg(_("Pattern found in every line: %s"), pat);
+ smsg(_("Pattern found in every line: %s"), used_pat);
} else {
- smsg(_("Pattern not found: %s"), pat);
+ smsg(_("Pattern not found: %s"), used_pat);
}
} else {
global_exe(cmd);
@@ -4653,32 +4510,30 @@ void free_old_sub(void)
/// @return true when it was created.
bool prepare_tagpreview(bool undo_sync)
{
+ if (curwin->w_p_pvw) {
+ return false;
+ }
+
// If there is already a preview window open, use that one.
- if (!curwin->w_p_pvw) {
- bool found_win = false;
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_p_pvw) {
- win_enter(wp, undo_sync);
- found_win = true;
- break;
- }
- }
- if (!found_win) {
- // There is no preview window open yet. Create one.
- if (win_split(g_do_tagpreview > 0 ? g_do_tagpreview : 0, 0)
- == FAIL) {
- return false;
- }
- curwin->w_p_pvw = true;
- curwin->w_p_wfh = true;
- RESET_BINDING(curwin); // don't take over 'scrollbind' and 'cursorbind'
- curwin->w_p_diff = false; // no 'diff'
- set_string_option_direct("fdc", -1, // no 'foldcolumn'
- "0", OPT_FREE, SID_NONE);
- return true;
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ if (wp->w_p_pvw) {
+ win_enter(wp, undo_sync);
+ return false;
}
}
- return false;
+
+ // There is no preview window open yet. Create one.
+ if (win_split(g_do_tagpreview > 0 ? g_do_tagpreview : 0, 0)
+ == FAIL) {
+ return false;
+ }
+ curwin->w_p_pvw = true;
+ curwin->w_p_wfh = true;
+ RESET_BINDING(curwin); // don't take over 'scrollbind' and 'cursorbind'
+ curwin->w_p_diff = false; // no 'diff'
+ set_string_option_direct("fdc", -1, // no 'foldcolumn'
+ "0", OPT_FREE, SID_NONE);
+ return true;
}
/// Shows the effects of the :substitute command being typed ('inccommand').
@@ -4835,7 +4690,7 @@ char *skip_vimgrep_pat(char *p, char **s, int *flags)
{
int c;
- if (vim_isIDc(*p)) {
+ if (vim_isIDc((uint8_t)(*p))) {
// ":vimgrep pattern fname"
if (s != NULL) {
*s = p;
@@ -4849,8 +4704,8 @@ char *skip_vimgrep_pat(char *p, char **s, int *flags)
if (s != NULL) {
*s = p + 1;
}
- c = (char_u)(*p);
- p = skip_regexp(p + 1, c, true, NULL);
+ c = (uint8_t)(*p);
+ p = skip_regexp(p + 1, c, true);
if (*p != c) {
return NULL;
}
@@ -4886,45 +4741,72 @@ void ex_oldfiles(exarg_T *eap)
if (l == NULL) {
msg(_("No old files"));
- } else {
- msg_start();
- msg_scroll = true;
- TV_LIST_ITER(l, li, {
- if (got_int) {
- break;
- }
- nr++;
- const char *fname = tv_get_string(TV_LIST_ITEM_TV(li));
- if (!message_filtered((char *)fname)) {
- msg_outnum(nr);
- msg_puts(": ");
- msg_outtrans((char *)tv_get_string(TV_LIST_ITEM_TV(li)));
- msg_clr_eos();
- msg_putchar('\n');
- os_breakcheck();
- }
- });
-
- // Assume "got_int" was set to truncate the listing.
- got_int = false;
-
- // File selection prompt on ":browse oldfiles"
- if (cmdmod.cmod_flags & CMOD_BROWSE) {
- quit_more = false;
- nr = prompt_for_number(false);
- msg_starthere();
- if (nr > 0 && nr <= tv_list_len(l)) {
- const char *const p = tv_list_find_str(l, (int)nr - 1);
- if (p == NULL) {
- return;
- }
- char *const s = expand_env_save((char *)p);
- eap->arg = s;
- eap->cmdidx = CMD_edit;
- cmdmod.cmod_flags &= ~CMOD_BROWSE;
- do_exedit(eap, NULL);
- xfree(s);
+ return;
+ }
+
+ msg_start();
+ msg_scroll = true;
+ TV_LIST_ITER(l, li, {
+ if (got_int) {
+ break;
+ }
+ nr++;
+ const char *fname = tv_get_string(TV_LIST_ITEM_TV(li));
+ if (!message_filtered((char *)fname)) {
+ msg_outnum(nr);
+ msg_puts(": ");
+ msg_outtrans((char *)tv_get_string(TV_LIST_ITEM_TV(li)));
+ msg_clr_eos();
+ msg_putchar('\n');
+ os_breakcheck();
+ }
+ });
+
+ // Assume "got_int" was set to truncate the listing.
+ got_int = false;
+
+ // File selection prompt on ":browse oldfiles"
+ if (cmdmod.cmod_flags & CMOD_BROWSE) {
+ quit_more = false;
+ nr = prompt_for_number(false);
+ msg_starthere();
+ if (nr > 0 && nr <= tv_list_len(l)) {
+ const char *const p = tv_list_find_str(l, (int)nr - 1);
+ if (p == NULL) {
+ return;
}
+ char *const s = expand_env_save((char *)p);
+ eap->arg = s;
+ eap->cmdidx = CMD_edit;
+ cmdmod.cmod_flags &= ~CMOD_BROWSE;
+ do_exedit(eap, NULL);
+ xfree(s);
}
}
}
+
+void ex_trust(exarg_T *eap)
+{
+ const char *const p = skiptowhite(eap->arg);
+ char *arg1 = xmemdupz(eap->arg, (size_t)(p - eap->arg));
+ const char *action = "allow";
+ const char *path = skipwhite(p);
+
+ if (strcmp(arg1, "++deny") == 0) {
+ action = "deny";
+ } else if (strcmp(arg1, "++remove") == 0) {
+ action = "remove";
+ } else if (*arg1 != '\0') {
+ semsg(e_invarg2, arg1);
+ goto theend;
+ }
+
+ if (path[0] == '\0') {
+ path = NULL;
+ }
+
+ nlua_trust(action, path);
+
+theend:
+ xfree(arg1);
+}