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.c100
1 files changed, 61 insertions, 39 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 2da8c205c1..854faf5377 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -790,7 +790,10 @@ void ex_retab(exarg_T *eap)
for (col = 0; col < len; col++) {
ptr[col] = (col < num_tabs) ? '\t' : ' ';
}
- ml_replace(lnum, new_line, false);
+ if (ml_replace(lnum, new_line, false) == OK) {
+ // "new_line" may have been copied
+ new_line = curbuf->b_ml.ml_line_ptr;
+ }
if (first_line == 0) {
first_line = lnum;
}
@@ -1404,19 +1407,20 @@ do_shell(
* 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 */
+ msg_putchar('\r'); // put cursor at start of line
+ msg_putchar('\n'); // may shift screen one line up
- /* warning message before calling the shell */
+ // warning message before calling the shell
if (p_warn
&& !autocmd_busy
- && msg_silent == 0)
+ && msg_silent == 0) {
FOR_ALL_BUFFERS(buf) {
if (bufIsChanged(buf)) {
MSG_PUTS(_("[No write since last change]\n"));
break;
}
}
+ }
// This ui_cursor_goto is required for when the '\n' resulted in a "delete line
// 1" command to the terminal.
@@ -2178,6 +2182,8 @@ theend:
/// ECMD_OLDBUF: use existing buffer if it exists
/// ECMD_FORCEIT: ! used for Ex command
/// ECMD_ADDBUF: don't edit, just add to buffer list
+/// ECMD_ALTBUF: like ECMD_ADDBUF and also set the alternate
+/// file
/// @param oldwin Should be "curwin" when editing a new buffer in the current
/// window, NULL when splitting the window first. When not NULL
/// info of the previous buffer for "oldwin" is stored.
@@ -2234,8 +2240,10 @@ int do_ecmd(
path_fix_case(sfname); // set correct case for sfname
#endif
- if ((flags & ECMD_ADDBUF) && (ffname == NULL || *ffname == NUL))
+ if ((flags & (ECMD_ADDBUF | ECMD_ALTBUF))
+ && (ffname == NULL || *ffname == NUL)) {
goto theend;
+ }
if (ffname == NULL)
other_file = TRUE;
@@ -2265,15 +2273,16 @@ int do_ecmd(
// If the file was changed we may not be allowed to abandon it:
// - if we are going to re-edit the same file
// - or if we are the only window on this file and if ECMD_HIDE is FALSE
- if ( ((!other_file && !(flags & ECMD_OLDBUF))
- || (curbuf->b_nwindows == 1
- && !(flags & (ECMD_HIDE | ECMD_ADDBUF))))
- && check_changed(curbuf, (p_awa ? CCGD_AW : 0)
- | (other_file ? 0 : CCGD_MULTWIN)
- | ((flags & ECMD_FORCEIT) ? CCGD_FORCEIT : 0)
- | (eap == NULL ? 0 : CCGD_EXCMD))) {
- if (fnum == 0 && other_file && ffname != NULL)
+ if (((!other_file && !(flags & ECMD_OLDBUF))
+ || (curbuf->b_nwindows == 1
+ && !(flags & (ECMD_HIDE | ECMD_ADDBUF | ECMD_ALTBUF))))
+ && check_changed(curbuf, (p_awa ? CCGD_AW : 0)
+ | (other_file ? 0 : CCGD_MULTWIN)
+ | ((flags & ECMD_FORCEIT) ? CCGD_FORCEIT : 0)
+ | (eap == NULL ? 0 : CCGD_EXCMD))) {
+ if (fnum == 0 && other_file && ffname != NULL) {
(void)setaltfname(ffname, sfname, newlnum < 0 ? 0 : newlnum);
+ }
goto theend;
}
@@ -2303,25 +2312,35 @@ int do_ecmd(
* Otherwise we re-use the current buffer.
*/
if (other_file) {
- if (!(flags & ECMD_ADDBUF)) {
- if (!cmdmod.keepalt)
+ if (!(flags & (ECMD_ADDBUF | ECMD_ALTBUF))) {
+ if (!cmdmod.keepalt) {
curwin->w_alt_fnum = curbuf->b_fnum;
- if (oldwin != NULL)
+ }
+ if (oldwin != NULL) {
buflist_altfpos(oldwin);
+ }
}
if (fnum) {
buf = buflist_findnr(fnum);
} else {
- if (flags & ECMD_ADDBUF) {
- linenr_T tlnum = 1L;
+ if (flags & (ECMD_ADDBUF | ECMD_ALTBUF)) {
+ // Default the line number to zero to avoid that a wininfo item
+ // is added for the current window.
+ linenr_T tlnum = 0;
if (command != NULL) {
tlnum = atol((char *)command);
if (tlnum <= 0)
tlnum = 1L;
}
- (void)buflist_new(ffname, sfname, tlnum, BLN_LISTED);
+ // Add BLN_NOCURWIN to avoid a new wininfo items are associated
+ // with the current window.
+ const buf_T *const newbuf
+ = buflist_new(ffname, sfname, tlnum, BLN_LISTED | BLN_NOCURWIN);
+ if (newbuf != NULL && (flags & ECMD_ALTBUF)) {
+ curwin->w_alt_fnum = newbuf->b_fnum;
+ }
goto theend;
}
buf = buflist_new(ffname, sfname, 0L,
@@ -2413,7 +2432,10 @@ int do_ecmd(
(flags & ECMD_HIDE) || curbuf->terminal ? 0 : DOBUF_UNLOAD,
false);
- the_curwin->w_closing = false;
+ // Autocommands may have closed the window.
+ if (win_valid(the_curwin)) {
+ the_curwin->w_closing = false;
+ }
buf->b_locked--;
// autocmds may abort script processing
@@ -2464,8 +2486,7 @@ int do_ecmd(
curwin->w_pcmark.lnum = 1;
curwin->w_pcmark.col = 0;
} else { // !other_file
- if ((flags & ECMD_ADDBUF)
- || check_fname() == FAIL) {
+ if ((flags & (ECMD_ADDBUF | ECMD_ALTBUF)) || check_fname() == FAIL) {
goto theend;
}
oldbuf = (flags & ECMD_OLDBUF);
@@ -2531,13 +2552,13 @@ int do_ecmd(
goto theend;
}
u_unchanged(curbuf);
- buf_updates_unregister_all(curbuf);
+ buf_updates_unload(curbuf, false);
buf_freeall(curbuf, BFA_KEEP_UNDO);
// Tell readfile() not to clear or reload undo info.
readfile_flags = READ_KEEP_UNDO;
} else {
- buf_updates_unregister_all(curbuf);
+ buf_updates_unload(curbuf, false);
buf_freeall(curbuf, 0); // Free all things for buffer.
}
// If autocommands deleted the buffer we were going to re-edit, give
@@ -3310,11 +3331,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
int save_b_changed = curbuf->b_changed;
bool preview = (State & CMDPREVIEW);
- // inccommand tests fail without this check
- if (!preview) {
- // Required for Undo to work for extmarks.
- u_save_cursor();
- }
+ bool did_save = false;
if (!global_busy) {
sub_nsubs = 0;
@@ -3991,6 +4008,11 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
int matchcols = end.col - ((end.lnum == start.lnum)
? start.col : 0);
int subcols = new_endcol - ((lnum == lnum_start) ? start_col : 0);
+ if (!did_save) {
+ // Required for Undo to work for extmarks.
+ u_save_cursor();
+ did_save = true;
+ }
extmark_splice(curbuf, lnum_start-1, start_col,
end.lnum-start.lnum, matchcols, replaced_bytes,
lnum-lnum_start, subcols, sublen-1, kExtmarkUndo);
@@ -4177,7 +4199,7 @@ skip:
// when interactive leave cursor on the match
if (!subflags.do_ask) {
if (endcolumn) {
- coladvance((colnr_T)MAXCOL);
+ coladvance(MAXCOL);
} else {
beginline(BL_WHITE | BL_FIX);
}
@@ -4220,7 +4242,7 @@ skip:
size_t subsize = preview_lines.subresults.size;
if (preview && !aborting()) {
if (got_quit || profile_passed_limit(timeout)) { // Too slow, disable.
- set_string_option_direct((char_u *)"icm", -1, (char_u *)"", OPT_FREE,
+ set_string_option_direct("icm", -1, (char_u *)"", OPT_FREE,
SID_NONE);
} else if (*p_icm != NUL && pat != NULL) {
if (pre_src_id == 0) {
@@ -4521,7 +4543,7 @@ prepare_tagpreview (
RESET_BINDING(curwin); /* don't take over 'scrollbind'
and 'cursorbind' */
curwin->w_p_diff = false; // no 'diff'
- set_string_option_direct((char_u *)"fdc", -1, // no 'foldcolumn'
+ set_string_option_direct("fdc", -1, // no 'foldcolumn'
(char_u *)"0", OPT_FREE, SID_NONE);
return true;
}
@@ -4999,7 +5021,7 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches,
if (keep_lang) {
flags |= TAG_KEEP_LANG;
}
- if (find_tags(IObuff, num_matches, matches, flags, (int)MAXCOL, NULL) == OK
+ if (find_tags(IObuff, num_matches, matches, flags, MAXCOL, NULL) == OK
&& *num_matches > 0) {
/* Sort the matches found on the heuristic number that is after the
* tag name. */
@@ -5016,7 +5038,7 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches,
static void prepare_help_buffer(void)
{
curbuf->b_help = true;
- set_string_option_direct((char_u *)"buftype", -1, (char_u *)"help",
+ set_string_option_direct("buftype", -1, (char_u *)"help",
OPT_FREE|OPT_LOCAL, 0);
// Always set these options after jumping to a help tag, because the
@@ -5026,13 +5048,13 @@ static void prepare_help_buffer(void)
// Only set it when needed, buf_init_chartab() is some work.
char_u *p = (char_u *)"!-~,^*,^|,^\",192-255";
if (STRCMP(curbuf->b_p_isk, p) != 0) {
- set_string_option_direct((char_u *)"isk", -1, p, OPT_FREE|OPT_LOCAL, 0);
+ set_string_option_direct("isk", -1, p, OPT_FREE|OPT_LOCAL, 0);
check_buf_options(curbuf);
(void)buf_init_chartab(curbuf, FALSE);
}
// Don't use the global foldmethod.
- set_string_option_direct((char_u *)"fdm", -1, (char_u *)"manual",
+ set_string_option_direct("fdm", -1, (char_u *)"manual",
OPT_FREE|OPT_LOCAL, 0);
curbuf->b_p_ts = 8; // 'tabstop' is 8.
@@ -5652,7 +5674,7 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr,
cmdmod.tab = 0; // disable :tab modifier
cmdmod.noswapfile = true; // disable swap for preview buffer
// disable file info message
- set_string_option_direct((char_u *)"shm", -1, (char_u *)"F", OPT_FREE,
+ set_string_option_direct("shm", -1, (char_u *)"F", OPT_FREE,
SID_NONE);
bool outside_curline = (eap->line1 != old_cusr.lnum
@@ -5775,7 +5797,7 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr,
update_screen(SOME_VALID);
RedrawingDisabled = save_rd;
- set_string_option_direct((char_u *)"shm", -1, save_shm_p, OPT_FREE, SID_NONE);
+ set_string_option_direct("shm", -1, save_shm_p, OPT_FREE, SID_NONE);
xfree(save_shm_p);
cmdmod = save_cmdmod;