aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ex_docmd.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2024-05-24 19:18:11 +0000
committerJosh Rahm <joshuarahm@gmail.com>2024-05-24 19:18:11 +0000
commitff7ed8f586589d620a806c3758fac4a47a8e7e15 (patch)
tree729bbcb92231538fa61dab6c3d890b025484b7f5 /src/nvim/ex_docmd.c
parent376914f419eb08fdf4c1a63a77e1f035898a0f10 (diff)
parent28c04948a1c887a1cc0cb64de79fa32631700466 (diff)
downloadrneovim-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.c153
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);
}
}