diff options
| author | Josh Rahm <joshuarahm@gmail.com> | 2023-01-25 18:31:31 +0000 |
|---|---|---|
| committer | Josh Rahm <joshuarahm@gmail.com> | 2023-01-25 18:31:31 +0000 |
| commit | 9243becbedbb6a1592208051f8fa2b090dcc5e7d (patch) | |
| tree | 607c2a862ec3f4399b8766383f6f8e04c4aa43b4 /src/nvim/ex_cmds.c | |
| parent | 9e40b6e9e1bc67f2d856adb837ee64dd0e25b717 (diff) | |
| parent | 3c48d3c83fc21dbc0841f9210f04bdb073d73cd1 (diff) | |
| download | rneovim-usermarks.tar.gz rneovim-usermarks.tar.bz2 rneovim-usermarks.zip | |
Merge remote-tracking branch 'upstream/master' into usermarksusermarks
Diffstat (limited to 'src/nvim/ex_cmds.c')
| -rw-r--r-- | src/nvim/ex_cmds.c | 1327 |
1 files changed, 554 insertions, 773 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 06a372bb93..437a05f61d 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -1,25 +1,30 @@ // 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 - */ +// 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" @@ -29,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" @@ -57,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" @@ -147,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); @@ -193,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") @@ -217,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. @@ -249,11 +260,9 @@ void ex_align(exarg_T *eap) indent = width; } } else { - /* - * if 'textwidth' set, use it - * else if 'wrapmargin' set, use it - * if invalid value, use 80 - */ + // if 'textwidth' set, use it + // else if 'wrapmargin' set, use it + // if invalid value, use 80 if (width <= 0) { width = (int)curbuf->b_p_tw; } @@ -270,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(); + has_tab = false; // avoid uninit warnings + len = linelen(eap->cmdidx == CMD_right ? &has_tab : NULL) - get_indent(); if (len <= 0) { // skip blank lines continue; @@ -287,18 +295,14 @@ void ex_align(exarg_T *eap) } else { new_indent = width - len; // right align - /* - * Make sure that embedded TABs don't make the text go too far - * to the right. - */ + // Make sure that embedded TABs don't make the text go too far + // to the right. if (has_tab) { while (new_indent > 0) { (void)set_indent(new_indent, 0); if (linelen(NULL) <= width) { - /* - * Now try to move the line as much as possible to - * the right. Stop when it moves too far. - */ + // Now try to move the line as much as possible to + // the right. Stop when it moves too far. do { (void)set_indent(++new_indent, 0); } while (linelen(NULL) <= width); @@ -330,7 +334,7 @@ static int linelen(int *has_tab) // Get the line. If it's empty bail out early (could be the empty string // for an unloaded buffer). - line = (char *)get_cursor_line_ptr(); + line = get_cursor_line_ptr(); if (*line == NUL) { return 0; } @@ -338,12 +342,12 @@ static int linelen(int *has_tab) first = skipwhite(line); // find the character after the last non-blank character - for (last = first + STRLEN(first); + for (last = first + strlen(first); last > first && ascii_iswhite(last[-1]); last--) {} 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; @@ -387,7 +391,7 @@ static int string_compare(const void *s1, const void *s2) FUNC_ATTR_NONNULL_ALL if (sort_lc) { return strcoll((char *)s1, (char *)s2); } - return sort_ic ? STRICMP(s1, s2) : STRCMP(s1, s2); + return sort_ic ? STRICMP(s1, s2) : strcmp(s1, s2); } static int sort_compare(const void *s1, const void *s2) @@ -404,7 +408,7 @@ static int sort_compare(const void *s1, const void *s2) } fast_breakcheck(); if (got_int) { - sort_abort = TRUE; + sort_abort = true; } // When sorting numbers "start_col_nr" is the number, not the column @@ -509,13 +513,12 @@ void ex_sort(exarg_T *eap) } else if (*p == '"') { // comment start break; - } else if (check_nextcmd((char_u *)p) != NULL) { - eap->nextcmd = (char *)check_nextcmd((char_u *)p); + } else if (check_nextcmd(p) != NULL) { + eap->nextcmd = check_nextcmd(p); break; } else if (!ASCII_ISALPHA(*p) && regmatch.regprog == NULL) { - s = (char *)skip_regexp((char_u *)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; @@ -525,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); } @@ -557,8 +560,8 @@ void ex_sort(exarg_T *eap) // 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 = (char *)ml_get(lnum); - len = (int)STRLEN(s); + s = ml_get(lnum); + len = (int)strlen(s); if (maxlen < len) { maxlen = len; } @@ -567,10 +570,10 @@ void ex_sort(exarg_T *eap) end_col = len; if (regmatch.regprog != NULL && vim_regexec(®match, s, 0)) { if (sort_rx) { - start_col = (colnr_T)(regmatch.startp[0] - (char_u *)s); - end_col = (colnr_T)(regmatch.endp[0] - (char_u *)s); + start_col = (colnr_T)(regmatch.startp[0] - s); + end_col = (colnr_T)(regmatch.endp[0] - s); } else { - start_col = (colnr_T)(regmatch.endp[0] - (char_u *)s); + start_col = (colnr_T)(regmatch.endp[0] - s); } } else if (regmatch.regprog != NULL) { end_col = 0; @@ -586,11 +589,11 @@ void ex_sort(exarg_T *eap) p = s + start_col; if (sort_nr) { if (sort_what & STR2NR_HEX) { - s = (char *)skiptohex((char_u *)p); + s = skiptohex(p); } else if (sort_what & STR2NR_BIN) { s = (char *)skiptobin(p); } else { - s = (char *)skiptodigit((char_u *)p); + s = skiptodigit(p); } if (s > p && s[-1] == '-') { s--; // include preceding negative sign @@ -601,7 +604,7 @@ void ex_sort(exarg_T *eap) nrs[lnum - eap->line1].st_u.num.value = 0; } else { nrs[lnum - eap->line1].st_u.num.is_number = true; - vim_str2nr((char_u *)s, NULL, NULL, sort_what, + vim_str2nr(s, NULL, NULL, sort_what, &nrs[lnum - eap->line1].st_u.num.value, NULL, 0, false); } } else { @@ -658,8 +661,8 @@ void ex_sort(exarg_T *eap) change_occurred = true; } - s = (char *)ml_get(get_lnum); - size_t bytelen = STRLEN(s) + 1; // include EOL in bytelen + 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 @@ -678,7 +681,7 @@ void ex_sort(exarg_T *eap) // delete the original lines if appending worked if (i == count) { - for (i = 0; i < count; ++i) { + for (i = 0; i < count; i++) { ml_delete(eap->line1, false); } } else { @@ -716,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((char_u *)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 = (char *)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, (char_u *)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(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 @@ -933,15 +755,13 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest) num_lines = line2 - line1 + 1; - /* - * First we copy the old text to its new location -- webb - * Also copy the flag that ":global" command uses. - */ + // First we copy the old text to its new location -- webb + // Also copy the flag that ":global" command uses. if (u_save(dest, dest + 1) == FAIL) { return FAIL; } for (extra = 0, l = line1; l <= line2; l++) { - str = (char *)vim_strsave(ml_get(l + extra)); + str = xstrdup(ml_get(l + extra)); ml_append(dest + l - line1, str, (colnr_T)0, false); xfree(str); if (dest < line1) { @@ -949,21 +769,19 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest) } } - /* - * Now we must be careful adjusting our marks so that we don't overlap our - * mark_adjust() calls. - * - * We adjust the marks within the old text so that they refer to the - * last lines of the file (temporarily), because we know no other marks - * will be set there since these line numbers did not exist until we added - * our new lines. - * - * Then we adjust the marks on lines between the old and new text positions - * (either forwards or backwards). - * - * 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 - */ + // Now we must be careful adjusting our marks so that we don't overlap our + // mark_adjust() calls. + // + // We adjust the marks within the old text so that they refer to the + // last lines of the file (temporarily), because we know no other marks + // will be set there since these line numbers did not exist until we added + // our new lines. + // + // Then we adjust the marks on lines between the old and new text positions + // (either forwards or backwards). + // + // 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); @@ -1011,9 +829,7 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest) // send update regarding the new lines that were added buf_updates_send_changes(curbuf, dest + 1, num_lines, 0); - /* - * Now we delete the original text -- webb - */ + // Now we delete the original text -- webb if (u_save(line1 + extra - 1, line2 + extra + 1) == FAIL) { return FAIL; } @@ -1022,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, @@ -1030,9 +848,7 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest) dest + line_off, 0, dest_byte + byte_off, kExtmarkUndo); - /* - * Leave the cursor on the last of the moved lines. - */ + // Leave the cursor on the last of the moved lines. if (dest >= line1) { curwin->w_cursor.lnum = dest; } else { @@ -1069,26 +885,24 @@ void ex_copy(linenr_T line1, linenr_T line2, linenr_T n) curbuf->b_op_start.col = curbuf->b_op_end.col = 0; } - /* - * there are three situations: - * 1. destination is above line1 - * 2. destination is between line1 and line2 - * 3. destination is below line2 - * - * n = destination (when starting) - * curwin->w_cursor.lnum = destination (while copying) - * line1 = start of source (while copying) - * line2 = end of source (while copying) - */ + // there are three situations: + // 1. destination is above line1 + // 2. destination is between line1 and line2 + // 3. destination is below line2 + // + // n = destination (when starting) + // curwin->w_cursor.lnum = destination (while copying) + // line1 = start of source (while copying) + // line2 = end of source (while copying) if (u_save(n, n + 1) == FAIL) { return; } curwin->w_cursor.lnum = n; while (line1 <= line2) { - // need to use vim_strsave() because the line will be unlocked within + // need to use xstrdup() because the line will be unlocked within // ml_append() - p = (char *)vim_strsave(ml_get(line1)); + p = xstrdup(ml_get(line1)); ml_append(curwin->w_cursor.lnum, p, (colnr_T)0, false); xfree(p); @@ -1103,7 +917,7 @@ void ex_copy(linenr_T line1, linenr_T line2, linenr_T n) if (curwin->w_cursor.lnum < line2) { line2++; } - ++curwin->w_cursor.lnum; + curwin->w_cursor.lnum++; } appended_lines_mark(n, count); @@ -1142,29 +956,28 @@ 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; } if (addr_count == 0) { // :! - msg_scroll = FALSE; // don't scroll here + msg_scroll = false; // don't scroll here autowrite_all(); 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; + len = strlen(trailarg) + 1; if (newcmd != NULL) { - len += STRLEN(newcmd); + len += strlen(newcmd); } if (ins_prevcmd) { if (prevcmd == NULL) { @@ -1172,7 +985,7 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out xfree(newcmd); return; } - len += STRLEN(prevcmd); + len += strlen(prevcmd); } t = xmalloc(len); *t = NUL; @@ -1182,15 +995,13 @@ 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); + p = t + strlen(t); STRCAT(t, trailarg); xfree(newcmd); newcmd = t; - /* - * Scan the rest of the argument for '!', which is replaced by the - * previous command. "\!" is replaced by "!" (this is vi compatible). - */ + // Scan the rest of the argument for '!', which is replaced by the + // previous command. "\!" is replaced by "!" (this is vi compatible). trailarg = NULL; while (*p) { if (*p == '!') { @@ -1214,18 +1025,16 @@ 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); AppendToRedobuff("\n"); bangredo = false; } - /* - * Add quotes around the command, for shells that need them. - */ + // 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); @@ -1298,18 +1107,16 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b changed_line_abv_curs(); invalidate_botline(); - /* - * When using temp files: - * 1. * Form temp file names - * 2. * Write the lines to a temp file - * 3. Run the filter command on the temp file - * 4. * Read the output of the command into the buffer - * 5. * Delete the original lines to be filtered - * 6. * Remove the temp files - * - * When writing the input with a pipe or when catching the output with a - * pipe only need to do 3. - */ + // When using temp files: + // 1. * Form temp file names + // 2. * Write the lines to a temp file + // 3. Run the filter command on the temp file + // 4. * Read the output of the command into the buffer + // 5. * Delete the original lines to be filtered + // 6. * Remove the temp files + // + // When writing the input with a pipe or when catching the output with a + // pipe only need to do 3. if (do_out) { shell_flags |= kShellOptDoOut; @@ -1331,23 +1138,22 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b curbuf->b_op_start.lnum = line1; curbuf->b_op_end.lnum = line2; curwin->w_cursor.lnum = line2; - } else if ((do_in && (itmp = (char *)vim_tempname()) == NULL) - || (do_out && (otmp = (char *)vim_tempname()) == NULL)) { + } else if ((do_in && (itmp = vim_tempname()) == NULL) + || (do_out && (otmp = vim_tempname()) == NULL)) { emsg(_(e_notmp)); goto filterend; } - /* - * The writing and reading of temp files will not be shown. - * Vi also doesn't do this and the messages are not very informative. - */ + // The writing and reading of temp files will not be shown. + // Vi also doesn't do this and the messages are not very informative. no_wait_return++; // don't call wait_return() while busy if (itmp != NULL && buf_write(curbuf, itmp, NULL, line1, line2, eap, false, false, false, true) == FAIL) { msg_putchar('\n'); // Keep message from buf_write(). no_wait_return--; if (!aborting()) { - semsg(_("E482: Can't create file %s"), itmp); // Will call wait_return. + // will call wait_return() + semsg(_("E482: Can't create file %s"), itmp); } goto filterend; } @@ -1368,22 +1174,22 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b xfree(cmd_buf); goto error; } - redraw_curbuf_later(VALID); + redraw_curbuf_later(UPD_VALID); } 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; - need_check_timestamps = TRUE; + did_check_timestamps = false; + need_check_timestamps = true; // When interrupting the shell command, it may still have produced some // useful output. Reset got_int here, so that readfile() won't cancel // reading. os_breakcheck(); - got_int = FALSE; + got_int = false; if (do_out) { if (otmp != NULL) { @@ -1427,10 +1233,8 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b } } - /* - * Put cursor on first filtered line for ":range!cmd". - * Adjust '[ and '] (set by buf_write()). - */ + // Put cursor on first filtered line for ":range!cmd". + // Adjust '[ and '] (set by buf_write()). curwin->w_cursor.lnum = line1; del_lines(linecount, true); curbuf->b_op_start.lnum -= linecount; // adjust '[ @@ -1439,9 +1243,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b // for next write foldUpdate(curwin, curbuf->b_op_start.lnum, curbuf->b_op_end.lnum); } else { - /* - * Put cursor on last new line for ":r !cmd". - */ + // Put cursor on last new line for ":r !cmd". linecount = curbuf->b_op_end.lnum - curbuf->b_op_start.lnum + 1; curwin->w_cursor.lnum = curbuf->b_op_end.lnum; } @@ -1496,17 +1298,14 @@ 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; } - /* - * For autocommands we want to get the output on the current screen, to - * avoid having to type return below. - */ + // For autocommands we want to get the output on the current screen, to + // avoid having to type return below. msg_putchar('\r'); // put cursor at start of line msg_putchar('\n'); // may shift screen one line up @@ -1525,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; @@ -1545,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++; } } @@ -1568,95 +1367,84 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp) { bool is_fish_shell = #if defined(UNIX) - STRNCMP(invocation_path_tail(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(p_sh, NULL), "pwsh", 4) == 0 - || STRNCMP(invocation_path_tail(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. + size_t len = strlen(cmd) + 1; // At least enough space for cmd + NULL. - len += is_fish_shell ? sizeof("begin; " "; end") - 1 - : is_pwsh ? sizeof("Start-Process ") - : sizeof("(" ")") - 1; + len += is_fish_shell ? sizeof("begin; " "; end") - 1 + : !is_pwsh ? sizeof("(" ")") - 1 + : 0; if (itmp != NULL) { - len += is_pwsh ? STRLEN(itmp) + sizeof(" -RedirectStandardInput ") - : 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 (" "), + len += strlen(otmp) + strlen(p_srr) + 2; // two extra spaces (" "), } - const char *const cmd_args = strchr(cmd, ' '); - len += (is_pwsh && cmd_args) - ? STRLEN(" -ArgumentList ") + 2 // two extra quotes - : 0; - char *const buf = xmalloc(len); if (is_pwsh) { - xstrlcpy(buf, "Start-Process ", len); - if (cmd_args == NULL) { - xstrlcat(buf, cmd, len); + if (itmp != NULL) { + xstrlcpy(buf, "& { Get-Content ", len - 1); // FIXME: should we add "-Encoding utf8"? + xstrlcat(buf, (const char *)itmp, len - 1); + xstrlcat(buf, " | & ", len - 1); // FIXME: add `&` ourself or leave to user? + xstrlcat(buf, cmd, len - 1); + xstrlcat(buf, " }", len - 1); } else { - xstrlcpy(buf + STRLEN(buf), cmd, (size_t)(cmd_args - cmd + 1)); - xstrlcat(buf, " -ArgumentList \"", len); - xstrlcat(buf, cmd_args + 1, len); // +1 to skip the leading space. - xstrlcat(buf, "\"", len); + xstrlcpy(buf, cmd, len - 1); } + } else { #if defined(UNIX) // Put delimiters around the command (for concatenated commands) when // redirecting input and/or output. - } else if (itmp != NULL || otmp != NULL) { - char *fmt = is_fish_shell ? "begin; %s; end" - : "(%s)"; - vim_snprintf(buf, len, fmt, cmd); -#endif - // For shells that don't understand braces around commands, at least allow - // the use of commands in a pipe. - } else { - xstrlcpy(buf, cmd, len); - } - -#if defined(UNIX) - if (itmp != NULL) { - if (is_pwsh) { - xstrlcat(buf, " -RedirectStandardInput ", len - 1); + if |