diff options
Diffstat (limited to 'src')
97 files changed, 2008 insertions, 1006 deletions
diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index eb32f46143..f4c6f646eb 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -17,6 +17,7 @@ #include "nvim/ascii.h" #include "nvim/autocmd.h" #include "nvim/buffer_defs.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/decoration.h" #include "nvim/ex_cmds.h" #include "nvim/ex_docmd.h" diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 675aaf1006..b8e0934669 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -941,6 +941,12 @@ Buffer nvim_create_buf(Boolean listed, Boolean scratch, Error *err) goto fail; } + // Set last_changedtick to avoid triggering a TextChanged autocommand right + // after it was added. + buf->b_last_changedtick = buf_get_changedtick(buf); + buf->b_last_changedtick_i = buf_get_changedtick(buf); + buf->b_last_changedtick_pum = buf_get_changedtick(buf); + // Only strictly needed for scratch, but could just as well be consistent // and do this now. buffer is created NOW, not when it latter first happen // to reach a window or aucmd_prepbuf() .. diff --git a/src/nvim/arglist.c b/src/nvim/arglist.c index a4221a1562..fb8849541d 100644 --- a/src/nvim/arglist.c +++ b/src/nvim/arglist.c @@ -14,6 +14,7 @@ #include "nvim/autocmd.h" #include "nvim/buffer.h" #include "nvim/charset.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" #include "nvim/eval/window.h" diff --git a/src/nvim/arglist.h b/src/nvim/arglist.h index 52894b73a0..bd5cfb4a11 100644 --- a/src/nvim/arglist.h +++ b/src/nvim/arglist.h @@ -2,6 +2,7 @@ #define NVIM_ARGLIST_H #include "nvim/arglist_defs.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" #include "nvim/types.h" diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index 657760914f..a40f7d8c26 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -2213,6 +2213,13 @@ char *expand_get_event_name(expand_T *xp, int idx) return event_names[idx - next_augroup_id].name; } +/// Function given to ExpandGeneric() to obtain the list of event names. Don't +/// include groups. +char *get_event_name_no_group(expand_T *xp FUNC_ATTR_UNUSED, int idx) +{ + return event_names[idx].name; +} + /// Check whether given autocommand is supported /// /// @param[in] event Event to check. diff --git a/src/nvim/autocmd.h b/src/nvim/autocmd.h index b3de57311e..324a31be47 100644 --- a/src/nvim/autocmd.h +++ b/src/nvim/autocmd.h @@ -6,6 +6,7 @@ #include "nvim/api/private/defs.h" #include "nvim/buffer_defs.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" #include "nvim/macros.h" diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 5025e86771..076cf63913 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -3480,8 +3480,8 @@ void get_rel_pos(win_T *wp, char *buf, int buflen) return; } - long above; // number of lines above window - long below; // number of lines below window + linenr_T above; // number of lines above window + linenr_T below; // number of lines below window above = wp->w_topline - 1; above += win_get_fill(wp, wp->w_topline) - wp->w_topfill; @@ -3580,7 +3580,7 @@ void ex_buffer_all(exarg_T *eap) bool p_ea_save; int open_wins = 0; int r; - long count; // Maximum number of windows to open. + linenr_T count; // Maximum number of windows to open. int all; // When true also load inactive buffers. int had_tab = cmdmod.cmod_tab; tabpage_T *tpnext; diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index a9ad0051ed..1a2e2fbdae 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -488,13 +488,13 @@ struct file_buffer { u_header_T *b_u_newhead; // pointer to newest header; may not be valid // if b_u_curhead is not NULL u_header_T *b_u_curhead; // pointer to current header - int b_u_numhead; // current number of headers - bool b_u_synced; // entry lists are synced - long b_u_seq_last; // last used undo sequence number - long b_u_save_nr_last; // counter for last file write - long b_u_seq_cur; // uh_seq of header below which we are now - time_t b_u_time_cur; // uh_time of header below which we are now - long b_u_save_nr_cur; // file write nr after which we are now + int b_u_numhead; // current number of headers + bool b_u_synced; // entry lists are synced + int b_u_seq_last; // last used undo sequence number + int b_u_save_nr_last; // counter for last file write + int b_u_seq_cur; // uh_seq of header below which we are now + time_t b_u_time_cur; // uh_time of header below which we are now + int b_u_save_nr_cur; // file write nr after which we are now // variables for "U" command in undo.c char *b_u_line_ptr; // saved line for "U" command diff --git a/src/nvim/bufwrite.c b/src/nvim/bufwrite.c index db813a3ae1..2e4dda78fc 100644 --- a/src/nvim/bufwrite.c +++ b/src/nvim/bufwrite.c @@ -1368,7 +1368,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en } int no_eol = false; // no end-of-line written - long nchars; + int nchars; linenr_T lnum; int fileformat; int checking_conversion; @@ -1789,7 +1789,7 @@ restore_backup: if (msg_add_fileformat(fileformat)) { insert_space = true; } - msg_add_lines(insert_space, (long)lnum, nchars); // add line/char count + msg_add_lines(insert_space, lnum, nchars); // add line/char count if (!shortmess(SHM_WRITE)) { if (append) { xstrlcat(IObuff, shortmess(SHM_WRI) ? _(" [a]") : _(" appended"), IOSIZE); diff --git a/src/nvim/change.c b/src/nvim/change.c index 48dc02b65b..abbfe2505e 100644 --- a/src/nvim/change.c +++ b/src/nvim/change.c @@ -1941,7 +1941,7 @@ void truncate_line(int fixpos) /// Delete "nlines" lines at the cursor. /// Saves the lines for undo first if "undo" is true. -void del_lines(long nlines, bool undo) +void del_lines(linenr_T nlines, bool undo) { int n; linenr_T first = curwin->w_cursor.lnum; diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c index d733ffe6ab..c2469b6574 100644 --- a/src/nvim/cmdexpand.c +++ b/src/nvim/cmdexpand.c @@ -69,9 +69,6 @@ #include "nvim/vim.h" #include "nvim/window.h" -/// Type used by ExpandGeneric() -typedef char *(*CompleteListItemGetter)(expand_T *, int); - /// Type used by call_user_expand_func typedef void *(*user_expand_func_T)(const char *, int, typval_T *); @@ -107,6 +104,8 @@ static bool cmdline_fuzzy_completion_supported(const expand_T *const xp) && xp->xp_context != EXPAND_HELP && xp->xp_context != EXPAND_LUA && xp->xp_context != EXPAND_OLD_SETTING + && xp->xp_context != EXPAND_STRING_SETTING + && xp->xp_context != EXPAND_SETTING_SUBTRACT && xp->xp_context != EXPAND_OWNSYNTAX && xp->xp_context != EXPAND_PACKADD && xp->xp_context != EXPAND_RUNTIME @@ -2599,7 +2598,7 @@ static int ExpandOther(char *pat, expand_T *xp, regmatch_T *rmp, char ***matches { EXPAND_MENUNAMES, get_menu_names, false, true }, { EXPAND_SYNTAX, get_syntax_name, true, true }, { EXPAND_SYNTIME, get_syntime_arg, true, true }, - { EXPAND_HIGHLIGHT, (ExpandFunc)get_highlight_name, true, false }, + { EXPAND_HIGHLIGHT, get_highlight_name, true, false }, { EXPAND_EVENTS, expand_get_event_name, true, false }, { EXPAND_AUGROUP, expand_get_augroup_name, true, false }, { EXPAND_SIGN, get_sign_name, true, true }, @@ -2694,8 +2693,7 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM return OK; } if (xp->xp_context == EXPAND_OLD_SETTING) { - ExpandOldSetting(numMatches, matches); - return OK; + return ExpandOldSetting(numMatches, matches); } if (xp->xp_context == EXPAND_BUFFERS) { return ExpandBufnames(pat, numMatches, matches, options); @@ -2765,6 +2763,10 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM if (xp->xp_context == EXPAND_SETTINGS || xp->xp_context == EXPAND_BOOL_SETTINGS) { ret = ExpandSettings(xp, ®match, pat, numMatches, matches, fuzzy); + } else if (xp->xp_context == EXPAND_STRING_SETTING) { + ret = ExpandStringSetting(xp, ®match, numMatches, matches); + } else if (xp->xp_context == EXPAND_SETTING_SUBTRACT) { + ret = ExpandSettingSubtract(xp, ®match, numMatches, matches); } else if (xp->xp_context == EXPAND_MAPPINGS) { ret = ExpandMappings(pat, ®match, numMatches, matches); } else if (xp->xp_context == EXPAND_USER_DEFINED) { @@ -2788,9 +2790,8 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM /// program. Matching strings are copied into an array, which is returned. /// /// @param func returns a string from the list -static void ExpandGeneric(const char *const pat, expand_T *xp, regmatch_T *regmatch, - char ***matches, int *numMatches, CompleteListItemGetter func, - int escaped) +void ExpandGeneric(const char *const pat, expand_T *xp, regmatch_T *regmatch, char ***matches, + int *numMatches, CompleteListItemGetter func, bool escaped) { const bool fuzzy = cmdline_fuzzy_complete(pat); *matches = NULL; @@ -2863,6 +2864,7 @@ static void ExpandGeneric(const char *const pat, expand_T *xp, regmatch_T *regma // in the specified order. const bool sort_matches = !fuzzy && xp->xp_context != EXPAND_MENUNAMES + && xp->xp_context != EXPAND_STRING_SETTING && xp->xp_context != EXPAND_MENUS && xp->xp_context != EXPAND_SCRIPTNAMES; @@ -3076,7 +3078,7 @@ static int ExpandUserDefined(const char *const pat, expand_T *xp, regmatch_T *re *matches = NULL; *numMatches = 0; - char *const retstr = call_user_expand_func((user_expand_func_T)call_func_retstr, xp); + char *const retstr = call_user_expand_func(call_func_retstr, xp); if (retstr == NULL) { return FAIL; } @@ -3148,7 +3150,7 @@ static int ExpandUserList(expand_T *xp, char ***matches, int *numMatches) { *matches = NULL; *numMatches = 0; - list_T *const retlist = call_user_expand_func((user_expand_func_T)call_func_retlist, xp); + list_T *const retlist = call_user_expand_func(call_func_retlist, xp); if (retlist == NULL) { return FAIL; } @@ -3221,8 +3223,7 @@ void globpath(char *path, char *file, garray_T *ga, int expand_options, bool dir char **p; int num_p = 0; - (void)ExpandFromContext(&xpc, buf, &p, &num_p, - WILD_SILENT | expand_options); + (void)ExpandFromContext(&xpc, buf, &p, &num_p, WILD_SILENT | expand_options); if (num_p > 0) { ExpandEscape(&xpc, buf, num_p, p, WILD_SILENT | expand_options); diff --git a/src/nvim/cmdexpand.h b/src/nvim/cmdexpand.h index 32c23c5d66..81e323c97b 100644 --- a/src/nvim/cmdexpand.h +++ b/src/nvim/cmdexpand.h @@ -1,6 +1,7 @@ #ifndef NVIM_CMDEXPAND_H #define NVIM_CMDEXPAND_H +#include "nvim/cmdexpand_defs.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_getln.h" #include "nvim/garray.h" diff --git a/src/nvim/cmdexpand_defs.h b/src/nvim/cmdexpand_defs.h new file mode 100644 index 0000000000..a302a32852 --- /dev/null +++ b/src/nvim/cmdexpand_defs.h @@ -0,0 +1,113 @@ +#ifndef NVIM_CMDEXPAND_DEFS_H +#define NVIM_CMDEXPAND_DEFS_H + +#include <stdbool.h> +#include <stddef.h> + +#include "nvim/eval/typval_defs.h" +#include "nvim/types.h" + +typedef enum { + XP_PREFIX_NONE, ///< prefix not used + XP_PREFIX_NO, ///< "no" prefix for bool option + XP_PREFIX_INV, ///< "inv" prefix for bool option +} xp_prefix_T; + +enum { EXPAND_BUF_LEN = 256, }; + +/// used for completion on the command line +typedef struct expand { + char *xp_pattern; ///< start of item to expand + int xp_context; ///< type of expansion + size_t xp_pattern_len; ///< bytes in xp_pattern before cursor + xp_prefix_T xp_prefix; + char *xp_arg; ///< completion function + LuaRef xp_luaref; ///< Ref to Lua completion function + sctx_T xp_script_ctx; ///< SCTX for completion function + int xp_backslash; ///< one of the XP_BS_ values +#ifndef BACKSLASH_IN_FILENAME + bool xp_shell; ///< true for a shell command, more + ///< characters need to be escaped +#endif + int xp_numfiles; ///< number of files found by file name completion + int xp_col; ///< cursor position in line + int xp_selected; ///< selected index in completion + char *xp_orig; ///< originally expanded string + char **xp_files; ///< list of files + char *xp_line; ///< text being completed + char xp_buf[EXPAND_BUF_LEN]; ///< buffer for returned match +} expand_T; + +/// values for xp_backslash +enum { + XP_BS_NONE = 0, ///< nothing special for backslashes + XP_BS_ONE = 1, ///< uses one backslash before a space + XP_BS_THREE = 2, ///< uses three backslashes before a space +}; + +/// values for xp_context when doing command line completion +enum { + EXPAND_UNSUCCESSFUL = -2, + EXPAND_OK = -1, + EXPAND_NOTHING = 0, + EXPAND_COMMANDS, + EXPAND_FILES, + EXPAND_DIRECTORIES, + EXPAND_SETTINGS, + EXPAND_BOOL_SETTINGS, + EXPAND_TAGS, + EXPAND_OLD_SETTING, + EXPAND_HELP, + EXPAND_BUFFERS, + EXPAND_EVENTS, + EXPAND_MENUS, + EXPAND_SYNTAX, + EXPAND_HIGHLIGHT, + EXPAND_AUGROUP, + EXPAND_USER_VARS, + EXPAND_MAPPINGS, + EXPAND_TAGS_LISTFILES, + EXPAND_FUNCTIONS, + EXPAND_USER_FUNC, + EXPAND_EXPRESSION, + EXPAND_MENUNAMES, + EXPAND_USER_COMMANDS, + EXPAND_USER_CMD_FLAGS, + EXPAND_USER_NARGS, + EXPAND_USER_COMPLETE, + EXPAND_ENV_VARS, + EXPAND_LANGUAGE, + EXPAND_COLORS, + EXPAND_COMPILER, + EXPAND_USER_DEFINED, + EXPAND_USER_LIST, + EXPAND_USER_LUA, + EXPAND_SHELLCMD, + EXPAND_SIGN, + EXPAND_PROFILE, + EXPAND_FILETYPE, + EXPAND_FILES_IN_PATH, + EXPAND_OWNSYNTAX, + EXPAND_LOCALES, + EXPAND_HISTORY, + EXPAND_USER, + EXPAND_SYNTIME, + EXPAND_USER_ADDR_TYPE, + EXPAND_PACKADD, + EXPAND_MESSAGES, + EXPAND_MAPCLEAR, + EXPAND_ARGLIST, + EXPAND_DIFF_BUFFERS, + EXPAND_BREAKPOINT, + EXPAND_SCRIPTNAMES, + EXPAND_RUNTIME, + EXPAND_STRING_SETTING, + EXPAND_SETTING_SUBTRACT, + EXPAND_CHECKHEALTH, + EXPAND_LUA, +}; + +/// Type used by ExpandGeneric() +typedef char *(*CompleteListItemGetter)(expand_T *, int); + +#endif // NVIM_CMDEXPAND_DEFS_H diff --git a/src/nvim/cmdhist.c b/src/nvim/cmdhist.c index 50bdfd892f..b0490670fe 100644 --- a/src/nvim/cmdhist.c +++ b/src/nvim/cmdhist.c @@ -12,6 +12,7 @@ #include "nvim/ascii.h" #include "nvim/charset.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/cmdhist.h" #include "nvim/eval/typval.h" #include "nvim/ex_cmds.h" diff --git a/src/nvim/cmdhist.h b/src/nvim/cmdhist.h index a0f2ab6934..2b7e47e38e 100644 --- a/src/nvim/cmdhist.h +++ b/src/nvim/cmdhist.h @@ -1,6 +1,7 @@ #ifndef NVIM_CMDHIST_H #define NVIM_CMDHIST_H +#include "nvim/cmdexpand_defs.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" #include "nvim/os/time.h" diff --git a/src/nvim/cursor_shape.c b/src/nvim/cursor_shape.c index fb2ca9ff8c..ba5f30c20f 100644 --- a/src/nvim/cursor_shape.c +++ b/src/nvim/cursor_shape.c @@ -364,9 +364,9 @@ static void clear_shape_table(void) { for (int idx = 0; idx < SHAPE_IDX_COUNT; idx++) { shape_table[idx].shape = SHAPE_BLOCK; - shape_table[idx].blinkwait = 0L; - shape_table[idx].blinkon = 0L; - shape_table[idx].blinkoff = 0L; + shape_table[idx].blinkwait = 0; + shape_table[idx].blinkon = 0; + shape_table[idx].blinkoff = 0; shape_table[idx].id = 0; shape_table[idx].id_lm = 0; } diff --git a/src/nvim/cursor_shape.h b/src/nvim/cursor_shape.h index 93bddd47c7..33d0344c2d 100644 --- a/src/nvim/cursor_shape.h +++ b/src/nvim/cursor_shape.h @@ -44,9 +44,9 @@ typedef struct cursor_entry { CursorShape shape; ///< cursor shape: one of the SHAPE_ defines int mshape; ///< mouse shape: one of the MSHAPE defines int percentage; ///< percentage of cell for bar - long blinkwait; ///< blinking, wait time before blinking starts - long blinkon; ///< blinking, on time - long blinkoff; ///< blinking, off time + int blinkwait; ///< blinking, wait time before blinking starts + int blinkon; ///< blinking, on time + int blinkoff; ///< blinking, off time int id; ///< highlight group ID int id_lm; ///< highlight group ID for :lmap mode char *name; ///< mode short name diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c index 3d5f27e76c..755579a3bc 100644 --- a/src/nvim/debugger.c +++ b/src/nvim/debugger.c @@ -12,6 +12,7 @@ #include "nvim/ascii.h" #include "nvim/charset.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/debugger.h" #include "nvim/drawscreen.h" #include "nvim/eval.h" diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 3ab1da76f4..8479675dfa 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -2467,6 +2467,7 @@ int diffopt_changed(void) char *p = p_dip; while (*p != NUL) { + // Note: Keep this in sync with p_dip_values if (strncmp(p, "filler", 6) == 0) { p += 6; diff_flags_new |= DIFF_FILLER; @@ -2513,6 +2514,7 @@ int diffopt_changed(void) p += 8; diff_flags_new |= DIFF_INTERNAL; } else if (strncmp(p, "algorithm:", 10) == 0) { + // Note: Keep this in sync with p_dip_algorithm_values. p += 10; if (strncmp(p, "myers", 5) == 0) { p += 5; @@ -3133,7 +3135,7 @@ static void diffgetput(const int addr_count, const int idx_cur, const int idx_fr if (added != 0) { // Adjust marks. This will change the following entries! - mark_adjust(lnum, lnum + count - 1, (long)MAXLNUM, added, kExtmarkNOOP); + mark_adjust(lnum, lnum + count - 1, MAXLNUM, added, kExtmarkNOOP); if (curwin->w_cursor.lnum >= lnum) { // Adjust the cursor position if it's in/after the changed // lines. @@ -3144,7 +3146,7 @@ static void diffgetput(const int addr_count, const int idx_cur, const int idx_fr } } } - extmark_adjust(curbuf, lnum, lnum + count - 1, (long)MAXLNUM, added, kExtmarkUndo); + extmark_adjust(curbuf, lnum, lnum + count - 1, MAXLNUM, added, kExtmarkUndo); changed_lines(curbuf, lnum, 0, lnum + count, added, true); if (did_free) { diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index cc22accf2b..a0cbc60f25 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -1519,16 +1519,12 @@ static void win_update(win_T *wp, DecorProviders *providers) } } - // Force redraw when width of 'number' or 'relativenumber' column - // changes. - int nrwidth = (wp->w_p_nu || wp->w_p_rnu || *wp->w_p_stc) ? number_width(wp) : 0; - if (wp->w_nrwidth != nrwidth) { + const int nrwidth_before = wp->w_nrwidth; + int nrwidth_new = (wp->w_p_nu || wp->w_p_rnu || *wp->w_p_stc) ? number_width(wp) : 0; + // Force redraw when width of 'number' or 'relativenumber' column changes. + if (wp->w_nrwidth != nrwidth_new) { type = UPD_NOT_VALID; - wp->w_nrwidth = nrwidth; - - if (buf->terminal) { - terminal_check_size(buf->terminal); - } + wp->w_nrwidth = nrwidth_new; } else if (buf->b_mod_set && buf->b_mod_xlines != 0 && wp->w_redraw_top != 0) { @@ -2498,6 +2494,10 @@ static void win_update(win_T *wp, DecorProviders *providers) } } + if (nrwidth_before != wp->w_nrwidth && buf->terminal) { + terminal_check_size(buf->terminal); + } + // restore got_int, unless CTRL-C was hit while redrawing if (!got_int) { got_int = save_got_int; diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 7f29e615ab..58cface37f 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -73,7 +73,7 @@ typedef struct insert_state { int cmdchar; int cmdchar_todo; // cmdchar to handle once in init_prompt int startln; - long count; + int count; int c; int lastc; int i; @@ -1230,7 +1230,7 @@ static void insert_do_cindent(InsertState *s) /// @param count repeat count for the command /// /// @return true if a CTRL-O command caused the return (insert mode pending). -bool edit(int cmdchar, bool startln, long count) +bool edit(int cmdchar, bool startln, int count) { if (curbuf->terminal) { if (ex_normal_busy) { @@ -3394,7 +3394,7 @@ static void ins_ctrl_hat(void) /// @param nomove when true, don't move the cursor /// /// @return true when leaving insert mode, false when repeating the insert. -static bool ins_esc(long *count, int cmdchar, bool nomove) +static bool ins_esc(int *count, int cmdchar, bool nomove) FUNC_ATTR_NONNULL_ARG(1) { static bool disabled_redraw = false; diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 0bf26b2451..9a90e430a7 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -21,6 +21,7 @@ #include "nvim/buffer_defs.h" #include "nvim/channel.h" #include "nvim/charset.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/cmdhist.h" #include "nvim/cursor.h" #include "nvim/edit.h" @@ -1225,7 +1226,7 @@ fail: /// /// @return [allocated] NULL when calling function fails, allocated string /// otherwise. -char *call_func_retstr(const char *const func, int argc, typval_T *argv) +void *call_func_retstr(const char *const func, int argc, typval_T *argv) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC { typval_T rettv; @@ -8093,13 +8094,6 @@ void ex_execute(exarg_T *eap) } if (ret != FAIL && ga.ga_data != NULL) { - if (eap->cmdidx == CMD_echomsg || eap->cmdidx == CMD_echoerr) { - // Mark the already saved text as finishing the line, so that what - // follows is displayed on a new line when scrolling back at the - // more prompt. - msg_sb_eol(); - } - if (eap->cmdidx == CMD_echomsg) { msg_ext_set_kind("echomsg"); msg(ga.ga_data, echo_attr); @@ -8296,7 +8290,7 @@ void option_last_set_msg(LastSet last_set) msg_puts(p); if (last_set.script_ctx.sc_lnum > 0) { msg_puts(_(line_msg)); - msg_outnum((long)last_set.script_ctx.sc_lnum); + msg_outnum(last_set.script_ctx.sc_lnum); } if (should_free) { xfree(p); diff --git a/src/nvim/eval.h b/src/nvim/eval.h index be69cd5657..38bcf8f50d 100644 --- a/src/nvim/eval.h +++ b/src/nvim/eval.h @@ -6,6 +6,7 @@ #include "nvim/buffer_defs.h" #include "nvim/channel.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/eval/typval_defs.h" #include "nvim/event/time.h" #include "nvim/ex_cmds_defs.h" diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 23ad3d3787..28fb9c6a5c 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -1542,6 +1542,7 @@ M.funcs = { count = { args = { 2, 4 }, base = 1, + tags = { 'E706' }, desc = [=[ Return the number of times an item with value {expr} appears in |String|, |List| or |Dictionary| {comp}. @@ -7381,6 +7382,7 @@ M.funcs = { using a {n$} positional argument specifier. See |printf-$|. + *E1520* The conversion specifiers and their meanings are: *printf-d* *printf-b* *printf-B* *printf-o* *printf-x* *printf-X* @@ -11121,8 +11123,8 @@ M.funcs = { user user name host host name fname original file name - pid PID of the Vim process that created the swap - file + pid PID of the Nvim process that created the swap + file, or zero if not running. mtime last modification time in seconds inode Optional: INODE number of the file dirty 1 if file was modified, 0 if not diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 5bfce7c272..4dd3f193e6 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -33,6 +33,7 @@ #include "nvim/channel.h" #include "nvim/charset.h" #include "nvim/cmdexpand.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/context.h" #include "nvim/cursor.h" #include "nvim/diff.h" @@ -8235,7 +8236,7 @@ static void f_swapfilelist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr static void f_swapinfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { tv_dict_alloc_ret(rettv); - get_b0_dict(tv_get_string(argvars), rettv->vval.v_dict); + swapfile_dict(tv_get_string(argvars), rettv->vval.v_dict); } /// "swapname(expr)" function diff --git a/src/nvim/eval/funcs.h b/src/nvim/eval/funcs.h index 5dab12787b..5f6132f68c 100644 --- a/src/nvim/eval/funcs.h +++ b/src/nvim/eval/funcs.h @@ -6,6 +6,7 @@ #include "nvim/api/private/dispatch.h" #include "nvim/buffer_defs.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/eval/typval_defs.h" #include "nvim/types.h" diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h index d5e8cb0109..c0b5416a05 100644 --- a/src/nvim/eval/typval_defs.h +++ b/src/nvim/eval/typval_defs.h @@ -115,6 +115,19 @@ typedef enum { VAR_BLOB, ///< Blob, .v_blob is used. } VarType; +/// Type values for type(). +enum { + VAR_TYPE_NUMBER = 0, + VAR_TYPE_STRING = 1, + VAR_TYPE_FUNC = 2, + VAR_TYPE_LIST = 3, + VAR_TYPE_DICT = 4, + VAR_TYPE_FLOAT = 5, + VAR_TYPE_BOOL = 6, + VAR_TYPE_SPECIAL = 7, + VAR_TYPE_BLOB = 10, +}; + /// Structure that holds an internal variable value typedef struct { VarType v_type; ///< Variable type. diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 8d85c55e15..ca98aad6bc 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -14,6 +14,7 @@ #include "nvim/ascii.h" #include "nvim/autocmd.h" #include "nvim/charset.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/debugger.h" #include "nvim/eval.h" #include "nvim/eval/encode.h" @@ -1125,7 +1126,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett msg_puts(", "); } if (argvars[i].v_type == VAR_NUMBER) { - msg_outnum((long)argvars[i].vval.v_number); + msg_outnum((int)argvars[i].vval.v_number); } else { // Do not want errors such as E724 here. emsg_off++; @@ -2262,7 +2263,7 @@ void ex_function(exarg_T *eap) } msg_putchar('\n'); if (!eap->forceit) { - msg_outnum((long)j + 1); + msg_outnum(j + 1); if (j < 9) { msg_putchar(' '); } @@ -2490,7 +2491,7 @@ void ex_function(exarg_T *eap) } else if (line_arg != NULL && *skipwhite(line_arg) != NUL) { nextcmd = line_arg; } else if (*p != NUL && *p != '"' && p_verbose > 0) { - give_warning2(_("W22: Text found after :endfunction: %s"), p, true); + swmsg(true, _("W22: Text found after :endfunction: %s"), p); } if (nextcmd != NULL) { // Another command follows. If the line came from "eap" we diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h index 562c549b4b..c3fe56d30c 100644 --- a/src/nvim/eval/userfunc.h +++ b/src/nvim/eval/userfunc.h @@ -4,6 +4,7 @@ #include <stdbool.h> #include <stddef.h> +#include "nvim/cmdexpand_defs.h" #include "nvim/eval.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 127397d9fa..c57324d5e9 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -27,6 +27,7 @@ #include "nvim/change.h" #include "nvim/channel.h" #include "nvim/charset.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/cmdhist.h" #include "nvim/cursor.h" #include "nvim/decoration.h" @@ -130,7 +131,7 @@ static const char e_non_numeric_argument_to_z[] = N_("E144: Non-numeric argument to :z"); /// ":ascii" and "ga" implementation -void do_ascii(const exarg_T *const eap) +void do_ascii(exarg_T *eap) { char *dig; int cc[MAX_MCO]; @@ -455,7 +456,7 @@ void ex_sort(exarg_T *eap) regmatch_T regmatch; int len; linenr_T lnum; - long maxlen = 0; + int maxlen = 0; size_t count = (size_t)(eap->line2 - eap->line1) + 1; size_t i; char *p; @@ -692,7 +693,7 @@ void ex_sort(exarg_T *eap) // Adjust marks for deleted (or added) lines and prepare for displaying. deleted = (linenr_T)count - (lnum - eap->line2); if (deleted > 0) { - mark_adjust(eap->line2 - deleted, eap->line2, (long)MAXLNUM, -deleted, kExtmarkNOOP); + mark_adjust(eap->line2 - deleted, eap->line2, MAXLNUM, -deleted, kExtmarkNOOP); msgmore(-deleted); } else if (deleted < 0) { mark_adjust(eap->line2, MAXLNUM, -deleted, 0L, kExtmarkNOOP); @@ -921,7 +922,7 @@ void ex_copy(linenr_T line1, linenr_T line2, linenr_T n) check_pos(curbuf, &VIsual); } - msgmore((long)count); + msgmore(count); } static char *prevcmd = NULL; // the previous command @@ -1280,7 +1281,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b set_keep_msg(msg_buf, 0); } } else { - msgmore((long)linecount); + msgmore(linecount); } } } else { @@ -3290,7 +3291,7 @@ static int check_regexp_delim(int c) /// @param cmdpreview_ns The namespace to show 'inccommand' preview highlights. /// If <= 0, preview shouldn't be shown. /// @return 0, 1 or 2. See show_cmdpreview() for more information on what the return value means. -static int do_sub(exarg_T *eap, const proftime_T timeout, const long cmdpreview_ns, +static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_ns, const handle_T cmdpreview_bufnr) { #define ADJUST_SUB_FIRSTLNUM() \ @@ -3317,7 +3318,7 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const long cmdpreview_ } \ } while (0) - long i = 0; + int i = 0; regmmatch_T regmatch; static subflags_T subflags = { .do_all = false, @@ -3345,7 +3346,7 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const long cmdpreview_ PreviewLines preview_lines = { KV_INITIAL_VALUE, 0 }; static int pre_hl_id = 0; pos_T old_cursor = curwin->w_cursor; - long start_nsubs; + int start_nsubs; bool did_save = false; @@ -3441,7 +3442,7 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const long cmdpreview_ // check for a trailing count cmd = skipwhite(cmd); if (ascii_isdigit(*cmd)) { - i = getdigits_long(&cmd, true, 0); + i = getdigits_int(&cmd, true, 0); if (i <= 0 && !eap->skip && subflags.do_error) { emsg(_(e_zerocount)); return 0; @@ -3520,8 +3521,8 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const long cmdpreview_ && (cmdpreview_ns <= 0 || preview_lines.lines_needed <= (linenr_T)p_cwh || lnum <= curwin->w_botline); lnum++) { - long nmatch = vim_regexec_multi(®match, curwin, curbuf, lnum, - (colnr_T)0, NULL, NULL); + int nmatch = (int)vim_regexec_multi(®match, curwin, curbuf, lnum, + (colnr_T)0, NULL, NULL); if (nmatch) { colnr_T copycol; colnr_T matchcol; @@ -3531,7 +3532,7 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const long cmdpreview_ char *p1; bool did_sub = false; int lastone; - long nmatch_tl = 0; // nr of lines matched below lnum + linenr_T nmatch_tl = 0; // nr of lines matched below lnum int do_again; // do it again after joining lines bool skip_match = false; linenr_T sub_firstlnum; // nr of first sub line @@ -3804,7 +3805,7 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const long cmdpreview_ // Same highlight as wait_return(). smsg(HL_ATTR(HLF_R), _("replace with %s (y/n/a/q/l/^E/^Y)?"), sub); msg_no_more = false; - msg_scroll = (int)i; + msg_scroll = i; if (!ui_has(kUIMessages)) { ui_cursor_goto(msg_row, msg_col); } @@ -4086,9 +4087,9 @@ skip: // need to replace the line first (using \zs after \n). if (lastone || nmatch_tl > 0 - || (nmatch = vim_regexec_multi(®match, curwin, - curbuf, sub_firstlnum, - matchcol, NULL, NULL)) == 0 + || (nmatch = (int)vim_regexec_multi(®match, curwin, + curbuf, sub_firstlnum, + matchcol, NULL, NULL)) == 0 || regmatch.startpos[0].lnum > 0) { if (new_start != NULL) { // Copy the rest of the line, that didn't match. @@ -4118,13 +4119,12 @@ skip: for (i = 0; i < nmatch_tl; i++) { ml_delete(lnum, false); } - mark_adjust(lnum, lnum + (linenr_T)nmatch_tl - 1, - (long)MAXLNUM, (linenr_T)(-nmatch_tl), kExtmarkNOOP); + mark_adjust(lnum, lnum + nmatch_tl - 1, MAXLNUM, -nmatch_tl, kExtmarkNOOP); if (subflags.do_ask) { - deleted_lines(lnum, (linenr_T)nmatch_tl); + deleted_lines(lnum, nmatch_tl); } lnum--; - line2 -= (linenr_T)nmatch_tl; // nr of lines decreases + line2 -= nmatch_tl; // nr of lines decreases nmatch_tl = 0; } @@ -4149,8 +4149,8 @@ skip: copycol = 0; } if (nmatch == -1 && !lastone) { - nmatch = vim_regexec_multi(®match, curwin, curbuf, - sub_firstlnum, matchcol, NULL, NULL); + nmatch = (int)vim_regexec_multi(®match, curwin, curbuf, + sub_firstlnum, matchcol, NULL, NULL); } // 5. break if there isn't another match in this line @@ -4581,7 +4581,7 @@ bool prepare_tagpreview(bool undo_sync) /// /// @return 1 if preview window isn't needed, 2 if preview window is needed. static int show_sub(exarg_T *eap, pos_T old_cusr, PreviewLines *preview_lines, int hl_id, - long cmdpreview_ns, handle_T cmdpreview_bufnr) + int cmdpreview_ns, handle_T cmdpreview_bufnr) FUNC_ATTR_NONNULL_ALL { char *save_shm_p = xstrdup(p_shm); @@ -4683,9 +4683,9 @@ static int show_sub(exarg_T *eap, pos_T old_cusr, PreviewLines *preview_lines, i } linenr_origbuf = match.end.lnum; - bufhl_add_hl_pos_offset(cmdpreview_buf, (int)cmdpreview_ns, hl_id, p_start, p_end, col_width); + bufhl_add_hl_pos_offset(cmdpreview_buf, cmdpreview_ns, hl_id, p_start, p_end, col_width); } - bufhl_add_hl_pos_offset(orig_buf, (int)cmdpreview_ns, hl_id, match.start, match.end, 0); + bufhl_add_hl_pos_offset(orig_buf, cmdpreview_ns, hl_id, match.start, match.end, 0); } xfree(str); @@ -4703,7 +4703,7 @@ void ex_substitute(exarg_T *eap) } /// :substitute command preview callback. -int ex_substitute_preview(exarg_T *eap, long cmdpreview_ns, handle_T cmdpreview_bufnr) +int ex_substitute_preview(exarg_T *eap, int cmdpreview_ns, handle_T cmdpreview_bufnr) { // Only preview once the pattern delimiter has been typed if (*eap->arg && !ASCII_ISALNUM(*eap->arg)) { @@ -4772,7 +4772,7 @@ char *skip_vimgrep_pat(char *p, char **s, int *flags) void ex_oldfiles(exarg_T *eap) { list_T *l = get_vim_var_list(VV_OLDFILES); - long nr = 0; + int nr = 0; if (l == NULL) { msg(_("No old files"), 0); @@ -4806,7 +4806,7 @@ void ex_oldfiles(exarg_T *eap) nr = prompt_for_number(false); msg_starthere(); if (nr > 0 && nr <= tv_list_len(l)) { - const char *const p = tv_list_find_str(l, (int)nr - 1); + const char *const p = tv_list_find_str(l, nr - 1); if (p == NULL) { return; } diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h index 78f880db56..e15ba673ce 100644 --- a/src/nvim/ex_cmds_defs.h +++ b/src/nvim/ex_cmds_defs.h @@ -5,6 +5,7 @@ #include <stdint.h> #include "nvim/eval/typval_defs.h" +#include "nvim/ex_eval_defs.h" #include "nvim/normal.h" #include "nvim/pos.h" #include "nvim/regexp_defs.h" @@ -69,20 +70,20 @@ #define EX_FILE1 (EX_FILES | EX_NOSPC) // 1 file, defaults to current file #define EX_WORD1 (EX_EXTRA | EX_NOSPC) // one extra word allowed -// values for cmd_addr_type +/// values for cmd_addr_type typedef enum { - ADDR_LINES, // buffer line numbers - ADDR_WINDOWS, // window number - ADDR_ARGUMENTS, // argument number - ADDR_LOADED_BUFFERS, // buffer number of loaded buffer - ADDR_BUFFERS, // buffer number - ADDR_TABS, // tab page number - ADDR_TABS_RELATIVE, // Tab page that only relative - ADDR_QUICKFIX_VALID, // quickfix list valid entry number - ADDR_QUICKFIX, // quickfix list entry number - ADDR_UNSIGNED, // positive count or zero, defaults to 1 - ADDR_OTHER, // something else, use line number for '$', '%', etc. - ADDR_NONE, // no range used + ADDR_LINES, ///< buffer line numbers + ADDR_WINDOWS, ///< window number + ADDR_ARGUMENTS, ///< argument number + ADDR_LOADED_BUFFERS, ///< buffer number of loaded buffer + ADDR_BUFFERS, ///< buffer number + ADDR_TABS, ///< tab page number + ADDR_TABS_RELATIVE, ///< Tab page that only relative + ADDR_QUICKFIX_VALID, ///< quickfix list valid entry number + ADDR_QUICKFIX, ///< quickfix list entry number + ADDR_UNSIGNED, ///< positive count or zero, defaults to 1 + ADDR_OTHER, ///< something else, use line number for '$', '%', etc. + ADDR_NONE, ///< no range used } cmd_addr_T; typedef struct exarg exarg_T; @@ -93,7 +94,7 @@ typedef struct exarg exarg_T; #define BAD_DROP (-2) // erase it typedef void (*ex_func_T)(exarg_T *eap); -typedef int (*ex_preview_func_T)(exarg_T *eap, long cmdpreview_ns, handle_T cmdpreview_bufnr); +typedef int (*ex_preview_func_T)(exarg_T *eap, int cmdpreview_ns, handle_T cmdpreview_bufnr); // NOTE: These possible could be removed and changed so that // Callback could take a "command" style string, and simply @@ -128,54 +129,13 @@ typedef char *(*LineGetter)(int, void *, int, bool); /// Structure for command definition. typedef struct cmdname { - char *cmd_name; ///< Name of the command. - ex_func_T cmd_func; ///< Function with implementation of this command. - ex_preview_func_T cmd_preview_func; ///< Preview callback function of this command. - uint32_t cmd_argt; ///< Relevant flags from the declared above. - cmd_addr_T cmd_addr_type; ///< Flag for address type. + char *cmd_name; ///< Name of the command. + ex_func_T cmd_func; ///< Function with implementation of this command. + ex_preview_func_T cmd_preview_func; ///< Preview callback function of this command. + uint32_t cmd_argt; ///< Relevant flags from the declared above. + cmd_addr_T cmd_addr_type; ///< Flag for address type. } CommandDefinition; -// A list used for saving values of "emsg_silent". Used by ex_try() to save the -// value of "emsg_silent" if it was non-zero. When this is done, the CSF_SILENT -// flag below is set. -typedef struct eslist_elem eslist_T; -struct eslist_elem { - int saved_emsg_silent; // saved value of "emsg_silent" - eslist_T *next; // next element on the list -}; - -// For conditional commands a stack is kept of nested conditionals. -// When cs_idx < 0, there is no conditional command. -enum { - CSTACK_LEN = 50, -}; - -typedef struct { - int cs_flags[CSTACK_LEN]; // CSF_ flags - char cs_pending[CSTACK_LEN]; // CSTP_: what's pending in ":finally" - union { - void *csp_rv[CSTACK_LEN]; // return typeval for pending return - void *csp_ex[CSTACK_LEN]; // exception for pending throw - } cs_pend; - void *cs_forinfo[CSTACK_LEN]; // info used by ":for" - int cs_line[CSTACK_LEN]; // line nr of ":while"/":for" line - int cs_idx; // current entry, or -1 if none - int cs_looplevel; // nr of nested ":while"s and ":for"s - int cs_trylevel; // nr of nested ":try"s - eslist_T *cs_emsg_silent_list; // saved values of "emsg_silent" - int cs_lflags; // loop flags: CSL_ flags -} cstack_T; -#define cs_rettv cs_pend.csp_rv -#define cs_exception cs_pend.csp_ex - -// Flags for the cs_lflags item in cstack_T. -enum { - CSL_HAD_LOOP = 1, // just found ":while" or ":for" - CSL_HAD_ENDLOOP = 2, // just found ":endwhile" or ":endfor" - CSL_HAD_CONT = 4, // just found ":continue" - CSL_HAD_FINA = 8, // just found ":finally" -}; - /// Arguments used for Ex commands. struct exarg { char *arg; ///< argument of the command @@ -222,41 +182,6 @@ struct exarg { #define EXFLAG_NR 0x02 // '#': number #define EXFLAG_PRINT 0x04 // 'p': print -typedef enum { - XP_PREFIX_NONE, ///< prefix not used - XP_PREFIX_NO, ///< "no" prefix for bool option - XP_PREFIX_INV, ///< "inv" prefix for bool option -} xp_prefix_T; - -// used for completion on the command line -struct expand { - char *xp_pattern; // start of item to expand - int xp_context; // type of expansion - size_t xp_pattern_len; // bytes in xp_pattern before cursor - xp_prefix_T xp_prefix; - char *xp_arg; // completion function - LuaRef xp_luaref; // Ref to Lua completion function - sctx_T xp_script_ctx; // SCTX for completion function - int xp_backslash; // one of the XP_BS_ values -#ifndef BACKSLASH_IN_FILENAME - int xp_shell; // true for a shell command, more - // characters need to be escaped -#endif - int xp_numfiles; // number of files found by file name completion - int xp_col; // cursor position in line - int xp_selected; // selected index in completion - char *xp_orig; // originally expanded string - char **xp_files; // list of files - char *xp_line; // text being completed -#define EXPAND_BUF_LEN 256 - char xp_buf[EXPAND_BUF_LEN]; // buffer for returned match -}; - -// values for xp_backslash -#define XP_BS_NONE 0 // nothing special for backslashes -#define XP_BS_ONE 1 // uses one backslash before a space -#define XP_BS_THREE 2 // uses three backslashes before a space - enum { CMOD_SANDBOX = 0x0001, ///< ":sandbox" CMOD_SILENT = 0x0002, ///< ":silent" diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 02783e032b..eb89e0fc9d 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -22,6 +22,7 @@ #include "nvim/change.h" #include "nvim/charset.h" #include "nvim/cmdexpand.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/cursor.h" #include "nvim/debugger.h" #include "nvim/digraph.h" @@ -1629,7 +1630,7 @@ static int execute_cmd0(int *retv, exarg_T *eap, const char **errormsg, bool pre // Call the function to execute the builtin command or the preview callback. eap->errmsg = NULL; if (preview) { - *retv = (cmdnames[eap->cmdidx].cmd_preview_func)(eap, cmdpreview_get_ns(), + *retv = (cmdnames[eap->cmdidx].cmd_preview_func)(eap, (int)cmdpreview_get_ns(), cmdpreview_get_bufnr()); } else { (cmdnames[eap->cmdidx].cmd_func)(eap); @@ -5910,7 +5911,7 @@ static void ex_submagic(exarg_T *eap) } /// ":smagic" and ":snomagic" preview callback. -static int ex_submagic_preview(exarg_T *eap, long cmdpreview_ns, handle_T cmdpreview_bufnr) +static int ex_submagic_preview(exarg_T *eap, int cmdpreview_ns, handle_T cmdpreview_bufnr) { const optmagic_T saved = magic_overruled; @@ -6043,7 +6044,7 @@ static void ex_redo(exarg_T *eap) /// ":earlier" and ":later". static void ex_later(exarg_T *eap) { - long count = 0; + int count = 0; bool sec = false; bool file = false; char *p = eap->arg; @@ -6051,7 +6052,7 @@ static void ex_later(exarg_T *eap) if (*p == NUL) { count = 1; } else if (isdigit((uint8_t)(*p))) { - count = getdigits_long(&p, false, 0); + count = getdigits_int(&p, false, 0); switch (*p) { case 's': p++; sec = true; break; diff --git a/src/nvim/ex_docmd.h b/src/nvim/ex_docmd.h index 0fd14c81d3..59f45fce88 100644 --- a/src/nvim/ex_docmd.h +++ b/src/nvim/ex_docmd.h @@ -4,6 +4,7 @@ #include <stdbool.h> #include "nvim/buffer_defs.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/ex_cmds_defs.h" #include "nvim/getchar_defs.h" #include "nvim/globals.h" diff --git a/src/nvim/ex_eval_defs.h b/src/nvim/ex_eval_defs.h index 3ad3368900..6713cdb549 100644 --- a/src/nvim/ex_eval_defs.h +++ b/src/nvim/ex_eval_defs.h @@ -5,6 +5,37 @@ #include "nvim/pos.h" +/// A list used for saving values of "emsg_silent". Used by ex_try() to save the +/// value of "emsg_silent" if it was non-zero. When this is done, the CSF_SILENT +/// flag below is set. +typedef struct eslist_elem eslist_T; +struct eslist_elem { + int saved_emsg_silent; ///< saved value of "emsg_silent" + eslist_T *next; ///< next element on the list +}; + +/// For conditional commands a stack is kept of nested conditionals. +/// When cs_idx < 0, there is no conditional command. +enum { CSTACK_LEN = 50, }; + +typedef struct { + int cs_flags[CSTACK_LEN]; ///< CSF_ flags + char cs_pending[CSTACK_LEN]; ///< CSTP_: what's pending in ":finally" + union { + void *csp_rv[CSTACK_LEN]; ///< return typeval for pending return + void *csp_ex[CSTACK_LEN]; ///< exception for pending throw + } cs_pend; + void *cs_forinfo[CSTACK_LEN]; ///< info used by ":for" + int cs_line[CSTACK_LEN]; ///< line nr of ":while"/":for" line + int cs_idx; ///< current entry, or -1 if none + int cs_looplevel; ///< nr of nested ":while"s and ":for"s + int cs_trylevel; ///< nr of nested ":try"s + eslist_T *cs_emsg_silent_list; ///< saved values of "emsg_silent" + int cs_lflags; ///< loop flags: CSL_ flags +} cstack_T; +#define cs_rettv cs_pend.csp_rv +#define cs_exception cs_pend.csp_ex + /// There is no CSF_IF, the lack of CSF_WHILE, CSF_FOR and CSF_TRY means ":if" /// was used. enum { @@ -37,6 +68,14 @@ enum { CSTP_FINISH = 32, ///< ":finish" is pending }; +/// Flags for the cs_lflags item in cstack_T. +enum { + CSL_HAD_LOOP = 1, ///< just found ":while" or ":for" + CSL_HAD_ENDLOOP = 2, ///< just found ":endwhile" or ":endfor" + CSL_HAD_CONT = 4, ///< just found ":continue" + CSL_HAD_FINA = 8, ///< just found ":finally" +}; + /// A list of error messages that can be converted to an exception. "throw_msg" /// is only set in the first element of the list. Usually, it points to the /// original message stored in that element, but sometimes it points to a later diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 6fa607d569..2a1dffacb7 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -71,6 +71,7 @@ #include "nvim/search.h" #include "nvim/state.h" #include "nvim/strings.h" +#include "nvim/types.h" #include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/usercmd.h" @@ -141,11 +142,11 @@ typedef struct cmdpreview_undo_info { u_header_T *save_b_u_curhead; int save_b_u_numhead; bool save_b_u_synced; - long save_b_u_seq_last; - long save_b_u_save_nr_last; - long save_b_u_seq_cur; + int save_b_u_seq_last; + int save_b_u_save_nr_last; + int save_b_u_seq_cur; time_t save_b_u_time_cur; - long save_b_u_save_nr_cur; + int save_b_u_save_nr_cur; char *save_b_u_line_ptr; linenr_T save_b_u_line_lnum; colnr_T save_b_u_line_colnr; @@ -206,7 +207,7 @@ static int cedit_key = -1; ///< key value of 'cedit' option #endif static handle_T cmdpreview_bufnr = 0; -static long cmdpreview_ns = 0; +static int cmdpreview_ns = 0; static void save_viewstate(win_T *wp, viewstate_T *vs) FUNC_ATTR_NONNULL_ALL @@ -1328,7 +1329,7 @@ static int command_line_execute(VimState *state, int key) if (!cmd_silent) { if (!ui_has(kUICmdline)) { - cmd_cursor_goto(msg_row, 0); + msg_cursor_goto(msg_row, 0); } ui_flush(); } @@ -2766,6 +2767,7 @@ int check_opt_wim(void) } for (char *p = p_wim; *p; p++) { + // Note: Keep this in sync with p_wim_values. for (i = 0; ASCII_ISALPHA(p[i]); i++) {} if (p[i] != NUL && p[i] != ',' && p[i] != ':') { return FAIL; @@ -3882,7 +3884,7 @@ void redrawcmd(void) // when 'incsearch' is set there may be no command line while redrawing if (ccline.cmdbuff == NULL) { - cmd_cursor_goto(cmdline_row, 0); + msg_cursor_goto(cmdline_row, 0); msg_clr_eos(); return; } @@ -3959,14 +3961,7 @@ void cursorcmd(void) } } - cmd_cursor_goto(msg_row, msg_col); -} - -static void cmd_cursor_goto(int row, int col) -{ - ScreenGrid *grid = &msg_grid_adj; - grid_adjust(&grid, &row, &col); - ui_grid_cursor_goto(grid->handle, row, col); + msg_cursor_goto(msg_row, msg_col); } void gotocmdline(bool clr) @@ -3983,7 +3978,7 @@ void gotocmdline(bool clr) if (clr) { // clear the bottom line(s) msg_clr_eos(); // will reset clear_cmdline } - cmd_cursor_goto(cmdline_row, 0); + msg_cursor_goto(cmdline_row, 0); } // Check the word in front of the cursor for an abbreviation. diff --git a/src/nvim/ex_getln.h b/src/nvim/ex_getln.h index aaafedcb4b..61bbd5b9e1 100644 --- a/src/nvim/ex_getln.h +++ b/src/nvim/ex_getln.h @@ -4,6 +4,7 @@ #include <stdbool.h> #include "klib/kvec.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" #include "nvim/option_defs.h" diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 4e8b7be4aa..05b48966ff 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -28,7 +28,7 @@ #include "nvim/drawscreen.h" #include "nvim/edit.h" #include "nvim/eval.h" -#include "nvim/ex_cmds.h" +#include "nvim/ex_cmds_defs.h" #include "nvim/ex_eval.h" #include "nvim/fileio.h" #include "nvim/fold.h" @@ -1753,7 +1753,7 @@ failed: c = true; } - msg_add_lines(c, (long)linecnt, filesize); + msg_add_lines(c, linecnt, filesize); XFREE_CLEAR(keep_msg); p = NULL; @@ -2156,7 +2156,7 @@ bool msg_add_fileformat(int eol_type) } /// Append line and character count to IObuff. -void msg_add_lines(int insert_space, long lnum, off_T nchars) +void msg_add_lines(int insert_space, linenr_T lnum, off_T nchars) { char *p = IObuff + strlen(IObuff); @@ -2700,7 +2700,7 @@ int vim_rename(const char *from, const char *to) } // Rename() failed, try copying the file. - long perm = os_getperm(from); + int perm = os_getperm(from); // For systems that support ACL: get the ACL from the original file. vim_acl_T acl = os_get_acl(from); int fd_in = os_open(from, O_RDONLY, 0); @@ -2710,7 +2710,7 @@ int vim_rename(const char *from, const char *to) } // Create the new file with same permissions as the original. - int fd_out = os_open(to, O_CREAT|O_EXCL|O_WRONLY|O_NOFOLLOW, (int)perm); + int fd_out = os_open(to, O_CREAT|O_EXCL|O_WRONLY|O_NOFOLLOW, perm); if (fd_out < 0) { close(fd_in); os_free_acl(acl); @@ -2905,7 +2905,7 @@ int buf_check_timestamp(buf_T *buf) && (!(file_info_ok = os_fileinfo(buf->b_ffname, &file_info)) || time_differs(&file_info, buf->b_mtime, buf->b_mtime_ns) || (int)file_info.stat.st_mode != buf->b_orig_mode)) { - const long prev_b_mtime = buf->b_mtime; + const int prev_b_mtime = (int)buf->b_mtime; retval = 1; diff --git a/src/nvim/fileio.h b/src/nvim/fileio.h index 5eb2689233..92ea866239 100644 --- a/src/nvim/fileio.h +++ b/src/nvim/fileio.h @@ -3,7 +3,10 @@ #include "nvim/buffer_defs.h" #include "nvim/eval/typval_defs.h" +#include "nvim/ex_cmds_defs.h" #include "nvim/garray.h" +#include "nvim/globals.h" +#include "nvim/os/fs_defs.h" #include "nvim/os/os.h" // Values for readfile() flags diff --git a/src/nvim/generators/gen_ex_cmds.lua b/src/nvim/generators/gen_ex_cmds.lua index b9fae7d0fe..61767583ec 100644 --- a/src/nvim/generators/gen_ex_cmds.lua +++ b/src/nvim/generators/gen_ex_cmds.lua @@ -102,7 +102,7 @@ for _, cmd in ipairs(defs) do end local preview_func if cmd.preview_func then - preview_func = string.format("(ex_preview_func_T)&%s", cmd.preview_func) + preview_func = string.format("&%s", cmd.preview_func) else preview_func = "NULL" end diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua index 0932a1357f..05def71caa 100644 --- a/src/nvim/generators/gen_options.lua +++ b/src/nvim/generators/gen_options.lua @@ -35,6 +35,8 @@ local redraw_flags={ local list_flags={ comma='P_COMMA', onecomma='P_ONECOMMA', + commacolon='P_COMMA|P_COLON', + onecommacolon='P_ONECOMMA|P_COLON', flags='P_FLAGLIST', flagscomma='P_COMMA|P_FLAGLIST', } @@ -166,6 +168,9 @@ local function dump_option(i, o) if o.cb then w(' .opt_did_set_cb=' .. o.cb) end + if o.expand_cb then + w(' .opt_expand_cb=' .. o.expand_cb) + end if o.enable_if then w('#else') w(' .var=NULL') diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index b696f8ab37..7c5d39bd70 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -291,10 +291,10 @@ static void delete_buff_tail(buffheader_T *buf, int slen) } /// Add number "n" to buffer "buf". -static void add_num_buff(buffheader_T *buf, long n) +static void add_num_buff(buffheader_T *buf, int n) { char number[32]; - snprintf(number, sizeof(number), "%ld", n); + snprintf(number, sizeof(number), "%d", n); add_buff(buf, number, -1L); } @@ -589,7 +589,7 @@ void AppendCharToRedobuff(int c) } // Append a number to the redo buffer. -void AppendNumberToRedobuff(long n) +void AppendNumberToRedobuff(int n) { if (!block_redo) { add_num_buff(&redobuff, n); @@ -643,7 +643,7 @@ void stuffcharReadbuff(int c) } // Append a number to the stuff buffer. -void stuffnumReadbuff(long n) +void stuffnumReadbuff(int n) { add_num_buff(&readbuf1, n); } @@ -753,7 +753,7 @@ static void copy_redo(bool old_redo) /// CTRL-O <.> in insert mode /// /// @return FAIL for failure, OK otherwise -int start_redo(long count, bool old_redo) +int start_redo(int count, bool old_redo) { // init the pointers; return if nothing to redo if (read_redo(true, old_redo) == FAIL) { diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 1a7a62174d..d462c83710 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -832,7 +832,7 @@ EXTERN char no_lines_msg[] INIT(= N_("--No lines in buffer--")); // When ":global" is used to number of substitutions and changed lines is // accumulated until it's finished. // Also used for ":spellrepall". -EXTERN long sub_nsubs; // total number of substitutions +EXTERN int sub_nsubs; // total number of substitutions EXTERN linenr_T sub_nlines; // total number of lines changed // table to store parsed 'wildmode' diff --git a/src/nvim/grid.c b/src/nvim/grid.c index 712688368b..7a707407d2 100644 --- a/src/nvim/grid.c +++ b/src/nvim/grid.c @@ -455,6 +455,22 @@ void grid_line_flush(void) false, 0, false, invalid_row); } +/// flush grid line but only if on a valid row +/// +/// This is a stopgap until message.c has been refactored to behave +void grid_line_flush_if_valid_row(void) +{ + if (grid_line_row < 0 || grid_line_row >= grid_line_grid->rows) { + if (rdb_flags & RDB_INVALID) { + abort(); + } else { + grid_line_grid = NULL; + return; + } + } + grid_line_flush(); +} + /// Fill the grid from "start_row" to "end_row" (exclusive), from "start_col" /// to "end_col" (exclusive) with character "c1" in first column followed by /// "c2" in the other columns. Use attributes "attr". diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index 09a28989e4..5cbff6e3dd 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -18,13 +18,13 @@ #include "nvim/ascii.h" #include "nvim/autocmd.h" #include "nvim/charset.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/cursor_shape.h" #include "nvim/decoration_provider.h" #include "nvim/drawscreen.h" #include "nvim/eval.h" #include "nvim/eval/typval_defs.h" #include "nvim/eval/vars.h" -#include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" #include "nvim/garray.h" #include "nvim/gettext.h" @@ -2291,10 +2291,10 @@ static void highlight_list_two(int cnt, int attr) } /// Function given to ExpandGeneric() to obtain the list of group names. -const char *get_highlight_name(expand_T *const xp, int idx) +char *get_highlight_name(expand_T *const xp, int idx) FUNC_ATTR_WARN_UNUSED_RESULT { - return get_highlight_name_ext(xp, idx, true); + return (char *)get_highlight_name_ext(xp, idx, true); } /// Obtain a highlight group name. diff --git a/src/nvim/highlight_group.h b/src/nvim/highlight_group.h index 77a3684067..369864552c 100644 --- a/src/nvim/highlight_group.h +++ b/src/nvim/highlight_group.h @@ -3,6 +3,7 @@ #include "nvim/api/keysets.h" #include "nvim/api/private/helpers.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/highlight_defs.h" #include "nvim/types.h" diff --git a/src/nvim/indent.c b/src/nvim/indent.c index b7bc23cda5..d19164b24f 100644 --- a/src/nvim/indent.c +++ b/src/nvim/indent.c @@ -55,7 +55,7 @@ /// @return false for an error. bool tabstop_set(char *var, colnr_T **array) { - long valcount = 1; + int valcount = 1; int t; char *cp; @@ -89,7 +89,7 @@ bool tabstop_set(char *var, colnr_T **array) return false; } - *array = (colnr_T *)xmalloc((unsigned)(valcount + 1) * sizeof(long)); + *array = (colnr_T *)xmalloc((unsigned)(valcount + 1) * sizeof(int)); (*array)[0] = (colnr_T)valcount; t = 1; @@ -122,13 +122,13 @@ int tabstop_padding(colnr_T col, OptInt ts_arg, const colnr_T *vts) OptInt ts = ts_arg == 0 ? 8 : ts_arg; colnr_T tabcol = 0; int t; - long padding = 0; + int padding = 0; if (vts == NULL || vts[0] == 0) { return (int)(ts - (col % ts)); } - const long tabcount = vts[0]; + const int tabcount = vts[0]; for (t = 1; t <= tabcount; t++) { tabcol += vts[t]; @@ -141,7 +141,7 @@ int tabstop_padding(colnr_T col, OptInt ts_arg, const colnr_T *vts) padding = vts[tabcount] - ((col - tabcol) % vts[tabcount]); } - return (int)padding; + return padding; } /// Find the size of the tab that covers a particular column. @@ -149,13 +149,13 @@ int tabstop_at(colnr_T col, OptInt ts, const colnr_T *vts) { colnr_T tabcol = 0; int t; - long tab_size = 0; + int tab_size = 0; if (vts == NULL || vts[0] == 0) { return (int)ts; } - const long tabcount = vts[0]; + const int tabcount = vts[0]; for (t = 1; t <= tabcount; t++) { tabcol += vts[t]; if (tabcol > col) { @@ -167,20 +167,20 @@ int tabstop_at(colnr_T col, OptInt ts, const colnr_T *vts) tab_size = vts[tabcount]; } - return (int)tab_size; + return tab_size; } /// Find the column on which a tab starts. -colnr_T tabstop_start(colnr_T col, long ts, colnr_T *vts) +colnr_T tabstop_start(colnr_T col, int ts, colnr_T *vts) { colnr_T tabcol = 0; int t; if (vts == NULL || vts[0] == 0) { - return (int)((col / ts) * ts); + return ((col / ts) * ts); } - const long tabcount = vts[0]; + const int tabcount = vts[0]; for (t = 1; t <= tabcount; t++) { tabcol += vts[t]; if (tabcol > col) { @@ -194,26 +194,26 @@ colnr_T tabstop_start(colnr_T col, long ts, colnr_T *vts) /// Find the number of tabs and spaces necessary to get from one column /// to another. -void tabstop_fromto(colnr_T start_col, colnr_T end_col, long ts_arg, const colnr_T *vts, int *ntabs, +void tabstop_fromto(colnr_T start_col, colnr_T end_col, int ts_arg, const colnr_T *vts, int *ntabs, int *nspcs) { int spaces = end_col - start_col; colnr_T tabcol = 0; - long padding = 0; + int padding = 0; int t; - long ts = ts_arg == 0 ? (long)curbuf->b_p_ts : ts_arg; + int ts = ts_arg == 0 ? (int)curbuf->b_p_ts : ts_arg; assert(ts != 0); // suppress clang "Division by zero" if (vts == NULL || vts[0] == 0) { int tabs = 0; - const int initspc = (int)(ts - (start_col % ts)); + const int initspc = (ts - (start_col % ts)); if (spaces >= initspc) { spaces -= initspc; tabs++; } - tabs += (int)(spaces / ts); - spaces -= (int)((spaces / ts) * ts); + tabs += (spaces / ts); + spaces -= ((spaces / ts) * ts); *ntabs = tabs; *nspcs = spaces; @@ -221,7 +221,7 @@ void tabstop_fromto(colnr_T start_col, colnr_T end_col, long ts_arg, const colnr } // Find the padding needed to reach the next tabstop. - const long tabcount = vts[0]; + const int tabcount = vts[0]; for (t = 1; t <= tabcount; t++) { tabcol += vts[t]; if (tabcol > start_col) { @@ -241,7 +241,7 @@ void tabstop_fromto(colnr_T start_col, colnr_T end_col, long ts_arg, const colnr } *ntabs = 1; - spaces -= (int)padding; + spaces -= padding; // At least one tab has been used. See if any more will fit. while (spaces != 0 && ++t <= tabcount) { @@ -251,7 +251,7 @@ void tabstop_fromto(colnr_T start_col, colnr_T end_col, long ts_arg, const colnr return; } *ntabs += 1; - spaces -= (int)padding; + spaces -= padding; } *ntabs += spaces / (int)vts[tabcount]; @@ -283,21 +283,21 @@ bool tabstop_eq(const colnr_T *ts1, const colnr_T *ts2) } /// Copy a tabstop array, allocating space for the new array. -int *tabstop_copy(const long *oldts) +int *tabstop_copy(const int *oldts) { - long *newts; + int *newts; int t; if (oldts == 0) { return 0; } - newts = xmalloc((unsigned)(oldts[0] + 1) * sizeof(long)); + newts = xmalloc((unsigned)(oldts[0] + 1) * sizeof(int)); for (t = 0; t <= oldts[0]; t++) { newts[t] = oldts[t]; } - return (int *)newts; + return newts; } /// Return a count of the number of tabstops. @@ -316,25 +316,23 @@ int tabstop_first(colnr_T *ts) /// 'tabstop' value when 'shiftwidth' is zero. int get_sw_value(buf_T *buf) { - long result = get_sw_value_col(buf, 0); - assert(result >= 0 && result <= INT_MAX); - return (int)result; + int result = get_sw_value_col(buf, 0); + return result; } /// Idem, using "pos". -long get_sw_value_pos(buf_T *buf, pos_T *pos) +int get_sw_value_pos(buf_T *buf, pos_T *pos) { pos_T save_cursor = curwin->w_cursor; - long sw_value; curwin->w_cursor = *pos; - sw_value = get_sw_value_col(buf, get_nolist_virtcol()); + int sw_value = get_sw_value_col(buf, get_nolist_virtcol()); curwin->w_cursor = save_cursor; return sw_value; } /// Idem, using the first non-black in the current line. -long get_sw_value_indent(buf_T *buf) +int get_sw_value_indent(buf_T *buf) { pos_T pos = curwin->w_cursor; @@ -343,9 +341,9 @@ long get_sw_value_indent(buf_T *buf) } /// Idem, using virtual column "col". -long get_sw_value_col(buf_T *buf, colnr_T col) +int get_sw_value_col(buf_T *buf, colnr_T col) { - return buf->b_p_sw ? (long)buf->b_p_sw + return buf->b_p_sw ? (int)buf->b_p_sw : tabstop_at(col, buf->b_p_ts, buf->b_p_vts_array); } @@ -760,6 +758,7 @@ bool briopt_check(win_T *wp) char *p = wp->w_p_briopt; while (*p != NUL) { + // Note: Keep this in sync with p_briopt_values if (strncmp(p, "shift:", 6) == 0 && ((p[6] == '-' && ascii_isdigit(p[7])) || ascii_isdigit(p[6]))) { p += 6; @@ -939,12 +938,12 @@ void ex_retab(exarg_T *eap) { linenr_T lnum; bool got_tab = false; - long num_spaces = 0; - long num_tabs; - long len; - long start_col = 0; // For start of white-space string - long start_vcol = 0; // For start of white-space string - long old_len; + int num_spaces = 0; + int num_tabs; + int len; + int start_col = 0; // For start of white-space string + int64_t start_vcol = 0; // For start of white-space string + int old_len; char *new_line = (char *)1; // init to non-NULL colnr_T *new_vts_array = NULL; char *new_ts_str; // string value of tab argument @@ -975,8 +974,8 @@ void ex_retab(exarg_T *eap) } for (lnum = eap->line1; !got_int && lnum <= eap->line2; lnum++) { char *ptr = ml_get(lnum); - long col = 0; - long vcol = 0; + int col = 0; + int64_t vcol = 0; bool did_undo = false; // called u_save for current line while (true) { if (ascii_iswhite(ptr[col])) { @@ -995,13 +994,13 @@ void ex_retab(exarg_T *eap) // Retabulate this string of white-space // len is virtual length of white string - len = num_spaces = vcol - start_vcol; + len = num_spaces = (int)(vcol - start_vcol); num_tabs = 0; if (!curbuf->b_p_et) { int t, s; tabstop_fromto((colnr_T)start_vcol, (colnr_T)vcol, - (long)curbuf->b_p_ts, new_vts_array, &t, &s); + (int)curbuf->b_p_ts, new_vts_array, &t, &s); num_tabs = t; num_spaces = s; } @@ -1018,7 +1017,7 @@ void ex_retab(exarg_T *eap) // len is actual number of white characters used len = num_spaces + num_tabs; - old_len = (long)strlen(ptr); + old_len = (int)strlen(ptr); const long new_len = old_len - col + start_col + len + 1; if (new_len <= 0 || new_len >= MAXCOL) { emsg_text_too_long(); @@ -1030,7 +1029,7 @@ void ex_retab(exarg_T *eap) memmove(new_line, ptr, (size_t)start_col); } memmove(new_line + start_col + len, - ptr + col, (size_t)(old_len - col + 1)); + ptr + col, (size_t)old_len - (size_t)col + 1); ptr = new_line + start_col; for (col = 0; col < len; col++) { ptr[col] = (col < num_tabs) ? '\t' : ' '; diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index 4a6c819015..3ada39c800 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -24,7 +24,6 @@ #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/userfunc.h" -#include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" #include "nvim/ex_eval.h" #include "nvim/ex_getln.h" diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 18da7af416..d6fd14cc10 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -20,6 +20,7 @@ #include "nvim/api/private/helpers.h" #include "nvim/ascii.h" #include "nvim/change.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/cursor.h" #include "nvim/drawscreen.h" #include "nvim/eval.h" diff --git a/src/nvim/lua/executor.h b/src/nvim/lua/executor.h index b132a0d147..f3e2b6d1d0 100644 --- a/src/nvim/lua/executor.h +++ b/src/nvim/lua/executor.h @@ -8,6 +8,7 @@ #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/assert.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" #include "nvim/func_attr.h" diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index 1fb91d85b4..2cfa264754 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -21,6 +21,7 @@ #include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/cmdexpand.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" diff --git a/src/nvim/mapping.h b/src/nvim/mapping.h index 405234dbd5..860bbad272 100644 --- a/src/nvim/mapping.h +++ b/src/nvim/mapping.h @@ -7,6 +7,7 @@ #include "nvim/api/keysets.h" #include "nvim/api/private/defs.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" #include "nvim/mapping_defs.h" diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index 7b7c822b3b..a3cd569846 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -43,6 +43,7 @@ #include "nvim/ascii.h" #include "nvim/buffer_defs.h" #include "nvim/charset.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/cursor.h" #include "nvim/drawscreen.h" #include "nvim/eval/typval.h" @@ -77,8 +78,8 @@ typedef struct { } convertStruct; struct interval { - long first; - long last; + int first; + int last; }; // uncrustify:off @@ -2830,3 +2831,14 @@ void f_charclass(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } rettv->vval.v_number = mb_get_class(argvars[0].vval.v_string); } + +/// Function given to ExpandGeneric() to obtain the possible arguments of the +/// encoding options. +char *get_encoding_name(expand_T *xp FUNC_ATTR_UNUSED, int idx) +{ + if (idx >= (int)ARRAY_SIZE(enc_canon_table)) { + return NULL; + } + + return (char *)enc_canon_table[idx].name; +} diff --git a/src/nvim/mbyte.h b/src/nvim/mbyte.h index 724a16014d..01a7d0d6ae 100644 --- a/src/nvim/mbyte.h +++ b/src/nvim/mbyte.h @@ -5,6 +5,7 @@ #include <stdint.h> #include <string.h> +#include "nvim/cmdexpand_defs.h" #include "nvim/eval/typval_defs.h" #include "nvim/func_attr.h" #include "nvim/mbyte_defs.h" diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 7bfa6db4ef..716d05e27a 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -168,17 +168,15 @@ enum { B0_MAGIC_CHAR = 0x55, }; -// Block zero holds all info about the swap file. This is the first block in -// the file. +// Block zero holds all info about the swapfile. This is the first block in the file. // -// NOTE: DEFINITION OF BLOCK 0 SHOULD NOT CHANGE! It would make all existing -// swap files unusable! +// NOTE: DEFINITION OF BLOCK 0 SHOULD NOT CHANGE! It would make all existing swapfiles unusable! // // If size of block0 changes anyway, adjust MIN_SWAP_PAGE_SIZE in vim.h!! // // This block is built up of single bytes, to make it portable across // different machines. b0_magic_* is used to check the byte order and size of -// variables, because the rest of the swap file is not portable. +// variables, because the rest of the swapfile is not portable. typedef struct { char b0_id[2]; ///< ID for block 0: BLOCK0_ID0 and BLOCK0_ID1. char b0_version[10]; // Vim version string @@ -210,8 +208,7 @@ typedef struct { // EOL_MAC + 1. #define B0_FF_MASK 3 -// Swap file is in directory of edited file. Used to find the file from -// different mount points. +// Swapfile is in directory of edited file. Used to find the file from different mount points. #define B0_SAME_DIR 4 // The 'fileencoding' is at the end of b0_fname[], with a NUL in front of it. @@ -289,14 +286,14 @@ int ml_open(buf_T *buf) buf->b_p_swf = false; } - // When 'updatecount' is non-zero swap file may be opened later. + // When 'updatecount' is non-zero swapfile may be opened later. if (!buf->terminal && p_uc && buf->b_p_swf) { buf->b_may_swap = true; } else { buf->b_may_swap = false; } - // Open the memfile. No swap file is created yet. + // Open the memfile. No swapfile is created yet. memfile_T *mfp = mf_open(NULL, 0); if (mfp == NULL) { goto error; @@ -335,7 +332,7 @@ int ml_open(buf_T *buf) } // Always sync block number 0 to disk, so we can check the file name in - // the swap file in findswapname(). Don't do this for a help files or + // the swapfile in findswapname(). Don't do this for a help files or // a spell buffer though. // Only works when there's a swapfile, otherwise it's done when the file // is created. @@ -386,17 +383,17 @@ error: } /// ml_setname() is called when the file name of "buf" has been changed. -/// It may rename the swap file. +/// It may rename the swapfile. void ml_setname(buf_T *buf) { bool success = false; memfile_T *mfp = buf->b_ml.ml_mfp; - if (mfp->mf_fd < 0) { // there is no swap file yet - // When 'updatecount' is 0 and 'noswapfile' there is no swap file. - // For help files we will make a swap file now. + if (mfp->mf_fd < 0) { // there is no swapfile yet + // When 'updatecount' is 0 and 'noswapfile' there is no swapfile. + // For help files we will make a swapfile now. if (p_uc != 0 && (cmdmod.cmod_flags & CMOD_NOSWAPFILE) == 0) { - ml_open_file(buf); // create a swap file + ml_open_file(buf); // create a swapfile } return; } @@ -423,13 +420,13 @@ void ml_setname(buf_T *buf) success = true; break; } - // need to close the swap file before renaming + // need to close the swapfile before renaming if (mfp->mf_fd >= 0) { close(mfp->mf_fd); mfp->mf_fd = -1; } - // try to rename the swap file + // try to rename the swapfile if (vim_rename(mfp->mf_fname, fname) == 0) { success = true; mf_free_fnames(mfp); @@ -440,10 +437,10 @@ void ml_setname(buf_T *buf) xfree(fname); // this fname didn't work, try another } - if (mfp->mf_fd == -1) { // need to (re)open the swap file + if (mfp->mf_fd == -1) { // need to (re)open the swapfile mfp->mf_fd = os_open(mfp->mf_fname, O_RDWR, 0); if (mfp->mf_fd < 0) { - // could not (re)open the swap file, what can we do???? + // could not (re)open the swapfile, what can we do???? emsg(_("E301: Oops, lost the swap file!!!")); return; } @@ -466,7 +463,7 @@ void ml_open_files(void) } } -/// Open a swap file for an existing memfile, if there is no swap file yet. +/// Open a swapfile for an existing memfile, if there is no swapfile yet. /// If we are unable to find a file name, mf_fname will be NULL /// and the memfile will be in memory only (no recovery possible). void ml_open_file(buf_T *buf) @@ -495,7 +492,7 @@ void ml_open_file(buf_T *buf) if (*dirp == NUL) { break; } - // There is a small chance that between choosing the swap file name + // There is a small chance that between choosing the swapfile name // and creating it, another Vim creates the file. In that case the // creation will fail and we will use another directory. char *fname = findswapname(buf, &dirp, NULL, &found_existing_dir); @@ -514,7 +511,7 @@ void ml_open_file(buf_T *buf) if (mf_sync(mfp, MFS_ZERO) == OK) { // Mark all blocks that should be in the swapfile as dirty. // Needed for when the 'swapfile' option was reset, so that - // the swap file was deleted, and then on again. + // the swapfile was deleted, and then on again. mf_set_dirty(mfp); break; } @@ -531,12 +528,12 @@ void ml_open_file(buf_T *buf) no_wait_return--; } - // don't try to open a swap file again + // don't try to open a swapfile again buf->b_may_swap = false; } -/// If still need to create a swap file, and starting to edit a not-readonly -/// file, or reading into an existing buffer, create a swap file now. +/// If still need to create a swapfile, and starting to edit a not-readonly +/// file, or reading into an existing buffer, create a swapfile now. /// /// @param newfile reading file into new buffer void check_need_swap(bool newfile) @@ -553,7 +550,7 @@ void check_need_swap(bool newfile) /// Close memline for buffer 'buf'. /// -/// @param del_file if true, delete the swap file +/// @param del_file if true, delete the swapfile void ml_close(buf_T *buf, int del_file) { if (buf->b_ml.ml_mfp == NULL) { // not open @@ -643,7 +640,7 @@ static void ml_upd_block0(buf_T *buf, upd_block0_T what) mf_put(mfp, hp, true, false); } -/// Write file name and timestamp into block 0 of a swap file. +/// Write file name and timestamp into block 0 of a swapfile. /// Also set buf->b_mtime. /// Don't use NameBuff[]!!! static void set_b0_fname(ZeroBlock *b0p, buf_T *buf) @@ -695,7 +692,7 @@ static void set_b0_fname(ZeroBlock *b0p, buf_T *buf) add_b0_fenc(b0p, curbuf); } -/// Update the B0_SAME_DIR flag of the swap file. It's set if the file and the +/// Update the B0_SAME_DIR flag of the swapfile. It's set if the file and the /// swapfile for "buf" are in the same directory. /// This is fail safe: if we are not sure the directories are equal the flag is /// not set. @@ -724,27 +721,30 @@ static void add_b0_fenc(ZeroBlock *b0p, buf_T *buf) } } -/// Return true if the process with number "b0p->b0_pid" is still running. -/// "swap_fname" is the name of the swap file, if it's from before a reboot then -/// the result is false; -static bool swapfile_process_running(const ZeroBlock *b0p, const char *swap_fname) +/// Returns the PID of the process that owns the swapfile, if it is running. +/// +/// @param b0p swapfile data +/// @param swap_fname Name of the swapfile. If it's from before a reboot, the result is 0. +/// +/// @return PID, or 0 if process is not running or the swapfile is from before a reboot. +static int swapfile_process_running(const ZeroBlock *b0p, const char *swap_fname) { FileInfo st; double uptime; - // If the system rebooted after when the swap file was written then the + // If the system rebooted after when the swapfile was written then the // process can't be running now. if (os_fileinfo(swap_fname, &st) && uv_uptime(&uptime) == 0 && (Timestamp)st.stat.st_mtim.tv_sec < os_time() - (Timestamp)uptime) { - return false; + return 0; } - return os_proc_running((int)char_to_long(b0p->b0_pid)); + int pid = (int)char_to_long(b0p->b0_pid); + return os_proc_running(pid) ? pid : 0; } /// Try to recover curbuf from the .swp file. /// -/// @param checkext if true, check the extension and detect whether it is a -/// swap file. +/// @param checkext if true, check the extension and detect whether it is a swapfile. void ml_recover(bool checkext) { buf_T *buf = NULL; @@ -766,8 +766,8 @@ void ml_recover(bool checkext) int called_from_main = (curbuf->b_ml.ml_mfp == NULL); int attr = HL_ATTR(HLF_E); - // If the file name ends in ".s[a-w][a-z]" we assume this is the swap file. - // Otherwise a search is done to find the swap file(s). + // If the file name ends in ".s[a-w][a-z]" we assume this is the swapfile. + // Otherwise a search is done to find the swapfile(s). char *fname = curbuf->b_fname; if (fname == NULL) { // When there is no file name fname = ""; @@ -782,17 +782,17 @@ void ml_recover(bool checkext) } else { directly = false; - // count the number of matching swap files + // count the number of matching swapfiles len = recover_names(fname, false, NULL, 0, NULL); - if (len == 0) { // no swap files found + if (len == 0) { // no swapfiles found semsg(_("E305: No swap file found for %s"), fname); goto theend; } int i; - if (len == 1) { // one swap file found, use it + if (len == 1) { // one swapfile found, use it i = 1; - } else { // several swap files found, choose - // list the names of the swap files + } else { // several swapfiles found, choose + // list the names of the swapfiles (void)recover_names(fname, true, NULL, 0, NULL); msg_putchar('\n'); msg_puts(_("Enter number of swap file to use (0 to quit): ")); @@ -801,7 +801,7 @@ void ml_recover(bool checkext) goto theend; } } - // get the swap file name that will be used + // get the swapfile name that will be used (void)recover_names(fname, false, NULL, i, &fname_used); } if (fname_used == NULL) { @@ -812,7 +812,7 @@ void ml_recover(bool checkext) getout(1); } - // Allocate a buffer structure for the swap file that is used for recovery. + // Allocate a buffer structure for the swapfile that is used for recovery. // Only the memline in it is really used. buf = xmalloc(sizeof(buf_T)); @@ -825,7 +825,7 @@ void ml_recover(bool checkext) buf->b_ml.ml_locked = NULL; // no locked block buf->b_ml.ml_flags = 0; - // open the memfile from the old swap file + // open the memfile from the old swapfile p = xstrdup(fname_used); // save "fname_used" for the message: // mf_open() will consume "fname_used"! mfp = mf_open(fname_used, O_RDONLY); @@ -837,7 +837,7 @@ void ml_recover(bool checkext) buf->b_ml.ml_mfp = mfp; // The page size set in mf_open() might be different from the page size - // used in the swap file, we must get it from block 0. But to read block + // used in the swapfile, we must get it from block 0. But to read block // 0 we need a page size. Use the minimal size for block 0 here, it will // be set to the real value below. mfp->mf_page_size = MIN_SWAP_PAGE_SIZE; @@ -910,7 +910,7 @@ void ml_recover(bool checkext) b0p = hp->bh_data; } - // If .swp file name given directly, use name from swap file for buffer. + // If .swp file name given directly, use name from swapfile for buffer. if (directly) { expand_env(b0p->b0_fname, NameBuff, MAXPATHL); if (setfname(curbuf, NameBuff, NULL, true) == FAIL) { @@ -929,7 +929,7 @@ void ml_recover(bool checkext) smsg(0, _("Original file \"%s\""), NameBuff); msg_putchar('\n'); - // check date of swap file and original file + // check date of swapfile and original file FileInfo org_file_info; FileInfo swp_file_info; long mtime = char_to_long(b0p->b0_mtime); @@ -968,7 +968,7 @@ void ml_recover(bool checkext) 0, MAXLNUM, NULL, READ_NEW, false); } - // Use the 'fileformat' and 'fileencoding' as stored in the swap file. + // Use the 'fileformat' and 'fileencoding' as stored in the swapfile. if (b0_ff != 0) { set_fileformat(b0_ff - 1, OPT_LOCAL); } @@ -1215,7 +1215,7 @@ void ml_recover(bool checkext) // Warn there could be an active Vim on the same file, the user may // want to kill it. msg_puts(_("\nNote: process STILL RUNNING: ")); - msg_outnum(char_to_long(b0p->b0_pid)); + msg_outnum((int)char_to_long(b0p->b0_pid)); } msg_puts("\n\n"); cmdline_row = msg_row; @@ -1231,7 +1231,7 @@ theend: } mf_close(mfp, false); // will also xfree(mfp->mf_fname) } - if (buf != NULL) { // may be NULL if swap file not found. + if (buf != NULL) { // may be NULL if swapfile not found. xfree(buf->b_ml.ml_stack); xfree(buf); } @@ -1243,20 +1243,20 @@ theend: } } -/// Find the names of swap files in current directory and the directory given +/// Find the names of swapfiles in current directory and the directory given /// with the 'directory' option. /// /// Used to: -/// - list the swap files for "vim -r" -/// - count the number of swap files when recovering -/// - list the swap files when recovering -/// - list the swap files for swapfilelist() -/// - find the name of the n'th swap file when recovering +/// - list the swapfiles for "vim -r" +/// - count the number of swapfiles when recovering +/// - list the swapfiles when recovering +/// - list the swapfiles for swapfilelist() +/// - find the name of the n'th swapfile when recovering /// -/// @param fname base for swap file name -/// @param do_list when true, list the swap file names +/// @param fname base for swapfile name +/// @param do_list when true, list the swapfile names /// @param ret_list when not NULL add file names to it -/// @param nr when non-zero, return nr'th swap file name +/// @param nr when non-zero, return nr'th swapfile name /// @param fname_out result when "nr" > 0 int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fname_out) { @@ -1273,7 +1273,7 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn if (fname != NULL) { #ifdef HAVE_READLINK - // Expand symlink in the file name, because the swap file is created + // Expand symlink in the file name, because the swapfile is created // with the actual file instead of with the symlink. if (resolve_symlink(fname, fname_buf) == OK) { fname_res = fname_buf; @@ -1342,9 +1342,9 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn num_files = 0; } - // When no swap file found, wildcard expansion might have failed (e.g. + // When no swapfile found, wildcard expansion might have failed (e.g. // not able to execute the shell). - // Try finding a swap file by simply adding ".swp" to the file name. + // Try finding a swapfile by simply adding ".swp" to the file name. if (*dirp == NUL && file_count + num_files == 0 && fname != NULL) { char *swapname = modname(fname_res, ".swp", true); if (swapname != NULL) { @@ -1402,8 +1402,8 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn if (num_files) { for (int i = 0; i < num_files; i++) { - // print the swap file name - msg_outnum((long)++file_count); + // print the swapfile name + msg_outnum(++file_count); msg_puts(". "); msg_puts(path_tail(files[i])); msg_putchar('\n'); @@ -1456,12 +1456,13 @@ char *make_percent_swname(const char *dir, const char *name) return d; } -static bool process_still_running; +// PID of swapfile owner, or zero if not running. +static int process_running; -/// This is used by the swapinfo() function. +/// For Vimscript "swapinfo()". /// /// @return information found in swapfile "fname" in dictionary "d". -void get_b0_dict(const char *fname, dict_T *d) +void swapfile_dict(const char *fname, dict_T *d) { int fd; ZeroBlock b0; @@ -1482,7 +1483,7 @@ void get_b0_dict(const char *fname, dict_T *d) tv_dict_add_str_len(d, S_LEN("fname"), b0.b0_fname, B0_FNAME_SIZE_ORG); - tv_dict_add_nr(d, S_LEN("pid"), char_to_long(b0.b0_pid)); + tv_dict_add_nr(d, S_LEN("pid"), swapfile_process_running(&b0, fname)); tv_dict_add_nr(d, S_LEN("mtime"), char_to_long(b0.b0_mtime)); tv_dict_add_nr(d, S_LEN("dirty"), b0.b0_dirty ? 1 : 0); tv_dict_add_nr(d, S_LEN("inode"), char_to_long(b0.b0_ino)); @@ -1496,7 +1497,7 @@ void get_b0_dict(const char *fname, dict_T *d) } } -/// Give information about an existing swap file. +/// Loads info from swapfile `fname`, and displays it to the user. /// /// @return timestamp (0 when unknown). static time_t swapfile_info(char *fname) @@ -1509,7 +1510,7 @@ static time_t swapfile_info(char *fname) char uname[B0_UNAME_SIZE]; #endif - // print the swap file date + // print the swapfile date FileInfo file_info; if (os_fileinfo(fname, &file_info)) { #ifdef UNIX @@ -1566,10 +1567,9 @@ static time_t swapfile_info(char *fname) if (char_to_long(b0.b0_pid) != 0L) { msg_puts(_("\n process ID: ")); - msg_outnum(char_to_long(b0.b0_pid)); - if (swapfile_process_running(&b0, fname)) { + msg_outnum((int)char_to_long(b0.b0_pid)); + if ((process_running = swapfile_process_running(&b0, fname))) { msg_puts(_(" (STILL RUNNING)")); - process_still_running = true; } } @@ -1589,13 +1589,12 @@ static time_t swapfile_info(char *fname) return x; } -/// @return true if the swap file looks OK and there are no changes, thus it -/// can be safely deleted. +/// @return true if the swapfile looks OK and there are no changes, thus it can be safely deleted. static bool swapfile_unchanged(char *fname) { ZeroBlock b0; - // Swap file must exist. + // Swapfile must exist. if (!os_path_exists(fname)) { return false; } @@ -1653,7 +1652,7 @@ static int recov_file_names(char **names, char *path, int prepend_dot) { int num_names = 0; - // May also add the file name with a dot prepended, for swap file in same + // May also add the file name with a dot prepended, for swapfile in same // dir as original file. if (prepend_dot) { names[num_names] = modname(path, ".sw?", true); @@ -1663,7 +1662,7 @@ static int recov_file_names(char **names, char *path, int prepend_dot) num_names++; } - // Form the normal swap file name pattern by appending ".sw?". + // Form the normal swapfile name pattern by appending ".sw?". names[num_names] = concat_fnames(path, ".sw?", false); if (num_names >= 1) { // check if we have the same name twice char *p = names[num_names - 1]; @@ -1724,7 +1723,7 @@ void ml_sync_all(int check_file, int check_char, bool do_fsync) /// sync one buffer, including negative blocks /// -/// after this all the blocks are in the swap file +/// after this all the blocks are in the swapfile /// /// Used for the :preserve command and when the original file has been /// changed or deleted. @@ -3132,7 +3131,7 @@ int resolve_symlink(const char *fname, char *buf) } #endif -/// Make swap file name out of the file name and a directory name. +/// Make swapfile name out of the file name and a directory name. /// /// @return pointer to allocated memory or NULL. char *makeswapname(char *fname, char *ffname, buf_T *buf, char *dir_name) @@ -3141,7 +3140,7 @@ char *makeswapname(char *fname, char *ffname, buf_T *buf, char *dir_name) #ifdef HAVE_READLINK char fname_buf[MAXPATHL]; - // Expand symlink in the file name, so that we put the swap file with the + // Expand symlink in the file name, so that we put the swapfile with the // actual file instead of with the symlink. if (resolve_symlink(fname, fname_buf) == OK) { fname_res = fname_buf; @@ -3162,7 +3161,7 @@ char *makeswapname(char *fname, char *ffname, buf_T *buf, char *dir_name) return r; } - // Prepend a '.' to the swap file name for the current directory. + // Prepend a '.' to the swapfile name for the current directory. char *r = modname(fname_res, ".swp", dir_name[0] == '.' && dir_name[1] == NUL); if (r == NULL) { // out of memory @@ -3174,14 +3173,11 @@ char *makeswapname(char *fname, char *ffname, buf_T *buf, char *dir_name) return s; } -/// Get file name to use for swap file or backup file. -/// Use the name of the edited file "fname" and an entry in the 'dir' or 'bdir' -/// option "dname". -/// - If "dname" is ".", return "fname" (swap file in dir of file). -/// - If "dname" starts with "./", insert "dname" in "fname" (swap file -/// relative to dir of file). -/// - Otherwise, prepend "dname" to the tail of "fname" (swap file in specific -/// dir). +/// Get file name to use for swapfile or backup file. +/// Use the name of the edited file "fname" and an entry in the 'dir' or 'bdir' option "dname". +/// - If "dname" is ".", return "fname" (swapfile in dir of file). +/// - If "dname" starts with "./", insert "dname" in "fname" (swapfile relative to dir of file). +/// - Otherwise, prepend "dname" to the tail of "fname" (swapfile in specific dir). /// /// The return value is an allocated string and can be NULL. /// @@ -3212,10 +3208,10 @@ char *get_file_in_dir(char *fname, char *dname) return retval; } -/// Print the ATTENTION message: info about an existing swap file. +/// Print the ATTENTION message: info about an existing swapfile. /// /// @param buf buffer being edited -/// @param fname swap file name +/// @param fname swapfile name static void attention_message(buf_T *buf, char *fname) { assert(buf->b_fname != NULL); @@ -3299,7 +3295,7 @@ static int do_swapexists(buf_T *buf, char *fname) return 0; } -/// Find out what name to use for the swap file for buffer 'buf'. +/// Find out what name to use for the swapfile for buffer 'buf'. /// /// Several names are tried to find one that does not exist. Last directory in /// option is automatically created. @@ -3308,20 +3304,20 @@ static int do_swapexists(buf_T *buf, char *fname) /// not being able to open the swap or undo file. /// @note May trigger SwapExists autocmd, pointers may change! /// -/// @param[in] buf Buffer for which swap file names needs to be found. +/// @param[in] buf Buffer for which swapfile names needs to be found. /// @param[in,out] dirp Pointer to a list of directories. When out of memory, /// is set to NULL. Is advanced to the next directory in /// the list otherwise. -/// @param[in] old_fname Allowed existing swap file name. Except for this +/// @param[in] old_fname Allowed existing swapfile name. Except for this /// case, name of the non-existing file is used. /// @param[in,out] found_existing_dir If points to true, then new directory -/// for swap file is not created. At first +/// for swapfile is not created. At first /// findswapname() call this argument must /// point to false. This parameter may only /// be set to true by this function, it is /// never set to false. /// -/// @return [allocated] Name of the swap file. +/// @return [allocated] Name of the swapfile. static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_existing_dir) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1, 2, 4) { @@ -3333,7 +3329,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ char *dir_name = xmalloc(dir_len); (void)copy_option_part(dirp, dir_name, dir_len, ","); - // we try different names until we find one that does not exist yet + // We try different swapfile names until we find one that does not exist yet. char *fname = makeswapname(buf_fname, buf->b_ffname, buf, dir_name); while (true) { @@ -3346,7 +3342,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ break; } // check if the swapfile already exists - // Extra security check: When a swap file is a symbolic link, this + // Extra security check: When a swapfile is a symbolic link, this // is most likely a symlink attack. FileInfo file_info; bool file_or_link_found = os_fileinfo_link(fname, &file_info); @@ -3365,17 +3361,17 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ // Give an error message, unless recovering, no file name, we are // viewing a help file or when the path of the file is different // (happens when all .swp files are in one directory). - if (!recoverymode && buf_fname != NULL - && !buf->b_help && !(buf->b_flags & BF_DUMMY)) { + if (!recoverymode && buf_fname != NULL && !buf->b_help && !(buf->b_flags & BF_DUMMY)) { int fd; ZeroBlock b0; int differ = false; - // Try to read block 0 from the swap file to get the original - // file name (and inode number). + // Try to read block 0 from the swapfile to get the original file name (and inode number). fd = os_open(fname, O_RDONLY, 0); if (fd >= 0) { if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0)) { + process_running = swapfile_process_running(&b0, fname); + // If the swapfile has the same directory as the // buffer don't compare the directory names, they can // have a different mountpoint. @@ -3393,8 +3389,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ } } } else { - // The name in the swap file may be - // "~user/path/file". Expand it first. + // The name in the swapfile may be "~user/path/file". Expand it first. expand_env(b0.b0_fname, NameBuff, MAXPATHL); if (fnamecmp_ino(buf->b_ffname, NameBuff, char_to_long(b0.b0_ino))) { @@ -3405,16 +3400,16 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ close(fd); } - // give the ATTENTION message when there is an old swap file - // for the current file, and the buffer was not recovered. + // Show the ATTENTION message when: + // - there is an old swapfile for the current file + // - the buffer was not recovered if (differ == false && !(curbuf->b_flags & BF_RECOVERED) && vim_strchr(p_shm, SHM_ATTENTION) == NULL) { int choice = 0; - process_still_running = false; - // It's safe to delete the swap file if all these are true: + // It's safe to delete the swapfile if all these are true: // - the edited file exists - // - the swap file has no changes and looks OK + // - the swapfile has no changes and looks OK if (os_path_exists(buf->b_fname) && swapfile_unchanged(fname)) { choice = 4; if (p_verbose > 0) { @@ -3430,8 +3425,9 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ choice = do_swapexists(buf, fname); } + process_running = 0; // Set by attention_message..swapfile_info. if (choice == 0) { - // Show info about the existing swap file. + // Show info about the existing swapfile. attention_message(buf, fname); // We don't want a 'q' typed at the more-prompt @@ -3459,15 +3455,15 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ xstrlcat(name, sw_msg_2, name_len); choice = do_dialog(VIM_WARNING, _("VIM - ATTENTION"), name, - process_still_running + process_running ? _("&Open Read-Only\n&Edit anyway\n&Recover" "\n&Quit\n&Abort") : _("&Open Read-Only\n&Edit anyway\n&Recover" "\n&Delete it\n&Quit\n&Abort"), 1, NULL, false); - if (process_still_running && choice >= 4) { - choice++; // Skip missing "Delete it" button. + if (process_running && choice >= 4) { + choice++; // Skip missing "Delete it" button. } xfree(name); @@ -3477,27 +3473,27 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ if (choice > 0) { switch (choice) { - case 1: + case 1: // "Open Read-Only" buf->b_p_ro = true; break; - case 2: + case 2: // "Edit anyway" break; - case 3: + case 3: // "Recover" swap_exists_action = SEA_RECOVER; break; - case 4: + case 4: // "Delete it" os_remove(fname); break; - case 5: + case 5: // "Quit" swap_exists_action = SEA_QUIT; break; - case 6: + case 6: // "Abort" swap_exists_action = SEA_QUIT; got_int = true; break; } - // If the file was deleted this fname can be used. + // If the swapfile was deleted this `fname` can be used. if (!os_path_exists(fname)) { break; } @@ -3512,10 +3508,10 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ } } - // Change the ".swp" extension to find another file that can be used. + // Permute the ".swp" extension to find a unique swapfile name. // First decrement the last char: ".swo", ".swn", etc. // If that still isn't enough decrement the last but one char: ".svz" - // Can happen when editing many "No Name" buffers. + // Can happen when many Nvim instances are editing the same file (including "No Name" buffers). if (fname[n - 1] == 'a') { // ".s?a" if (fname[n - 2] == 'a') { // ".saa": tried enough, give up emsg(_("E326: Too many swap files found")); @@ -3553,7 +3549,7 @@ static int b0_magic_wrong(ZeroBlock *b0p) || b0p->b0_magic_char != B0_MAGIC_CHAR; } -/// Compare current file name with file name from swap file. +/// Compare current file name with file name from swapfile. /// Try to use inode numbers when possible. /// Return non-zero when files are different. /// @@ -3563,7 +3559,7 @@ static int b0_magic_wrong(ZeroBlock *b0p) /// because the device number cannot be used over a network. /// - When a file does not exist yet (editing a new file) there is no inode /// number. -/// - The file name in a swap file may not be valid on the current host. The +/// - The file name in a swapfile may not be valid on the current host. The /// "~user" form is used whenever possible to avoid this. /// /// This is getting complicated, let's make a table: @@ -3577,7 +3573,7 @@ static int b0_magic_wrong(ZeroBlock *b0p) /// == 0 X OK OK fname_c != fname_s /// X == 0 OK OK fname_c != fname_s /// -/// current file doesn't exist, file for swap file exist, file name(s) not +/// current file doesn't exist, file for swapfile exist, file name(s) not /// available -> probably different /// == 0 != 0 FAIL X true /// == 0 != 0 X FAIL true @@ -3600,11 +3596,11 @@ static int b0_magic_wrong(ZeroBlock *b0p) /// without making the block 0 incompatible with 32 bit versions. /// /// @param fname_c current file name -/// @param fname_s file name from swap file +/// @param fname_s file name from swapfile static bool fnamecmp_ino(char *fname_c, char *fname_s, long ino_block0) { uint64_t ino_c = 0; // ino of current file - uint64_t ino_s; // ino of file from swap file + uint64_t ino_s; // ino of file from swapfile char buf_c[MAXPATHL]; // full path of fname_c char buf_s[MAXPATHL]; // full path of fname_s int retval_c; // flag: buf_c valid @@ -3616,7 +3612,7 @@ static bool fnamecmp_ino(char *fname_c, char *fname_s, long ino_block0) } // First we try to get the inode from the file name, because the inode in - // the swap file may be outdated. If that fails (e.g. this path is not + // the swapfile may be outdated. If that fails (e.g. this path is not // valid on this machine), use the inode from block 0. if (os_fileinfo(fname_s, &file_info)) { ino_s = os_fileinfo_inode(&file_info); @@ -3638,7 +3634,7 @@ static bool fnamecmp_ino(char *fname_c, char *fname_s, long ino_block0) // Can't compare inodes or file names, guess that the files are different, // unless both appear not to exist at all, then compare with the file name - // in the swap file. + // in the swapfile. if (ino_s == 0 && ino_c == 0 && retval_c == FAIL && retval_s == FAIL) { return strcmp(fname_c, fname_s) != 0; } @@ -3675,7 +3671,7 @@ static long char_to_long(const char *s_in) return retval; } -/// Set the flags in the first block of the swap file: +/// Set the flags in the first block of the swapfile: /// - file is modified or not: buf->b_changed /// - 'fileformat' /// - 'fileencoding' diff --git a/src/nvim/menu.c b/src/nvim/menu.c index 2204a0a291..4a72464527 100644 --- a/src/nvim/menu.c +++ b/src/nvim/menu.c @@ -12,6 +12,7 @@ #include "nvim/ascii.h" #include "nvim/autocmd.h" #include "nvim/charset.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/cursor.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" @@ -365,7 +366,7 @@ static int add_menu_path(const char *const menu_path, vimmenu_T *menuarg, const menu->en_name = NULL; menu->en_dname = NULL; } - menu->priority = pri_tab[pri_idx]; + menu->priority = (int)pri_tab[pri_idx]; menu->parent = parent; // Add after menu that has lower priority. @@ -658,7 +659,7 @@ static dict_T *menu_get_recursive(const vimmenu_T *menu, int modes) dict_T *dict = tv_dict_alloc(); tv_dict_add_str(dict, S_LEN("name"), menu->dname); - tv_dict_add_nr(dict, S_LEN("priority"), (int)menu->priority); + tv_dict_add_nr(dict, S_LEN("priority"), menu->priority); tv_dict_add_nr(dict, S_LEN("hidden"), menu_is_hidden(menu->dname)); if (menu->mnemonic) { @@ -1846,7 +1847,7 @@ static void menuitem_getinfo(const char *menu_name, const vimmenu_T *menu, int m if (menu->actext != NULL) { tv_dict_add_str(dict, S_LEN("accel"), menu->actext); } - tv_dict_add_nr(dict, S_LEN("priority"), (int)menu->priority); + tv_dict_add_nr(dict, S_LEN("priority"), menu->priority); tv_dict_add_str(dict, S_LEN("modes"), get_menu_mode_str(menu->modes)); char buf[NUMBUFLEN]; diff --git a/src/nvim/menu.h b/src/nvim/menu.h index 32959cf35f..8d7a98d270 100644 --- a/src/nvim/menu.h +++ b/src/nvim/menu.h @@ -3,6 +3,7 @@ #include <stdbool.h> +#include "nvim/cmdexpand_defs.h" #include "nvim/ex_cmds_defs.h" #include "nvim/menu_defs.h" #include "nvim/types.h" diff --git a/src/nvim/menu_defs.h b/src/nvim/menu_defs.h index 79b267ae49..1e010c07ba 100644 --- a/src/nvim/menu_defs.h +++ b/src/nvim/menu_defs.h @@ -52,7 +52,7 @@ struct VimMenu { char *en_dname; ///< NULL when "dname" untranslated int mnemonic; ///< mnemonic key (after '&') char *actext; ///< accelerator text (after TAB) - long priority; ///< Menu order priority + int priority; ///< Menu order priority char *strings[MENU_MODES]; ///< Mapped string for each mode int noremap[MENU_MODES]; ///< A \ref REMAP_VALUES flag for each mode bool silent[MENU_MODES]; ///< A silent flag for each mode diff --git a/src/nvim/message.c b/src/nvim/message.c index 68ea49d53b..97402276b2 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -475,7 +475,14 @@ void trunc_string(const char *s, char *buf, int room_in, int buflen) } } -// Note: Caller of smsg() must check the resulting string is shorter than IOSIZE!!! +/// Shows a printf-style message with attributes. +/// +/// Note: Caller must check the resulting string is shorter than IOSIZE!!! +/// +/// @see semsg +/// @see swmsg +/// +/// @param s printf-style format message int smsg(int attr, const char *s, ...) FUNC_ATTR_PRINTF(2, 3) { @@ -757,6 +764,8 @@ void emsg_invreg(int name) } /// Print an error message with unknown number of arguments +/// +/// @return whether the message was displayed bool semsg(const char *const fmt, ...) FUNC_ATTR_PRINTF(1, 2) { @@ -1025,10 +1034,9 @@ int delete_first_msg(void) } /// :messages command implementation -void ex_messages(void *const eap_p) +void ex_messages(exarg_T *eap) FUNC_ATTR_NONNULL_ALL { - const exarg_T *const eap = (const exarg_T *)eap_p; struct msg_hist *p; if (strcmp(eap->arg, "clear") == 0) { @@ -1347,7 +1355,7 @@ bool messaging(void) return !(p_lz && char_avail() && !KeyTyped) && (p_ch > 0 || ui_has(kUIMessages)); } -void msgmore(long n) +void msgmore(int n) { long pn; @@ -1481,11 +1489,11 @@ void msg_putchar_attr(int c, int attr) msg_puts_attr(buf, attr); } -void msg_outnum(long n) +void msg_outnum(int n) { char buf[20]; - snprintf(buf, sizeof(buf), "%ld", n); + snprintf(buf, sizeof(buf), "%d", n); msg_puts(buf); } @@ -1962,40 +1970,6 @@ void msg_prt_line(const char *s, int list) msg_clr_eos(); } -/// Use grid_puts() to output one multi-byte character. -/// -/// @return the pointer "s" advanced to the next character. -static const char *screen_puts_mbyte(const char *s, int l, int attr) -{ - int cw; - attr = hl_combine_attr(HL_ATTR(HLF_MSG), attr); - - msg_didout = true; // remember that line is not empty - cw = utf_ptr2cells(s); - if (cw > 1 - && (cmdmsg_rl ? msg_col <= 1 : msg_col == Columns - 1)) { - // Doesn't fit, print a highlighted '>' to fill it up. - msg_screen_putchar('>', HL_ATTR(HLF_AT)); - return s; - } - - grid_puts(&msg_grid_adj, s, l, msg_row, msg_col, attr); - if (cmdmsg_rl) { - msg_col -= cw; - if (msg_col == 0) { - msg_col = Columns; - msg_row++; - } - } else { - msg_col += cw; - if (msg_col >= Columns) { - msg_col = 0; - msg_row++; - } - } - return s + l; -} - /// Output a string to the screen at position msg_row, msg_col. /// Update msg_row and msg_col for the next message. void msg_puts(const char *s) @@ -2133,14 +2107,8 @@ static void msg_ext_emit_chunk(void) static void msg_puts_display(const char *str, int maxlen, int attr, int recurse) { const char *s = str; - const char *t_s = str; // String from "t_s" to "s" is still todo. - int t_col = 0; // Screen cells todo, 0 when "t_s" not used. - int l; - int cw; const char *sb_str = str; int sb_col = msg_col; - int wrap; - int did_last_char; did_wait_return = false; @@ -2156,175 +2124,143 @@ static void msg_puts_display(const char *str, int maxlen, int attr, int recurse) return; } + int print_attr = hl_combine_attr(HL_ATTR(HLF_MSG), attr); msg_grid_validate(); cmdline_was_last_drawn = redrawing_cmdline; - while ((maxlen < 0 || (int)(s - str) < maxlen) && *s != NUL) { - // We are at the end of the screen line when: - // - When outputting a newline. - // - When outputting a character in the last column. - if (!recurse && msg_row >= Rows - 1 - && (*s == '\n' || (cmdmsg_rl - ? (msg_col <= 1 - || (*s == TAB && msg_col <= 7) - || (utf_ptr2cells(s) > 1 - && msg_col <= 2)) - : ((*s != '\r' && msg_col + t_col >= Columns - 1) - || (*s == TAB - && msg_col + t_col >= ((Columns - 1) & ~7)) - || (utf_ptr2cells(s) > 1 - && msg_col + t_col >= Columns - 2))))) { - // The screen is scrolled up when at the last row (some terminals - // scroll automatically, some don't. To avoid problems we scroll - // ourselves). - if (t_col > 0) { - // output postponed text - t_puts(&t_col, t_s, s, attr); - } + int msg_row_pending = -1; - // When no more prompt and no more room, truncate here + while (true) { + if (cmdmsg_rl ? msg_col <= 0 : msg_col >= Columns) { + if (p_more && !recurse) { + // Store text for scrolling back. + store_sb_text(&sb_str, s, attr, &sb_col, true); + } if (msg_no_more && lines_left == 0) { break; } - // Scroll the screen up one line. - bool has_last_char = ((uint8_t)(*s) >= ' ' && !cmdmsg_rl); - msg_scroll_up(!has_last_char, false); + msg_col = cmdmsg_rl ? Columns - 1 : 0; + msg_row++; + msg_didout = false; + } - msg_row = Rows - 2; - if (msg_col >= Columns) { // can happen after screen resize - msg_col = Columns - 1; - } + if (msg_row >= Rows) { + msg_row = Rows - 1; - // Display char in last column before showing more-prompt. - if (has_last_char) { - if (maxlen >= 0) { - // Avoid including composing chars after the end. - l = utfc_ptr2len_len(s, (int)((str + maxlen) - s)); - } else { - l = utfc_ptr2len(s); - } - s = screen_puts_mbyte(s, l, attr); - did_last_char = true; - } else { - did_last_char = false; + // When no more prompt and no more room, truncate here + if (msg_no_more && lines_left == 0) { + break; } - // Tricky: if last cell will be written, delay the throttle until - // after the first scroll. Otherwise we would need to keep track of it. - if (has_last_char && msg_do_throttle()) { - if (!msg_grid.throttled) { - msg_grid_scroll_discount++; + if (!recurse) { + if (msg_row_pending >= 0) { + grid_line_flush_if_valid_row(); + msg_row_pending = -1; } - msg_grid.throttled = true; - } - if (p_more) { - // Store text for scrolling back. - store_sb_text(&sb_str, s, attr, &sb_col, true); - } - - inc_msg_scrolled(); - need_wait_return = true; // may need wait_return() in main() - redraw_cmdline = true; - if (cmdline_row > 0 && !exmode_active) { - cmdline_row--; - } + // Scroll the screen up one line. + msg_scroll_up(true, false); - // If screen is completely filled and 'more' is set then wait - // for a character. - if (lines_left > 0) { - lines_left--; - } - if (p_more && lines_left == 0 && State != MODE_HITRETURN - && !msg_no_more && !exmode_active) { - if (do_more_prompt(NUL)) { - s = confirm_msg_tail; + inc_msg_scrolled(); + need_wait_return = true; // may need wait_return() in main() + redraw_cmdline = true; + if (cmdline_row > 0 && !exmode_active) { + cmdline_row--; } - if (quit_more) { - return; + + // If screen is completely filled and 'more' is set then wait + // for a character. + if (lines_left > 0) { + lines_left--; } - } - // When we displayed a char in last column need to check if there - // is still more. - if (did_last_char) { - continue; + if (p_more && lines_left == 0 && State != MODE_HITRETURN + && !msg_no_more && !exmode_active) { + if (do_more_prompt(NUL)) { + s = confirm_msg_tail; + } + if (quit_more) { + return; + } + } } } - wrap = *s == '\n' - || msg_col + t_col >= Columns - || (utf_ptr2cells(s) > 1 - && msg_col + t_col >= Columns - 1) - ; - if (t_col > 0 && (wrap || *s == '\r' || *s == '\b' - || *s == '\t' || *s == BELL)) { - // Output any postponed text. - t_puts(&t_col, t_s, s, attr); + if (!((maxlen < 0 || (int)(s - str) < maxlen) && *s != NUL)) { + break; } - if (wrap && p_more && !recurse) { - // Store text for scrolling back. - store_sb_text(&sb_str, s, attr, &sb_col, true); + if (msg_row != msg_row_pending && ((uint8_t)(*s) >= 0x20 || *s == TAB)) { + // TODO(bfredl): this logic is messier that it has to be. What + // messages really want is its own private linebuf_char buffer. + if (msg_row_pending >= 0) { + grid_line_flush_if_valid_row(); + } + grid_line_start(&msg_grid_adj, msg_row); + msg_row_pending = msg_row; } - if (*s == '\n') { // go to next line - msg_didout = false; // remember that line is empty - if (cmdmsg_rl) { - msg_col = Columns - 1; + if ((uint8_t)(*s) >= 0x20) { // printable char + int cw = utf_ptr2cells(s); + // avoid including composing chars after the end + int l = (maxlen >= 0) ? utfc_ptr2len_len(s, (int)((str + maxlen) - s)) : utfc_ptr2len(s); + + if (cw > 1 && (cmdmsg_rl ? msg_col <= 1 : msg_col == Columns - 1)) { + // Doesn't fit, print a highlighted '>' to fill it up. + grid_line_puts(msg_col, ">", 1, HL_ATTR(HLF_AT)); + cw = 1; } else { - msg_col = 0; - } - if (++msg_row >= Rows) { // safety check - msg_row = Rows - 1; + grid_line_puts(msg_col, s, l, print_attr); + s += l; } - } else if (*s == '\r') { // go to column 0 - msg_col = 0; - } else if (*s == '\b') { // go to previous char - if (msg_col) { - msg_col--; - } - } else if (*s == TAB) { // translate Tab into spaces - do { - msg_screen_putchar(' ', attr); - } while (msg_col & 7); - } else if (*s == BELL) { // beep (from ":sh") - vim_beep(BO_SH); - } else if ((uint8_t)(*s) >= 0x20) { // printable char - cw = utf_ptr2cells(s); - if (maxlen >= 0) { - // avoid including composing chars after the end - l = utfc_ptr2len_len(s, (int)((str + maxlen) - s)); + msg_didout = true; // remember that line is not empty + if (cmdmsg_rl) { + msg_col -= cw; } else { - l = utfc_ptr2len(s); + msg_col += cw; } - // When drawing from right to left or when a double-wide character - // doesn't fit, draw a single character here. Otherwise collect - // characters and draw them all at once later. - if (cmdmsg_rl || (cw > 1 && msg_col + t_col >= Columns - 1)) { - if (l > 1) { - s = screen_puts_mbyte(s, l, attr) - 1; + } else { + char c = *s++; + if (c == '\n') { // go to next line + msg_didout = false; // remember that line is empty + if (cmdmsg_rl) { + msg_col = Columns - 1; } else { - msg_screen_putchar(*s, attr); + msg_col = 0; } - } else { - // postpone this character until later - if (t_col == 0) { - t_s = s; + msg_row++; + if (p_more && !recurse) { + // Store text for scrolling back. + store_sb_text(&sb_str, s, attr, &sb_col, true); + } + } else if (c == '\r') { // go to column 0 + msg_col = 0; + } else if (c == '\b') { // go to previous char + if (msg_col) { + msg_col--; } - t_col += cw; - s += l - 1; + } else if (c == TAB) { // translate Tab into spaces + do { + grid_line_puts(msg_col, " ", 1, print_attr); + msg_col += cmdmsg_rl ? -1 : 1; + + if (msg_col == (cmdmsg_rl ? 0 : Columns)) { + break; + } + } while (msg_col & 7); + } else if (c == BELL) { // beep (from ":sh") + vim_beep(BO_SH); } } - s++; } - // Output any postponed text. - if (t_col > 0) { - t_puts(&t_col, t_s, s, attr); + if (msg_row_pending >= 0) { + grid_line_flush_if_valid_row(); } + msg_cursor_goto(msg_row, msg_col); + if (p_more && !recurse && !(s == sb_str + 1 && *sb_str == '\n')) { store_sb_text(&sb_str, s, attr, &sb_col, false); } @@ -2332,6 +2268,13 @@ static void msg_puts_display(const char *str, int maxlen, int attr, int recurse) msg_check(); } +void msg_cursor_goto(int row, int col) +{ + ScreenGrid *grid = &msg_grid_adj; + grid_adjust(&grid, &row, &col); + ui_grid_cursor_goto(grid->handle, row, col); +} + /// @return true when ":filter pattern" was used and "msg" does not match /// "pattern". bool message_filtered(const char *msg) @@ -2508,6 +2451,9 @@ static void store_sb_text(const char **sb_str, const char *s, int attr, int *sb_ || do_clear_sb_text == SB_CLEAR_CMDLINE_DONE) { clear_sb_text(do_clear_sb_text == SB_CLEAR_ALL); msg_sb_eol(); // prevent messages from overlapping + if (do_clear_sb_text == SB_CLEAR_CMDLINE_DONE && s > *sb_str && **sb_str == '\n') { + (*sb_str)++; + } do_clear_sb_text = SB_CLEAR_NONE; } @@ -2655,9 +2601,6 @@ static msgchunk_T *disp_sb_line(int row, msgchunk_T *smp) msg_row = row; msg_col = mp->sb_msg_col; char *p = mp->sb_text; - if (*p == '\n') { // don't display the line break - p++; - } msg_puts_display(p, -1, mp->sb_attr, true); if (mp->sb_eol || mp->sb_next == NULL) { break; @@ -2668,26 +2611,6 @@ static msgchunk_T *disp_sb_line(int row, msgchunk_T *smp) return mp->sb_next; } -/// Output any postponed text for msg_puts_len(). -static void t_puts(int *t_col, const char *t_s, const char *s, int attr) -{ - attr = hl_combine_attr(HL_ATTR(HLF_MSG), attr); - // Output postponed text. - msg_didout = true; // Remember that line is not empty. - grid_puts(&msg_grid_adj, t_s, (int)(s - t_s), msg_row, msg_col, attr); - msg_col += *t_col; - *t_col = 0; - // If the string starts with a composing character don't increment the - // column position for it. - if (utf_iscomposing(utf_ptr2char(t_s))) { - msg_col--; - } - if (msg_col >= Columns) { - msg_col = 0; - msg_row++; - } -} - /// @return true when messages should be printed to stdout/stderr: /// - "batch mode" ("silent mode", -es/-Es) /// - no UI and not embedded @@ -3034,26 +2957,6 @@ void os_msg(const char *str) } #endif // MSWIN -/// Put a character on the screen at the current message position and advance -/// to the next position. Only for printable ASCII! -static void msg_screen_putchar(int c, int attr) -{ - attr = hl_combine_attr(HL_ATTR(HLF_MSG), attr); - msg_didout = true; // remember that line is not empty - grid_putchar(&msg_grid_adj, c, msg_row, msg_col, attr); - if (cmdmsg_rl) { - if (--msg_col == 0) { - msg_col = Columns; - msg_row++; - } - } else { - if (++msg_col >= Columns) { - msg_col = 0; - msg_row++; - } - } -} - void msg_moremsg(int full) { int attr; @@ -3443,9 +3346,22 @@ void give_warning(const char *message, bool hl) no_wait_return--; } -void give_warning2(const char *const message, const char *const a1, bool hl) +/// Shows a warning, with optional highlighting. +/// +/// @param hl enable highlighting +/// @param fmt printf-style format message +/// +/// @see smsg +/// @see semsg +void swmsg(bool hl, const char *const fmt, ...) + FUNC_ATTR_PRINTF(2, 3) { - vim_snprintf(IObuff, IOSIZE, message, a1); + va_list args; + + va_start(args, fmt); + vim_vsnprintf(IObuff, IOSIZE, fmt, args); + va_end(args); + give_warning(IObuff, hl); } diff --git a/src/nvim/message.h b/src/nvim/message.h index 78cd5b7d0e..6fc6674cc2 100644 --- a/src/nvim/message.h +++ b/src/nvim/message.h @@ -7,6 +7,7 @@ #include "klib/kvec.h" #include "nvim/api/private/defs.h" +#include "nvim/ex_cmds_defs.h" #include "nvim/grid_defs.h" #include "nvim/macros.h" #include "nvim/types.h" diff --git a/src/nvim/move.c b/src/nvim/move.c index 8efb038a55..dd9737ede2 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -2699,7 +2699,7 @@ void do_check_cursorbind(void) FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { curwin = wp; curbuf = curwin->w_buffer; - // skip original window and windows with 'noscrollbind' + // skip original window and windows with 'nocursorbind' if (curwin != old_curwin && curwin->w_p_crb) { if (curwin->w_p_diff) { curwin->w_cursor.lnum = diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 715b98377a..1a212661c5 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1735,13 +1735,13 @@ static void prep_redo_cmd(cmdarg_T *cap) /// Prepare for redo of any command. /// Note that only the last argument can be a multi-byte char. -void prep_redo(int regname, long num, int cmd1, int cmd2, int cmd3, int cmd4, int cmd5) +void prep_redo(int regname, int num, int cmd1, int cmd2, int cmd3, int cmd4, int cmd5) { prep_redo_num2(regname, num, cmd1, cmd2, 0L, cmd3, cmd4, cmd5); } /// Prepare for redo of any command with extra count after "cmd2". -void prep_redo_num2(int regname, long num1, int cmd1, int cmd2, long num2, int cmd3, int cmd4, +void prep_redo_num2(int regname, int num1, int cmd1, int cmd2, int num2, int cmd3, int cmd4, int cmd5) { ResetRedobuff(); diff --git a/src/nvim/normal.h b/src/nvim/normal.h index b9fdd21652..3d7782c05c 100644 --- a/src/nvim/normal.h +++ b/src/nvim/normal.h @@ -39,7 +39,7 @@ typedef struct oparg_S { pos_T end; // end of the operator pos_T cursor_start; // cursor position before motion for "gw" - long line_count; // number of lines from op_start to op_end + linenr_T line_count; // number of lines from op_start to op_end // (inclusive) bool empty; // op_start and op_end the same (only used by // op_change()) diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 5d3e285e3b..348a86a0f6 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -217,7 +217,7 @@ int get_extra_op_char(int optype) /// handle a shift operation void op_shift(oparg_T *oap, int curs_top, int amount) { - long i; + int i; int block_col = 0; if (u_save((linenr_T)(oap->start.lnum - 1), @@ -292,7 +292,7 @@ void op_shift(oparg_T *oap, int curs_top, int amount) /// @param call_changed_bytes call changed_bytes() void shift_line(int left, int round, int amount, int call_changed_bytes) { - const int sw_val = (int)get_sw_value_indent(curbuf); + const int sw_val = get_sw_value_indent(curbuf); int count = get_indent(); // get current indent @@ -338,7 +338,7 @@ static void shift_block(oparg_T *oap, int amount) const int oldstate = State; char *newp; const int oldcol = curwin->w_cursor.col; - const int sw_val = (int)get_sw_value_indent(curbuf); + const int sw_val = get_sw_value_indent(curbuf); const int ts_val = (int)curbuf->b_p_ts; struct block_def bd; int incr; @@ -634,7 +634,7 @@ static void block_insert(oparg_T *oap, char *s, int b_insert, struct block_def * /// Handle reindenting a block of lines. void op_reindent(oparg_T *oap, Indenter how) { - long i = 0; + int i = 0; linenr_T first_changed = 0; linenr_T last_changed = 0; linenr_T start_lnum = curwin->w_cursor.lnum; @@ -647,8 +647,8 @@ void op_reindent(oparg_T *oap, Indenter how) // Save for undo. Do this once for all lines, much faster than doing this // for each line separately, especially when undoing. - if (u_savecommon(curbuf, start_lnum - 1, start_lnum + (linenr_T)oap->line_count, - start_lnum + (linenr_T)oap->line_count, false) == OK) { + if (u_savecommon(curbuf, start_lnum - 1, start_lnum + oap->line_count, + start_lnum + oap->line_count, false) == OK) { char *l; int amount; for (i = oap->line_count - 1; i >= 0 && !got_int; i--) { @@ -693,7 +693,7 @@ void op_reindent(oparg_T *oap, Indenter how) // there is no change still need to remove the Visual highlighting. if (last_changed != 0) { changed_lines(curbuf, first_changed, 0, - oap->is_VIsual ? start_lnum + (linenr_T)oap->line_count : + oap->is_VIsual ? start_lnum + oap->line_count : last_changed + 1, 0L, true); } else if (oap->is_VIsual) { redraw_curbuf_later(UPD_INVERTED); @@ -1717,8 +1717,8 @@ int op_delete(oparg_T *oap) pos_T curpos; // save deleted and changed lines for undo - if (u_save((linenr_T)(curwin->w_cursor.lnum - 1), - (linenr_T)(curwin->w_cursor.lnum + oap->line_count)) == FAIL) { + if (u_save(curwin->w_cursor.lnum - 1, + curwin->w_cursor.lnum + oap->line_count) == FAIL) { return FAIL; } @@ -2204,7 +2204,7 @@ bool swapchar(int op_type, pos_T *pos) /// Insert and append operators for Visual mode. void op_insert(oparg_T *oap, long count1) { - long pre_textlen = 0; + int pre_textlen = 0; char *firstline; colnr_T ind_pre_col = 0; int ind_pre_vcol = 0; @@ -2251,7 +2251,7 @@ void op_insert(oparg_T *oap, long count1) if (oap->op_type == OP_APPEND) { firstline += bd.textlen; } - pre_textlen = (long)strlen(firstline); + pre_textlen = (int)strlen(firstline); } if (oap->op_type == OP_APPEND) { @@ -2400,7 +2400,7 @@ void op_insert(oparg_T *oap, long count1) } else { firstline += add; } - long ins_len = (long)strlen(firstline) - pre_textlen - offset; + int ins_len = (int)strlen(firstline) - pre_textlen - offset; if (pre_textlen >= 0 && ins_len > 0) { char *ins_text = xstrnsave(firstline, (size_t)ins_len); // block handled here @@ -2421,8 +2421,8 @@ void op_insert(oparg_T *oap, long count1) int op_change(oparg_T *oap) { int retval; - long pre_textlen = 0; - long pre_indent = 0; + int pre_textlen = 0; + int pre_indent = 0; char *firstline; struct block_def bd; @@ -2456,8 +2456,8 @@ int op_change(oparg_T *oap) coladvance_force(getviscol()); } firstline = ml_get(oap->start.lnum); - pre_textlen = (long)strlen(firstline); - pre_indent = (long)getwhitecols(firstline); + pre_textlen = (int)strlen(firstline); + pre_indent = (int)getwhitecols(firstline); bd.textcol = curwin->w_cursor.col; } @@ -2478,25 +2478,25 @@ int op_change(oparg_T *oap) // Don't repeat the insert when Insert mode ended with CTRL-C. if (oap->motion_type == kMTBlockWise && oap->start.lnum != oap->end.lnum && !got_int) { - long ins_len; + int ins_len; // Auto-indenting may have changed the indent. If the cursor was past // the indent, exclude that indent change from the inserted text. firstline = ml_get(oap->start.lnum); if (bd.textcol > (colnr_T)pre_indent) { - long new_indent = (long)getwhitecols(firstline); + int new_indent = (int)getwhitecols(firstline); pre_textlen += new_indent - pre_indent; bd.textcol += (colnr_T)(new_indent - pre_indent); } - ins_len = (long)strlen(firstline) - pre_textlen; + ins_len = (int)strlen(firstline) - pre_textlen; if (ins_len > 0) { long offset; char *newp; char *oldp; // Subsequent calls to ml_get() flush the firstline data - take a // copy of the inserted text. - char *ins_text = xmalloc((size_t)(ins_len + 1)); + char *ins_text = xmalloc((size_t)ins_len + 1); xstrlcpy(ins_text, firstline + bd.textcol, (size_t)ins_len + 1); for (linenr_T linenr = oap->start.lnum + 1; linenr <= oap->end.lnum; linenr++) { @@ -2526,7 +2526,7 @@ int op_change(oparg_T *oap) STRMOVE(newp + offset, oldp); ml_replace(linenr, newp, false); extmark_splice_cols(curbuf, (int)linenr - 1, bd.textcol, - 0, vpos.coladd + (int)ins_len, kExtmarkUndo); + 0, vpos.coladd + ins_len, kExtmarkUndo); } } check_cursor(); @@ -2903,7 +2903,7 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg) /// PUT_LINE force linewise put (":put") /// PUT_BLOCK_INNER in block mode, do not add trailing spaces /// @param dir BACKWARD for 'P', FORWARD for 'p' -void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) +void do_put(int regname, yankreg_T *reg, int dir, int count, int flags) { char *ptr; char *newp; @@ -3320,7 +3320,8 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) break; } - totlen = (size_t)(count * (yanklen + spaces) + bd.startspaces + bd.endspaces); + totlen = (size_t)count * (size_t)(yanklen + spaces) + (size_t)bd.startspaces + + (size_t)bd.endspaces; newp = xmalloc(totlen + oldlen + 1); // copy part up to cursor to new line @@ -3446,7 +3447,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) // multiplication overflow emsg(_(e_resulting_text_too_long)); } else { - totlen = (size_t)(count * yanklen); + totlen = (size_t)count * (size_t)yanklen; do { oldp = ml_get(lnum); oldlen = strlen(oldp); @@ -4166,7 +4167,7 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions // have moved up (last line deleted), so the current lnum is kept in t. t = curwin->w_cursor.lnum; curwin->w_cursor.lnum++; - del_lines((long)count - 1, false); + del_lines((int)count - 1, false); curwin->w_cursor.lnum = t; curbuf_splice_pending--; curbuf->deleted_bytes2 = 0; @@ -5569,7 +5570,7 @@ static void op_colon(oparg_T *oap) if (oap->start.lnum == curwin->w_cursor.lnum) { stuffcharReadbuff('.'); } else { - stuffnumReadbuff((long)oap->start.lnum); + stuffnumReadbuff(oap->start.lnum); } // When using !! on a closed fold the range ".!" works best to operate @@ -5590,7 +5591,7 @@ static void op_colon(oparg_T *oap) stuffReadbuff(".+"); stuffnumReadbuff(oap->line_count - 1); } else { - stuffnumReadbuff((long)oap->end.lnum); + stuffnumReadbuff(oap->end.lnum); } } } @@ -5996,7 +5997,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) resel_VIsual_vcol = oap->end_vcol; } } - resel_VIsual_line_count = (linenr_T)oap->line_count; + resel_VIsual_line_count = oap->line_count; } // can't redo yank (unless 'y' is in 'cpoptions') and ":" diff --git a/src/nvim/option.c b/src/nvim/option.c index eef5e66aeb..c0353e52be 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -40,6 +40,7 @@ #include "nvim/change.h" #include "nvim/charset.h" #include "nvim/cmdexpand.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/cursor_shape.h" #include "nvim/decoration_provider.h" #include "nvim/diff.h" @@ -136,12 +137,12 @@ static char *p_vsts_nopaste; #define OPTION_COUNT ARRAY_SIZE(options) +/// :set boolean option prefix typedef enum { - OP_NONE = 0, - OP_ADDING, ///< "opt+=arg" - OP_PREPENDING, ///< "opt^=arg" - OP_REMOVING, ///< "opt-=arg" -} set_op_T; + PREFIX_NO = 0, ///< "no" prefix + PREFIX_NONE, ///< no prefix + PREFIX_INV, ///< "inv" prefix +} set_prefix_T; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "option.c.generated.h" @@ -557,7 +558,7 @@ static char *find_dup_item(char *origval, const char *newval, uint32_t flags) /// Set the Vi-default value of a number option. /// Used for 'lines' and 'columns'. -void set_number_default(char *name, long val) +void set_number_default(char *name, OptInt val) { int opt_idx = findoption(name); if (opt_idx >= 0) { @@ -752,8 +753,8 @@ void ex_set(exarg_T *eap) (void)do_set(eap->arg, flags); } -static void do_set_bool(int opt_idx, int opt_flags, int prefix, int nextchar, const void *varp, - const char **errmsg) +static void do_set_bool(int opt_idx, int opt_flags, set_prefix_T prefix, int nextchar, + const void *varp, const char **errmsg) { varnumber_T value; @@ -772,10 +773,12 @@ static void do_set_bool(int opt_idx, int opt_flags, int prefix, int nextchar, co value = *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL); } } else { - if (prefix == 2) { - value = *(int *)varp ^ 1; // ":set invopt": invert + // ":set invopt": invert + // ":set opt" or ":set noopt": set or reset + if (prefix == PREFIX_INV) { + value = *(int *)varp ^ 1; } else { - value = prefix; // ":set opt" or ":set noopt": set or reset + value = prefix == PREFIX_NO ? 0 : 1; } } @@ -797,7 +800,7 @@ static void do_set_num(int opt_idx, int opt_flags, char **argp, int nextchar, co // other error arg++; if (nextchar == '&') { - value = (long)(intptr_t)options[opt_idx].def_val; + value = (varnumber_T)options[opt_idx].def_val; } else if (nextchar == '<') { if ((OptInt *)varp == &curbuf->b_p_ul && opt_flags == OPT_LOCAL) { // for 'undolevels' NO_LOCAL_UNDOLEVEL means using the global value @@ -843,7 +846,7 @@ static void do_set_num(int opt_idx, int opt_flags, char **argp, int nextchar, co if (op == OP_REMOVING) { value = *(OptInt *)varp - value; } - *errmsg = set_num_option(opt_idx, (void *)varp, (long)value, + *errmsg = set_num_option(opt_idx, (void *)varp, value, errbuf, errbuflen, opt_flags); } @@ -888,7 +891,7 @@ static char *stropt_copy_value(char *origval, char **argp, set_op_T op, // For MS-Windows backslashes before normal file name characters // are not removed, and keep backslash at start, for "\\machine\path", // but do remove it for "\\\\machine\\path". - // The reverse is found in ExpandOldSetting(). + // The reverse is found in escape_option_str_cmdline(). while (*arg != NUL && !ascii_iswhite(*arg)) { if (*arg == '\\' && arg[1] != NUL #ifdef BACKSLASH_IN_FILENAME @@ -1168,7 +1171,7 @@ static void do_set_option_string(int opt_idx, int opt_flags, char **argp, int ne // be triggered that can cause havoc. *errmsg = did_set_string_option(curbuf, curwin, opt_idx, (char **)varp, oldval, errbuf, errbuflen, - opt_flags, value_checked); + opt_flags, op, value_checked); secure = secure_saved; @@ -1204,17 +1207,17 @@ static set_op_T get_op(const char *arg) return op; } -static int get_option_prefix(char **argp) +static set_prefix_T get_option_prefix(char **argp) { if (strncmp(*argp, "no", 2) == 0) { *argp += 2; - return 0; + return PREFIX_NO; } else if (strncmp(*argp, "inv", 3) == 0) { *argp += 3; - return 2; + return PREFIX_INV; } - return 1; + return PREFIX_NONE; } /// @param[in] arg Pointer to start option name @@ -1273,11 +1276,11 @@ static int parse_option_name(char *arg, int *keyp, int *lenp, int *opt_idxp) return OK; } -static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t flags, int prefix, - const char **errmsg) +static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t flags, + set_prefix_T prefix, const char **errmsg) { // Only bools can have a prefix of 'inv' or 'no' - if (!(flags & P_BOOL) && prefix != 1) { + if (!(flags & P_BOOL) && prefix != PREFIX_NONE) { *errmsg = e_invarg; return FAIL; } @@ -1325,8 +1328,8 @@ static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t fla return OK; } -static void do_set_option_value(int opt_idx, int opt_flags, char **argp, int prefix, int nextchar, - set_op_T op, uint32_t flags, void *varp, char *errbuf, +static void do_set_option_value(int opt_idx, int opt_flags, char **argp, set_prefix_T prefix, + int nextchar, set_op_T op, uint32_t flags, void *varp, char *errbuf, size_t errbuflen, const char **errmsg) { bool value_checked = false; @@ -1355,7 +1358,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb size_t errbuflen, const char **errmsg) { // 1: nothing, 0: "no", 2: "inv" in front of name - int prefix = get_option_prefix(argp); + set_prefix_T prefix = get_option_prefix(argp); char *arg = *argp; @@ -1434,7 +1437,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb // '=' character per "set" command line. grrr. (jw) // if (nextchar == '?' - || (prefix == 1 + || (prefix == PREFIX_NONE && vim_strchr("=:&<", nextchar) == NULL && !(flags & P_BOOL))) { // print value @@ -1976,8 +1979,8 @@ void set_option_sctx_idx(int opt_idx, int opt_flags, sctx_T script_ctx) } /// Apply the OptionSet autocommand. -static void apply_optionset_autocmd(int opt_idx, long opt_flags, OptInt oldval, OptInt oldval_g, - long newval, const char *errmsg) +static void apply_optionset_autocmd(int opt_idx, int opt_flags, OptInt oldval, OptInt oldval_g, + OptInt newval, const char *errmsg) { // Don't do this while starting up, failure or recursively. if (starting || errmsg != NULL || *get_vim_var_str(VV_OPTION_TYPE) != NUL) { @@ -1988,7 +1991,7 @@ static void apply_optionset_autocmd(int opt_idx, long opt_flags, OptInt oldval, vim_snprintf(buf_old, sizeof(buf_old), "%" PRId64, oldval); vim_snprintf(buf_old_global, sizeof(buf_old_global), "%" PRId64, oldval_g); - vim_snprintf(buf_new, sizeof(buf_new), "%ld", newval); + vim_snprintf(buf_new, sizeof(buf_new), "%" PRId64, newval); vim_snprintf(buf_type, sizeof(buf_type), "%s", (opt_flags & OPT_LOCAL) ? "local" : "global"); set_vim_var_string(VV_OPTION_NEW, buf_new, -1); @@ -2899,9 +2902,9 @@ static const char *set_bool_option(const int opt_idx, char *const varp, const in options[opt_idx].flags |= P_WAS_SET; apply_optionset_autocmd(opt_idx, opt_flags, - (long)(old_value ? true : false), - (long)(old_global_value ? true : false), - (long)(value ? true : false), NULL); + (old_value ? true : false), + (old_global_value ? true : false), + (value ? true : false), NULL); if (options[opt_idx].flags & P_UI_OPTION) { ui_call_option_set(cstr_as_string(options[opt_idx].fullname), @@ -2921,8 +2924,8 @@ static const char *set_bool_option(const int opt_idx, char *const varp, const in } /// Check the bounds of numeric options. -static const char *check_num_option_bounds(OptInt *pp, OptInt old_value, long old_Rows, - char *errbuf, size_t errbuflen, const char *errmsg) +static const char *check_num_option_bounds(OptInt *pp, OptInt old_value, int old_Rows, char *errbuf, + size_t errbuflen, const char *errmsg) { // Check the (new) bounds for Rows and Columns here. if (p_lines < min_rows() && full_screen) { @@ -2997,9 +3000,9 @@ static const char *check_num_option_bounds(OptInt *pp, OptInt old_value, long ol } /// Options that need some validation. -static const char *validate_num_option(const OptInt *pp, long *valuep) +static const char *validate_num_option(const OptInt *pp, OptInt *valuep) { - long value = *valuep; + OptInt value = *valuep; // Many number options assume their value is in the signed int range. if (value < INT_MIN || value > INT_MAX) { @@ -3157,12 +3160,12 @@ static const char *validate_num_option(const OptInt *pp, long *valuep) /// @param[in] opt_flags OPT_LOCAL, OPT_GLOBAL or OPT_MODELINE. /// /// @return NULL on success, error message on error. -static const char *set_num_option(int opt_idx, void *varp, long value, char *errbuf, +static const char *set_num_option(int opt_idx, void *varp, OptInt value, char *errbuf, size_t errbuflen, int opt_flags) { OptInt old_value = *(OptInt *)varp; OptInt old_global_value = 0; // only used when setting a local and global option - long old_Rows = Rows; // remember old Rows + int old_Rows = Rows; // remember old Rows OptInt *pp = (OptInt *)varp; // Disallow changing some options from secure mode. @@ -3184,7 +3187,7 @@ static const char *set_num_option(int opt_idx, void *varp, long value, char *err return errmsg; } - *pp = (OptInt)value; + *pp = value; // Remember where the option was set. set_option_sctx_idx(opt_idx, opt_flags, current_sctx); @@ -3195,7 +3198,7 @@ static const char *set_num_option(int opt_idx, void *varp, long value, char *err .os_varp = varp, .os_flags = opt_flags, .os_oldval.number = old_value, - .os_newval.number = (OptInt)value, + .os_newval.number = value, .os_errbuf = NULL, .os_errbuflen = 0, .os_buf = curbuf, @@ -3215,7 +3218,7 @@ static const char *set_num_option(int opt_idx, void *varp, long value, char *err options[opt_idx].flags |= P_WAS_SET; apply_optionset_autocmd(opt_idx, opt_flags, old_value, old_global_value, - value, errmsg); + (int)value, errmsg); if (errmsg == NULL && options[opt_idx].flags & P_UI_OPTION) { ui_call_option_set(cstr_as_string(options[opt_idx].fullname), @@ -3786,7 +3789,7 @@ static const char *set_option(int opt_idx, void *varp, OptVal *v, int opt_flags, if (v->type == kOptValTypeBoolean) { errmsg = set_bool_option(opt_idx, varp, (int)v->data.boolean, opt_flags); } else if (v->type == kOptValTypeNumber) { - errmsg = set_num_option(opt_idx, varp, (long)v->data.number, errbuf, errbuflen, opt_flags); + errmsg = set_num_option(opt_idx, varp, v->data.number, errbuf, errbuflen, opt_flags); } else if (v->type == kOptValTypeString) { errmsg = set_string_option(opt_idx, varp, v->data.string.data, opt_flags, &value_checked, errbuf, errbuflen); @@ -5305,8 +5308,10 @@ void set_imsearch_global(buf_T *buf) } static int expand_option_idx = -1; +static int expand_option_start_col = 0; static char expand_option_name[5] = { 't', '_', NUL, NUL, NUL }; static int expand_option_flags = 0; +static bool expand_option_append = false; /// @param opt_flags OPT_GLOBAL and/or OPT_LOCAL void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags) @@ -5405,7 +5410,15 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags) } } // handle "-=" and "+=" + expand_option_append = false; + bool expand_option_subtract = false; if ((nextchar == '-' || nextchar == '+' || nextchar == '^') && p[1] == '=') { + if (nextchar == '-') { + expand_option_subtract = true; + } + if (nextchar == '+' || nextchar == '^') { + expand_option_append = true; + } p++; nextchar = '='; } @@ -5414,28 +5427,51 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags) xp->xp_context = EXPAND_UNSUCCESSFUL; return; } - if (p[1] == NUL) { - xp->xp_context = EXPAND_OLD_SETTING; - if (is_term_option) { - expand_option_idx = -1; - } else { - expand_option_idx = opt_idx; - } - xp->xp_pattern = p + 1; - return; - } - xp->xp_context = EXPAND_NOTHING; - if (is_term_option || (flags & P_NUM)) { - return; + + // Below are for handling expanding a specific option's value after the '=' or ':' + + if (is_term_option) { + expand_option_idx = -1; + } else { + expand_option_idx = opt_idx; } xp->xp_pattern = p + 1; + expand_option_start_col = (int)(p + 1 - xp->xp_line); + // Certain options currently have special case handling to reuse the + // expansion logic with other commands. if (options[opt_idx].var == &p_syn) { xp->xp_context = EXPAND_OWNSYNTAX; return; } + if (options[opt_idx].var == &p_ft) { + xp->xp_context = EXPAND_FILETYPE; + return; + } + // Now pick. If the option has a custom expander, use that. Otherwise, just + // fill with the existing option value. + if (expand_option_subtract) { + xp->xp_context = EXPAND_SETTING_SUBTRACT; + return; + } else if (expand_option_idx >= 0 + && options[expand_option_idx].opt_expand_cb != NULL) { + xp->xp_context = EXPAND_STRING_SETTING; + } else if (*xp->xp_pattern == NUL) { + xp->xp_context = EXPAND_OLD_SETTING; + return; + } else { + xp->xp_context = EXPAND_NOTHING; + } + + if (is_term_option || (flags & P_NUM)) { + return; + } + + // Only string options below + + // Options that have P_EXPAND are considered to all use file/dir expansion. if (flags & P_EXPAND) { p = options[opt_idx].var; if (p == (char *)&p_bdir @@ -5451,8 +5487,6 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags) } else { xp->xp_backslash = XP_BS_ONE; } - } else if (p == (char *)&p_ft) { - xp->xp_context = EXPAND_FILETYPE; } else { xp->xp_context = EXPAND_FILES; // for 'tags' need three backslashes for a space @@ -5464,27 +5498,45 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags) } } - // For an option that is a list of file names, find the start of the - // last file name. - for (p = arg + strlen(arg) - 1; p > xp->xp_pattern; p--) { - // count number of backslashes before ' ' or ',' - if (*p == ' ' || *p == ',') { - char *s = p; - while (s > xp->xp_pattern && *(s - 1) == '\\') { - s--; - } - if ((*p == ' ' && (xp->xp_backslash == XP_BS_THREE && (p - s) < 3)) - || (*p == ',' && (flags & P_COMMA) && ((p - s) & 1) == 0)) { - xp->xp_pattern = p + 1; - break; + // For an option that is a list of file names, or comma/colon-separated + // values, split it by the delimiter and find the start of the current + // pattern, while accounting for backslash-escaped space/commas/colons. + // Triple-backslashed escaped file names (e.g. 'path') can also be + // delimited by space. + if ((flags & P_EXPAND) || (flags & P_COMMA) || (flags & P_COLON)) { + for (p = arg + strlen(arg) - 1; p > xp->xp_pattern; p--) { + // count number of backslashes before ' ' or ',' + if (*p == ' ' || *p == ',' || (*p == ':' && (flags & P_COLON))) { + char *s = p; + while (s > xp->xp_pattern && *(s - 1) == '\\') { + s--; + } + if ((*p == ' ' && (xp->xp_backslash == XP_BS_THREE && (p - s) < 3)) + || (*p == ',' && (flags & P_COMMA) && ((p - s) % 1) == 0) + || (*p == ':' && (flags & P_COLON))) { + xp->xp_pattern = p + 1; + break; + } } } + } - // for 'spellsuggest' start at "file:" - if (options[opt_idx].var == &p_sps - && strncmp(p, "file:", 5) == 0) { - xp->xp_pattern = p + 5; - break; + // An option that is a list of single-character flags should always start + // at the end as we don't complete words. + if (flags & P_FLAGLIST) { + xp->xp_pattern = arg + strlen(arg); + } + + // Some options can either be using file/dir expansions, or custom value + // expansion depending on what the user typed. Unfortunately we have to + // manually handle it here to make sure we have the correct xp_context set. + // for 'spellsuggest' start at "file:" + if (options[opt_idx].var == &p_sps) { + if (strncmp(xp->xp_pattern, "file:", 5) == 0) { + xp->xp_pattern += 5; + return; + } else if (options[expand_option_idx].opt_expand_cb != NULL) { + xp->xp_context = EXPAND_STRING_SETTING; } } } @@ -5609,7 +5661,33 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, char *fuzzystr, int *numM return OK; } -void ExpandOldSetting(int *numMatches, char ***matches) +/// Escape an option value that can be used on the command-line with :set. +/// Caller needs to free the returned string, unless NULL is returned. +static char *escape_option_str_cmdline(char *var) +{ + // A backslash is required before some characters. This is the reverse of + // what happens in do_set(). + char *buf = vim_strsave_escaped(var, escape_chars); + +#ifdef BACKSLASH_IN_FILENAME + // For MS-Windows et al. we don't double backslashes at the start and + // before a file name character. + // The reverse is found at stropt_copy_value(). + for (var = buf; *var != NUL; MB_PTR_ADV(var)) { + if (var[0] == '\\' && var[1] == '\\' + && expand_option_idx >= 0 + && (options[expand_option_idx].flags & P_EXPAND) + && vim_isfilec((uint8_t)var[2]) + && (var[2] != '\\' || (var == buf && var[4] != '\\'))) { + STRMOVE(var, var + 1); + } + } +#endif + return buf; +} + +/// Expansion handler for :set= when we just want to fill in with the existing value. +int ExpandOldSetting(int *numMatches, char ***matches) { char *var = NULL; @@ -5629,26 +5707,149 @@ void ExpandOldSetting(int *numMatches, char ***matches) var = ""; } - // A backslash is required before some characters. This is the reverse of - // what happens in do_set(). - char *buf = vim_strsave_escaped(var, escape_chars); + char *buf = escape_option_str_cmdline(var); -#ifdef BACKSLASH_IN_FILENAME - // For MS-Windows et al. we don't double backslashes at the start and - // before a file name character. - for (var = buf; *var != NUL; MB_PTR_ADV(var)) { - if (var[0] == '\\' && var[1] == '\\' - && expand_option_idx >= 0 - && (options[expand_option_idx].flags & P_EXPAND) - && vim_isfilec((uint8_t)var[2]) - && (var[2] != '\\' || (var == buf && var[4] != '\\'))) { - STRMOVE(var, var + 1); + (*matches)[0] = buf; + *numMatches = 1; + return OK; +} + +/// Expansion handler for :set=/:set+= when the option has a custom expansion handler. +int ExpandStringSetting(expand_T *xp, regmatch_T *regmatch, int *numMatches, char ***matches) +{ + if (expand_option_idx < 0 + || options[expand_option_idx].opt_expand_cb == NULL) { + // Not supposed to reach this. This function is only for options with + // custom expansion callbacks. + return FAIL; + } + + optexpand_T args = { + .oe_varp = get_varp_scope(&options[expand_option_idx], expand_option_flags), + .oe_append = expand_option_append, + .oe_regmatch = regmatch, + .oe_xp = xp, + .oe_set_arg = xp->xp_line + expand_option_start_col, + }; + args.oe_include_orig_val = !expand_option_append && (*args.oe_set_arg == NUL); + + // Retrieve the existing value, but escape it as a reverse of setting it. + // We technically only need to do this when oe_append or + // oe_include_orig_val is true. + option_value2string(&options[expand_option_idx], expand_option_flags); + char *var = NameBuff; + char *buf = escape_option_str_cmdline(var); + args.oe_opt_value = buf; + + int num_ret = options[expand_option_idx].opt_expand_cb(&args, numMatches, matches); + + xfree(buf); + return num_ret; +} + +/// Expansion handler for :set-= +int ExpandSettingSubtract(expand_T *xp, regmatch_T *regmatch, int *numMatches, char ***matches) +{ + if (expand_option_idx < 0) { + // term option + return ExpandOldSetting(numMatches, matches); + } + + char *option_val = *(char **)get_option_varp_scope_from(expand_option_idx, + expand_option_flags, + curbuf, curwin); + + uint32_t option_flags = options[expand_option_idx].flags; + + if (option_flags & P_NUM) { + return ExpandOldSetting(numMatches, matches); + } else if (option_flags & P_COMMA) { + // Split the option by comma, then present each option to the user if + // it matches the pattern. + // This condition needs to go first, because 'whichwrap' has both + // P_COMMA and P_FLAGLIST. + + if (*option_val == NUL) { + return FAIL; } + + // Make a copy as we need to inject null characters destructively. + char *option_copy = xstrdup(option_val); + char *next_val = option_copy; + + garray_T ga; + ga_init(&ga, sizeof(char *), 10); + + do { + char *item = next_val; + char *comma = vim_strchr(next_val, ','); + while (comma != NULL && comma != next_val && *(comma - 1) == '\\') { + // "\," is interpreted as a literal comma rather than option + // separator when reading options in copy_option_part(). Skip + // it. + comma = vim_strchr(comma + 1, ','); + } + if (comma != NULL) { + *comma = NUL; // null-terminate this value, required by later functions + next_val = comma + 1; + } else { + next_val = NULL; + } + + if (*item == NUL) { + // empty value, don't add to list + continue; + } + + if (!vim_regexec(regmatch, item, (colnr_T)0)) { + continue; + } + + char *buf = escape_option_str_cmdline(item); + GA_APPEND(char *, &ga, buf); + } while (next_val != NULL); + + xfree(option_copy); + + *matches = ga.ga_data; + *numMatches = ga.ga_len; + return OK; + } else if (option_flags & P_FLAGLIST) { + // Only present the flags that are set on the option as the other flags + // are not meaningful to do set-= on. + + if (*xp->xp_pattern != NUL) { + // Don't suggest anything if cmdline is non-empty. Vim's set-= + // behavior requires consecutive strings and it's usually + // unintuitive to users if ther try to subtract multiple flags at + // once. + return FAIL; + } + + size_t num_flags = strlen(option_val); + if (num_flags == 0) { + return FAIL; + } + + *matches = xmalloc(sizeof(char *) * (num_flags + 1)); + + int count = 0; + + (*matches)[count++] = xstrdup(option_val); + + if (num_flags > 1) { + // If more than one flags, split the flags up and expose each + // character as individual choice. + for (char *flag = option_val; *flag != NUL; flag++) { + (*matches)[count++] = xstrnsave(flag, 1); + } + } + + *numMatches = count; + return OK; } -#endif - *matches[0] = buf; - *numMatches = 1; + return ExpandOldSetting(numMatches, matches); } /// Get the value for the numeric or string option///opp in a nice format into @@ -5772,6 +5973,7 @@ int fill_culopt_flags(char *val, win_T *wp) p = val; } while (*p != NUL) { + // Note: Keep this in sync with p_culopt_values. if (strncmp(p, "line", 4) == 0) { p += 4; culopt_flags_new |= CULOPT_LINE; diff --git a/src/nvim/option.h b/src/nvim/option.h index 9e3bf25bc3..593917407a 100644 --- a/src/nvim/option.h +++ b/src/nvim/option.h @@ -4,9 +4,11 @@ #include <stdint.h> #include "nvim/api/private/helpers.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" #include "nvim/option_defs.h" +#include "nvim/search.h" /// The options that are local to a window or buffer have "indir" set to one of /// these values. Special values: @@ -45,7 +47,15 @@ typedef struct vimoption { ///< local option: indirect option index ///< callback function to invoke after an option is modified to validate and ///< apply the new value. + + /// callback function to invoke after an option is modified to validate and + /// apply the new value. opt_did_set_cb_T opt_did_set_cb; + + /// callback function to invoke when expanding possible values on the + /// cmdline. Only useful for string options. + opt_expand_cb_T opt_expand_cb; + void *def_val; ///< default values for variable (neovim!!) LastSet last_set; ///< script in which the option was last set } vimoption_T; diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index f078f6073c..a11ed9188c 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -1,8 +1,12 @@ #ifndef NVIM_OPTION_DEFS_H #define NVIM_OPTION_DEFS_H +#include <stdbool.h> +#include <stddef.h> + #include "nvim/api/private/defs.h" -#include "nvim/eval/typval_defs.h" +#include "nvim/cmdexpand_defs.h" +#include "nvim/regexp_defs.h" #include "nvim/types.h" /// Option value type @@ -25,6 +29,14 @@ typedef struct { } data; } OptVal; +/// :set operator types +typedef enum { + OP_NONE = 0, + OP_ADDING, ///< "opt+=arg" + OP_PREPENDING, ///< "opt^=arg" + OP_REMOVING, ///< "opt-=arg" +} set_op_T; + /// Argument for the callback function (opt_did_set_cb_T) invoked after an /// option value is modified. typedef struct { @@ -33,6 +45,7 @@ typedef struct { void *os_varp; int os_idx; int os_flags; + set_op_T os_op; /// old value of the option (can be a string, number or a boolean) union { @@ -80,4 +93,40 @@ typedef struct { /// Otherwise returns an error message. typedef const char *(*opt_did_set_cb_T)(optset_T *args); +/// Argument for the callback function (opt_expand_cb_T) invoked after a string +/// option value is expanded for cmdline completion. +typedef struct { + /// Pointer to the option variable. It's always a string. + char *oe_varp; + /// The original option value, escaped. + char *oe_opt_value; + + /// true if using set+= instead of set= + bool oe_append; + /// true if we would like to add the original option value as the first choice. + bool oe_include_orig_val; + + /// Regex from the cmdline, for matching potential options against. + regmatch_T *oe_regmatch; + /// The expansion context. + expand_T *oe_xp; + + /// The full argument passed to :set. For example, if the user inputs + /// ":set dip=icase,algorithm:my<Tab>", oe_xp->xp_pattern will only have + /// "my", but oe_set_arg will contain the whole "icase,algorithm:my". + char *oe_set_arg; +} optexpand_T; + +/// Type for the callback function that is invoked when expanding possible +/// string option values during cmdline completion. +/// +/// Strings in returned matches will be managed and freed by caller. +/// +/// Returns OK if the expansion succeeded (numMatches and matches have to be +/// set). Otherwise returns FAIL. +/// +/// Note: If returned FAIL or *numMatches is 0, *matches will NOT be freed by +/// caller. +typedef int (*opt_expand_cb_T)(optexpand_T *args, int *numMatches, char ***matches); + #endif // NVIM_OPTION_DEFS_H diff --git a/src/nvim/option_vars.h b/src/nvim/option_vars.h index d8bbce21b3..86e7f4cee8 100644 --- a/src/nvim/option_vars.h +++ b/src/nvim/option_vars.h @@ -16,6 +16,7 @@ ///< the same. #define P_EXPAND 0x10U ///< environment expansion. NOTE: P_EXPAND can ///< never be used for local or hidden options +#define P_NO_DEF_EXP 0x20U ///< do not expand default value #define P_NODEFAULT 0x40U ///< don't set to default value #define P_DEF_ALLOCED 0x80U ///< default value is in allocated memory, must ///< use free() when assigning new value @@ -51,8 +52,10 @@ #define P_RWINONLY 0x10000000U ///< only redraw current window #define P_MLE 0x20000000U ///< under control of 'modelineexpr' #define P_FUNC 0x40000000U ///< accept a function reference or a lambda - -#define P_NO_DEF_EXP 0x80000000U ///< Do not expand default value. +#define P_COLON 0x80000000U ///< values use colons to create sublists +// Warning: Currently we have used all 32 bits for option flags, and adding more +// flags will overflow it. Adding another flag will need to change how +// it's stored first. #define HIGHLIGHT_INIT \ "8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@:NonText,d:Directory,e:ErrorMsg," \ @@ -183,7 +186,7 @@ #define CPO_VI "aAbBcCdDeEfFiIJKlLmMnoOpPqrRsStuvWxXyZ$!%+>;_" // characters for p_ww option: -#define WW_ALL "bshl<>[],~" +#define WW_ALL "bshl<>[]~" // characters for p_mouse option: #define MOUSE_NORMAL 'n' // use mouse in Normal mode @@ -757,9 +760,9 @@ extern char *p_vfile; ///< 'verbosefile' EXTERN int p_warn; ///< 'warn' EXTERN char *p_wop; ///< 'wildoptions' EXTERN unsigned wop_flags; -#define WOP_TAGFILE 0x01 -#define WOP_PUM 0x02 -#define WOP_FUZZY 0x04 +#define WOP_FUZZY 0x01 +#define WOP_TAGFILE 0x02 +#define WOP_PUM 0x04 EXTERN OptInt p_window; ///< 'window' EXTERN char *p_wak; ///< 'winaltkeys' EXTERN char *p_wig; ///< 'wildignore' diff --git a/src/nvim/options.lua b/src/nvim/options.lua index cd1d760836..a0b9306908 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -6,7 +6,7 @@ --- @field varname? string --- @field pv_name? string --- @field type 'bool'|'number'|'string' ---- @field list? 'comma'|'onecomma'|'flags'|'flagscomma' +--- @field list? 'comma'|'onecomma'|'commacolon'|'onecommacolon'|'flags'|'flagscomma' --- @field scope vim.option_scope[] --- @field deny_duplicates? boolean --- @field enable_if? string|false @@ -25,6 +25,7 @@ --- @field alloced? true --- @field redraw? vim.option_redraw[] --- @field cb? string +--- @field expand_cb? string --- @field tags? string[] --- @class vim.option_defaults @@ -192,6 +193,7 @@ return { set to one of CJK locales. See Unicode Standard Annex #11 (https://www.unicode.org/reports/tr11). ]=], + expand_cb = 'expand_set_ambiwidth', full_name = 'ambiwidth', redraw = { 'all_windows', 'ui_option' }, scope = { 'global' }, @@ -331,6 +333,7 @@ return { option, you must load syntax.vim again to see the result. This can be done with ":syntax on". ]=], + expand_cb = 'expand_set_background', full_name = 'background', scope = { 'global' }, short_desc = N_('"dark" or "light", used for highlight colors'), @@ -357,6 +360,7 @@ return { When the value is empty, Vi compatible backspacing is used, none of the ways mentioned for the items above are possible. ]=], + expand_cb = 'expand_set_backspace', full_name = 'backspace', list = 'onecomma', scope = { 'global' }, @@ -453,6 +457,7 @@ return { the system may refuse to do this. In that case the "auto" value will again not rename the file. ]=], + expand_cb = 'expand_set_backupcopy', full_name = 'backupcopy', list = 'onecomma', scope = { 'global', 'buffer' }, @@ -621,6 +626,7 @@ return { indicate that an error occurred. It can be silenced by adding the "error" keyword. ]=], + expand_cb = 'expand_set_belloff', full_name = 'belloff', list = 'comma', scope = { 'global' }, @@ -763,6 +769,7 @@ return { added for the 'showbreak' setting. (default: off) ]=], + expand_cb = 'expand_set_breakindentopt', full_name = 'breakindentopt', list = 'onecomma', redraw = { 'current_buffer' }, @@ -816,6 +823,7 @@ return { This option is used together with 'buftype' and 'swapfile' to specify special kinds of buffers. See |special-buffers|. ]=], + expand_cb = 'expand_set_bufhidden', full_name = 'bufhidden', noglob = true, scope = { 'buffer' }, @@ -893,6 +901,7 @@ return { without saving. For writing there must be matching |BufWriteCmd|, |FileWriteCmd| or |FileAppendCmd| autocommands. ]=], + expand_cb = 'expand_set_buftype', full_name = 'buftype', noglob = true, scope = { 'buffer' }, @@ -917,6 +926,7 @@ return { case mapping, the current locale is not effective. This probably only matters for Turkish. ]=], + expand_cb = 'expand_set_casemap', full_name = 'casemap', list = 'onecomma', scope = { 'global' }, @@ -1183,6 +1193,7 @@ return { "*". See |clipboard|. ]=], deny_duplicates = true, + expand_cb = 'expand_set_clipboard', full_name = 'clipboard', list = 'onecomma', scope = { 'global' }, @@ -1369,6 +1380,7 @@ return { based expansion (e.g., dictionary |i_CTRL-X_CTRL-K|, included patterns |i_CTRL-X_CTRL-I|, tags |i_CTRL-X_CTRL-]| and normal expansions). ]=], + expand_cb = 'expand_set_complete', full_name = 'complete', list = 'onecomma', scope = { 'buffer' }, @@ -1399,7 +1411,9 @@ return { Keep in mind that the cursor position is not always where it's displayed. E.g., when moving vertically it may change column. ]=], + expand_cb = 'expand_set_concealcursor', full_name = 'concealcursor', + list = 'flags', redraw = { 'current_window' }, scope = { 'window' }, short_desc = N_('whether concealable text is hidden in cursor line'), @@ -1492,6 +1506,7 @@ return { select one from the menu. Only works in combination with "menu" or "menuone". ]=], + expand_cb = 'expand_set_completeopt', full_name = 'completeopt', list = 'onecomma', scope = { 'global' }, @@ -1517,6 +1532,7 @@ return { command line completion the global value is used. ]=], enable_if = 'BACKSLASH_IN_FILENAME', + expand_cb = 'expand_set_completeslash', full_name = 'completeslash', scope = { 'buffer' }, type = 'string', @@ -1797,6 +1813,7 @@ return { _ When using |cw| on a word, do not include the whitespace following the word in the motion. ]=], + expand_cb = 'expand_set_cpoptions', full_name = 'cpoptions', list = 'flags', redraw = { 'all_windows' }, @@ -1878,6 +1895,7 @@ return { "line" and "screenline" cannot be used together. ]=], + expand_cb = 'expand_set_cursorlineopt', full_name = 'cursorlineopt', list = 'onecomma', redraw = { 'current_window_only' }, @@ -1900,6 +1918,7 @@ return { "msg" and "throw" are useful for debugging 'foldexpr', 'formatexpr' or 'indentexpr'. ]=], + expand_cb = 'expand_set_debug', full_name = 'debug', scope = { 'global' }, short_desc = N_('to "msg" to see all error messages'), @@ -2048,7 +2067,8 @@ return { When omitted a context of six lines is used. When using zero the context is actually one, since folds require a line in between, also - for a deleted line. + for a deleted line. Set it to a very large + value (999999) to disable folding completely. See |fold-diff|. iblank Ignore changes where lines are all blank. Adds @@ -2140,8 +2160,9 @@ return { :set diffopt-=internal " do NOT use the internal diff parser < ]=], + expand_cb = 'expand_set_diffopt', full_name = 'diffopt', - list = 'onecomma', + list = 'onecommacolon', redraw = { 'current_window' }, scope = { 'global' }, short_desc = N_('options for using diff mode'), @@ -2242,6 +2263,7 @@ return { The "@" character can be changed by setting the "lastline" item in 'fillchars'. The character is highlighted with |hl-NonText|. ]=], + expand_cb = 'expand_set_display', full_name = 'display', list = 'onecomma', redraw = { 'all_windows' }, @@ -2260,6 +2282,7 @@ return { hor horizontally, height of windows is not affected both width and height of windows is affected ]=], + expand_cb = 'expand_set_eadirection', full_name = 'eadirection', scope = { 'global' }, short_desc = N_("in which direction 'equalalways' works"), @@ -2470,6 +2493,7 @@ return { :set ei=WinEnter,WinLeave < ]=], + expand_cb = 'expand_set_eventignore', full_name = 'eventignore', list = 'onecomma', scope = { 'global' }, @@ -2558,6 +2582,7 @@ return { This option cannot be changed when 'modifiable' is off. ]=], + expand_cb = 'expand_set_encoding', full_name = 'fileencoding', no_mkrc = true, redraw = { 'statuslines', 'current_buffer' }, @@ -2619,6 +2644,7 @@ return { Setting this option does not have an effect until the next time a file is read. ]=], + expand_cb = 'expand_set_encoding', full_name = 'fileencodings', list = 'onecomma', scope = { 'global' }, @@ -2651,6 +2677,7 @@ return { option is set, because the file would be different when written. This option cannot be changed when 'modifiable' is off. ]=], + expand_cb = 'expand_set_fileformat', full_name = 'fileformat', no_mkrc = true, redraw = { 'curswant', 'statuslines' }, @@ -2714,6 +2741,7 @@ return { used. Also see |file-formats|. ]=], + expand_cb = 'expand_set_fileformat', full_name = 'fileformats', list = 'onecomma', scope = { 'global' }, @@ -2846,6 +2874,7 @@ return { eob EndOfBuffer |hl-EndOfBuffer| lastline NonText |hl-NonText| ]=], + expand_cb = 'expand_set_chars_option', full_name = 'fillchars', list = 'onecomma', redraw = { 'current_window' }, @@ -2884,6 +2913,7 @@ return { its level is higher than 'foldlevel'. Useful if you want folds to automatically close when moving out of them. ]=], + expand_cb = 'expand_set_foldclose', full_name = 'foldclose', list = 'onecomma', redraw = { 'current_window' }, @@ -2906,6 +2936,7 @@ return { "[1-9]": to display a fixed number of columns See |folding|. ]=], + expand_cb = 'expand_set_foldcolumn', full_name = 'foldcolumn', redraw = { 'current_window' }, scope = { 'window' }, @@ -3045,6 +3076,7 @@ return { |fold-syntax| syntax Syntax highlighting items specify folds. |fold-diff| diff Fold text that is not changed. ]=], + expand_cb = 'expand_set_foldmethod', full_name = 'foldmethod', redraw = { 'current_window' }, scope = { 'window' }, @@ -3122,6 +3154,7 @@ return { To close folds you can re-apply 'foldlevel' with the |zx| command or set the 'foldclose' option to "all". ]=], + expand_cb = 'expand_set_foldopen', full_name = 'foldopen', list = 'onecomma', redraw = { 'curswant' }, @@ -3218,6 +3251,7 @@ return { To avoid problems with flags that are added in the future, use the "+=" and "-=" feature of ":set" |add-option-flags|. ]=], + expand_cb = 'expand_set_formatoptions', full_name = 'formatoptions', list = 'flags', scope = { 'buffer' }, @@ -4050,6 +4084,7 @@ return { 'redrawtime') then 'inccommand' is automatically disabled until |Command-line-mode| is done. ]=], + expand_cb = 'expand_set_inccommand', full_name = 'inccommand', scope = { 'global' }, short_desc = N_('Live preview of substitution'), @@ -4451,6 +4486,7 @@ return { |alternate-file| or using |mark-motions| try to restore the |mark-view| in which the action occurred. ]=], + expand_cb = 'expand_set_jumpoptions', full_name = 'jumpoptions', list = 'onecomma', scope = { 'global' }, @@ -4495,6 +4531,7 @@ return { Special keys in this context are the cursor keys, <End>, <Home>, <PageUp> and <PageDown>. ]=], + expand_cb = 'expand_set_keymodel', full_name = 'keymodel', list = 'onecomma', scope = { 'global' }, @@ -4779,6 +4816,7 @@ return { Note that when using 'indentexpr' the `=` operator indents all the lines, otherwise the first line is not indented (Vi-compatible). ]=], + expand_cb = 'expand_set_lispoptions', full_name = 'lispoptions', list = 'onecomma', pv_name = 'p_lop', @@ -4933,6 +4971,7 @@ return { "precedes". |hl-Whitespace| for "nbsp", "space", "tab", "multispace", "lead" and "trail". ]=], + expand_cb = 'expand_set_chars_option', full_name = 'listchars', list = 'onecomma', redraw = { 'current_window' }, @@ -5015,6 +5054,7 @@ return { :set makeencoding=char " system locale is used < ]=], + expand_cb = 'expand_set_encoding', full_name = 'makeencoding', scope = { 'global', 'buffer' }, short_desc = N_('Converts the output of external commands'), @@ -5377,6 +5417,7 @@ return { 'mousehide' hide mouse pointer while typing text 'selectmode' whether to start Select mode or Visual mode ]=], + expand_cb = 'expand_set_mouse', full_name = 'mouse', list = 'flags', scope = { 'global' }, @@ -5468,6 +5509,7 @@ return { "g<LeftMouse>" is "<C-LeftMouse> (jump to tag under mouse click) "g<RightMouse>" is "<C-RightMouse> ("CTRL-T") ]=], + expand_cb = 'expand_set_mousemodel', full_name = 'mousemodel', scope = { 'global' }, short_desc = N_('changes meaning of mouse buttons'), @@ -5513,6 +5555,7 @@ return { < Will make Nvim scroll 5 lines at a time when scrolling vertically, and scroll 2 columns at a time when scrolling horizontally. ]=], + expand_cb = 'expand_set_mousescroll', full_name = 'mousescroll', list = 'comma', scope = { 'global' }, @@ -5645,6 +5688,7 @@ return { considered decimal. This also happens for numbers that are not recognized as octal or hex. ]=], + expand_cb = 'expand_set_nrformats', full_name = 'nrformats', list = 'onecomma', scope = { 'buffer' }, @@ -6307,6 +6351,7 @@ return { This is useful for languages such as Hebrew, Arabic and Farsi. The 'rightleft' option must be set for 'rightleftcmd' to take effect. ]=], + expand_cb = 'expand_set_rightleftcmd', full_name = 'rightleftcmd', redraw = { 'current_window' }, scope = { 'window' }, @@ -6634,6 +6679,7 @@ return { When 'diff' mode is active there always is vertical scroll binding, even when "ver" isn't there. ]=], + expand_cb = 'expand_set_scrollopt', full_name = 'scrollopt', list = 'onecomma', scope = { 'global' }, @@ -6687,6 +6733,7 @@ return { backwards, you cannot include the last character of a line, when starting in Normal mode and 'virtualedit' empty. ]=], + expand_cb = 'expand_set_selection', full_name = 'selection', scope = { 'global' }, short_desc = N_('what type of selection to use'), @@ -6707,6 +6754,7 @@ return { cmd when using "v", "V" or CTRL-V See |Select-mode|. ]=], + expand_cb = 'expand_set_selectmode', full_name = 'selectmode', list = 'onecomma', scope = { 'global' }, @@ -6758,6 +6806,7 @@ return { If you leave out "options" many things won't work well after restoring the session. ]=], + expand_cb = 'expand_set_sessionoptions', full_name = 'sessionoptions', list = 'onecomma', scope = { 'global' }, @@ -7292,6 +7341,7 @@ return { shm=a Abbreviation, but no loss of information. shm=at Abbreviation, and truncate message when necessary. ]=], + expand_cb = 'expand_set_shortmess', full_name = 'shortmess', list = 'flags', scope = { 'global' }, @@ -7368,6 +7418,7 @@ return { place the text. Without a custom 'statusline' or 'tabline' it will be displayed in a convenient location. ]=], + expand_cb = 'expand_set_showcmdloc', full_name = 'showcmdloc', scope = { 'global' }, short_desc = N_('change location of partial command'), @@ -7530,6 +7581,7 @@ return { This is done in order for the signcolumn appearance not appear weird during line deletion. ]=], + expand_cb = 'expand_set_signcolumn', full_name = 'signcolumn', redraw = { 'current_window' }, scope = { 'window' }, @@ -7828,6 +7880,7 @@ return { security reasons. ]=], expand = true, + expand_cb = 'expand_set_spellsuggest', full_name = 'spellsuggest', list = 'onecomma', scope = { 'global' }, @@ -7852,7 +7905,7 @@ return { designated regions of the buffer are spellchecked in this case. ]=], - expand = true, + expand_cb = 'expand_set_spelloptions', full_name = 'spelloptions', list = 'onecomma', redraw = { 'current_buffer' }, @@ -7892,6 +7945,7 @@ return { with the previous cursor position. For "screen", the text cannot always be kept on the same screen line when 'wrap' is enabled. ]=], + expand_cb = 'expand_set_splitkeep', full_name = 'splitkeep', scope = { 'global' }, short_desc = N_('determines scroll behavior for split windows'), @@ -8326,6 +8380,7 @@ return { uselast If included, jump to the previously used window when jumping to errors with |quickfix| commands. ]=], + expand_cb = 'expand_set_switchbuf', full_name = 'switchbuf', list = 'onecomma', scope = { 'global' }, @@ -8580,6 +8635,7 @@ return { match Match case smart Ignore case unless an upper case letter is used ]=], + expand_cb = 'expand_set_tagcase', full_name = 'tagcase', scope = { 'global', 'buffer' }, short_desc = N_('how to handle case when searching in tags files'), @@ -8728,6 +8784,7 @@ return { C1 Control characters 0x80...0x9F ]=], + expand_cb = 'expand_set_termpastefilter', full_name = 'termpastefilter', list = 'onecomma', scope = { 'global' }, @@ -9275,6 +9332,7 @@ return { slash |deprecated| Always enabled. Uses "/" in filenames. unix |deprecated| Always enabled. Uses "\n" line endings. ]=], + expand_cb = 'expand_set_sessionoptions', full_name = 'viewoptions', list = 'onecomma', scope = { 'global' }, @@ -9331,6 +9389,7 @@ return { not get a warning for it. When combined with other words, "none" is ignored. ]=], + expand_cb = 'expand_set_virtualedit', full_name = 'virtualedit', list = 'onecomma', redraw = { 'curswant' }, @@ -9395,6 +9454,7 @@ return { line (not an empty line) then it will not move to the next line. This makes "dl", "cl", "yl" etc. work normally. ]=], + expand_cb = 'expand_set_whichwrap', full_name = 'whichwrap', list = 'flagscomma', scope = { 'global' }, @@ -9578,8 +9638,9 @@ return { < Complete longest common string, then list alternatives. More info here: |cmdline-completion|. ]=], + expand_cb = 'expand_set_wildmode', full_name = 'wildmode', - list = 'onecomma', + list = 'onecommacolon', scope = { 'global' }, short_desc = N_("mode for 'wildchar' command-line expansion"), type = 'string', @@ -9609,6 +9670,7 @@ return { d #define f function ]=], + expand_cb = 'expand_set_wildoptions', full_name = 'wildoptions', list = 'onecomma', scope = { 'global' }, @@ -9637,6 +9699,7 @@ return { key is never used for the menu. This option is not used for <F10>; on Win32. ]=], + expand_cb = 'expand_set_winaltkeys', full_name = 'winaltkeys', scope = { 'global' }, short_desc = N_('when the windows system handles ALT keys'), @@ -9691,7 +9754,7 @@ return { { abbreviation = 'winhl', alloced = true, - cb = 'did_set_winhl', + cb = 'did_set_winhighlight', defaults = { if_true = '' }, deny_duplicates = true, desc = [=[ @@ -9713,8 +9776,9 @@ return { set winhighlight=Normal:MyNormal,NormalNC:MyNormalNC < ]=], + expand_cb = 'expand_set_winhighlight', full_name = 'winhighlight', - list = 'onecomma', + list = 'onecommacolon', redraw = { 'current_window' }, scope = { 'window' }, short_desc = N_('Setup window-local highlights'), diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 750941da07..6f41bba99b 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -11,6 +11,8 @@ #include "nvim/autocmd.h" #include "nvim/buffer_defs.h" #include "nvim/charset.h" +#include "nvim/cmdexpand.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/cursor.h" #include "nvim/cursor_shape.h" #include "nvim/diff.h" @@ -41,6 +43,7 @@ #include "nvim/optionstr.h" #include "nvim/os/os.h" #include "nvim/pos.h" +#include "nvim/regexp.h" #include "nvim/runtime.h" #include "nvim/spell.h" #include "nvim/spellfile.h" @@ -72,12 +75,25 @@ static char *(p_bkc_values[]) = { "yes", "auto", "no", "breaksymlink", "breakhar static char *(p_bo_values[]) = { "all", "backspace", "cursor", "complete", "copy", "ctrlg", "error", "esc", "ex", "hangul", "lang", "mess", "showmatch", "operator", "register", "shell", "spell", "wildmode", NULL }; +// Note: Keep this in sync with briopt_check() +static char *(p_briopt_values[]) = { "shift:", "min:", "sbr", "list:", "column:", NULL }; +// Note: Keep this in sync with diffopt_changed() +static char *(p_dip_values[]) = { "filler", "context:", "iblank", "icase", + "iwhite", "iwhiteall", "iwhiteeol", "horizontal", "vertical", + "closeoff", "hiddenoff", "foldcolumn:", "followwrap", "internal", + "indent-heuristic", "linematch:", "algorithm:", NULL }; +static char *(p_dip_algorithm_values[]) = { "myers", "minimal", "patience", "histogram", NULL }; static char *(p_nf_values[]) = { "bin", "octal", "hex", "alpha", "unsigned", NULL }; static char *(p_ff_values[]) = { FF_UNIX, FF_DOS, FF_MAC, NULL }; +static char *(p_cb_values[]) = { "unnamed", "unnamedplus", NULL }; static char *(p_cmp_values[]) = { "internal", "keepascii", NULL }; +// Note: Keep this in sync with fill_culopt_flags() +static char *(p_culopt_values[]) = { "line", "screenline", "number", "both", NULL }; static char *(p_dy_values[]) = { "lastline", "truncate", "uhex", "msgsep", NULL }; static char *(p_fdo_values[]) = { "all", "block", "hor", "mark", "percent", "quickfix", "search", "tag", "insert", "undo", "jump", NULL }; +// Note: Keep this in sync with spell_check_sps() +static char *(p_sps_values[]) = { "best", "fast", "double", "expr:", "file:", "timeout:", NULL }; /// Also used for 'viewoptions'! Keep in sync with SSOP_ flags. static char *(p_ssop_values[]) = { "buffers", "winpos", "resize", "winsize", "localoptions", "options", "help", "blank", "globals", "slash", "unix", "sesdir", @@ -89,7 +105,9 @@ static char *(p_swb_values[]) = { "useopen", "usetab", "split", "newtab", "vspli static char *(p_spk_values[]) = { "cursor", "screen", "topline", NULL }; static char *(p_tc_values[]) = { "followic", "ignore", "match", "followscs", "smart", NULL }; static char *(p_ve_values[]) = { "block", "insert", "all", "onemore", "none", "NONE", NULL }; -static char *(p_wop_values[]) = { "tagfile", "pum", "fuzzy", NULL }; +// Note: Keep this in sync with check_opt_wim() +static char *(p_wim_values[]) = { "full", "longest", "list", "lastused", NULL }; +static char *(p_wop_values[]) = { "fuzzy", "tagfile", "pum", NULL }; static char *(p_wak_values[]) = { "yes", "menu", "no", NULL }; static char *(p_mousem_values[]) = { "extend", "popup", "popup_setpos", "mac", NULL }; static char *(p_sel_values[]) = { "inclusive", "exclusive", "old", NULL }; @@ -118,7 +136,6 @@ static char *(p_scl_values[]) = { "yes", "no", "auto", "auto:1", "auto:2", "auto static char *(p_fdc_values[]) = { "auto", "auto:1", "auto:2", "auto:3", "auto:4", "auto:5", "auto:6", "auto:7", "auto:8", "auto:9", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL }; -static char *(p_cb_values[]) = { "unnamed", "unnamedplus", NULL }; static char *(p_spo_values[]) = { "camel", "noplainbuffer", NULL }; static char *(p_icm_values[]) = { "nosplit", "split", NULL }; static char *(p_jop_values[]) = { "stack", "view", NULL }; @@ -487,8 +504,9 @@ const char *set_string_option(const int opt_idx, void *varp_arg, const char *val secure = 1; } - const char *const errmsg = did_set_string_option(curbuf, curwin, opt_idx, varp, oldval, errbuf, - errbuflen, opt_flags, value_checked); + const char *const errmsg = did_set_string_option(curbuf, curwin, opt_idx, varp, oldval, + errbuf, errbuflen, + opt_flags, OP_NONE, value_checked); secure = secure_saved; @@ -659,6 +677,116 @@ static const char *did_set_option_listflag(char *val, char *flags, char *errbuf, return NULL; } +/// Expand an option that accepts a list of string values. +static int expand_set_opt_string(optexpand_T *args, char **values, size_t numValues, + int *numMatches, char ***matches) +{ + regmatch_T *regmatch = args->oe_regmatch; + bool include_orig_val = args->oe_include_orig_val; + char *option_val = args->oe_opt_value; + + // Assume numValues is small since they are fixed enums, so just allocate + // upfront instead of needing two passes to calculate output size. + *matches = xmalloc(sizeof(char *) * (numValues + 1)); + + int count = 0; + + if (include_orig_val && *option_val != NUL) { + (*matches)[count++] = xstrdup(option_val); + } + + for (char **val = values; *val != NULL; val++) { + if (include_orig_val && *option_val != NUL) { + if (strcmp(*val, option_val) == 0) { + continue; + } + } + if (vim_regexec(regmatch, *val, (colnr_T)0)) { + (*matches)[count++] = xstrdup(*val); + } + } + if (count == 0) { + XFREE_CLEAR(*matches); + return FAIL; + } + *numMatches = count; + return OK; +} + +static char *set_opt_callback_orig_option = NULL; +static char *((*set_opt_callback_func)(expand_T *, int)); + +/// Callback used by expand_set_opt_generic to also include the original value. +static char *expand_set_opt_callback(expand_T *xp, int idx) +{ + if (idx == 0) { + if (set_opt_callback_orig_option != NULL) { + return set_opt_callback_orig_option; + } else { + return ""; // empty strings are ignored + } + } + return set_opt_callback_func(xp, idx - 1); +} + +/// Expand an option with a callback that iterates through a list of possible names. +static int expand_set_opt_generic(optexpand_T *args, CompleteListItemGetter func, int *numMatches, + char ***matches) +{ + set_opt_callback_orig_option = args->oe_include_orig_val ? args->oe_opt_value : NULL; + set_opt_callback_func = func; + + // not using fuzzy as currently EXPAND_STRING_SETTING doesn't use it + ExpandGeneric("", args->oe_xp, args->oe_regmatch, matches, numMatches, + expand_set_opt_callback, false); + + set_opt_callback_orig_option = NULL; + set_opt_callback_func = NULL; + return OK; +} + +/// Expand an option which is a list of flags. +static int expand_set_opt_listflag(optexpand_T *args, char *flags, int *numMatches, char ***matches) +{ + char *option_val = args->oe_opt_value; + char *cmdline_val = args->oe_set_arg; + bool append = args->oe_append; + bool include_orig_val = args->oe_include_orig_val && (*option_val != NUL); + + size_t num_flags = strlen(flags); + + // Assume we only have small number of flags, so just allocate max size. + *matches = xmalloc(sizeof(char *) * (num_flags + 1)); + + int count = 0; + + if (include_orig_val) { + (*matches)[count++] = xstrdup(option_val); + } + + for (char *flag = flags; *flag != NUL; flag++) { + if (append && vim_strchr(option_val, *flag) != NULL) { + continue; + } + + if (vim_strchr(cmdline_val, *flag) == NULL) { + if (include_orig_val && option_val[1] == NUL && *flag == option_val[0]) { + // This value is already used as the first choice as it's the + // existing flag. Just skip it to avoid duplicate. + continue; + } + (*matches)[count++] = xstrnsave(flag, 1); + } + } + + if (count == 0) { + XFREE_CLEAR(*matches); + return FAIL; + } + *numMatches = count; + return OK; +} + /// The 'ambiwidth' option is changed. const char *did_set_ambiwidth(optset_T *args FUNC_ATTR_UNUSED) { @@ -668,6 +796,15 @@ const char *did_set_ambiwidth(optset_T *args FUNC_ATTR_UNUSED) return check_chars_options(); } +int expand_set_ambiwidth(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_ambw_values, + ARRAY_SIZE(p_ambw_values) - 1, + numMatches, + matches); +} + /// The 'background' option is changed. const char *did_set_background(optset_T *args FUNC_ATTR_UNUSED) { @@ -692,6 +829,15 @@ const char *did_set_background(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_background(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_bg_values, + ARRAY_SIZE(p_bg_values) - 1, + numMatches, + matches); +} + /// The 'backspace' option is changed. const char *did_set_backspace(optset_T *args FUNC_ATTR_UNUSED) { @@ -705,6 +851,15 @@ const char *did_set_backspace(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_backspace(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_bs_values, + ARRAY_SIZE(p_bs_values) - 1, + numMatches, + matches); +} + /// The 'backupcopy' option is changed. const char *did_set_backupcopy(optset_T *args) { @@ -739,6 +894,15 @@ const char *did_set_backupcopy(optset_T *args) return NULL; } +int expand_set_backupcopy(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_bkc_values, + ARRAY_SIZE(p_bkc_values) - 1, + numMatches, + matches); +} + /// The 'backupext' or the 'patchmode' option is changed. const char *did_set_backupext_or_patchmode(optset_T *args FUNC_ATTR_UNUSED) { @@ -756,6 +920,15 @@ const char *did_set_belloff(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_flags(p_bo, p_bo_values, &bo_flags, true); } +int expand_set_belloff(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_bo_values, + ARRAY_SIZE(p_bo_values) - 1, + numMatches, + matches); +} + /// The 'breakindentopt' option is changed. const char *did_set_breakindentopt(optset_T *args) { @@ -771,6 +944,15 @@ const char *did_set_breakindentopt(optset_T *args) return NULL; } +int expand_set_breakindentopt(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_briopt_values, + ARRAY_SIZE(p_briopt_values) - 1, + numMatches, + matches); +} + /// The 'bufhidden' option is changed. const char *did_set_bufhidden(optset_T *args) { @@ -778,6 +960,15 @@ const char *did_set_bufhidden(optset_T *args) return did_set_opt_strings(buf->b_p_bh, p_bufhidden_values, false); } +int expand_set_bufhidden(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_bufhidden_values, + ARRAY_SIZE(p_bufhidden_values) - 1, + numMatches, + matches); +} + /// The 'buftype' option is changed. const char *did_set_buftype(optset_T *args) { @@ -798,12 +989,30 @@ const char *did_set_buftype(optset_T *args) return NULL; } +int expand_set_buftype(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_buftype_values, + ARRAY_SIZE(p_buftype_values) - 1, + numMatches, + matches); +} + /// The 'casemap' option is changed. const char *did_set_casemap(optset_T *args FUNC_ATTR_UNUSED) { return did_set_opt_flags(p_cmp, p_cmp_values, &cmp_flags, true); } +int expand_set_casemap(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_cmp_values, + ARRAY_SIZE(p_cmp_values) - 1, + numMatches, + matches); +} + /// The global 'listchars' or 'fillchars' option is changed. static const char *did_set_global_listfillchars(win_T *win, char *val, bool opt_lcs, int opt_flags) { @@ -867,6 +1076,17 @@ const char *did_set_chars_option(optset_T *args) return errmsg; } +/// Expand 'fillchars' or 'listchars' option value. +int expand_set_chars_option(optexpand_T *args, int *numMatches, char ***matches) +{ + char **varp = (char **)args->oe_varp; + bool is_lcs = (varp == &p_lcs || varp == &curwin->w_p_lcs); + return expand_set_opt_generic(args, + is_lcs ? get_listchars_name : get_fillchars_name, + numMatches, + matches); +} + /// The 'cinoptions' option is changed. const char *did_set_cinoptions(optset_T *args FUNC_ATTR_UNUSED) { @@ -882,6 +1102,15 @@ const char *did_set_clipboard(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_flags(p_cb, p_cb_values, &cb_flags, true); } +int expand_set_clipboard(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_cb_values, + ARRAY_SIZE(p_cb_values) - 1, + numMatches, + matches); +} + /// The 'colorcolumn' option is changed. const char *did_set_colorcolumn(optset_T *args) { @@ -972,6 +1201,18 @@ const char *did_set_complete(optset_T *args) return NULL; } +int expand_set_complete(optexpand_T *args, int *numMatches, char ***matches) +{ + static char *(p_cpt_values[]) = { + ".", "w", "b", "u", "k", "kspell", "s", "i", "d", "]", "t", "U", NULL + }; + return expand_set_opt_string(args, + p_cpt_values, + ARRAY_SIZE(p_cpt_values) - 1, + numMatches, + matches); +} + /// The 'completeopt' option is changed. const char *did_set_completeopt(optset_T *args FUNC_ATTR_UNUSED) { @@ -982,6 +1223,15 @@ const char *did_set_completeopt(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_completeopt(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_cot_values, + ARRAY_SIZE(p_cot_values) - 1, + numMatches, + matches); +} + #ifdef BACKSLASH_IN_FILENAME /// The 'completeslash' option is changed. const char *did_set_completeslash(optset_T *args) @@ -993,6 +1243,15 @@ const char *did_set_completeslash(optset_T *args) } return NULL; } + +int expand_set_completeslash(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_csl_values, + ARRAY_SIZE(p_csl_values) - 1, + numMatches, + matches); +} #endif /// The 'concealcursor' option is changed. @@ -1003,6 +1262,11 @@ const char *did_set_concealcursor(optset_T *args) return did_set_option_listflag(*varp, COCU_ALL, args->os_errbuf, args->os_errbuflen); } +int expand_set_concealcursor(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_listflag(args, COCU_ALL, numMatches, matches); +} + /// The 'cpoptions' option is changed. const char *did_set_cpoptions(optset_T *args) { @@ -1011,12 +1275,18 @@ const char *did_set_cpoptions(optset_T *args) return did_set_option_listflag(*varp, CPO_VI, args->os_errbuf, args->os_errbuflen); } +int expand_set_cpoptions(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_listflag(args, CPO_VI, numMatches, matches); +} + /// The 'cursorlineopt' option is changed. const char *did_set_cursorlineopt(optset_T *args) { win_T *win = (win_T *)args->os_win; char **varp = (char **)args->os_varp; + // This could be changed to use opt_strings_flags() instead. if (**varp == NUL || fill_culopt_flags(*varp, win) != OK) { return e_invarg; } @@ -1024,12 +1294,30 @@ const char *did_set_cursorlineopt(optset_T *args) return NULL; } +int expand_set_cursorlineopt(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_culopt_values, + ARRAY_SIZE(p_culopt_values) - 1, + numMatches, + matches); +} + /// The 'debug' option is changed. const char *did_set_debug(optset_T *args FUNC_ATTR_UNUSED) { return did_set_opt_strings(p_debug, p_debug_values, false); } +int expand_set_debug(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_debug_values, + ARRAY_SIZE(p_debug_values) - 1, + numMatches, + matches); +} + /// The 'diffopt' option is changed. const char *did_set_diffopt(optset_T *args FUNC_ATTR_UNUSED) { @@ -1039,6 +1327,31 @@ const char *did_set_diffopt(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_diffopt(optexpand_T *args, int *numMatches, char ***matches) +{ + expand_T *xp = args->oe_xp; + + if (xp->xp_pattern > args->oe_set_arg && *(xp->xp_pattern - 1) == ':') { + // Within "algorithm:", we have a subgroup of possible options. + const size_t algo_len = strlen("algorithm:"); + if (xp->xp_pattern - args->oe_set_arg >= (int)algo_len + && strncmp(xp->xp_pattern - algo_len, "algorithm:", algo_len) == 0) { + return expand_set_opt_string(args, + p_dip_algorithm_values, + ARRAY_SIZE(p_dip_algorithm_values) - 1, + numMatches, + matches); + } + return FAIL; + } + + return expand_set_opt_string(args, + p_dip_values, + ARRAY_SIZE(p_dip_values) - 1, + numMatches, + matches); +} + /// The 'display' option is changed. const char *did_set_display(optset_T *args FUNC_ATTR_UNUSED) { @@ -1050,12 +1363,30 @@ const char *did_set_display(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_display(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_dy_values, + ARRAY_SIZE(p_dy_values) - 1, + numMatches, + matches); +} + /// The 'eadirection' option is changed. const char *did_set_eadirection(optset_T *args FUNC_ATTR_UNUSED) { return did_set_opt_strings(p_ead, p_ead_values, false); } +int expand_set_eadirection(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_ead_values, + ARRAY_SIZE(p_ead_values) - 1, + numMatches, + matches); +} + /// One of the 'encoding', 'fileencoding' or 'makeencoding' /// options is changed. const char *did_set_encoding(optset_T *args) @@ -1098,6 +1429,11 @@ const char *did_set_encoding(optset_T *args) return NULL; } +int expand_set_encoding(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_generic(args, get_encoding_name, numMatches, matches); +} + /// The 'eventignore' option is changed. const char *did_set_eventignore(optset_T *args FUNC_ATTR_UNUSED) { @@ -1107,6 +1443,21 @@ const char *did_set_eventignore(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +static char *get_eventignore_name(expand_T *xp, int idx) +{ + // 'eventignore' allows special keyword "all" in addition to + // all event names. + if (idx == 0) { + return "all"; + } + return get_event_name_no_group(xp, idx - 1); +} + +int expand_set_eventignore(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_generic(args, get_eventignore_name, numMatches, matches); +} + /// The 'fileformat' option is changed. const char *did_set_fileformat(optset_T *args) { @@ -1130,6 +1481,15 @@ const char *did_set_fileformat(optset_T *args) return NULL; } +int expand_set_fileformat(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_ff_values, + ARRAY_SIZE(p_ff_values) - 1, + numMatches, + matches); +} + /// The 'fileformats' option is changed. const char *did_set_fileformats(optset_T *args) { @@ -1160,6 +1520,15 @@ const char *did_set_foldclose(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_strings(p_fcl, p_fcl_values, true); } +int expand_set_foldclose(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_fcl_values, + ARRAY_SIZE(p_fcl_values) - 1, + numMatches, + matches); +} + /// The 'foldcolumn' option is changed. const char *did_set_foldcolumn(optset_T *args) { @@ -1170,6 +1539,15 @@ const char *did_set_foldcolumn(optset_T *args) return NULL; } +int expand_set_foldcolumn(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_fdc_values, + ARRAY_SIZE(p_fdc_values) - 1, + numMatches, + matches); +} + /// The 'foldexpr' option is changed. const char *did_set_foldexpr(optset_T *args) { @@ -1229,12 +1607,30 @@ const char *did_set_foldmethod(optset_T *args) return NULL; } +int expand_set_foldmethod(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_fdm_values, + ARRAY_SIZE(p_fdm_values) - 1, + numMatches, + matches); +} + /// The 'foldopen' option is changed. const char *did_set_foldopen(optset_T *args FUNC_ATTR_UNUSED) { return did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, true); } +int expand_set_foldopen(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_fdo_values, + ARRAY_SIZE(p_fdo_values) - 1, + numMatches, + matches); +} + /// The 'formatoptions' option is changed. const char *did_set_formatoptions(optset_T *args) { @@ -1243,6 +1639,11 @@ const char *did_set_formatoptions(optset_T *args) return did_set_option_listflag(*varp, FO_ALL, args->os_errbuf, args->os_errbuflen); } +int expand_set_formatoptions(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_listflag(args, FO_ALL, numMatches, matches); +} + /// The 'guicursor' option is changed. const char *did_set_guicursor(optset_T *args FUNC_ATTR_UNUSED) { @@ -1300,6 +1701,15 @@ const char *did_set_inccommand(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_strings(p_icm, p_icm_values, false); } +int expand_set_inccommand(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_icm_values, + ARRAY_SIZE(p_icm_values) - 1, + numMatches, + matches); +} + /// The 'isident' or the 'iskeyword' or the 'isprint' or the 'isfname' option is /// changed. const char *did_set_isopt(optset_T *args) @@ -1321,6 +1731,15 @@ const char *did_set_jumpoptions(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_flags(p_jop, p_jop_values, &jop_flags, true); } +int expand_set_jumpoptions(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_jop_values, + ARRAY_SIZE(p_jop_values) - 1, + numMatches, + matches); +} + /// The 'keymap' option has changed. const char *did_set_keymap(optset_T *args) { @@ -1384,6 +1803,15 @@ const char *did_set_keymodel(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_keymodel(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_km_values, + ARRAY_SIZE(p_km_values) - 1, + numMatches, + matches); +} + /// The 'lispoptions' option is changed. const char *did_set_lispoptions(optset_T *args) { @@ -1395,6 +1823,16 @@ const char *did_set_lispoptions(optset_T *args) return NULL; } +int expand_set_lispoptions(optexpand_T *args, int *numMatches, char ***matches) +{ + static char *(p_lop_values[]) = { "expr:0", "expr:1", NULL }; + return expand_set_opt_string(args, + p_lop_values, + ARRAY_SIZE(p_lop_values) - 1, + numMatches, + matches); +} + /// The 'matchpairs' option is changed. const char *did_set_matchpairs(optset_T *args) { @@ -1439,12 +1877,26 @@ const char *did_set_mouse(optset_T *args) return did_set_option_listflag(*varp, MOUSE_ALL, args->os_errbuf, args->os_errbuflen); } +int expand_set_mouse(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_listflag(args, MOUSE_ALL, numMatches, matches); +} + /// The 'mousemodel' option is changed. const char *did_set_mousemodel(optset_T *args FUNC_ATTR_UNUSED) { return did_set_opt_strings(p_mousem, p_mousem_values, false); } +int expand_set_mousemodel(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_mousem_values, + ARRAY_SIZE(p_mousem_values) - 1, + numMatches, + matches); +} + /// Handle setting 'mousescroll'. /// @return error message, NULL if it's OK. const char *did_set_mousescroll(optset_T *args FUNC_ATTR_UNUSED) @@ -1510,6 +1962,16 @@ const char *did_set_mousescroll(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_mousescroll(optexpand_T *args, int *numMatches, char ***matches) +{ + static char *(p_mousescroll_values[]) = { "hor:", "ver:", NULL }; + return expand_set_opt_string(args, + p_mousescroll_values, + ARRAY_SIZE(p_mousescroll_values) - 1, + numMatches, + matches); +} + /// The 'nrformats' option is changed. const char *did_set_nrformats(optset_T *args) { @@ -1518,6 +1980,15 @@ const char *did_set_nrformats(optset_T *args) return did_set_opt_strings(*varp, p_nf_values, true); } +int expand_set_nrformats(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_nf_values, + ARRAY_SIZE(p_nf_values) - 1, + numMatches, + matches); +} + /// One of the '*expr' options is changed:, 'diffexpr', 'foldexpr', 'foldtext', /// 'formatexpr', 'includeexpr', 'indentexpr', 'patchexpr' and 'charconvert'. const char *did_set_optexpr(optset_T *args) @@ -1553,6 +2024,16 @@ const char *did_set_rightleftcmd(optset_T *args) return NULL; } +int expand_set_rightleftcmd(optexpand_T *args, int *numMatches, char ***matches) +{ + static char *(p_rlc_values[]) = { "search", NULL }; + return expand_set_opt_string(args, + p_rlc_values, + ARRAY_SIZE(p_rlc_values) - 1, + numMatches, + matches); +} + /// The 'rulerformat' option is changed. const char *did_set_rulerformat(optset_T *args) { @@ -1565,6 +2046,15 @@ const char *did_set_scrollopt(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_strings(p_sbo, p_scbopt_values, true); } +int expand_set_scrollopt(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_scbopt_values, + ARRAY_SIZE(p_scbopt_values) - 1, + numMatches, + matches); +} + /// The 'selection' option is changed. const char *did_set_selection(optset_T *args FUNC_ATTR_UNUSED) { @@ -1574,12 +2064,30 @@ const char *did_set_selection(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_selection(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_sel_values, + ARRAY_SIZE(p_sel_values) - 1, + numMatches, + matches); +} + /// The 'selectmode' option is changed. const char *did_set_selectmode(optset_T *args FUNC_ATTR_UNUSED) { return did_set_opt_strings(p_slm, p_slm_values, true); } +int expand_set_selectmode(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_slm_values, + ARRAY_SIZE(p_slm_values) - 1, + numMatches, + matches); +} + /// The 'sessionoptions' option is changed. const char *did_set_sessionoptions(optset_T *args) { @@ -1595,6 +2103,15 @@ const char *did_set_sessionoptions(optset_T *args) return NULL; } +int expand_set_sessionoptions(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_ssop_values, + ARRAY_SIZE(p_ssop_values) - 1, + numMatches, + matches); +} + static const char *did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, char *errbuf, size_t errbuflen) { @@ -1661,6 +2178,11 @@ const char *did_set_shortmess(optset_T *args) return did_set_option_listflag(*varp, SHM_ALL, args->os_errbuf, args->os_errbuflen); } +int expand_set_shortmess(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_listflag(args, SHM_ALL, numMatches, matches); +} + /// The 'showbreak' option is changed. const char *did_set_showbreak(optset_T *args) { @@ -1681,6 +2203,15 @@ const char *did_set_showcmdloc(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_strings(p_sloc, p_sloc_values, true); } +int expand_set_showcmdloc(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_sloc_values, + ARRAY_SIZE(p_sloc_values) - 1, + numMatches, + matches); +} + /// The 'signcolumn' option is changed. const char *did_set_signcolumn(optset_T *args) { @@ -1700,6 +2231,15 @@ const char *did_set_signcolumn(optset_T *args) return NULL; } +int expand_set_signcolumn(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_scl_values, + ARRAY_SIZE(p_scl_values) - 1, + numMatches, + matches); +} + /// The 'spellcapcheck' option is changed. const char *did_set_spellcapcheck(optset_T *args) { @@ -1745,6 +2285,15 @@ const char *did_set_spelloptions(optset_T *args) return NULL; } +int expand_set_spelloptions(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_spo_values, + ARRAY_SIZE(p_spo_values) - 1, + numMatches, + matches); +} + /// The 'spellsuggest' option is changed. const char *did_set_spellsuggest(optset_T *args FUNC_ATTR_UNUSED) { @@ -1754,12 +2303,30 @@ const char *did_set_spellsuggest(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_spellsuggest(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_sps_values, + ARRAY_SIZE(p_sps_values) - 1, + numMatches, + matches); +} + /// The 'splitkeep' option is changed. const char *did_set_splitkeep(optset_T *args FUNC_ATTR_UNUSED) { return did_set_opt_strings(p_spk, p_spk_values, false); } +int expand_set_splitkeep(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_spk_values, + ARRAY_SIZE(p_spk_values) - 1, + numMatches, + matches); +} + /// The 'statuscolumn' option is changed. const char *did_set_statuscolumn(optset_T *args) { @@ -1817,6 +2384,15 @@ const char *did_set_switchbuf(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_flags(p_swb, p_swb_values, &swb_flags, true); } +int expand_set_switchbuf(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_swb_values, + ARRAY_SIZE(p_swb_values) - 1, + numMatches, + matches); +} + /// The 'tabline' option is changed. const char *did_set_tabline(optset_T *args) { @@ -1850,12 +2426,30 @@ const char *did_set_tagcase(optset_T *args) return NULL; } +int expand_set_tagcase(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_tc_values, + ARRAY_SIZE(p_tc_values) - 1, + numMatches, + matches); +} + /// The 'termpastefilter' option is changed. const char *did_set_termpastefilter(optset_T *args FUNC_ATTR_UNUSED) { return did_set_opt_flags(p_tpf, p_tpf_values, &tpf_flags, true); } +int expand_set_termpastefilter(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_tpf_values, + ARRAY_SIZE(p_tpf_values) - 1, + numMatches, + matches); +} + /// The 'titlestring' or the 'iconstring' option is changed. static const char *did_set_titleiconstring(optset_T *args, int flagval) { @@ -1988,12 +2582,28 @@ const char *did_set_virtualedit(optset_T *args) return NULL; } +int expand_set_virtualedit(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_ve_values, + ARRAY_SIZE(p_ve_values) - 1, + numMatches, + matches); +} + /// The 'whichwrap' option is changed. const char *did_set_whichwrap(optset_T *args) { char **varp = (char **)args->os_varp; - return did_set_option_listflag(*varp, WW_ALL, args->os_errbuf, args->os_errbuflen); + // Add ',' to the list flags because 'whichwrap' is a flag + // list that is comma-separated. + return did_set_option_listflag(*varp, WW_ALL ",", args->os_errbuf, args->os_errbuflen); +} + +int expand_set_whichwrap(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_listflag(args, WW_ALL, numMatches, matches); } /// The 'wildmode' option is changed. @@ -2005,12 +2615,30 @@ const char *did_set_wildmode(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_wildmode(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_wim_values, + ARRAY_SIZE(p_wim_values) - 1, + numMatches, + matches); +} + /// The 'wildoptions' option is changed. const char *did_set_wildoptions(optset_T *args FUNC_ATTR_UNUSED) { return did_set_opt_flags(p_wop, p_wop_values, &wop_flags, true); } +int expand_set_wildoptions(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_wop_values, + ARRAY_SIZE(p_wop_values) - 1, + numMatches, + matches); +} + /// The 'winaltkeys' option is changed. const char *did_set_winaltkeys(optset_T *args FUNC_ATTR_UNUSED) { @@ -2020,13 +2648,23 @@ const char *did_set_winaltkeys(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_winaltkeys(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_wak_values, + ARRAY_SIZE(p_wak_values) - 1, + numMatches, + matches); +} + /// The 'winbar' option is changed. const char *did_set_winbar(optset_T *args) { return did_set_statustabline_rulerformat(args, false, false); } -const char *did_set_winhl(optset_T *args) +/// The 'winhighlight' option is changed. +const char *did_set_winhighlight(optset_T *args) { win_T *win = (win_T *)args->os_win; if (!parse_winhl_opt(win)) { @@ -2035,6 +2673,11 @@ const char *did_set_winhl(optset_T *args) return NULL; } +int expand_set_winhighlight(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_generic(args, get_highlight_name, numMatches, matches); +} + // When 'syntax' is set, load the syntax of that name static void do_syntax_autocmd(buf_T *buf, bool value_changed) { @@ -2084,11 +2727,12 @@ static void do_spelllang_source(win_T *win) /// @param errbuf buffer for errors, or NULL /// @param errbuflen length of errors buffer /// @param opt_flags OPT_LOCAL and/or OPT_GLOBAL +/// @param op OP_ADDING/OP_PREPENDING/OP_REMOVING /// @param value_checked value was checked to be safe, no need to set P_INSECURE /// /// @return NULL for success, or an untranslated error message for an error const char *did_set_string_option(buf_T *buf, win_T *win, int opt_idx, char **varp, char *oldval, - char *errbuf, size_t errbuflen, int opt_flags, + char *errbuf, size_t errbuflen, int opt_flags, set_op_T op, bool *value_checked) { const char *errmsg = NULL; @@ -2102,6 +2746,7 @@ const char *did_set_string_option(buf_T *buf, win_T *win, int opt_idx, char **va .os_varp = varp, .os_idx = opt_idx, .os_flags = opt_flags, + .os_op = op, .os_oldval.string = oldval, .os_newval.string = *varp, .os_value_checked = false, @@ -2324,15 +2969,17 @@ static const struct chars_tab fcs_tab[] = { static lcs_chars_T lcs_chars; static const struct chars_tab lcs_tab[] = { - { &lcs_chars.eol, "eol", NUL, NUL }, - { &lcs_chars.ext, "extends", NUL, NUL }, - { &lcs_chars.nbsp, "nbsp", NUL, NUL }, - { &lcs_chars.prec, "precedes", NUL, NUL }, - { &lcs_chars.space, "space", NUL, NUL }, - { &lcs_chars.tab2, "tab", NUL, NUL }, - { &lcs_chars.lead, "lead", NUL, NUL }, - { &lcs_chars.trail, "trail", NUL, NUL }, - { &lcs_chars.conceal, "conceal", NUL, NUL }, + { &lcs_chars.eol, "eol", NUL, NUL }, + { &lcs_chars.ext, "extends", NUL, NUL }, + { &lcs_chars.nbsp, "nbsp", NUL, NUL }, + { &lcs_chars.prec, "precedes", NUL, NUL }, + { &lcs_chars.space, "space", NUL, NUL }, + { &lcs_chars.tab2, "tab", NUL, NUL }, + { &lcs_chars.lead, "lead", NUL, NUL }, + { &lcs_chars.trail, "trail", NUL, NUL }, + { &lcs_chars.conceal, "conceal", NUL, NUL }, + { NULL, "multispace", NUL, NUL }, + { NULL, "leadmultispace", NUL, NUL }, }; /// Handle setting 'listchars' or 'fillchars'. @@ -2403,54 +3050,13 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_ int i; for (i = 0; i < entries; i++) { const size_t len = strlen(tab[i].name); - if (strncmp(p, tab[i].name, len) == 0 - && p[len] == ':' - && p[len + 1] != NUL) { - const char *s = p + len + 1; - int c1 = get_encoded_char_adv(&s); - if (c1 == 0 || char2cells(c1) > 1) { - return e_invarg; - } - int c2 = 0, c3 = 0; - if (tab[i].cp == &lcs_chars.tab2) { - if (*s == NUL) { - return e_invarg; - } - c2 = get_encoded_char_adv(&s); - if (c2 == 0 || char2cells(c2) > 1) { - return e_invarg; - } - if (!(*s == ',' || *s == NUL)) { - c3 = get_encoded_char_adv(&s); - if (c3 == 0 || char2cells(c3) > 1) { - return e_invarg; - } - } - } - - if (*s == ',' || *s == NUL) { - if (round > 0) { - if (tab[i].cp == &lcs_chars.tab2) { - lcs_chars.tab1 = c1; - lcs_chars.tab2 = c2; - lcs_chars.tab3 = c3; - } else if (tab[i].cp != NULL) { - *(tab[i].cp) = c1; - } - } - p = s; - break; - } + if (!(strncmp(p, tab[i].name, len) == 0 + && p[len] == ':' + && p[len + 1] != NUL)) { + continue; } - } - if (i == entries) { - const size_t len = strlen("multispace"); - const size_t len2 = strlen("leadmultispace"); - if (is_listchars - && strncmp(p, "multispace", len) == 0 - && p[len] == ':' - && p[len + 1] != NUL) { + if (is_listchars && strcmp(tab[i].name, "multispace") == 0) { const char *s = p + len + 1; if (round == 0) { // Get length of lcs-multispace string in the first round @@ -2478,11 +3084,11 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_ } p = s; } - } else if (is_listchars - && strncmp(p, "leadmultispace", len2) == 0 - && p[len2] == ':' - && p[len2 + 1] != NUL) { - const char *s = p + len2 + 1; + break; + } + + if (is_listchars && strcmp(tab[i].name, "leadmultispace") == 0) { + const char *s = p + len + 1; if (round == 0) { // get length of lcs-leadmultispace string in first round last_lmultispace = p; @@ -2509,9 +3115,48 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_ } p = s; } - } else { + break; + } + + const char *s = p + len + 1; + int c1 = get_encoded_char_adv(&s); + if (c1 == 0 || char2cells(c1) > 1) { return e_invarg; } + int c2 = 0, c3 = 0; + if (tab[i].cp == &lcs_chars.tab2) { + if (*s == NUL) { + return e_invarg; + } + c2 = get_encoded_char_adv(&s); + if (c2 == 0 || char2cells(c2) > 1) { + return e_invarg; + } + if (!(*s == ',' || *s == NUL)) { + c3 = get_encoded_char_adv(&s); + if (c3 == 0 || char2cells(c3) > 1) { + return e_invarg; + } + } + } + + if (*s == ',' || *s == NUL) { + if (round > 0) { + if (tab[i].cp == &lcs_chars.tab2) { + lcs_chars.tab1 = c1; + lcs_chars.tab2 = c2; + lcs_chars.tab3 = c3; + } else if (tab[i].cp != NULL) { + *(tab[i].cp) = c1; + } + } + p = s; + break; + } + } + + if (i == entries) { + return e_invarg; } if (*p == ',') { @@ -2536,6 +3181,40 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_ return NULL; // no error } +/// Handle the new value of 'fillchars'. +const char *set_fillchars_option(win_T *wp, char *val, bool apply) +{ + return set_chars_option(wp, val, false, apply); +} + +/// Handle the new value of 'listchars'. +const char *set_listchars_option(win_T *wp, char *val, bool apply) +{ + return set_chars_option(wp, val, true, apply); +} + +/// Function given to ExpandGeneric() to obtain possible arguments of the +/// 'fillchars' option. +char *get_fillchars_name(expand_T *xp FUNC_ATTR_UNUSED, int idx) +{ + if (idx >= (int)ARRAY_SIZE(fcs_tab)) { + return NULL; + } + + return (char *)fcs_tab[idx].name; +} + +/// Function given to ExpandGeneric() to obtain possible arguments of the +/// 'listchars' option. +char *get_listchars_name(expand_T *xp FUNC_ATTR_UNUSED, int idx) +{ + if (idx >= (int)ARRAY_SIZE(lcs_tab)) { + return NULL; + } + + return (char *)lcs_tab[idx].name; +} + /// Check all global and local values of 'listchars' and 'fillchars'. /// May set different defaults in case character widths change. /// @@ -2558,15 +3237,3 @@ const char *check_chars_options(void) } return NULL; } - -/// Handle the new value of 'fillchars'. -const char *set_fillchars_option(win_T *wp, char *val, bool apply) -{ - return set_chars_option(wp, val, false, apply); -} - -/// Handle the new value of 'listchars'. -const char *set_listchars_option(win_T *wp, char *val, bool apply) -{ - return set_chars_option(wp, val, true, apply); -} diff --git a/src/nvim/optionstr.h b/src/nvim/optionstr.h index 3520cc2061..a481ed1d07 100644 --- a/src/nvim/optionstr.h +++ b/src/nvim/optionstr.h @@ -2,6 +2,7 @@ #define NVIM_OPTIONSTR_H #include "nvim/buffer_defs.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/option_defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c index b03509a313..7de7168d62 100644 --- a/src/nvim/os/env.c +++ b/src/nvim/os/env.c @@ -17,7 +17,6 @@ #include "nvim/charset.h" #include "nvim/cmdexpand.h" #include "nvim/eval.h" -#include "nvim/ex_cmds_defs.h" #include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/log.h" @@ -29,7 +28,6 @@ #include "nvim/os/os.h" #include "nvim/path.h" #include "nvim/strings.h" -#include "nvim/types.h" #include "nvim/version.h" #include "nvim/vim.h" diff --git a/src/nvim/os/fileio.c b/src/nvim/os/fileio.c index 846219f720..119a42f074 100644 --- a/src/nvim/os/fileio.c +++ b/src/nvim/os/fileio.c @@ -282,9 +282,10 @@ static char writebuf[kRWBufferSize]; /// /// @param[in,out] rv RBuffer instance used. /// @param[in,out] fp File to work with. -static void file_rb_write_full_cb(RBuffer *const rv, FileDescriptor *const fp) +static void file_rb_write_full_cb(RBuffer *const rv, void *const fp_in) FUNC_ATTR_NONNULL_ALL { + FileDescriptor *const fp = fp_in; assert(fp->wr); assert(rv->data == (void *)fp); if (rbuffer_size(rv) == 0) { diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 476ede2046..2712b874bb 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -63,8 +63,6 @@ #ifdef HAVE_XATTR static const char e_xattr_erange[] = N_("E1506: Buffer too small to copy xattr value or key"); -static const char e_xattr_enotsup[] - = N_("E1507: Extended attributes are not supported by the filesystem"); static const char e_xattr_e2big[] = N_("E1508: Size of the extended attribute value is larger than the maximum size allowed"); static const char e_xattr_other[] @@ -800,9 +798,9 @@ void os_copy_xattr(const char *from_file, const char *to_file) case E2BIG: errmsg = e_xattr_e2big; goto error_exit; - case ENOTSUP: - errmsg = e_xattr_enotsup; - goto error_exit; + case EACCES: + case EPERM: + break; case ERANGE: errmsg = e_xattr_erange; goto error_exit; diff --git a/src/nvim/os/lang.c b/src/nvim/os/lang.c index 652b851903..c3958cb3f2 100644 --- a/src/nvim/os/lang.c +++ b/src/nvim/os/lang.c @@ -5,6 +5,7 @@ # define Boolean CFBoolean // Avoid conflict with API's Boolean # define FileInfo CSFileInfo // Avoid conflict with API's Fileinfo # include <CoreServices/CoreServices.h> + # undef Boolean # undef FileInfo #endif @@ -17,6 +18,7 @@ #include "nvim/ascii.h" #include "nvim/buffer.h" #include "nvim/charset.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/eval.h" #include "nvim/ex_cmds_defs.h" #include "nvim/garray.h" @@ -30,7 +32,6 @@ #include "nvim/os/shell.h" #include "nvim/path.h" #include "nvim/profile.h" -#include "nvim/types.h" #include "nvim/vim.h" #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/os/lang.h b/src/nvim/os/lang.h index bb1ebfb721..ad64b38916 100644 --- a/src/nvim/os/lang.h +++ b/src/nvim/os/lang.h @@ -1,6 +1,7 @@ #ifndef NVIM_OS_LANG_H #define NVIM_OS_LANG_H +#include "nvim/cmdexpand_defs.h" #include "nvim/ex_cmds_defs.h" #include "nvim/types.h" diff --git a/src/nvim/os/os.h b/src/nvim/os/os.h index a7496130cc..006dfbfc04 100644 --- a/src/nvim/os/os.h +++ b/src/nvim/os/os.h @@ -4,9 +4,12 @@ #include <stdbool.h> #include <uv.h> +#include "nvim/buffer_defs.h" +#include "nvim/cmdexpand_defs.h" +#include "nvim/garray.h" #include "nvim/os/fs_defs.h" #include "nvim/os/stdpaths_defs.h" -#include "nvim/vim.h" +#include "nvim/types.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/env.h.generated.h" diff --git a/src/nvim/os/users.c b/src/nvim/os/users.c index 411ba91fa7..b23d2b7b13 100644 --- a/src/nvim/os/users.c +++ b/src/nvim/os/users.c @@ -10,10 +10,10 @@ #include "auto/config.h" #include "nvim/ascii.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/garray.h" #include "nvim/memory.h" #include "nvim/os/os.h" -#include "nvim/types.h" #include "nvim/vim.h" #ifdef HAVE_PWD_FUNCS # include <pwd.h> diff --git a/src/nvim/path.c b/src/nvim/path.c index 21f0543756..5d991ce719 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -648,11 +648,13 @@ static size_t do_path_expand(garray_T *gap, const char *path, size_t wildoff, in } s = p + 1; } else if (path_end >= path + wildoff +#ifdef MSWIN + && vim_strchr("*?[~", (uint8_t)(*path_end)) != NULL +#else && (vim_strchr("*?[{~$", (uint8_t)(*path_end)) != NULL -#ifndef MSWIN - || (!p_fic && (flags & EW_ICASE) && mb_isalpha(utf_ptr2char(path_end))) + || (!p_fic && (flags & EW_ICASE) && mb_isalpha(utf_ptr2char(path_end)))) #endif - )) { // NOLINT(whitespace/parens) + ) { // NOLINT(whitespace/parens) e = p; } len = (size_t)(utfc_ptr2len(path_end)); diff --git a/src/nvim/profile.c b/src/nvim/profile.c index 3162a446c0..73ad534de7 100644 --- a/src/nvim/profile.c +++ b/src/nvim/profile.c @@ -11,6 +11,7 @@ #include "nvim/ascii.h" #include "nvim/charset.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/debugger.h" #include "nvim/eval.h" #include "nvim/eval/typval_defs.h" @@ -30,7 +31,6 @@ #include "nvim/profile.h" #include "nvim/runtime.h" #include "nvim/types.h" -#include "nvim/vim.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "profile.c.generated.h" diff --git a/src/nvim/profile.h b/src/nvim/profile.h index 547d11185f..7450a0dfdc 100644 --- a/src/nvim/profile.h +++ b/src/nvim/profile.h @@ -4,6 +4,7 @@ #include <stdint.h> #include <time.h> +#include "nvim/cmdexpand_defs.h" #include "nvim/ex_cmds_defs.h" #include "nvim/runtime.h" diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index 12cf08636f..360088758d 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -20,6 +20,7 @@ #include "nvim/autocmd.h" #include "nvim/charset.h" #include "nvim/cmdexpand.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/debugger.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" diff --git a/src/nvim/runtime.h b/src/nvim/runtime.h index 7308ef5f75..8286a11f89 100644 --- a/src/nvim/runtime.h +++ b/src/nvim/runtime.h @@ -5,6 +5,7 @@ #include "klib/kvec.h" #include "nvim/autocmd.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" #include "nvim/ex_eval_defs.h" diff --git a/src/nvim/shada.c b/src/nvim/shada.c index 14d35d9b59..cd1d016c7b 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -1564,15 +1564,14 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, ShadaEntr break; } case kSDItemVariable: { - if (entry.data.global_var.value.v_type == VAR_TYPE_BLOB) { + if (entry.data.global_var.value.v_type == VAR_BLOB) { // Strings and Blobs both pack as msgpack BINs; differentiate them by // storing an additional VAR_TYPE_BLOB element alongside Blobs list_T *const list = tv_list_alloc(1); tv_list_append_number(list, VAR_TYPE_BLOB); entry.data.global_var.additional_elements = list; } - const size_t arr_size = 2 + (size_t)( - tv_list_len(entry.data.global_var.additional_elements)); + const size_t arr_size = 2 + (size_t)(tv_list_len(entry.data.global_var.additional_elements)); msgpack_pack_array(spacker, arr_size); const String varname = cstr_as_string(entry.data.global_var.name); PACK_BIN(varname); diff --git a/src/nvim/sign.c b/src/nvim/sign.c index 96af14bfc6..5d18ed393a 100644 --- a/src/nvim/sign.c +++ b/src/nvim/sign.c @@ -16,6 +16,7 @@ #include "nvim/buffer.h" #include "nvim/buffer_defs.h" #include "nvim/charset.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/cursor.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" diff --git a/src/nvim/sign.h b/src/nvim/sign.h index ba84cd71a4..89d765bf38 100644 --- a/src/nvim/sign.h +++ b/src/nvim/sign.h @@ -4,6 +4,7 @@ #include <stdbool.h> #include "nvim/buffer_defs.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/ex_cmds_defs.h" #include "nvim/sign_defs.h" diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index f1df2e56f3..25e08abb0e 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -452,24 +452,24 @@ struct wordnode_S { // Info used while reading the spell files. typedef struct spellinfo_S { wordnode_T *si_foldroot; // tree with case-folded words - long si_foldwcount; // nr of words in si_foldroot + int si_foldwcount; // nr of words in si_foldroot wordnode_T *si_keeproot; // tree with keep-case words - long si_keepwcount; // nr of words in si_keeproot + int si_keepwcount; // nr of words in si_keeproot wordnode_T *si_prefroot; // tree with postponed prefixes - long si_sugtree; // creating the soundfolding trie + int si_sugtree; // creating the soundfolding trie sblock_T *si_blocks; // memory blocks used - long si_blocks_cnt; // memory blocks allocated + int si_blocks_cnt; // memory blocks allocated int si_did_emsg; // true when ran out of memory - long si_compress_cnt; // words to add before lowering - // compression limit + int si_compress_cnt; // words to add before lowering + // compression limit wordnode_T *si_first_free; // List of nodes that have been freed during // compression, linked by "wn_child" field. - long si_free_count; // number of nodes in si_first_free + int si_free_count; // number of nodes in si_first_free #ifdef SPELL_PRINTTREE int si_wordnode_nr; // sequence nr for nodes #endif @@ -1874,24 +1874,24 @@ static void spell_reload_one(char *fname, bool added_word) // Tunable parameters for when the tree is compressed. Filled from the // 'mkspellmem' option. -static long compress_start = 30000; // memory / SBLOCKSIZE -static long compress_inc = 100; // memory / SBLOCKSIZE -static long compress_added = 500000; // word count +static int compress_start = 30000; // memory / SBLOCKSIZE +static int compress_inc = 100; // memory / SBLOCKSIZE +static int compress_added = 500000; // word count // Check the 'mkspellmem' option. Return FAIL if it's wrong. // Sets "sps_flags". int spell_check_msm(void) { char *p = p_msm; - long start = 0; - long incr = 0; - long added = 0; + int start = 0; + int incr = 0; + int added = 0; if (!ascii_isdigit(*p)) { return FAIL; } // block count = (value * 1024) / SBLOCKSIZE (but avoid overflow) - start = (getdigits_long(&p, true, 0) * 10) / (SBLOCKSIZE / 102); + start = (getdigits_int(&p, true, 0) * 10) / (SBLOCKSIZE / 102); if (*p != ',') { return FAIL; } @@ -1899,7 +1899,7 @@ int spell_check_msm(void) if (!ascii_isdigit(*p)) { return FAIL; } - incr = (getdigits_long(&p, true, 0) * 102) / (SBLOCKSIZE / 10); + incr = (getdigits_int(&p, true, 0) * 102) / (SBLOCKSIZE / 10); if (*p != ',') { return FAIL; } @@ -1907,7 +1907,7 @@ int spell_check_msm(void) if (!ascii_isdigit(*p)) { return FAIL; } - added = getdigits_long(&p, true, 0) * 1024; + added = getdigits_int(&p, true, 0) * 1024; if (*p != NUL) { return FAIL; } @@ -3177,7 +3177,7 @@ static int spell_read_dic(spellinfo_T *spin, char *fname, afffile_T *affile) if (os_time() > last_msg_time) { last_msg_time = os_time(); vim_snprintf(message, sizeof(message), - _("line %6d, word %6ld - %s"), + _("line %6d, word %6d - %s"), lnum, spin->si_foldwcount + spin->si_keepwcount, w); msg_start(); msg_outtrans_long(message, 0); @@ -3635,7 +3635,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char *afflist, afffile_ static int spell_read_wordfile(spellinfo_T *spin, char *fname) { FILE *fd; - long lnum = 0; + linenr_T lnum = 0; char rline[MAXLINELEN]; char *line; char *pc = NULL; @@ -3682,7 +3682,7 @@ static int spell_read_wordfile(spellinfo_T *spin, char *fname) if (spin->si_conv.vc_type != CONV_NONE) { pc = string_convert(&spin->si_conv, rline, NULL); if (pc == NULL) { - smsg(0, _("Conversion failure for word in %s line %ld: %s"), + smsg(0, _("Conversion failure for word in %s line %" PRIdLINENR ": %s"), fname, lnum, rline); continue; } @@ -3696,10 +3696,10 @@ static int spell_read_wordfile(spellinfo_T *spin, char *fname) line++; if (strncmp(line, "encoding=", 9) == 0) { if (spin->si_conv.vc_type != CONV_NONE) { - smsg(0, _("Duplicate /encoding= line ignored in %s line %ld: %s"), + smsg(0, _("Duplicate /encoding= line ignored in %s line %" PRIdLINENR ": %s"), fname, lnum, line - 1); } else if (did_word) { - smsg(0, _("/encoding= line after word ignored in %s line %ld: %s"), + smsg(0, _("/encoding= line after word ignored in %s line %" PRIdLINENR ": %s"), fname, lnum, line - 1); } else { char *enc; @@ -3720,12 +3720,12 @@ static int spell_read_wordfile(spellinfo_T *spin, char *fname) if (strncmp(line, "regions=", 8) == 0) { if (spin->si_region_count > 1) { - smsg(0, _("Duplicate /regions= line ignored in %s line %ld: %s"), + smsg(0, _("Duplicate /regions= line ignored in %s line %" PRIdLINENR ": %s"), fname, lnum, line); } else { line += 8; if (strlen(line) > MAXREGIONS * 2) { - smsg(0, _("Too many regions in %s line %ld: %s"), + smsg(0, _("Too many regions in %s line %" PRIdLINENR ": %s"), fname, lnum, line); } else { spin->si_region_count = (int)strlen(line) / 2; @@ -3738,7 +3738,7 @@ static int spell_read_wordfile(spellinfo_T *spin, char *fname) continue; } - smsg(0, _("/ line ignored in %s line %ld: %s"), + smsg(0, _("/ line ignored in %s line %" PRIdLINENR ": %s"), fname, lnum, line - 1); continue; } @@ -3765,13 +3765,13 @@ static int spell_read_wordfile(spellinfo_T *spin, char *fname) l = (uint8_t)(*p) - '0'; if (l == 0 || l > spin->si_region_count) { - smsg(0, _("Invalid region nr in %s line %ld: %s"), + smsg(0, _("Invalid region nr in %s line %" PRIdLINENR ": %s"), fname, lnum, p); break; } regionmask |= 1 << (l - 1); } else { - smsg(0, _("Unrecognized flags in %s line %ld: %s"), + smsg(0, _("Unrecognized flags in %s line %" PRIdLINENR ": %s"), fname, lnum, p); break; } @@ -4168,7 +4168,7 @@ static void wordtree_compress(spellinfo_T *spin, wordnode_T *root, const char *n FUNC_ATTR_NONNULL_ALL { hashtab_T ht; - long tot = 0; + int tot = 0; long perc; // Skip the root itself, it's not actually used. The first sibling is the @@ -4178,7 +4178,7 @@ static void wordtree_compress(spellinfo_T *spin, wordnode_T *root, const char *n } hash_init(&ht); - const long n = node_compress(spin, root->wn_sibling, &ht, &tot); + const int n = node_compress(spin, root->wn_sibling, &ht, &tot); #ifndef SPELL_PRINTTREE if (spin->si_verbose || p_verbose > 2) @@ -4192,7 +4192,7 @@ static void wordtree_compress(spellinfo_T *spin, wordnode_T *root, const char *n perc = (tot - n) * 100 / tot; } vim_snprintf(IObuff, IOSIZE, - _("Compressed %s of %ld nodes; %ld (%ld%%) remaining"), + _("Compressed %s of %d nodes; %d (%ld%%) remaining"), name, tot, tot - n, perc); spell_message(spin, IObuff); } @@ -4206,7 +4206,7 @@ static void wordtree_compress(spellinfo_T *spin, wordnode_T *root, const char *n /// Returns the number of compressed nodes. /// /// @param tot total count of nodes before compressing, incremented while going through the tree -static long node_compress(spellinfo_T *spin, wordnode_T *node, hashtab_T *ht, long *tot) +static int node_compress(spellinfo_T *spin, wordnode_T *node, hashtab_T *ht, int *tot) FUNC_ATTR_NONNULL_ALL { wordnode_T *np; @@ -4216,7 +4216,7 @@ static long node_compress(spellinfo_T *spin, wordnode_T *node, hashtab_T *ht, lo hashitem_T *hi; long len = 0; unsigned nr, n; - long compressed = 0; + int compressed = 0; // Go through the list of siblings. Compress each child and then try // finding an identical child to replace it. @@ -4262,7 +4262,7 @@ static long node_compress(spellinfo_T *spin, wordnode_T *node, hashtab_T *ht, lo } } } - *tot += len + 1; // add one for the node that stores the length + *tot += (int)len + 1; // add one for the node that stores the length // Make a hash key for the node and its siblings, so that we can quickly // find a lookalike node. This must be done after compressing the sibling @@ -5559,15 +5559,15 @@ void spell_add_word(char *word, int len, SpellAddType what, int idx, bool undo) } if (what == SPELL_ADD_BAD || undo) { - long fpos_next = 0; - long fpos = 0; + int fpos_next = 0; + int fpos = 0; // When the word appears as good word we need to remove that one, // since its flags sort before the one with WF_BANNED. fd = os_fopen(fname, "r"); if (fd != NULL) { while (!vim_fgets(line, MAXWLEN * 2, fd)) { fpos = fpos_next; - fpos_next = ftell(fd); + fpos_next = (int)ftell(fd); if (fpos_next < 0) { break; // should never happen } diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c index 2ee93b4934..7b92e69821 100644 --- a/src/nvim/spellsuggest.c +++ b/src/nvim/spellsuggest.c @@ -403,6 +403,7 @@ int spell_check_sps(void) if (*s != NUL && !ascii_isdigit(*s)) { f = -1; } + // Note: Keep this in sync with p_sps_values. } else if (strcmp(buf, "best") == 0) { f = SPS_BEST; } else if (strcmp(buf, "fast") == 0) { diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 9b238e6ff9..6bb841b1f8 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -15,6 +15,7 @@ #include "nvim/buffer.h" #include "nvim/buffer_defs.h" #include "nvim/charset.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/drawscreen.h" #include "nvim/eval.h" #include "nvim/eval/typval_defs.h" @@ -3554,7 +3555,7 @@ static void put_pattern(const char *const s, const int c, const synpat_T *const msg_putchar(','); // Separate with commas. } msg_puts(spo_name_tab[i]); - const long n = spp->sp_offsets[i]; + const int n = spp->sp_offsets[i]; if (i != SPO_LC_OFF) { if (spp->sp_off_flags & mask) { msg_putchar('s'); diff --git a/src/nvim/syntax.h b/src/nvim/syntax.h index 0a63392a04..c56624bc37 100644 --- a/src/nvim/syntax.h +++ b/src/nvim/syntax.h @@ -4,6 +4,7 @@ #include <stdbool.h> #include "nvim/buffer_defs.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/ex_cmds_defs.h" #include "nvim/globals.h" #include "nvim/macros.h" diff --git a/src/nvim/tag.c b/src/nvim/tag.c index 636d16d4e6..674d22ba44 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -56,7 +56,6 @@ #include "nvim/search.h" #include "nvim/strings.h" #include "nvim/tag.h" -#include "nvim/types.h" #include "nvim/ui.h" #include "nvim/vim.h" #include "nvim/window.h" diff --git a/src/nvim/textformat.c b/src/nvim/textformat.c index 0de62440f9..13e51b9a9e 100644 --- a/src/nvim/textformat.c +++ b/src/nvim/textformat.c @@ -822,7 +822,7 @@ void op_format(oparg_T *oap, bool keep_cursor) saved_cursor = oap->cursor_start; } - format_lines((linenr_T)oap->line_count, keep_cursor); + format_lines(oap->line_count, keep_cursor); // Leave the cursor at the first non-blank of the last formatted line. // If the cursor was moved one line back (e.g. with "Q}") go to the next diff --git a/src/nvim/types.h b/src/nvim/types.h index c2c815a0bc..7b23fe419b 100644 --- a/src/nvim/types.h +++ b/src/nvim/types.h @@ -31,8 +31,6 @@ typedef union { typedef handle_T NS; -typedef struct expand expand_T; - typedef uint64_t proftime_T; typedef enum { diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 5396bfcda2..758ee036b4 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -260,10 +260,10 @@ int u_save_buf(buf_T *buf, linenr_T top, linenr_T bot) } if (top + 2 == bot) { - u_saveline(buf, (linenr_T)(top + 1)); + u_saveline(buf, top + 1); } - return u_savecommon(buf, top, bot, (linenr_T)0, false); + return u_savecommon(buf, top, bot, 0, false); } /// Save the line "lnum" (used by ":s" and "~" command). @@ -289,9 +289,9 @@ int u_inssub(linenr_T lnum) /// becomes empty. /// Careful: may trigger autocommands that reload the buffer. /// Returns FAIL when lines could not be saved, OK otherwise. -int u_savedel(linenr_T lnum, long nlines) +int u_savedel(linenr_T lnum, linenr_T nlines) { - return u_savecommon(curbuf, lnum - 1, lnum + (linenr_T)nlines, + return u_savecommon(curbuf, lnum - 1, lnum + nlines, nlines == curbuf->b_ml.ml_line_count ? 2 : lnum, false); } @@ -378,7 +378,7 @@ int u_savecommon(buf_T *buf, linenr_T top, linenr_T bot, linenr_T newbot, int re u_entry_T *uep; u_entry_T *prev_uep; - long size = bot - top - 1; + linenr_T size = bot - top - 1; // If curbuf->b_u_synced == true make a new header. if (buf->b_u_synced) { @@ -1488,7 +1488,7 @@ void u_read_undo(char *name, const uint8_t *hash, const char *orig_name FUNC_ATT time_t seq_time = undo_read_time(&bi); // Optional header fields. - long last_save_nr = 0; + int last_save_nr = 0; while (true) { int len = undo_read_byte(&bi); @@ -1519,7 +1519,7 @@ void u_read_undo(char *name, const uint8_t *hash, const char *orig_name FUNC_ATT } } - long num_read_uhps = 0; + int num_read_uhps = 0; int c; while ((c = undo_read_2c(&bi)) == UF_HEADER_MAGIC) { @@ -1655,7 +1655,7 @@ void u_read_undo(char *name, const uint8_t *hash, const char *orig_name FUNC_ATT error: xfree(line_ptr); if (uhp_table != NULL) { - for (long i = 0; i < num_read_uhps; i++) { + for (int i = 0; i < num_read_uhps; i++) { if (uhp_table[i] != NULL) { u_free_uhp(uhp_table[i]); } @@ -1920,7 +1920,7 @@ static void u_doit(int startcount, bool quiet, bool do_buf_event) // When "file" is true use "step" as a number of file writes. // When "absolute" is true use "step" as the sequence number to jump to. // "sec" must be false then. -void undo_time(long step, bool sec, bool file, bool absolute) +void undo_time(int step, bool sec, bool file, bool absolute) { if (text_locked()) { text_locked_msg(); @@ -1938,8 +1938,8 @@ void undo_time(long step, bool sec, bool file, bool absolute) u_oldcount = -1; } - long target; - long closest; + int target; + int closest; u_header_T *uhp = NULL; bool dosec = sec; bool dofile = file; @@ -1953,7 +1953,7 @@ void undo_time(long step, bool sec, bool file, bool absolute) closest = -1; } else { if (dosec) { - target = (long)(curbuf->b_u_time_cur) + step; + target = (int)curbuf->b_u_time_cur + step; } else if (dofile) { if (step < 0) { // Going back to a previous write. If there were changes after @@ -1998,7 +1998,7 @@ void undo_time(long step, bool sec, bool file, bool absolute) closest = -1; } else { if (dosec) { - closest = (long)(os_time() + 1); + closest = (int)(os_time() + 1); } else if (dofile) { closest = curbuf->b_u_save_nr_last + 2; } else { @@ -2010,7 +2010,7 @@ void undo_time(long step, bool sec, bool file, bool absolute) } } long closest_start = closest; - long closest_seq = curbuf->b_u_seq_cur; + int closest_seq = curbuf->b_u_seq_cur; int mark; int nomark = 0; // shut up compiler @@ -2042,8 +2042,8 @@ void undo_time(long step, bool sec, bool file, bool absolute) while (uhp != NULL) { uhp->uh_walk = mark; - long val = dosec ? (long)(uhp->uh_time) : - dofile ? uhp->uh_save_nr + int val = dosec ? (int)(uhp->uh_time) : + dofile ? uhp->uh_save_nr : uhp->uh_seq; if (round == 1 && !(dofile && val == 0)) { @@ -2298,7 +2298,7 @@ static void u_undoredo(int undo, bool do_buf_event) } linenr_T oldsize = bot - top - 1; // number of lines before undo - linenr_T newsize = (linenr_T)uep->ue_size; // number of lines after undo + linenr_T newsize = uep->ue_size; // number of lines after undo if (top < newlnum) { // If the saved cursor is somewhere in this undo block, move it to @@ -2676,13 +2676,13 @@ void ex_undolist(exarg_T *eap) while (uhp != NULL) { if (uhp->uh_prev.ptr == NULL && uhp->uh_walk != nomark && uhp->uh_walk != mark) { - vim_snprintf(IObuff, IOSIZE, "%6ld %7d ", uhp->uh_seq, changes); + vim_snprintf(IObuff, IOSIZE, "%6d %7d ", uhp->uh_seq, changes); undo_fmt_time(IObuff + strlen(IObuff), IOSIZE - strlen(IObuff), uhp->uh_time); if (uhp->uh_save_nr > 0) { while (strlen(IObuff) < 33) { xstrlcat(IObuff, " ", IOSIZE); } - vim_snprintf_add(IObuff, IOSIZE, " %3ld", uhp->uh_save_nr); + vim_snprintf_add(IObuff, IOSIZE, " %3d", uhp->uh_save_nr); } GA_APPEND(char *, &ga, xstrdup(IObuff)); } @@ -2850,7 +2850,7 @@ static void u_getbot(buf_T *buf) // inserted (0 - deleted) since calling u_save. This is equal to the // old line count subtracted from the current line count. linenr_T extra = buf->b_ml.ml_line_count - uep->ue_lcount; - uep->ue_bot = uep->ue_top + (linenr_T)uep->ue_size + 1 + extra; + uep->ue_bot = uep->ue_top + uep->ue_size + 1 + extra; if (uep->ue_bot < 1 || uep->ue_bot > buf->b_ml.ml_line_count) { iemsg(_(e_undo_line_missing)); uep->ue_bot = uep->ue_top + 1; // assume all lines deleted, will diff --git a/src/nvim/undo_defs.h b/src/nvim/undo_defs.h index 9cc2e4a52b..aa7d6e3355 100644 --- a/src/nvim/undo_defs.h +++ b/src/nvim/undo_defs.h @@ -26,7 +26,7 @@ struct u_entry { linenr_T ue_bot; // number of line below undo block linenr_T ue_lcount; // linecount when u_save called char **ue_array; // array of lines in undo block - long ue_size; // number of lines in ue_array + linenr_T ue_size; // number of lines in ue_array #ifdef U_DEBUG int ue_magic; // magic number to check allocation #endif @@ -51,19 +51,19 @@ struct u_header { u_header_T *ptr; // pointer to previous header for alt. redo long seq; } uh_alt_prev; - long uh_seq; // sequence number, higher == newer undo + int uh_seq; // sequence number, higher == newer undo int uh_walk; // used by undo_time() - u_entry_T *uh_entry; // pointer to first entry + u_entry_T *uh_entry; // pointer to first entry u_entry_T *uh_getbot_entry; // pointer to where ue_bot must be set pos_T uh_cursor; // cursor position before saving colnr_T uh_cursor_vcol; - int uh_flags; // see below - fmark_T uh_namedm[NMARKS]; // marks before undo/after redo + int uh_flags; // see below + fmark_T uh_namedm[NMARKS]; // marks before undo/after redo extmark_undo_vec_t uh_extmark; // info to move extmarks - visualinfo_T uh_visual; // Visual areas before undo/after redo - time_t uh_time; // timestamp when the change was made - long uh_save_nr; // set when the file was saved after the - // changes in this block + visualinfo_T uh_visual; // Visual areas before undo/after redo + time_t uh_time; // timestamp when the change was made + int uh_save_nr; // set when the file was saved after the + // changes in this block #ifdef U_DEBUG int uh_magic; // magic number to check allocation #endif diff --git a/src/nvim/usercmd.c b/src/nvim/usercmd.c index 131b1ce3ef..4bab3f52cd 100644 --- a/src/nvim/usercmd.c +++ b/src/nvim/usercmd.c @@ -16,6 +16,7 @@ #include "nvim/ascii.h" #include "nvim/buffer_defs.h" #include "nvim/charset.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/eval.h" #include "nvim/ex_docmd.h" #include "nvim/garray.h" diff --git a/src/nvim/usercmd.h b/src/nvim/usercmd.h index 0d9838abf2..34f1439b10 100644 --- a/src/nvim/usercmd.h +++ b/src/nvim/usercmd.h @@ -3,6 +3,7 @@ #include <stdint.h> +#include "nvim/cmdexpand_defs.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" #include "nvim/garray.h" diff --git a/src/nvim/vim.h b/src/nvim/vim.h index fc1f15b285..22db3751cd 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -96,83 +96,10 @@ typedef enum { #define FAIL 0 #define NOTDONE 2 // not OK or FAIL but skipped -// Type values for type(). -#define VAR_TYPE_NUMBER 0 -#define VAR_TYPE_STRING 1 -#define VAR_TYPE_FUNC 2 -#define VAR_TYPE_LIST 3 -#define VAR_TYPE_DICT 4 -#define VAR_TYPE_FLOAT 5 -#define VAR_TYPE_BOOL 6 -#define VAR_TYPE_SPECIAL 7 -#define VAR_TYPE_BLOB 10 - -// values for xp_context when doing command line completion - -enum { - EXPAND_UNSUCCESSFUL = -2, - EXPAND_OK = -1, - EXPAND_NOTHING = 0, - EXPAND_COMMANDS, - EXPAND_FILES, - EXPAND_DIRECTORIES, - EXPAND_SETTINGS, - EXPAND_BOOL_SETTINGS, - EXPAND_TAGS, - EXPAND_OLD_SETTING, - EXPAND_HELP, - EXPAND_BUFFERS, - EXPAND_EVENTS, - EXPAND_MENUS, - EXPAND_SYNTAX, - EXPAND_HIGHLIGHT, - EXPAND_AUGROUP, - EXPAND_USER_VARS, - EXPAND_MAPPINGS, - EXPAND_TAGS_LISTFILES, - EXPAND_FUNCTIONS, - EXPAND_USER_FUNC, - EXPAND_EXPRESSION, - EXPAND_MENUNAMES, - EXPAND_USER_COMMANDS, - EXPAND_USER_CMD_FLAGS, - EXPAND_USER_NARGS, - EXPAND_USER_COMPLETE, - EXPAND_ENV_VARS, - EXPAND_LANGUAGE, - EXPAND_COLORS, - EXPAND_COMPILER, - EXPAND_USER_DEFINED, - EXPAND_USER_LIST, - EXPAND_USER_LUA, - EXPAND_SHELLCMD, - EXPAND_SIGN, - EXPAND_PROFILE, - EXPAND_FILETYPE, - EXPAND_FILES_IN_PATH, - EXPAND_OWNSYNTAX, - EXPAND_LOCALES, - EXPAND_HISTORY, - EXPAND_USER, - EXPAND_SYNTIME, - EXPAND_USER_ADDR_TYPE, - EXPAND_PACKADD, - EXPAND_MESSAGES, - EXPAND_MAPCLEAR, - EXPAND_ARGLIST, - EXPAND_DIFF_BUFFERS, - EXPAND_BREAKPOINT, - EXPAND_SCRIPTNAMES, - EXPAND_RUNTIME, - EXPAND_CHECKHEALTH, - EXPAND_LUA, -}; - // Minimal size for block 0 of a swap file. // NOTE: This depends on size of struct block0! It's not done with a sizeof(), // because struct block0 is defined in memline.c (Sorry). // The maximal block size is arbitrary. - #define MIN_SWAP_PAGE_SIZE 1048 #define MAX_SWAP_PAGE_SIZE 50000 |