diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2024-05-24 19:18:11 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2024-05-24 19:18:11 +0000 |
commit | ff7ed8f586589d620a806c3758fac4a47a8e7e15 (patch) | |
tree | 729bbcb92231538fa61dab6c3d890b025484b7f5 /src/nvim/ex_docmd.c | |
parent | 376914f419eb08fdf4c1a63a77e1f035898a0f10 (diff) | |
parent | 28c04948a1c887a1cc0cb64de79fa32631700466 (diff) | |
download | rneovim-ff7ed8f586589d620a806c3758fac4a47a8e7e15.tar.gz rneovim-ff7ed8f586589d620a806c3758fac4a47a8e7e15.tar.bz2 rneovim-ff7ed8f586589d620a806c3758fac4a47a8e7e15.zip |
Merge remote-tracking branch 'upstream/master' into mix_20240309
Diffstat (limited to 'src/nvim/ex_docmd.c')
-rw-r--r-- | src/nvim/ex_docmd.c | 153 |
1 files changed, 98 insertions, 55 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 2913f6d4e9..1fcfc505df 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -144,7 +144,7 @@ struct loop_cookie { int current_line; // last read line from growarray int repeating; // true when looping a second time // When "repeating" is false use "getline" and "cookie" to get lines - char *(*getline)(int, void *, int, bool); + LineGetter lc_getline; void *cookie; }; @@ -216,6 +216,38 @@ static void restore_dbg_stuff(struct dbg_stuff *dsp) current_exception = dsp->current_exception; } +/// Check if ffname differs from fnum. +/// fnum is a buffer number. 0 == current buffer, 1-or-more must be a valid buffer ID. +/// ffname is a full path to where a buffer lives on-disk or would live on-disk. +static bool is_other_file(int fnum, char *ffname) +{ + if (fnum != 0) { + if (fnum == curbuf->b_fnum) { + return false; + } + + return true; + } + + if (ffname == NULL) { + return true; + } + + if (*ffname == NUL) { + return false; + } + + if (!curbuf->file_id_valid + && curbuf->b_sfname != NULL + && *curbuf->b_sfname != NUL) { + // This occurs with unsaved buffers. In which case `ffname` + // actually corresponds to curbuf->b_sfname + return path_fnamecmp(ffname, curbuf->b_sfname) != 0; + } + + return otherfile(ffname); +} + /// Repeatedly get commands for Ex mode, until the ":vi" command is given. void do_exmode(void) { @@ -590,7 +622,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags) cmd_cookie = (void *)&cmd_loop_cookie; cmd_loop_cookie.lines_gap = &lines_ga; cmd_loop_cookie.current_line = current_line; - cmd_loop_cookie.getline = fgetline; + cmd_loop_cookie.lc_getline = fgetline; cmd_loop_cookie.cookie = cookie; cmd_loop_cookie.repeating = (current_line < lines_ga.ga_len); @@ -971,10 +1003,10 @@ static char *get_loop_line(int c, void *cookie, int indent, bool do_concat) } char *line; // First time inside the ":while"/":for": get line normally. - if (cp->getline == NULL) { + if (cp->lc_getline == NULL) { line = getcmdline(c, 0, indent, do_concat); } else { - line = cp->getline(c, cp->cookie, indent, do_concat); + line = cp->lc_getline(c, cp->cookie, indent, do_concat); } if (line != NULL) { store_loop_line(cp->lines_gap, line); @@ -1011,7 +1043,7 @@ bool getline_equal(LineGetter fgetline, void *cookie, LineGetter func) LineGetter gp = fgetline; struct loop_cookie *cp = (struct loop_cookie *)cookie; while (gp == get_loop_line) { - gp = cp->getline; + gp = cp->lc_getline; cp = cp->cookie; } return gp == func; @@ -1029,7 +1061,7 @@ void *getline_cookie(LineGetter fgetline, void *cookie) LineGetter gp = fgetline; struct loop_cookie *cp = (struct loop_cookie *)cookie; while (gp == get_loop_line) { - gp = cp->getline; + gp = cp->lc_getline; cp = cp->cookie; } return cp; @@ -1456,7 +1488,7 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, const cha .line2 = 1, .cmd = cmdline, .cmdlinep = &cmdline, - .getline = NULL, + .ea_getline = NULL, .cookie = NULL, }; @@ -1743,8 +1775,8 @@ int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview) && eap->addr_type == ADDR_LINES) { // Put the first line at the start of a closed fold, put the last line // at the end of a closed fold. - hasFolding(eap->line1, &eap->line1, NULL); - hasFolding(eap->line2, NULL, &eap->line2); + hasFolding(curwin, eap->line1, &eap->line1, NULL); + hasFolding(curwin, eap->line2, NULL, &eap->line2); } // Use first argument as count when possible @@ -1965,7 +1997,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter // The "ea" structure holds the arguments that can be used. ea.cmd = *cmdlinep; ea.cmdlinep = cmdlinep; - ea.getline = fgetline; + ea.ea_getline = fgetline; ea.cookie = cookie; ea.cstack = cstack; @@ -2213,8 +2245,8 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter && ea.addr_type == ADDR_LINES) { // Put the first line at the start of a closed fold, put the last line // at the end of a closed fold. - hasFolding(ea.line1, &ea.line1, NULL); - hasFolding(ea.line2, NULL, &ea.line2); + hasFolding(curwin, ea.line1, &ea.line1, NULL); + hasFolding(curwin, ea.line2, NULL, &ea.line2); } // For the ":make" and ":grep" commands we insert the 'makeprg'/'grepprg' @@ -2440,7 +2472,7 @@ int parse_command_modifiers(exarg_T *eap, const char **errormsg, cmdmod_T *cmod, // in ex mode, an empty line works like :+ if (*eap->cmd == NUL && exmode_active - && getline_equal(eap->getline, eap->cookie, getexline) + && getline_equal(eap->ea_getline, eap->cookie, getexline) && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) { eap->cmd = "+"; if (!skip_only) { @@ -2697,7 +2729,7 @@ static void apply_cmdmod(cmdmod_T *cmod) // Set 'eventignore' to "all". // First save the existing option value for restoring it later. cmod->cmod_save_ei = xstrdup(p_ei); - set_string_option_direct(kOptEventignore, "all", 0, SID_NONE); + set_option_direct(kOptEventignore, STATIC_CSTR_AS_OPTVAL("all"), 0, SID_NONE); } } @@ -2717,7 +2749,7 @@ void undo_cmdmod(cmdmod_T *cmod) if (cmod->cmod_save_ei != NULL) { // Restore 'eventignore' to the value before ":noautocmd". - set_string_option_direct(kOptEventignore, cmod->cmod_save_ei, 0, SID_NONE); + set_option_direct(kOptEventignore, CSTR_AS_OPTVAL(cmod->cmod_save_ei), 0, SID_NONE); free_string_option(cmod->cmod_save_ei); cmod->cmod_save_ei = NULL; } @@ -2875,9 +2907,9 @@ int parse_cmd_address(exarg_T *eap, const char **errormsg, bool silent) // (where zero usually means to use the first line). // Check the cursor position before returning. if (eap->line2 > 0) { - check_cursor(); + check_cursor(curwin); } else { - check_cursor_col(); + check_cursor_col(curwin); } need_check_cursor = true; } @@ -2899,7 +2931,7 @@ int parse_cmd_address(exarg_T *eap, const char **errormsg, bool silent) theend: if (need_check_cursor) { - check_cursor(); + check_cursor(curwin); } return ret; } @@ -3474,7 +3506,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, bool } searchcmdlen = 0; flags = silent ? 0 : SEARCH_HIS | SEARCH_MSG; - if (!do_search(NULL, c, c, cmd, 1, flags, NULL)) { + if (!do_search(NULL, c, c, cmd, strlen(cmd), 1, flags, NULL)) { curwin->w_cursor = pos; cmd = NULL; goto error; @@ -3511,7 +3543,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, bool pos.coladd = 0; if (searchit(curwin, curbuf, &pos, NULL, *cmd == '?' ? BACKWARD : FORWARD, - "", 1, SEARCH_MSG, i, NULL) != FAIL) { + "", 0, 1, SEARCH_MSG, i, NULL) != FAIL) { lnum = pos.lnum; } else { cmd = NULL; @@ -3596,7 +3628,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, bool // closed fold after the first address. if (addr_type == ADDR_LINES && (i == '-' || i == '+') && address_count >= 2) { - hasFolding(lnum, NULL, &lnum); + hasFolding(curwin, lnum, NULL, &lnum); } if (i == '-') { lnum -= n; @@ -4050,7 +4082,7 @@ void separate_nextcmd(exarg_T *eap) break; } } else if ( - // Check for '"': start of comment or '|': next command */ + // Check for '"': start of comment or '|': next command // :@" does not start a comment! // :redir @" doesn't either. (*p == '"' @@ -4368,12 +4400,15 @@ static int get_tabpage_arg(exarg_T *eap) tab_number = 0; } else { tab_number = (int)eap->line2; - char *cmdp = eap->cmd; - while (--cmdp > *eap->cmdlinep && (*cmdp == ' ' || ascii_isdigit(*cmdp))) {} - if (!unaccept_arg0 && *cmdp == '-') { - tab_number--; - if (tab_number < unaccept_arg0) { - eap->errmsg = _(e_invrange); + if (!unaccept_arg0) { + char *cmdp = eap->cmd; + while (--cmdp > *eap->cmdlinep + && (ascii_iswhite(*cmdp) || ascii_isdigit(*cmdp))) {} + if (*cmdp == '-') { + tab_number--; + if (tab_number < unaccept_arg0) { + eap->errmsg = _(e_invrange); + } } } } @@ -5334,6 +5369,10 @@ static void ex_resize(exarg_T *eap) /// ":find [+command] <file>" command. static void ex_find(exarg_T *eap) { + if (!check_can_set_curbuf_forceit(eap->forceit)) { + return; + } + char *file_to_find = NULL; char *search_ctx = NULL; char *fname = find_file_in_path(eap->arg, strlen(eap->arg), @@ -5364,6 +5403,16 @@ static void ex_find(exarg_T *eap) /// ":edit", ":badd", ":balt", ":visual". static void ex_edit(exarg_T *eap) { + char *ffname = eap->cmdidx == CMD_enew ? NULL : eap->arg; + + // Exclude commands which keep the window's current buffer + if (eap->cmdidx != CMD_badd + && eap->cmdidx != CMD_balt + // All other commands must obey 'winfixbuf' / ! rules + && (is_other_file(0, ffname) && !check_can_set_curbuf_forceit(eap->forceit))) { + return; + } + do_exedit(eap, NULL); } @@ -5516,8 +5565,6 @@ static void ex_swapname(exarg_T *eap) /// (1998-11-02 16:21:01 R. Edward Ralston <eralston@computer.org>) static void ex_syncbind(exarg_T *eap) { - win_T *save_curwin = curwin; - buf_T *save_curbuf = curbuf; linenr_T topline; int y; linenr_T old_linenr = curwin->w_cursor.lnum; @@ -5544,23 +5591,19 @@ static void ex_syncbind(exarg_T *eap) // Set all scrollbind windows to the same topline. FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - curwin = wp; - if (curwin->w_p_scb) { - curbuf = curwin->w_buffer; - y = topline - curwin->w_topline; + if (wp->w_p_scb) { + y = topline - wp->w_topline; if (y > 0) { - scrollup(y, true); + scrollup(wp, y, true); } else { - scrolldown(-y, true); + scrolldown(wp, -y, true); } - curwin->w_scbind_pos = topline; - redraw_later(curwin, UPD_VALID); - cursor_correct(); - curwin->w_redr_status = true; + wp->w_scbind_pos = topline; + redraw_later(wp, UPD_VALID); + cursor_correct(wp); + wp->w_redr_status = true; } } - curwin = save_curwin; - curbuf = save_curbuf; if (curwin->w_p_scb) { did_syncbind = true; checkpcmark(); @@ -5842,8 +5885,8 @@ static void ex_equal(exarg_T *eap) static void ex_sleep(exarg_T *eap) { - if (cursor_valid()) { - setcursor_mayforce(true); + if (cursor_valid(curwin)) { + setcursor_mayforce(curwin, true); } int64_t len = eap->line2; @@ -5978,7 +6021,7 @@ static void ex_put(exarg_T *eap) eap->forceit = true; } curwin->w_cursor.lnum = eap->line2; - check_cursor_col(); + check_cursor_col(curwin); do_put(eap->regname, NULL, eap->forceit ? BACKWARD : FORWARD, 1, PUT_LINE|PUT_CURSLINE); } @@ -6072,7 +6115,7 @@ static void ex_at(exarg_T *eap) int prev_len = typebuf.tb_len; curwin->w_cursor.lnum = eap->line2; - check_cursor_col(); + check_cursor_col(curwin); // Get the register name. No name means use the previous one. int c = (uint8_t)(*eap->arg); @@ -6294,7 +6337,7 @@ static void ex_redraw(exarg_T *eap) RedrawingDisabled = 0; p_lz = false; - validate_cursor(); + validate_cursor(curwin); update_topline(curwin); if (eap->forceit) { redraw_all_later(UPD_NOT_VALID); @@ -6447,10 +6490,10 @@ static void ex_mark(exarg_T *eap) /// Update w_topline, w_leftcol and the cursor position. void update_topline_cursor(void) { - check_cursor(); // put cursor on valid line + check_cursor(curwin); // put cursor on valid line update_topline(curwin); if (!curwin->w_p_wrap) { - validate_cursor(); + validate_cursor(curwin); } update_curswant(); } @@ -6670,7 +6713,7 @@ static void ex_checkpath(exarg_T *eap) { find_pattern_in_path(NULL, 0, 0, false, false, CHECK_PATH, 1, eap->forceit ? ACTION_SHOW_ALL : ACTION_SHOW, - 1, (linenr_T)MAXLNUM); + 1, (linenr_T)MAXLNUM, eap->forceit); } /// ":psearch" @@ -6729,7 +6772,7 @@ static void ex_findpat(exarg_T *eap) if (!eap->skip) { find_pattern_in_path(eap->arg, 0, strlen(eap->arg), whole, !eap->forceit, *eap->cmd == 'd' ? FIND_DEFINE : FIND_ANY, - n, action, eap->line1, eap->line2); + n, action, eap->line1, eap->line2, eap->forceit); } } @@ -6754,7 +6797,7 @@ static void ex_pedit(exarg_T *eap) if (curwin != curwin_save && win_valid(curwin_save)) { // Return cursor to where we were - validate_cursor(); + validate_cursor(curwin); redraw_later(curwin, UPD_VALID); win_enter(curwin_save, true); } @@ -7339,7 +7382,7 @@ void filetype_maybe_enable(void) /// ":setfiletype [FALLBACK] {name}" static void ex_setfiletype(exarg_T *eap) { - if (did_filetype) { + if (curbuf->b_did_filetype) { return; } @@ -7350,7 +7393,7 @@ static void ex_setfiletype(exarg_T *eap) set_option_value_give_err(kOptFiletype, CSTR_AS_OPTVAL(arg), OPT_LOCAL); if (arg != eap->arg) { - did_filetype = false; + curbuf->b_did_filetype = false; } } @@ -7396,7 +7439,7 @@ static void ex_folddo(exarg_T *eap) { // First set the marks for all lines closed/open. for (linenr_T lnum = eap->line1; lnum <= eap->line2; lnum++) { - if (hasFolding(lnum, NULL, NULL) == (eap->cmdidx == CMD_folddoclosed)) { + if (hasFolding(curwin, lnum, NULL, NULL) == (eap->cmdidx == CMD_folddoclosed)) { ml_setmarked(lnum); } } |