aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ex_cmds.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-11-30 20:35:25 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-11-30 20:35:25 +0000
commit1b7b916b7631ddf73c38e3a0070d64e4636cb2f3 (patch)
treecd08258054db80bb9a11b1061bb091c70b76926a /src/nvim/ex_cmds.c
parenteaa89c11d0f8aefbb512de769c6c82f61a8baca3 (diff)
parent4a8bf24ac690004aedf5540fa440e788459e5e34 (diff)
downloadrneovim-aucmd_textputpost.tar.gz
rneovim-aucmd_textputpost.tar.bz2
rneovim-aucmd_textputpost.zip
Merge remote-tracking branch 'upstream/master' into aucmd_textputpostaucmd_textputpost
Diffstat (limited to 'src/nvim/ex_cmds.c')
-rw-r--r--src/nvim/ex_cmds.c757
1 files changed, 368 insertions, 389 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 437a05f61d..e369397047 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -1,12 +1,10 @@
-// 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_cmds.c: some functions for command line commands
#include <assert.h>
#include <ctype.h>
#include <float.h>
#include <inttypes.h>
+#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stddef.h>
@@ -18,11 +16,12 @@
#include "auto/config.h"
#include "klib/kvec.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/buffer_updates.h"
+#include "nvim/bufwrite.h"
#include "nvim/change.h"
#include "nvim/channel.h"
#include "nvim/charset.h"
@@ -44,17 +43,16 @@
#include "nvim/extmark.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
+#include "nvim/func_attr.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_defs.h"
+#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
#include "nvim/indent.h"
#include "nvim/input.h"
-#include "nvim/lua/executor.h"
-#include "nvim/macros.h"
+#include "nvim/macros_defs.h"
#include "nvim/main.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
@@ -66,26 +64,28 @@
#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_defs.h"
+#include "nvim/os/fs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
#include "nvim/os/shell.h"
#include "nvim/os/time.h"
#include "nvim/path.h"
#include "nvim/plines.h"
+#include "nvim/pos_defs.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/state_defs.h"
#include "nvim/strings.h"
#include "nvim/terminal.h"
-#include "nvim/types.h"
+#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
-#include "nvim/vim.h"
+#include "nvim/vim_defs.h"
#include "nvim/window.h"
/// Case matching style to use for :substitute
@@ -126,20 +126,28 @@ typedef struct {
# include "ex_cmds.c.generated.h"
#endif
+static const char e_non_numeric_argument_to_z[]
+ = N_("E144: Non-numeric argument to :z");
+
/// ":ascii" and "ga" implementation
-void do_ascii(const exarg_T *const eap)
+void do_ascii(exarg_T *eap)
{
- char *dig;
- int cc[MAX_MCO];
- int c = utfc_ptr2char(get_cursor_pos_ptr(), cc);
- if (c == NUL) {
- msg("NUL");
+ char *data = get_cursor_pos_ptr();
+ size_t len = (size_t)utfc_ptr2len(data);
+
+ if (len == 0) {
+ msg("NUL", 0);
return;
}
- size_t iobuff_len = 0;
+ bool need_clear = true;
+ msg_sb_eol();
+ msg_start();
+
+ int c = utf_ptr2char(data);
+ size_t off = 0;
- int ci = 0;
+ // TODO(bfredl): merge this with the main loop
if (c < 0x80) {
if (c == NL) { // NUL is stored as NL.
c = NUL;
@@ -148,56 +156,39 @@ void do_ascii(const exarg_T *const eap)
? NL // NL is stored as CR.
: c);
char buf1[20];
- if (vim_isprintc_strict(c) && (c < ' ' || c > '~')) {
+ if (vim_isprintc(c) && (c < ' ' || c > '~')) {
char buf3[7];
- transchar_nonprint(curbuf, (char_u *)buf3, c);
- vim_snprintf(buf1, sizeof(buf1), " <%s>", (char *)buf3);
+ transchar_nonprint(curbuf, buf3, c);
+ vim_snprintf(buf1, sizeof(buf1), " <%s>", buf3);
} else {
buf1[0] = NUL;
}
char buf2[20];
buf2[0] = NUL;
- dig = get_digraph_for_char(cval);
+ char *dig = get_digraph_for_char(cval);
if (dig != NULL) {
- 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);
+ vim_snprintf(IObuff, sizeof(IObuff),
+ _("<%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(IObuff + iobuff_len,
- sizeof(IObuff) - iobuff_len,
- _("<%s>%s%s %d, Hex %02x, Octal %03o"),
- transchar(c), buf1, buf2, cval, cval, cval);
- }
-
- c = cc[ci++];
- }
-
-#define SPACE_FOR_DESC (1 + 1 + 1 + MB_MAXBYTES + 16 + 4 + 3 + 3 + 1)
- // Space for description:
- // - 1 byte for separator (starting from second entry)
- // - 1 byte for "<"
- // - 1 byte for space to draw composing character on (optional, but really
- // mostly required)
- // - up to MB_MAXBYTES bytes for character itself
- // - 16 bytes for raw text ("> , Hex , Octal ").
- // - at least 4 bytes for hexadecimal representation
- // - at least 3 bytes for decimal representation
- // - at least 3 bytes for octal representation
- // - 1 byte for NUL
- //
- // Taking into account MAX_MCO and characters which need 8 bytes for
- // hexadecimal representation, but not taking translation into account:
- // resulting string will occupy less then 400 bytes (conservative estimate).
- //
- // Less then 1000 bytes if translation multiplies number of bytes needed for
- // raw text by 6, so it should always fit into 1025 bytes reserved for IObuff.
+ vim_snprintf(IObuff, sizeof(IObuff),
+ _("<%s>%s%s %d, Hex %02x, Octal %03o"),
+ transchar(c), buf1, buf2, cval, cval, cval);
+ }
+
+ msg_multiline(IObuff, 0, true, &need_clear);
+
+ off += (size_t)utf_ptr2len(data); // needed for overlong ascii?
+ }
// Repeat for combining characters, also handle multiby here.
- while (c >= 0x80 && iobuff_len < sizeof(IObuff) - SPACE_FOR_DESC) {
+ while (off < len) {
+ c = utf_ptr2char(data + off);
+
+ size_t iobuff_len = 0;
// This assumes every multi-byte char is printable...
- if (iobuff_len > 0) {
+ if (off > 0) {
IObuff[iobuff_len++] = ' ';
}
IObuff[iobuff_len++] = '<';
@@ -206,43 +197,37 @@ void do_ascii(const exarg_T *const eap)
}
iobuff_len += (size_t)utf_char2bytes(c, IObuff + iobuff_len);
- dig = get_digraph_for_char(c);
+ char *dig = get_digraph_for_char(c);
if (dig != NULL) {
- 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);
+ 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(IObuff + iobuff_len,
- sizeof(IObuff) - iobuff_len,
- (c < 0x10000
- ? _("> %d, Hex %04x, Octal %o")
- : _("> %d, Hex %08x, Octal %o")),
- c, c, c);
- }
- if (ci == MAX_MCO) {
- break;
+ vim_snprintf(IObuff + iobuff_len, sizeof(IObuff) - iobuff_len,
+ (c < 0x10000
+ ? _("> %d, Hex %04x, Octal %o")
+ : _("> %d, Hex %08x, Octal %o")),
+ c, c, c);
}
- c = cc[ci++];
- }
- if (ci != MAX_MCO && c != 0) {
- xstrlcpy(IObuff + iobuff_len, " ...", sizeof(IObuff) - iobuff_len);
+
+ msg_multiline(IObuff, 0, true, &need_clear);
+
+ off += (size_t)utf_ptr2len(data + off); // needed for overlong ascii?
}
- msg(IObuff);
+ if (need_clear) {
+ msg_clr_eos();
+ }
+ msg_end();
}
/// ":left", ":center" and ":right": align text.
void ex_align(exarg_T *eap)
{
- pos_T save_curpos;
- int len;
int indent = 0;
int new_indent;
- int has_tab;
- int width;
if (curwin->w_p_rl) {
// switch left and right aligning
@@ -253,8 +238,8 @@ void ex_align(exarg_T *eap)
}
}
- width = atoi(eap->arg);
- save_curpos = curwin->w_cursor;
+ int width = atoi(eap->arg);
+ pos_T save_curpos = curwin->w_cursor;
if (eap->cmdidx == CMD_left) { // width is used for new indent
if (width >= 0) {
indent = width;
@@ -283,8 +268,8 @@ void ex_align(exarg_T *eap)
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();
+ int has_tab = false; // avoid uninit warnings
+ int len = linelen(eap->cmdidx == CMD_right ? &has_tab : NULL) - get_indent();
if (len <= 0) { // skip blank lines
continue;
@@ -319,7 +304,7 @@ void ex_align(exarg_T *eap)
}
(void)set_indent(new_indent, 0); // set indent
}
- changed_lines(eap->line1, 0, eap->line2 + 1, 0L, true);
+ changed_lines(curbuf, eap->line1, 0, eap->line2 + 1, 0, true);
curwin->w_cursor = save_curpos;
beginline(BL_WHITE | BL_FIX);
}
@@ -327,29 +312,24 @@ void ex_align(exarg_T *eap)
/// @return the length of the current line, excluding trailing white space.
static int linelen(int *has_tab)
{
- char *line;
- char *first;
char *last;
- int len;
// Get the line. If it's empty bail out early (could be the empty string
// for an unloaded buffer).
- line = get_cursor_line_ptr();
+ char *line = get_cursor_line_ptr();
if (*line == NUL) {
return 0;
}
// find the first non-blank character
- first = skipwhite(line);
+ char *first = skipwhite(line);
// find the character after the last non-blank character
for (last = first + strlen(first);
last > first && ascii_iswhite(last[-1]); last--) {}
char save = *last;
*last = NUL;
- // Get line length.
- len = linetabsize(line);
- // Check for embedded TAB.
- if (has_tab != NULL) {
+ int len = linetabsize_str(line); // Get line length.
+ if (has_tab != NULL) { // Check for embedded TAB.
*has_tab = vim_strchr(first, TAB) != NULL;
}
*last = save;
@@ -389,7 +369,7 @@ typedef struct {
static int string_compare(const void *s1, const void *s2) FUNC_ATTR_NONNULL_ALL
{
if (sort_lc) {
- return strcoll((char *)s1, (char *)s2);
+ return strcoll((const char *)s1, (const char *)s2);
}
return sort_ic ? STRICMP(s1, s2) : strcmp(s1, s2);
}
@@ -418,10 +398,10 @@ static int sort_compare(const void *s1, const void *s2)
result = l1.st_u.num.is_number - l2.st_u.num.is_number;
} else {
result = l1.st_u.num.value == l2.st_u.num.value
- ? 0
- : l1.st_u.num.value > l2.st_u.num.value
- ? 1
- : -1;
+ ? 0
+ : l1.st_u.num.value > l2.st_u.num.value
+ ? 1
+ : -1;
}
} else if (sort_flt) {
result = l1.st_u.value_flt == l2.st_u.value_flt
@@ -452,19 +432,10 @@ static int sort_compare(const void *s1, const void *s2)
void ex_sort(exarg_T *eap)
{
regmatch_T regmatch;
- int len;
- linenr_T lnum;
- long maxlen = 0;
+ int maxlen = 0;
size_t count = (size_t)(eap->line2 - eap->line1) + 1;
size_t i;
- char *p;
- char *s;
- char *s2;
- char c; // temporary character storage
bool unique = false;
- long deleted;
- colnr_T start_col;
- colnr_T end_col;
int sort_what = 0;
// Sorting one line is really quick!
@@ -484,7 +455,7 @@ void ex_sort(exarg_T *eap)
size_t format_found = 0;
bool change_occurred = false; // Buffer contents changed.
- for (p = eap->arg; *p != NUL; p++) {
+ for (char *p = eap->arg; *p != NUL; p++) {
if (ascii_iswhite(*p)) {
// Skip
} else if (*p == 'i') {
@@ -517,7 +488,7 @@ void ex_sort(exarg_T *eap)
eap->nextcmd = check_nextcmd(p);
break;
} else if (!ASCII_ISALPHA(*p) && regmatch.regprog == NULL) {
- s = skip_regexp_err(p + 1, *p, true);
+ char *s = skip_regexp_err(p + 1, *p, true);
if (s == NULL) {
goto sortend;
}
@@ -559,15 +530,15 @@ void ex_sort(exarg_T *eap)
// numbers sorting it's the number to sort on. This means the pattern
// matching and number conversion only has to be done once per line.
// Also get the longest line length for allocating "sortbuf".
- for (lnum = eap->line1; lnum <= eap->line2; lnum++) {
- s = ml_get(lnum);
- len = (int)strlen(s);
+ for (linenr_T lnum = eap->line1; lnum <= eap->line2; lnum++) {
+ char *s = ml_get(lnum);
+ int len = (int)strlen(s);
if (maxlen < len) {
maxlen = len;
}
- start_col = 0;
- end_col = len;
+ colnr_T start_col = 0;
+ colnr_T end_col = len;
if (regmatch.regprog != NULL && vim_regexec(&regmatch, s, 0)) {
if (sort_rx) {
start_col = (colnr_T)(regmatch.startp[0] - s);
@@ -580,13 +551,13 @@ void ex_sort(exarg_T *eap)
}
if (sort_nr || sort_flt) {
- // Make sure vim_str2nr doesn't read any digits past the end
+ // Make sure vim_str2nr() doesn't read any digits past the end
// of the match, by temporarily terminating the string there
- s2 = s + end_col;
- c = *s2;
+ char *s2 = s + end_col;
+ char c = *s2; // temporary character storage
*s2 = NUL;
// Sorting on number: Store the number itself.
- p = s + start_col;
+ char *p = s + start_col;
if (sort_nr) {
if (sort_what & STR2NR_HEX) {
s = skiptohex(p);
@@ -605,7 +576,7 @@ void ex_sort(exarg_T *eap)
} else {
nrs[lnum - eap->line1].st_u.num.is_number = true;
vim_str2nr(s, NULL, NULL, sort_what,
- &nrs[lnum - eap->line1].st_u.num.value, NULL, 0, false);
+ &nrs[lnum - eap->line1].st_u.num.value, NULL, 0, false, NULL);
}
} else {
s = skipwhite(p);
@@ -651,7 +622,7 @@ void ex_sort(exarg_T *eap)
bcount_t old_count = 0, new_count = 0;
// Insert the lines in the sorted order below the last one.
- lnum = eap->line2;
+ linenr_T lnum = eap->line2;
for (i = 0; i < count; i++) {
const linenr_T get_lnum = nrs[eap->forceit ? count - i - 1 : i].lnum;
@@ -661,14 +632,14 @@ void ex_sort(exarg_T *eap)
change_occurred = true;
}
- s = ml_get(get_lnum);
+ char *s = ml_get(get_lnum);
size_t bytelen = strlen(s) + 1; // include EOL in bytelen
old_count += (bcount_t)bytelen;
if (!unique || i == 0 || string_compare(s, sortbuf1) != 0) {
// Copy the line into a buffer, it may become invalid in
// ml_append(). And it's needed for "unique".
STRCPY(sortbuf1, s);
- if (ml_append(lnum++, sortbuf1, (colnr_T)0, false) == FAIL) {
+ if (ml_append(lnum++, sortbuf1, 0, false) == FAIL) {
break;
}
new_count += (bcount_t)bytelen;
@@ -689,13 +660,12 @@ void ex_sort(exarg_T *eap)
}
// Adjust marks for deleted (or added) lines and prepare for displaying.
- deleted = (long)count - (lnum - eap->line2);
+ linenr_T deleted = (linenr_T)count - (lnum - eap->line2);
if (deleted > 0) {
- mark_adjust(eap->line2 - (linenr_T)deleted, eap->line2, (long)MAXLNUM, (linenr_T)(-deleted),
- kExtmarkNOOP);
+ mark_adjust(eap->line2 - deleted, eap->line2, MAXLNUM, -deleted, kExtmarkNOOP);
msgmore(-deleted);
} else if (deleted < 0) {
- mark_adjust(eap->line2, MAXLNUM, (linenr_T)(-deleted), 0L, kExtmarkNOOP);
+ mark_adjust(eap->line2, MAXLNUM, -deleted, 0, kExtmarkNOOP);
}
if (change_occurred || deleted != 0) {
@@ -703,7 +673,7 @@ void ex_sort(exarg_T *eap)
(int)count, 0, old_count,
lnum - eap->line2, 0, new_count, kExtmarkUndo);
- changed_lines(eap->line1, 0, eap->line2 + 1, (linenr_T)(-deleted), true);
+ changed_lines(curbuf, eap->line1, 0, eap->line2 + 1, -deleted, true);
}
curwin->w_cursor.lnum = eap->line1;
@@ -724,7 +694,6 @@ sortend:
/// @return FAIL for failure, OK otherwise
int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
{
- char *str;
linenr_T l;
linenr_T extra; // Num lines added before line1
linenr_T num_lines; // Num lines moved
@@ -761,8 +730,8 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
return FAIL;
}
for (extra = 0, l = line1; l <= line2; l++) {
- str = xstrdup(ml_get(l + extra));
- ml_append(dest + l - line1, str, (colnr_T)0, false);
+ char *str = xstrdup(ml_get(l + extra));
+ ml_append(dest + l - line1, str, 0, false);
xfree(str);
if (dest < line1) {
extra++;
@@ -783,16 +752,16 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
// And Finally we adjust the marks we put at the end of the file back to
// their final destination at the new text position -- webb
last_line = curbuf->b_ml.ml_line_count;
- mark_adjust_nofold(line1, line2, last_line - line2, 0L, kExtmarkNOOP);
+ mark_adjust_nofold(line1, line2, last_line - line2, 0, kExtmarkNOOP);
disable_fold_update++;
- changed_lines(last_line - num_lines + 1, 0, last_line + 1, num_lines, false);
+ changed_lines(curbuf, last_line - num_lines + 1, 0, last_line + 1, num_lines, false);
disable_fold_update--;
int line_off = 0;
bcount_t byte_off = 0;
if (dest >= line2) {
- mark_adjust_nofold(line2 + 1, dest, -num_lines, 0L, kExtmarkNOOP);
+ mark_adjust_nofold(line2 + 1, dest, -num_lines, 0, kExtmarkNOOP);
FOR_ALL_TAB_WINDOWS(tab, win) {
if (win->w_buffer == curbuf) {
foldMoveRange(win, &win->w_folds, line1, line2, dest);
@@ -805,7 +774,7 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
line_off = -num_lines;
byte_off = -extent_byte;
} else {
- mark_adjust_nofold(dest + 1, line1 - 1, num_lines, 0L, kExtmarkNOOP);
+ mark_adjust_nofold(dest + 1, line1 - 1, num_lines, 0, kExtmarkNOOP);
FOR_ALL_TAB_WINDOWS(tab, win) {
if (win->w_buffer == curbuf) {
foldMoveRange(win, &win->w_folds, dest + 1, line1 - 1, line2);
@@ -820,10 +789,10 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
}
mark_adjust_nofold(last_line - num_lines + 1, last_line,
- -(last_line - dest - extra), 0L, kExtmarkNOOP);
+ -(last_line - dest - extra), 0, kExtmarkNOOP);
disable_fold_update++;
- changed_lines(last_line - num_lines + 1, 0, last_line + 1, -extra, false);
+ changed_lines(curbuf, last_line - num_lines + 1, 0, last_line + 1, -extra, false);
disable_fold_update--;
// send update regarding the new lines that were added
@@ -838,8 +807,8 @@ 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("%" PRId64 " line moved",
- "%" PRId64 " lines moved", num_lines),
+ smsg(0, NGETTEXT("%" PRId64 " line moved",
+ "%" PRId64 " lines moved", num_lines),
(int64_t)num_lines);
}
@@ -861,9 +830,9 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
if (dest > last_line + 1) {
dest = last_line + 1;
}
- changed_lines(line1, 0, dest, 0L, false);
+ changed_lines(curbuf, line1, 0, dest, 0, false);
} else {
- changed_lines(dest + 1, 0, line1 + num_lines, 0L, false);
+ changed_lines(curbuf, dest + 1, 0, line1 + num_lines, 0, false);
}
// send nvim_buf_lines_event regarding lines that were deleted
@@ -875,10 +844,7 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
/// ":copy"
void ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
{
- linenr_T count;
- char *p;
-
- count = line2 - line1 + 1;
+ linenr_T count = line2 - line1 + 1;
if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
curbuf->b_op_start.lnum = n + 1;
curbuf->b_op_end.lnum = n + count;
@@ -902,8 +868,8 @@ void ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
while (line1 <= line2) {
// need to use xstrdup() because the line will be unlocked within
// ml_append()
- p = xstrdup(ml_get(line1));
- ml_append(curwin->w_cursor.lnum, p, (colnr_T)0, false);
+ char *p = xstrdup(ml_get(line1));
+ ml_append(curwin->w_cursor.lnum, p, 0, false);
xfree(p);
// situation 2: skip already copied lines
@@ -925,7 +891,7 @@ void ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
check_pos(curbuf, &VIsual);
}
- msgmore((long)count);
+ msgmore(count);
}
static char *prevcmd = NULL; // the previous command
@@ -938,6 +904,17 @@ void free_prev_shellcmd(void)
#endif
+/// Check that "prevcmd" is not NULL. If it is NULL then give an error message
+/// and return false.
+static int prevcmd_is_set(void)
+{
+ if (prevcmd == NULL) {
+ emsg(_(e_noprev));
+ return false;
+ }
+ return true;
+}
+
/// Handle the ":!cmd" command. Also for ":r !cmd" and ":w !cmd"
/// Bangs in the argument are replaced with the previously entered command.
/// Remember the argument.
@@ -949,15 +926,9 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
linenr_T line2 = eap->line2; // end of range
char *newcmd = NULL; // the new command
bool free_newcmd = false; // need to free() newcmd
- char *t;
- char *p;
- char *trailarg;
- size_t len;
int scroll_save = msg_scroll;
- //
// Disallow shell commands in secure mode
- //
if (check_secure()) {
return;
}
@@ -973,21 +944,20 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
bool ins_prevcmd = forceit;
// Skip leading white space to avoid a strange error with some shells.
- trailarg = skipwhite(arg);
+ char *trailarg = skipwhite(arg);
do {
- len = strlen(trailarg) + 1;
+ size_t len = strlen(trailarg) + 1;
if (newcmd != NULL) {
len += strlen(newcmd);
}
if (ins_prevcmd) {
- if (prevcmd == NULL) {
- emsg(_(e_noprev));
+ if (!prevcmd_is_set()) {
xfree(newcmd);
return;
}
len += strlen(prevcmd);
}
- t = xmalloc(len);
+ char *t = xmalloc(len);
*t = NUL;
if (newcmd != NULL) {
STRCAT(t, newcmd);
@@ -995,7 +965,7 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
if (ins_prevcmd) {
STRCAT(t, prevcmd);
}
- p = t + strlen(t);
+ char *p = t + strlen(t);
STRCAT(t, trailarg);
xfree(newcmd);
newcmd = t;
@@ -1018,10 +988,20 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
}
} while (trailarg != NULL);
- xfree(prevcmd);
- prevcmd = newcmd;
+ // Only set "prevcmd" if there is a command to run, otherwise keep te one
+ // we have.
+ if (strlen(newcmd) > 0) {
+ xfree(prevcmd);
+ prevcmd = newcmd;
+ } else {
+ free_newcmd = true;
+ }
if (bangredo) { // put cmd in redo buffer for ! command
+ if (!prevcmd_is_set()) {
+ goto theend;
+ }
+
// If % or # appears in the command, it must have been escaped.
// Reescape them, so that redoing them does not substitute them by the
// buffername.
@@ -1034,6 +1014,9 @@ 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) {
+ if (free_newcmd) {
+ xfree(newcmd);
+ }
newcmd = xmalloc(strlen(prevcmd) + 2 * strlen(p_shq) + 1);
STRCPY(newcmd, p_shq);
STRCAT(newcmd, prevcmd);
@@ -1045,7 +1028,7 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
msg_start();
msg_putchar(':');
msg_putchar('!');
- msg_outtrans(newcmd);
+ msg_outtrans(newcmd, 0);
msg_clr_eos();
ui_cursor_goto(msg_row, msg_col);
@@ -1056,6 +1039,8 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
do_filter(line1, line2, eap, newcmd, do_in, do_out);
apply_autocmds(EVENT_SHELLFILTERPOST, NULL, NULL, false, curbuf);
}
+
+theend:
if (free_newcmd) {
xfree(newcmd);
}
@@ -1081,10 +1066,6 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
{
char *itmp = NULL;
char *otmp = NULL;
- linenr_T linecount;
- linenr_T read_linecount;
- pos_T cursor_save;
- char *cmd_buf;
buf_T *old_curbuf = curbuf;
int shell_flags = 0;
const pos_T orig_start = curbuf->b_op_start;
@@ -1100,12 +1081,12 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
// regions of the buffer for foldUpdate(), linecount, etc.
cmdmod.cmod_flags &= ~CMOD_LOCKMARKS;
- cursor_save = curwin->w_cursor;
- linecount = line2 - line1 + 1;
+ pos_T cursor_save = curwin->w_cursor;
+ linenr_T linecount = line2 - line1 + 1;
curwin->w_cursor.lnum = line1;
curwin->w_cursor.col = 0;
changed_line_abv_curs();
- invalidate_botline();
+ invalidate_botline(curwin);
// When using temp files:
// 1. * Form temp file names
@@ -1166,7 +1147,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
}
// Create the shell command in allocated memory.
- cmd_buf = make_filter_cmd(cmd, itmp, otmp);
+ char *cmd_buf = make_filter_cmd(cmd, itmp, otmp);
ui_cursor_goto(Rows - 1, 0);
if (do_out) {
@@ -1176,7 +1157,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
}
redraw_curbuf_later(UPD_VALID);
}
- read_linecount = curbuf->b_ml.ml_line_count;
+ linenr_T read_linecount = curbuf->b_ml.ml_line_count;
// Pass on the kShellOptDoOut flag when the output is being redirected.
call_shell(cmd_buf, (ShellOpts)(kShellOptFilter | shell_flags), NULL);
@@ -1193,7 +1174,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
if (do_out) {
if (otmp != NULL) {
- if (readfile(otmp, NULL, line2, (linenr_T)0, (linenr_T)MAXLNUM, eap,
+ if (readfile(otmp, NULL, line2, 0, (linenr_T)MAXLNUM, eap,
READ_FILTER, false) != OK) {
if (!aborting()) {
msg_putchar('\n');
@@ -1222,13 +1203,13 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
// end of each line?
if (read_linecount >= linecount) {
// move all marks from old lines to new lines
- mark_adjust(line1, line2, linecount, 0L, kExtmarkNOOP);
+ mark_adjust(line1, line2, linecount, 0, kExtmarkNOOP);
} else {
// move marks from old lines to new lines, delete marks
// that are in deleted lines
- mark_adjust(line1, line1 + read_linecount - 1, linecount, 0L,
+ mark_adjust(line1, line1 + read_linecount - 1, linecount, 0,
kExtmarkNOOP);
- mark_adjust(line1 + read_linecount, line2, MAXLNUM, 0L,
+ mark_adjust(line1 + read_linecount, line2, MAXLNUM, 0,
kExtmarkNOOP);
}
}
@@ -1255,12 +1236,12 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
if (do_in) {
vim_snprintf(msg_buf, sizeof(msg_buf),
_("%" PRId64 " lines filtered"), (int64_t)linecount);
- if (msg(msg_buf) && !msg_scroll) {
+ if (msg(msg_buf, 0) && !msg_scroll) {
// save message to display it after redraw
set_keep_msg(msg_buf, 0);
}
} else {
- msgmore((long)linecount);
+ msgmore(linecount);
}
}
} else {
@@ -1325,7 +1306,9 @@ void do_shell(char *cmd, int flags)
// 1" command to the terminal.
ui_cursor_goto(msg_row, msg_col);
(void)call_shell(cmd, (ShellOpts)flags, NULL);
- msg_didout = true;
+ if (msg_silent == 0) {
+ msg_didout = true;
+ }
did_check_timestamps = false;
need_check_timestamps = true;
@@ -1367,12 +1350,12 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
{
bool is_fish_shell =
#if defined(UNIX)
- strncmp((char *)invocation_path_tail(p_sh, NULL), "fish", 4) == 0;
+ strncmp(invocation_path_tail(p_sh, NULL), "fish", 4) == 0;
#else
false;
#endif
- bool is_pwsh = strncmp((char *)invocation_path_tail(p_sh, NULL), "pwsh", 4) == 0
- || strncmp((char *)invocation_path_tail(p_sh, NULL), "powershell",
+ bool is_pwsh = strncmp(invocation_path_tail(p_sh, NULL), "pwsh", 4) == 0
+ || strncmp(invocation_path_tail(p_sh, NULL), "powershell",
10) == 0;
size_t len = strlen(cmd) + 1; // At least enough space for cmd + NULL.
@@ -1382,8 +1365,8 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
: 0;
if (itmp != NULL) {
- len += is_pwsh ? strlen(itmp) + sizeof("& { Get-Content " " | & " " }") - 1 + 6 // +6: #20530
- : strlen(itmp) + sizeof(" { " " < " " } ") - 1;
+ len += is_pwsh ? strlen(itmp) + sizeof("& { Get-Content " " | & " " }") - 1 + 6 // +6: #20530
+ : strlen(itmp) + sizeof(" { " " < " " } ") - 1;
}
if (otmp != NULL) {
len += strlen(otmp) + strlen(p_srr) + 2; // two extra spaces (" "),
@@ -1394,7 +1377,7 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
if (is_pwsh) {
if (itmp != NULL) {
xstrlcpy(buf, "& { Get-Content ", len - 1); // FIXME: should we add "-Encoding utf8"?
- xstrlcat(buf, (const char *)itmp, len - 1);
+ xstrlcat(buf, itmp, len - 1);
xstrlcat(buf, " | & ", len - 1); // FIXME: add `&` ourself or leave to user?
xstrlcat(buf, cmd, len - 1);
xstrlcat(buf, " }", len - 1);
@@ -1407,7 +1390,7 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
// redirecting input and/or output.
if (itmp != NULL || otmp != NULL) {
char *fmt = is_fish_shell ? "begin; %s; end"
- : "(%s)";
+ : "(%s)";
vim_snprintf(buf, len, fmt, cmd);
} else {
xstrlcpy(buf, cmd, len);
@@ -1415,7 +1398,7 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
if (itmp != NULL) {
xstrlcat(buf, " < ", len - 1);
- xstrlcat(buf, (const char *)itmp, len - 1);
+ xstrlcat(buf, itmp, len - 1);
}
#else
// For shells that don't understand braces around commands, at least allow
@@ -1432,9 +1415,9 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
}
}
xstrlcat(buf, " < ", len);
- xstrlcat(buf, (const char *)itmp, len);
+ xstrlcat(buf, itmp, len);
if (*p_shq == NUL) {
- const char *const p = find_pipe((const char *)cmd);
+ const char *const p = find_pipe(cmd);
if (p != NULL) {
xstrlcat(buf, " ", len - 1); // Insert a space before the '|' for DOS
xstrlcat(buf, p, len - 1);
@@ -1507,7 +1490,6 @@ void print_line(linenr_T lnum, int use_number, int list)
print_line_no_prefix(lnum, use_number, list);
if (save_silent) {
msg_putchar('\n');
- ui_flush();
silent_mode = save_silent;
}
info_message = false;
@@ -1515,10 +1497,7 @@ void print_line(linenr_T lnum, int use_number, int list)
int rename_buffer(char *new_fname)
{
- char *fname, *sfname, *xfname;
- buf_T *buf;
-
- buf = curbuf;
+ buf_T *buf = curbuf;
apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, false, curbuf);
// buffer changed, don't change name now
if (buf != curbuf) {
@@ -1532,9 +1511,9 @@ int rename_buffer(char *new_fname)
// name, which will become the alternate file name.
// But don't set the alternate file name if the buffer didn't have a
// name.
- fname = curbuf->b_ffname;
- sfname = curbuf->b_sfname;
- xfname = curbuf->b_fname;
+ char *fname = curbuf->b_ffname;
+ char *sfname = curbuf->b_sfname;
+ char *xfname = curbuf->b_fname;
curbuf->b_ffname = NULL;
curbuf->b_sfname = NULL;
if (setfname(curbuf, new_fname, NULL, true) == FAIL) {
@@ -1628,17 +1607,15 @@ int do_write(exarg_T *eap)
{
int other;
char *fname = NULL; // init to shut up gcc
- char *ffname;
int retval = FAIL;
char *free_fname = NULL;
buf_T *alt_buf = NULL;
- int name_was_missing;
if (not_writing()) { // check 'write' option
return FAIL;
}
- ffname = eap->arg;
+ char *ffname = eap->arg;
if (*ffname == NUL) {
if (eap->cmdidx == CMD_saveas) {
emsg(_(e_argreq));
@@ -1660,7 +1637,7 @@ int do_write(exarg_T *eap)
if (other) {
if (vim_strchr(p_cpo, CPO_ALTWRITE) != NULL
|| eap->cmdidx == CMD_saveas) {
- alt_buf = setaltfname(ffname, fname, (linenr_T)1);
+ alt_buf = setaltfname(ffname, fname, 1);
} else {
alt_buf = buflist_findname(ffname);
}
@@ -1764,7 +1741,7 @@ int do_write(exarg_T *eap)
}
}
- name_was_missing = curbuf->b_ffname == NULL;
+ int name_was_missing = curbuf->b_ffname == NULL;
retval = buf_write(curbuf, ffname, fname, eap->line1, eap->line2,
eap, eap->append, eap->forceit, true, false);
@@ -1824,7 +1801,7 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char *fname, char *ffname, int oth
if (p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) {
char buff[DIALOG_MSG_SIZE];
- dialog_msg((char *)buff, _("Overwrite existing file \"%s\"?"), fname);
+ dialog_msg(buff, _("Overwrite existing file \"%s\"?"), fname);
if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) != VIM_YES) {
return FAIL;
}
@@ -1860,7 +1837,7 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char *fname, char *ffname, int oth
if (p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) {
char buff[DIALOG_MSG_SIZE];
- dialog_msg((char *)buff,
+ dialog_msg(buff,
_("Swap file \"%s\" exists, overwrite anyway?"),
swapname);
if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2)
@@ -1906,6 +1883,9 @@ void do_wqall(exarg_T *eap)
int save_forceit = eap->forceit;
if (eap->cmdidx == CMD_xall || eap->cmdidx == CMD_wqall) {
+ if (before_quit_all(eap) == FAIL) {
+ return;
+ }
exiting = t