diff options
Diffstat (limited to 'src/nvim/ex_docmd.c')
-rw-r--r-- | src/nvim/ex_docmd.c | 405 |
1 files changed, 262 insertions, 143 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index c1b9eff697..6361267d9b 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -208,8 +208,8 @@ void do_exmode(int improved) return; save_msg_scroll = msg_scroll; - ++RedrawingDisabled; /* don't redisplay the window */ - ++no_wait_return; /* don't wait for return */ + RedrawingDisabled++; // don't redisplay the window + no_wait_return++; // don't wait for return MSG(_("Entering Ex mode. Type \"visual\" to go to Normal mode.")); while (exmode_active) { @@ -253,10 +253,11 @@ void do_exmode(int improved) } } - --RedrawingDisabled; - --no_wait_return; - update_screen(CLEAR); - need_wait_return = FALSE; + RedrawingDisabled--; + no_wait_return--; + redraw_all_later(NOT_VALID); + update_screen(NOT_VALID); + need_wait_return = false; msg_scroll = save_msg_scroll; } @@ -400,7 +401,7 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, */ if (!(flags & DOCMD_KEYTYPED) && !getline_equal(fgetline, cookie, getexline)) - KeyTyped = FALSE; + KeyTyped = false; /* * Continue executing command lines: @@ -973,8 +974,8 @@ static char_u *get_loop_line(int c, void *cookie, int indent) return line; } - KeyTyped = FALSE; - ++cp->current_line; + KeyTyped = false; + cp->current_line++; wp = (wcmd_T *)(cp->lines_gap->ga_data) + cp->current_line; sourcing_lnum = wp->lnum; return vim_strsave(wp->line); @@ -1803,15 +1804,19 @@ static char_u * do_one_cmd(char_u **cmdlinep, errormsg = (char_u *)_(get_text_locked_msg()); goto doend; } - /* Disallow editing another buffer when "curbuf_lock" is set. - * Do allow ":edit" (check for argument later). - * Do allow ":checktime" (it's postponed). */ + + // Disallow editing another buffer when "curbuf_lock" is set. + // Do allow ":checktime" (it is postponed). + // Do allow ":edit" (check for an argument later). + // Do allow ":file" with no arguments (check for an argument later). if (!(ea.argt & CMDWIN) - && ea.cmdidx != CMD_edit && ea.cmdidx != CMD_checktime + && ea.cmdidx != CMD_edit + && ea.cmdidx != CMD_file && !IS_USER_CMDIDX(ea.cmdidx) - && curbuf_locked()) + && curbuf_locked()) { goto doend; + } if (!ni && !(ea.argt & RANGE) && ea.addr_count > 0) { /* no range allowed */ @@ -1883,6 +1888,11 @@ static char_u * do_one_cmd(char_u **cmdlinep, else ea.arg = skipwhite(p); + // ":file" cannot be run with an argument when "curbuf_lock" is set + if (ea.cmdidx == CMD_file && *ea.arg != NUL && curbuf_locked()) { + goto doend; + } + /* * Check for "++opt=val" argument. * Must be first, allow ":w ++enc=utf8 !cmd" @@ -2665,8 +2675,8 @@ const char * set_one_cmd_context( size_t len = 0; exarg_T ea; int context = EXPAND_NOTHING; - int forceit = false; - int usefilter = false; // Filter instead of file name. + bool forceit = false; + bool usefilter = false; // Filter instead of file name. ExpandInit(xp); xp->xp_pattern = (char_u *)buff; @@ -2786,9 +2796,9 @@ const char * set_one_cmd_context( xp->xp_context = EXPAND_NOTHING; /* Default now that we're past command */ - if (*p == '!') { /* forced commands */ - forceit = TRUE; - ++p; + if (*p == '!') { // forced commands + forceit = true; + p++; } /* @@ -2813,10 +2823,10 @@ const char * set_one_cmd_context( } if (ea.cmdidx == CMD_read) { - usefilter = forceit; /* :r! filter if forced */ - if (*arg == '!') { /* :r !filter */ - ++arg; - usefilter = TRUE; + usefilter = forceit; // :r! filter if forced + if (*arg == '!') { // :r !filter + arg++; + usefilter = true; } } @@ -2899,11 +2909,7 @@ const char * set_one_cmd_context( xp->xp_pattern = skipwhite((const char_u *)arg); p = (const char *)xp->xp_pattern; while (*p != NUL) { - if (has_mbyte) { - c = mb_ptr2char((const char_u *)p); - } else { - c = (uint8_t)(*p); - } + c = utf_ptr2char((const char_u *)p); if (c == '\\' && p[1] != NUL) { p++; } else if (c == '`') { @@ -2921,19 +2927,11 @@ const char * set_one_cmd_context( || ascii_iswhite(c)) { len = 0; /* avoid getting stuck when space is in 'isfname' */ while (*p != NUL) { - if (has_mbyte) { - c = mb_ptr2char((const char_u *)p); - } else { - c = *p; - } + c = utf_ptr2char((const char_u *)p); if (c == '`' || vim_isfilec_or_wc(c)) { break; } - if (has_mbyte) { - len = (size_t)(*mb_ptr2len)((const char_u *)p); - } else { - len = 1; - } + len = (size_t)utfc_ptr2len((const char_u *)p); MB_PTR_ADV(p); } if (in_quote) { @@ -2990,7 +2988,7 @@ const char * set_one_cmd_context( // A full match ~user<Tab> will be replaced by user's home // directory i.e. something like ~user<Tab> -> /home/user/ if (*p == NUL && p > (const char *)xp->xp_pattern + 1 - && match_user(xp->xp_pattern + 1) == 1) { + && match_user(xp->xp_pattern + 1) >= 1) { xp->xp_context = EXPAND_USER; ++xp->xp_pattern; } @@ -3272,8 +3270,15 @@ const char * set_one_cmd_context( while ((xp->xp_pattern = (char_u *)strchr(arg, ' ')) != NULL) { arg = (const char *)xp->xp_pattern + 1; } + xp->xp_context = EXPAND_USER_VARS; xp->xp_pattern = (char_u *)arg; + + if (*xp->xp_pattern == '$') { + xp->xp_context = EXPAND_ENV_VARS; + xp->xp_pattern++; + } + break; case CMD_function: @@ -3302,7 +3307,7 @@ const char * set_one_cmd_context( while ((xp->xp_pattern = (char_u *)strchr(arg, ' ')) != NULL) { arg = (const char *)xp->xp_pattern + 1; } - // FALLTHROUGH + FALLTHROUGH; case CMD_buffer: case CMD_sbuffer: case CMD_checktime: @@ -3362,6 +3367,19 @@ const char * set_one_cmd_context( case CMD_xunmap: return (const char *)set_context_in_map_cmd( xp, (char_u *)cmd, (char_u *)arg, forceit, false, true, ea.cmdidx); + case CMD_mapclear: + case CMD_nmapclear: + case CMD_vmapclear: + case CMD_omapclear: + case CMD_imapclear: + case CMD_cmapclear: + case CMD_lmapclear: + case CMD_smapclear: + case CMD_xmapclear: + xp->xp_context = EXPAND_MAPCLEAR; + xp->xp_pattern = (char_u *)arg; + break; + case CMD_abbreviate: case CMD_noreabbrev: case CMD_cabbrev: case CMD_cnoreabbrev: case CMD_iabbrev: case CMD_inoreabbrev: @@ -3453,6 +3471,13 @@ const char * set_one_cmd_context( xp->xp_pattern = (char_u *)arg; break; + case CMD_argdelete: + while ((xp->xp_pattern = vim_strchr((const char_u *)arg, ' ')) != NULL) { + arg = (const char *)(xp->xp_pattern + 1); + } + xp->xp_context = EXPAND_ARGLIST; + xp->xp_pattern = (char_u *)arg; + break; default: break; @@ -3656,17 +3681,18 @@ static linenr_T get_address(exarg_T *eap, */ if (lnum != MAXLNUM) curwin->w_cursor.lnum = lnum; - /* - * Start a forward search at the end of the line. - * Start a backward search at the start of the line. - * This makes sure we never match in the current - * line, and can match anywhere in the - * next/previous line. - */ - if (c == '/') + + // Start a forward search at the end of the line (unless + // before the first line). + // Start a backward search at the start of the line. + // This makes sure we never match in the current + // line, and can match anywhere in the + // next/previous line. + if (c == '/' && curwin->w_cursor.lnum > 0) { curwin->w_cursor.col = MAXCOL; - else + } else { curwin->w_cursor.col = 0; + } searchcmdlen = 0; if (!do_search(NULL, c, cmd, 1L, SEARCH_HIS | SEARCH_MSG, NULL)) { @@ -4858,6 +4884,7 @@ static struct { */ static const char *command_complete[] = { + [EXPAND_ARGLIST] = "arglist", [EXPAND_AUGROUP] = "augroup", [EXPAND_BEHAVE] = "behave", [EXPAND_BUFFERS] = "buffer", @@ -4882,6 +4909,7 @@ static const char *command_complete[] = #ifdef HAVE_WORKING_LIBINTL [EXPAND_LOCALES] = "locale", #endif + [EXPAND_MAPCLEAR] = "mapclear", [EXPAND_MAPPINGS] = "mapping", [EXPAND_MENUS] = "menu", [EXPAND_MESSAGES] = "messages", @@ -5178,9 +5206,10 @@ static void ex_command(exarg_T *eap) while (*p == '-') { ++p; end = skiptowhite(p); - if (uc_scan_attr(p, end - p, &argt, &def, &flags, &compl, &compl_arg, &addr_type_arg) - == FAIL) + if (uc_scan_attr(p, end - p, &argt, &def, &flags, &compl, &compl_arg, + &addr_type_arg) == FAIL) { return; + } p = skipwhite(end); } @@ -5211,9 +5240,10 @@ static void ex_command(exarg_T *eap) || (name_len <= 4 && STRNCMP(name, "Next", name_len) == 0)) { EMSG(_("E841: Reserved name, cannot be used for user defined command")); return; - } else + } else { uc_add_command(name, end - name, p, argt, def, flags, compl, compl_arg, addr_type_arg, eap->forceit); + } } /* @@ -5387,8 +5417,18 @@ uc_check_code( char_u *p = code + 1; size_t l = len - 2; int quote = 0; - enum { ct_ARGS, ct_BANG, ct_COUNT, ct_LINE1, ct_LINE2, ct_MODS, - ct_REGISTER, ct_LT, ct_NONE } type = ct_NONE; + enum { + ct_ARGS, + ct_BANG, + ct_COUNT, + ct_LINE1, + ct_LINE2, + ct_RANGE, + ct_MODS, + ct_REGISTER, + ct_LT, + ct_NONE + } type = ct_NONE; if ((vim_strchr((char_u *)"qQfF", *p) != NULL) && p[1] == '-') { quote = (*p == 'q' || *p == 'Q') ? 1 : 2; @@ -5409,6 +5449,8 @@ uc_check_code( type = ct_LINE1; } else if (STRNICMP(p, "line2>", l) == 0) { type = ct_LINE2; + } else if (STRNICMP(p, "range>", l) == 0) { + type = ct_RANGE; } else if (STRNICMP(p, "lt>", l) == 0) { type = ct_LT; } else if (STRNICMP(p, "reg>", l) == 0 || STRNICMP(p, "register>", l) == 0) { @@ -5496,11 +5538,13 @@ uc_check_code( case ct_LINE1: case ct_LINE2: + case ct_RANGE: case ct_COUNT: { char num_buf[20]; long num = (type == ct_LINE1) ? eap->line1 : (type == ct_LINE2) ? eap->line2 : + (type == ct_RANGE) ? eap->addr_count : (eap->addr_count > 0) ? eap->line2 : cmd->uc_def; size_t num_len; @@ -5954,9 +5998,35 @@ void not_exiting(void) exiting = FALSE; } -/* - * ":quit": quit current window, quit Vim if the last window is closed. - */ +static bool before_quit_autocmds(win_T *wp, bool quit_all, int forceit) +{ + apply_autocmds(EVENT_QUITPRE, NULL, NULL, false, wp->w_buffer); + + // Bail out when autocommands closed the window. + // Refuse to quit when the buffer in the last window is being closed (can + // only happen in autocommands). + if (!win_valid(wp) + || curbuf_locked() + || (wp->w_buffer->b_nwindows == 1 && wp->w_buffer->b_locked > 0)) { + return true; + } + + if (quit_all + || (check_more(false, forceit) == OK && only_one_window())) { + apply_autocmds(EVENT_EXITPRE, NULL, NULL, false, curbuf); + // Refuse to quit when locked or when the buffer in the last window is + // being closed (can only happen in autocommands). + if (curbuf_locked() + || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0)) { + return true; + } + } + + return false; +} + +// ":quit": quit current window, quit Vim if the last window is closed. +// ":{nr}quit": quit window {nr} static void ex_quit(exarg_T *eap) { if (cmdwin_type != 0) { @@ -5986,11 +6056,9 @@ static void ex_quit(exarg_T *eap) if (curbuf_locked()) { return; } - apply_autocmds(EVENT_QUITPRE, NULL, NULL, false, wp->w_buffer); - // Refuse to quit when locked or when the buffer in the last window is - // being closed (can only happen in autocommands). - if (!win_valid(wp) - || (wp->w_buffer->b_nwindows == 1 && wp->w_buffer->b_locked > 0)) { + + // Trigger QuitPre and maybe ExitPre + if (before_quit_autocmds(wp, false, eap->forceit)) { return; } @@ -6015,6 +6083,7 @@ static void ex_quit(exarg_T *eap) if (only_one_window() && (ONE_WINDOW || eap->addr_count == 0)) { getout(0); } + not_exiting(); // close window; may free buffer win_close(wp, !buf_hide(wp->w_buffer) || eap->forceit); } @@ -6047,10 +6116,8 @@ static void ex_quit_all(exarg_T *eap) text_locked_msg(); return; } - apply_autocmds(EVENT_QUITPRE, NULL, NULL, false, curbuf); - // Refuse to quit when locked or when the buffer in the last window is - // being closed (can only happen in autocommands). - if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0)) { + + if (before_quit_autocmds(curwin, true, eap->forceit)) { return; } @@ -6309,9 +6376,7 @@ static void ex_hide(exarg_T *eap) } } -/* - * ":stop" and ":suspend": Suspend Vim. - */ +/// ":stop" and ":suspend": Suspend Vim. static void ex_stop(exarg_T *eap) { // Disallow suspending in restricted mode (-Z) @@ -6320,23 +6385,22 @@ static void ex_stop(exarg_T *eap) autowrite_all(); } apply_autocmds(EVENT_VIMSUSPEND, NULL, NULL, false, NULL); + + // TODO(bfredl): the TUI should do this on suspend ui_cursor_goto((int)Rows - 1, 0); - ui_linefeed(); + ui_call_grid_scroll(1, 0, Rows, 0, Columns, 1, 0); ui_flush(); ui_call_suspend(); // call machine specific function ui_flush(); maketitle(); resettitle(); // force updating the title - redraw_later_clear(); ui_refresh(); // may have resized window apply_autocmds(EVENT_VIMRESUME, NULL, NULL, false, NULL); } } -/* - * ":exit", ":xit" and ":wq": Write file and exit Vim. - */ +// ":exit", ":xit" and ":wq": Write file and quite the current window. static void ex_exit(exarg_T *eap) { if (cmdwin_type != 0) { @@ -6348,10 +6412,8 @@ static void ex_exit(exarg_T *eap) text_locked_msg(); return; } - apply_autocmds(EVENT_QUITPRE, NULL, NULL, false, curbuf); - // Refuse to quit when locked or when the buffer in the last window is - // being closed (can only happen in autocommands). - if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0)) { + + if (before_quit_autocmds(curwin, false, eap->forceit)) { return; } @@ -6370,6 +6432,7 @@ static void ex_exit(exarg_T *eap) // quit last window, exit Vim getout(0); } + not_exiting(); // Quit current window, may free the buffer. win_close(curwin, !buf_hide(curwin->w_buffer)); } @@ -6490,6 +6553,13 @@ void alist_expand(int *fnum_list, int fnum_len) void alist_set(alist_T *al, int count, char_u **files, int use_curbuf, int *fnum_list, int fnum_len) { int i; + static int recursive = 0; + + if (recursive) { + EMSG(_(e_au_recursive)); + return; + } + recursive++; alist_clear(al); ga_grow(&al->al_ga, count); @@ -6514,8 +6584,10 @@ void alist_set(alist_T *al, int count, char_u **files, int use_curbuf, int *fnum xfree(files); } - if (al == &global_alist) - arg_had_last = FALSE; + if (al == &global_alist) { + arg_had_last = false; + } + recursive--; } /* @@ -6795,7 +6867,8 @@ static void ex_tabs(exarg_T *eap) static void ex_mode(exarg_T *eap) { if (*eap->arg == NUL) { - ui_refresh(); + must_redraw = CLEAR; + ex_redraw(eap); } else { EMSG(_(e_screenmode)); } @@ -6901,7 +6974,7 @@ do_exedit( no_wait_return = 0; need_wait_return = FALSE; msg_scroll = 0; - must_redraw = CLEAR; + redraw_all_later(NOT_VALID); normal_enter(false, true); @@ -7393,7 +7466,7 @@ static void ex_operators(exarg_T *eap) oa.end.lnum = eap->line2; oa.line_count = eap->line2 - eap->line1 + 1; oa.motion_type = kMTLineWise; - virtual_op = false; + virtual_op = kFalse; if (eap->cmdidx != CMD_yank) { // position cursor for undo setpcmark(); curwin->w_cursor.lnum = eap->line1; @@ -7424,7 +7497,7 @@ static void ex_operators(exarg_T *eap) op_shift(&oa, FALSE, eap->amount); break; } - virtual_op = MAYBE; + virtual_op = kNone; ex_may_print(eap); } @@ -7565,10 +7638,11 @@ static void ex_bang(exarg_T *eap) */ static void ex_undo(exarg_T *eap) { - if (eap->addr_count == 1) /* :undo 123 */ - undo_time(eap->line2, FALSE, FALSE, TRUE); - else + if (eap->addr_count == 1) { // :undo 123 + undo_time(eap->line2, false, false, true); + } else { u_undo(1); + } } static void ex_wundo(exarg_T *eap) @@ -7601,8 +7675,8 @@ static void ex_redo(exarg_T *eap) static void ex_later(exarg_T *eap) { long count = 0; - int sec = FALSE; - int file = FALSE; + bool sec = false; + bool file = false; char_u *p = eap->arg; if (*p == NUL) @@ -7610,11 +7684,11 @@ static void ex_later(exarg_T *eap) else if (isdigit(*p)) { count = getdigits_long(&p); switch (*p) { - case 's': ++p; sec = TRUE; break; - case 'm': ++p; sec = TRUE; count *= 60; break; - case 'h': ++p; sec = TRUE; count *= 60 * 60; break; - case 'd': ++p; sec = TRUE; count *= 24 * 60 * 60; break; - case 'f': ++p; file = TRUE; break; + case 's': ++p; sec = true; break; + case 'm': ++p; sec = true; count *= 60; break; + case 'h': ++p; sec = true; count *= 60 * 60; break; + case 'd': ++p; sec = true; count *= 24 * 60 * 60; break; + case 'f': ++p; file = true; break; } } @@ -7622,7 +7696,7 @@ static void ex_later(exarg_T *eap) EMSG2(_(e_invarg2), eap->arg); else undo_time(eap->cmdidx == CMD_earlier ? -count : count, - sec, file, FALSE); + sec, file, false); } /* @@ -7719,11 +7793,14 @@ static void ex_redraw(exarg_T *eap) p_lz = FALSE; validate_cursor(); update_topline(); - update_screen(eap->forceit ? CLEAR : - VIsual_active ? INVERTED : - 0); - if (need_maketitle) + if (eap->forceit) { + redraw_all_later(NOT_VALID); + } + update_screen(eap->forceit ? NOT_VALID + : VIsual_active ? INVERTED : 0); + if (need_maketitle) { maketitle(); + } RedrawingDisabled = r; p_lz = p; @@ -7918,7 +7995,7 @@ static void ex_mkrc(exarg_T *eap) if (failed) { EMSG(_(e_write)); } else if (eap->cmdidx == CMD_mksession) { - // successful session write - set this_session var + // successful session write - set v:this_session char *const tbuf = xmalloc(MAXPATHL); if (vim_FullName(fname, tbuf, MAXPATHL, false) == OK) { set_vim_var_string(VV_THIS_SESSION, tbuf, -1); @@ -8141,6 +8218,10 @@ static void ex_normal(exarg_T *eap) static void ex_startinsert(exarg_T *eap) { if (eap->forceit) { + // cursor line can be zero on startup + if (!curwin->w_cursor.lnum) { + curwin->w_cursor.lnum = 1; + } coladvance((colnr_T)MAXCOL); curwin->w_curswant = MAXCOL; curwin->w_set_curswant = FALSE; @@ -8380,23 +8461,25 @@ ssize_t find_cmdline_var(const char_u *src, size_t *usedlen) "%", #define SPEC_PERC 0 "#", -#define SPEC_HASH 1 - "<cword>", /* cursor word */ -#define SPEC_CWORD 2 - "<cWORD>", /* cursor WORD */ -#define SPEC_CCWORD 3 - "<cfile>", /* cursor path name */ -#define SPEC_CFILE 4 - "<sfile>", /* ":so" file name */ -#define SPEC_SFILE 5 - "<slnum>", /* ":so" file line number */ -#define SPEC_SLNUM 6 - "<afile>", /* autocommand file name */ -# define SPEC_AFILE 7 - "<abuf>", /* autocommand buffer number */ -# define SPEC_ABUF 8 - "<amatch>", /* autocommand match name */ -# define SPEC_AMATCH 9 +#define SPEC_HASH (SPEC_PERC + 1) + "<cword>", // cursor word +#define SPEC_CWORD (SPEC_HASH + 1) + "<cWORD>", // cursor WORD +#define SPEC_CCWORD (SPEC_CWORD + 1) + "<cexpr>", // expr under cursor +#define SPEC_CEXPR (SPEC_CCWORD + 1) + "<cfile>", // cursor path name +#define SPEC_CFILE (SPEC_CEXPR + 1) + "<sfile>", // ":so" file name +#define SPEC_SFILE (SPEC_CFILE + 1) + "<slnum>", // ":so" file line number +#define SPEC_SLNUM (SPEC_SFILE + 1) + "<afile>", // autocommand file name +#define SPEC_AFILE (SPEC_SLNUM + 1) + "<abuf>", // autocommand buffer number +#define SPEC_ABUF (SPEC_AFILE + 1) + "<amatch>", // autocommand match name +#define SPEC_AMATCH (SPEC_ABUF + 1) }; for (size_t i = 0; i < ARRAY_SIZE(spec_str); ++i) { @@ -8477,10 +8560,16 @@ eval_vars ( /* * word or WORD under cursor */ - if (spec_idx == SPEC_CWORD || spec_idx == SPEC_CCWORD) { - resultlen = find_ident_under_cursor(&result, (spec_idx == SPEC_CWORD - ? (FIND_IDENT|FIND_STRING) - : FIND_STRING)); + if (spec_idx == SPEC_CWORD + || spec_idx == SPEC_CCWORD + || spec_idx == SPEC_CEXPR) { + resultlen = find_ident_under_cursor( + &result, + spec_idx == SPEC_CWORD + ? (FIND_IDENT | FIND_STRING) + : (spec_idx == SPEC_CEXPR + ? (FIND_IDENT | FIND_STRING | FIND_EVAL) + : FIND_STRING)); if (resultlen == 0) { *errormsg = (char_u *)""; return NULL; @@ -8517,9 +8606,13 @@ eval_vars ( if (*s == '<') /* "#<99" uses v:oldfiles */ ++s; i = getdigits_int(&s); - *usedlen = (size_t)(s - src); /* length of what we expand */ + if (s == src + 2 && src[1] == '-') { + // just a minus sign, don't skip over it + s--; + } + *usedlen = (size_t)(s - src); // length of what we expand - if (src[1] == '<') { + if (src[1] == '<' && i != 0) { if (*usedlen < 2) { /* Should we give an error message for #<text? */ *usedlen = 1; @@ -8532,6 +8625,9 @@ eval_vars ( return NULL; } } else { + if (i == 0 && src[1] == '<' && *usedlen > 1) { + *usedlen = 1; + } buf = buflist_findnr(i); if (buf == NULL) { *errormsg = (char_u *)_( @@ -8617,11 +8713,14 @@ eval_vars ( break; } - resultlen = STRLEN(result); /* length of new string */ - if (src[*usedlen] == '<') { /* remove the file name extension */ - ++*usedlen; - if ((s = vim_strrchr(result, '.')) != NULL && s >= path_tail(result)) + // Length of new string. + resultlen = STRLEN(result); + // Remove the file name extension. + if (src[*usedlen] == '<') { + (*usedlen)++; + if ((s = STRRCHR(result, '.')) != NULL && s >= path_tail(result)) { resultlen = (size_t)(s - result); + } } else if (!skip_mod) { valid |= modify_fname(src, usedlen, &result, &resultbuf, &resultlen); if (result == NULL) { @@ -8680,7 +8779,7 @@ static char_u *arg_all(void) #ifndef BACKSLASH_IN_FILENAME || *p == '\\' #endif - ) { + || *p == '`') { // insert a backslash if (retval != NULL) { retval[len] = '\\'; @@ -8782,15 +8881,15 @@ makeopens( if (ssop_flags & SSOP_BUFFERS) only_save_windows = FALSE; /* Save ALL buffers */ - /* - * Begin by setting the this_session variable, and then other - * sessionable variables. - */ - if (put_line(fd, "let v:this_session=expand(\"<sfile>:p\")") == FAIL) + // Begin by setting v:this_session, and then other sessionable variables. + if (put_line(fd, "let v:this_session=expand(\"<sfile>:p\")") == FAIL) { return FAIL; - if (ssop_flags & SSOP_GLOBALS) - if (store_session_globals(fd) == FAIL) + } + if (ssop_flags & SSOP_GLOBALS) { + if (store_session_globals(fd) == FAIL) { return FAIL; + } + } /* * Close all windows but one. @@ -8971,8 +9070,10 @@ makeopens( // cursor can be set. This is done again below. // winminheight and winminwidth need to be set to avoid an error if the // user has set winheight or winwidth. - if (put_line(fd, "set winminheight=1 winminwidth=1 winheight=1 winwidth=1") - == FAIL) { + if (put_line(fd, "set winminheight=0") == FAIL + || put_line(fd, "set winheight=1") == FAIL + || put_line(fd, "set winminwidth=0") == FAIL + || put_line(fd, "set winwidth=1") == FAIL) { return FAIL; } if (nr > 1 && ses_winsizes(fd, restore_size, tab_firstwin) == FAIL) { @@ -9204,6 +9305,18 @@ static int ses_do_win(win_T *wp) return true; } +static int put_view_curpos(FILE *fd, const win_T *wp, char *spaces) +{ + int r; + + if (wp->w_curswant == MAXCOL) { + r = fprintf(fd, "%snormal! $", spaces); + } else { + r = fprintf(fd, "%snormal! 0%d|", spaces, wp->w_virtcol + 1); + } + return r < 0 || put_eol(fd) == FAIL ? FAIL : OK; +} + /* * Write commands to "fd" to restore the view of a window. * Caller must make sure 'scrolloff' is zero. @@ -9370,14 +9483,11 @@ put_view( (int64_t)(wp->w_virtcol + 1)) < 0 || put_eol(fd) == FAIL || put_line(fd, "else") == FAIL - || fprintf(fd, " normal! 0%d|", wp->w_virtcol + 1) < 0 - || put_eol(fd) == FAIL + || put_view_curpos(fd, wp, " ") == FAIL || put_line(fd, "endif") == FAIL) return FAIL; - } else { - if (fprintf(fd, "normal! 0%d|", wp->w_virtcol + 1) < 0 - || put_eol(fd) == FAIL) - return FAIL; + } else if (put_view_curpos(fd, wp, "") == FAIL) { + return FAIL; } } } @@ -9662,6 +9772,14 @@ char_u *get_messages_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx) return NULL; } +char_u *get_mapclear_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx) +{ + if (idx == 0) { + return (char_u *)"<buffer>"; + } + return NULL; +} + static TriState filetype_detect = kNone; static TriState filetype_plugin = kNone; static TriState filetype_indent = kNone; @@ -9944,6 +10062,7 @@ bool cmd_can_preview(char_u *cmd) } exarg_T ea; + memset(&ea, 0, sizeof(ea)); // parse the command line ea.cmd = skip_range(cmd, NULL); if (*ea.cmd == '*') { |