Merge #11929 from janlazo/vim-8.1.1510

vim-patch:8.0.1587,8.1.{253,881,883,885,896,939,1107,1108,1466,1489,1510,1552,1642,1793},8.2.{108,133,135}
This commit is contained in:
Justin M. Keyes 2020-03-01 23:23:50 -08:00 committed by GitHub
commit 0110735547
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 1162 additions and 466 deletions

View File

@ -2110,6 +2110,7 @@ extend({expr1}, {expr2} [, {expr3}])
exp({expr}) Float exponential of {expr}
expand({expr} [, {nosuf} [, {list}]])
any expand special keywords in {expr}
expandcmd({expr}) String expand {expr} like with `:edit`
feedkeys({string} [, {mode}]) Number add key sequence to typeahead buffer
filereadable({file}) Number |TRUE| if {file} is a readable file
filewritable({file}) Number |TRUE| if {file} is a writable file
@ -3733,6 +3734,14 @@ expand({expr} [, {nosuf} [, {list}]]) *expand()*
See |glob()| for finding existing files. See |system()| for
getting the raw output of an external command.
expandcmd({expr}) *expandcmd()*
Expand special items in {expr} like what is done for an Ex
command such as `:edit`. This expands special keywords, like
with |expand()|, and environment variables, anywhere in
{expr}. Returns the expanded string.
Example: >
:echo expandcmd('make %<.o')
<
extend({expr1}, {expr2} [, {expr3}]) *extend()*
{expr1} and {expr2} must be both |Lists| or both
|Dictionaries|.
@ -7809,7 +7818,7 @@ sign_getplaced([{expr} [, {dict}]]) *sign_getplaced()*
priority sign priority
The returned signs in a buffer are ordered by their line
number.
number and priority.
Returns an empty list on failure or if there are no placed
signs.

View File

@ -176,9 +176,9 @@ See |sign_place()| for the equivalent Vim script function.
By default, the sign is assigned a default priority of 10. To
assign a different priority value, use "priority={prio}" to
specify a value. The priority is used to determine the
highlight group used when multiple signs are placed on the
same line.
specify a value. The priority is used to determine the sign
that is displayed when multiple signs are placed on the same
line.
Examples: >
:sign place 5 line=3 name=sign1 file=a.py
@ -198,7 +198,9 @@ See |sign_place()| for the equivalent Vim script function.
it (e.g., when the debugger has stopped at a breakpoint).
The optional "group={group}" attribute can be used before
"file=" to select a sign in a particular group.
"file=" to select a sign in a particular group. The optional
"priority={prio}" attribute can be used to change the priority
of an existing sign.
:sign place {id} name={name} [buffer={nr}]
Same, but use buffer {nr}. If the buffer argument is not

View File

@ -184,12 +184,17 @@ argument.
the 'modifiable' and 'write' options can be set to enable
changes and writing.
*-Z* *restricted-mode* *E145*
*-Z* *restricted-mode* *E145* *E981*
-Z Restricted mode. All commands that make use of an external
shell are disabled. This includes suspending with CTRL-Z,
":sh", filtering, the system() function, backtick expansion,
delete(), rename(), mkdir(), writefile(), libcall(),
jobstart(), etc.
":sh", filtering, the system() function, backtick expansion
and libcall().
Also disallowed are delete(), rename(), mkdir(), jobstart(),
etc.
Interfaces, such as Python, Ruby and Lua, are also disabled,
since they could be used to execute shell commands.
Note that the user may still find a loophole to execute a
shell command, it has only been made difficult.
-e *-e* *-E*
-E Start Nvim in Ex mode |gQ|.

View File

@ -609,6 +609,7 @@ String manipulation: *string-functions*
strcharpart() get part of a string using char index
strgetchar() get character from a string using char index
expand() expand special keywords
expandcmd() expand a command like done for `:edit`
iconv() convert text from one encoding to another
byteidx() byte index of a character in a string
byteidxcomp() like byteidx() but count composing characters

View File

@ -1570,6 +1570,7 @@ char_u* skiptohex(char_u *q)
///
/// @return Pointer to the next whitespace or NUL character.
char_u *skiptowhite(const char_u *p)
FUNC_ATTR_NONNULL_ALL
{
while (*p != ' ' && *p != '\t' && *p != NUL) {
p++;

View File

@ -102,6 +102,7 @@ return {
exists={args=1},
exp={args=1, func="float_op_wrapper", data="&exp"},
expand={args={1, 3}},
expandcmd={args=1},
extend={args={2, 3}},
feedkeys={args={1, 2}},
file_readable={args=1, func='f_filereadable'}, -- obsolete

View File

@ -2103,6 +2103,31 @@ static void f_menu_get(typval_T *argvars, typval_T *rettv, FunPtr fptr)
menu_get((char_u *)tv_get_string(&argvars[0]), modes, rettv->vval.v_list);
}
// "expandcmd()" function
// Expand all the special characters in a command string.
static void f_expandcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *errormsg = NULL;
rettv->v_type = VAR_STRING;
char_u *cmdstr = (char_u *)xstrdup(tv_get_string(&argvars[0]));
exarg_T eap = {
.cmd = cmdstr,
.arg = cmdstr,
.usefilter = false,
.nextcmd = NULL,
.cmdidx = CMD_USER,
};
eap.argt |= NOSPC;
expand_filename(&eap, &cmdstr, &errormsg);
if (errormsg != NULL && *errormsg != NUL) {
EMSG(errormsg);
}
rettv->vval.v_string = cmdstr;
}
/*
* "extend(list, list [, idx])" function
* "extend(dict, dict [, action])" function
@ -4292,7 +4317,7 @@ static void f_histadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
HistoryType histype;
rettv->vval.v_number = false;
if (check_restricted() || check_secure()) {
if (check_secure()) {
return;
}
const char *str = tv_get_string_chk(&argvars[0]); // NULL on type error
@ -5272,7 +5297,6 @@ static void f_list2str(typval_T *argvars, typval_T *rettv, FunPtr fptr)
});
ga_append(&ga, NUL);
rettv->v_type = VAR_STRING;
rettv->vval.v_string = ga.ga_data;
}
@ -7755,8 +7779,7 @@ static void f_setbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (check_restricted()
|| check_secure()
if (check_secure()
|| !tv_check_str_or_nr(&argvars[0])) {
return;
}
@ -8260,7 +8283,7 @@ static void f_settabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = 0;
if (check_restricted() || check_secure()) {
if (check_secure()) {
return;
}
@ -10981,7 +11004,7 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = -1;
if (check_restricted() || check_secure()) {
if (check_secure()) {
return;
}

View File

@ -3008,18 +3008,18 @@ void ex_z(exarg_T *eap)
ex_no_reprint = true;
}
/*
* Check if the restricted flag is set.
* If so, give an error message and return TRUE.
* Otherwise, return FALSE.
*/
int check_restricted(void)
// Check if the restricted flag is set.
// If so, give an error message and return true.
// Otherwise, return false.
bool check_restricted(void)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
if (restricted) {
EMSG(_("E145: Shell commands not allowed in restricted mode"));
return TRUE;
EMSG(_("E145: Shell commands and some functionality not allowed"
" in restricted mode"));
return true;
}
return FALSE;
return false;
}
/*

View File

@ -24,6 +24,7 @@ local SBOXOK = 0x80000
local CMDWIN = 0x100000
local MODIFY = 0x200000
local EXFLAGS = 0x400000
local RESTRICT = 0x800000
local FILES = bit.bor(XFILE, EXTRA)
local WORD1 = bit.bor(EXTRA, NOSPC)
local FILE1 = bit.bor(FILES, NOSPC)
@ -1582,19 +1583,19 @@ return {
},
{
command='lua',
flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
addr_type=ADDR_LINES,
func='ex_lua',
},
{
command='luado',
flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN),
flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT),
addr_type=ADDR_LINES,
func='ex_luado',
},
{
command='luafile',
flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT),
addr_type=ADDR_LINES,
func='ex_luafile',
},
@ -1924,13 +1925,13 @@ return {
},
{
command='perl',
flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, SBOXOK, CMDWIN),
flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, SBOXOK, CMDWIN, RESTRICT),
addr_type=ADDR_LINES,
func='ex_script_ni',
},
{
command='perldo',
flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, CMDWIN),
flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, CMDWIN, RESTRICT),
addr_type=ADDR_LINES,
func='ex_ni',
},
@ -2056,67 +2057,67 @@ return {
},
{
command='python',
flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
addr_type=ADDR_LINES,
func='ex_python',
},
{
command='pydo',
flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN),
flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT),
addr_type=ADDR_LINES,
func='ex_pydo',
},
{
command='pyfile',
flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT),
addr_type=ADDR_LINES,
func='ex_pyfile',
},
{
command='py3',
flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
addr_type=ADDR_LINES,
func='ex_python3',
},
{
command='py3do',
flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN),
flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT),
addr_type=ADDR_LINES,
func='ex_pydo3',
},
{
command='python3',
flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
addr_type=ADDR_LINES,
func='ex_python3',
},
{
command='py3file',
flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT),
addr_type=ADDR_LINES,
func='ex_py3file',
},
{
command='pyx',
flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
addr_type=ADDR_LINES,
func='ex_pyx',
},
{
command='pyxdo',
flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN),
flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT),
addr_type=ADDR_LINES,
func='ex_pyxdo',
},
{
command='pythonx',
flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
addr_type=ADDR_LINES,
func='ex_pyx',
},
{
command='pyxfile',
flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT),
addr_type=ADDR_LINES,
func='ex_pyxfile',
},
@ -2242,19 +2243,19 @@ return {
},
{
command='ruby',
flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
addr_type=ADDR_LINES,
func='ex_ruby',
},
{
command='rubydo',
flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN),
flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT),
addr_type=ADDR_LINES,
func='ex_rubydo',
},
{
command='rubyfile',
flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT),
addr_type=ADDR_LINES,
func='ex_rubyfile',
},

View File

@ -36,35 +36,36 @@
// 4. Add documentation in ../doc/xxx.txt. Add a tag for both the short and
// long name of the command.
#define RANGE 0x001 /* allow a linespecs */
#define BANG 0x002 /* allow a ! after the command name */
#define EXTRA 0x004 /* allow extra args after command name */
#define XFILE 0x008 /* expand wildcards in extra part */
#define NOSPC 0x010 /* no spaces allowed in the extra part */
#define DFLALL 0x020 /* default file range is 1,$ */
#define WHOLEFOLD 0x040 /* extend range to include whole fold also
when less than two numbers given */
#define NEEDARG 0x080 /* argument required */
#define TRLBAR 0x100 /* check for trailing vertical bar */
#define REGSTR 0x200 /* allow "x for register designation */
#define COUNT 0x400 /* allow count in argument, after command */
#define NOTRLCOM 0x800 /* no trailing comment allowed */
#define ZEROR 0x1000 /* zero line number allowed */
#define USECTRLV 0x2000 /* do not remove CTRL-V from argument */
#define NOTADR 0x4000 /* number before command is not an address */
#define EDITCMD 0x8000 /* allow "+command" argument */
#define BUFNAME 0x10000 /* accepts buffer name */
#define BUFUNL 0x20000 /* accepts unlisted buffer too */
#define ARGOPT 0x40000 /* allow "++opt=val" argument */
#define SBOXOK 0x80000 /* allowed in the sandbox */
#define CMDWIN 0x100000 /* allowed in cmdline window; when missing
* disallows editing another buffer when
* curbuf_lock is set */
#define MODIFY 0x200000 /* forbidden in non-'modifiable' buffer */
#define EXFLAGS 0x400000 /* allow flags after count in argument */
#define FILES (XFILE | EXTRA) /* multiple extra files allowed */
#define WORD1 (EXTRA | NOSPC) /* one extra word allowed */
#define FILE1 (FILES | NOSPC) /* 1 file allowed, defaults to current file */
#define RANGE 0x001 // allow a linespecs
#define BANG 0x002 // allow a ! after the command name
#define EXTRA 0x004 // allow extra args after command name
#define XFILE 0x008 // expand wildcards in extra part
#define NOSPC 0x010 // no spaces allowed in the extra part
#define DFLALL 0x020 // default file range is 1,$
#define WHOLEFOLD 0x040 // extend range to include whole fold also
// when less than two numbers given
#define NEEDARG 0x080 // argument required
#define TRLBAR 0x100 // check for trailing vertical bar
#define REGSTR 0x200 // allow "x for register designation
#define COUNT 0x400 // allow count in argument, after command
#define NOTRLCOM 0x800 // no trailing comment allowed
#define ZEROR 0x1000 // zero line number allowed
#define USECTRLV 0x2000 // do not remove CTRL-V from argument
#define NOTADR 0x4000 // number before command is not an address
#define EDITCMD 0x8000 // allow "+command" argument
#define BUFNAME 0x10000 // accepts buffer name
#define BUFUNL 0x20000 // accepts unlisted buffer too
#define ARGOPT 0x40000 // allow "++opt=val" argument
#define SBOXOK 0x80000 // allowed in the sandbox
#define CMDWIN 0x100000 // allowed in cmdline window; when missing
// disallows editing another buffer when
// curbuf_lock is set
#define MODIFY 0x200000 // forbidden in non-'modifiable' buffer
#define EXFLAGS 0x400000 // allow flags after count in argument
#define RESTRICT 0x800000L // forbidden in restricted mode
#define FILES (XFILE | EXTRA) // multiple extra files allowed
#define WORD1 (EXTRA | NOSPC) // one extra word allowed
#define FILE1 (FILES | NOSPC) // 1 file allowed, defaults to current file
// values for cmd_addr_type
#define ADDR_LINES 0

View File

@ -1783,10 +1783,14 @@ static char_u * do_one_cmd(char_u **cmdlinep,
if (!ea.skip) {
if (sandbox != 0 && !(ea.argt & SBOXOK)) {
/* Command not allowed in sandbox. */
// Command not allowed in sandbox.
errormsg = (char_u *)_(e_sandbox);
goto doend;
}
if (restricted != 0 && (ea.argt & RESTRICT)) {
errormsg = (char_u *)_("E981: Command not allowed in restricted mode");
goto doend;
}
if (!MODIFIABLE(curbuf) && (ea.argt & MODIFY)
// allow :put in terminals
&& (!curbuf->terminal || ea.cmdidx != CMD_put)) {

View File

@ -86,7 +86,7 @@ uint64_t extmark_set(buf_T *buf, uint64_t ns_id, uint64_t id,
extmark_del(buf, ns_id, id);
} else {
// TODO(bfredl): we need to do more if "revising" a decoration mark.
MarkTreeIter itr[1];
MarkTreeIter itr[1] = { 0 };
old_pos = marktree_lookup(buf->b_marktree, old_mark, itr);
assert(itr->node);
if (old_pos.row == row && old_pos.col == col) {
@ -119,7 +119,7 @@ revised:
static bool extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col)
{
MarkTreeIter itr[1];
MarkTreeIter itr[1] = { 0 };
mtpos_t pos = marktree_lookup(buf->b_marktree, mark, itr);
if (pos.row == -1) {
return false;
@ -147,7 +147,7 @@ bool extmark_del(buf_T *buf, uint64_t ns_id, uint64_t id)
return false;
}
MarkTreeIter itr[1];
MarkTreeIter itr[1] = { 0 };
mtpos_t pos = marktree_lookup(buf->b_marktree, mark, itr);
assert(pos.row >= 0);
marktree_del_itr(buf->b_marktree, itr, false);
@ -207,7 +207,7 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id,
delete_set = map_new(uint64_t, uint64_t)();
}
MarkTreeIter itr[1];
MarkTreeIter itr[1] = { 0 };
marktree_itr_get(buf->b_marktree, l_row, l_col, itr);
while (true) {
mtmark_t mark = marktree_itr_current(itr);
@ -276,7 +276,7 @@ ExtmarkArray extmark_get(buf_T *buf, uint64_t ns_id,
int64_t amount, bool reverse)
{
ExtmarkArray array = KV_INITIAL_VALUE;
MarkTreeIter itr[1];
MarkTreeIter itr[1] = { 0 };
// Find all the marks
marktree_itr_get_ext(buf->b_marktree, (mtpos_t){ l_row, l_col },
itr, reverse, false, NULL);
@ -396,7 +396,7 @@ void u_extmark_copy(buf_T *buf,
ExtmarkUndoObject undo;
MarkTreeIter itr[1];
MarkTreeIter itr[1] = { 0 };
marktree_itr_get(buf->b_marktree, l_row, l_col, itr);
while (true) {
mtmark_t mark = marktree_itr_current(itr);
@ -738,7 +738,7 @@ void clear_virttext(VirtText *text)
VirtText *extmark_find_virttext(buf_T *buf, int row, uint64_t ns_id)
{
MarkTreeIter itr[1];
MarkTreeIter itr[1] = { 0 };
marktree_itr_get(buf->b_marktree, row, 0, itr);
while (true) {
mtmark_t mark = marktree_itr_current(itr);

View File

@ -120,24 +120,20 @@ typedef off_t off_T;
# endif
#endif
/*
* When vgetc() is called, it sets mod_mask to the set of modifiers that are
* held down based on the MOD_MASK_* symbols that are read first.
*/
EXTERN int mod_mask INIT(= 0x0); /* current key modifiers */
// When vgetc() is called, it sets mod_mask to the set of modifiers that are
// held down based on the MOD_MASK_* symbols that are read first.
EXTERN int mod_mask INIT(= 0x0); // current key modifiers
EXTERN bool lua_attr_active INIT(= false);
/*
* Cmdline_row is the row where the command line starts, just below the
* last window.
* When the cmdline gets longer than the available space the screen gets
* scrolled up. After a CTRL-D (show matches), after hitting ':' after
* "hit return", and for the :global command, the command line is
* temporarily moved. The old position is restored with the next call to
* update_screen().
*/
// Cmdline_row is the row where the command line starts, just below the
// last window.
// When the cmdline gets longer than the available space the screen gets
// scrolled up. After a CTRL-D (show matches), after hitting ':' after
// "hit return", and for the :global command, the command line is
// temporarily moved. The old position is restored with the next call to
// update_screen().
EXTERN int cmdline_row;
EXTERN int redraw_cmdline INIT(= false); // cmdline must be redrawn
@ -149,42 +145,38 @@ EXTERN int cmdline_was_last_drawn INIT(= false); // cmdline was last drawn
EXTERN int exec_from_reg INIT(= false); // executing register
/*
* When '$' is included in 'cpoptions' option set:
* When a change command is given that deletes only part of a line, a dollar
* is put at the end of the changed text. dollar_vcol is set to the virtual
* column of this '$'. -1 is used to indicate no $ is being displayed.
*/
// When '$' is included in 'cpoptions' option set:
// When a change command is given that deletes only part of a line, a dollar
// is put at the end of the changed text. dollar_vcol is set to the virtual
// column of this '$'. -1 is used to indicate no $ is being displayed.
EXTERN colnr_T dollar_vcol INIT(= -1);
/*
* Variables for Insert mode completion.
*/
// Variables for Insert mode completion.
/* Length in bytes of the text being completed (this is deleted to be replaced
* by the match.) */
// Length in bytes of the text being completed (this is deleted to be replaced
// by the match.)
EXTERN int compl_length INIT(= 0);
/* Set when character typed while looking for matches and it means we should
* stop looking for matches. */
EXTERN int compl_interrupted INIT(= FALSE);
// Set when character typed while looking for matches and it means we should
// stop looking for matches.
EXTERN int compl_interrupted INIT(= false);
// Set when doing something for completion that may call edit() recursively,
// which is not allowed. Also used to disable folding during completion
EXTERN int compl_busy INIT(= false);
/* List of flags for method of completion. */
// List of flags for method of completion.
EXTERN int compl_cont_status INIT(= 0);
# define CONT_ADDING 1 /* "normal" or "adding" expansion */
# define CONT_INTRPT (2 + 4) /* a ^X interrupted the current expansion */
/* it's set only iff N_ADDS is set */
# define CONT_N_ADDS 4 /* next ^X<> will add-new or expand-current */
# define CONT_S_IPOS 8 /* next ^X<> will set initial_pos?
* if so, word-wise-expansion will set SOL */
# define CONT_SOL 16 /* pattern includes start of line, just for
* word-wise expansion, not set for ^X^L */
# define CONT_LOCAL 32 /* for ctrl_x_mode 0, ^X^P/^X^N do a local
* expansion, (eg use complete=.) */
# define CONT_ADDING 1 // "normal" or "adding" expansion
# define CONT_INTRPT (2 + 4) // a ^X interrupted the current expansion
// it's set only iff N_ADDS is set
# define CONT_N_ADDS 4 // next ^X<> will add-new or expand-current
# define CONT_S_IPOS 8 // next ^X<> will set initial_pos?
// if so, word-wise-expansion will set SOL
# define CONT_SOL 16 // pattern includes start of line, just for
// word-wise expansion, not set for ^X^L
# define CONT_LOCAL 32 // for ctrl_x_mode 0, ^X^P/^X^N do a local
// expansion, (eg use complete=.)
// state for putting characters in the message area
EXTERN int cmdmsg_rl INIT(= false); // cmdline is drawn right to left
@ -200,49 +192,49 @@ EXTERN bool msg_scrolled_ign INIT(= false);
EXTERN bool msg_did_scroll INIT(= false);
EXTERN char_u *keep_msg INIT(= NULL); /* msg to be shown after redraw */
EXTERN int keep_msg_attr INIT(= 0); /* highlight attr for keep_msg */
EXTERN int keep_msg_more INIT(= FALSE); /* keep_msg was set by msgmore() */
EXTERN int need_fileinfo INIT(= FALSE); /* do fileinfo() after redraw */
EXTERN int msg_scroll INIT(= FALSE); /* msg_start() will scroll */
EXTERN int msg_didout INIT(= FALSE); /* msg_outstr() was used in line */
EXTERN int msg_didany INIT(= FALSE); /* msg_outstr() was used at all */
EXTERN int msg_nowait INIT(= FALSE); /* don't wait for this msg */
EXTERN int emsg_off INIT(= 0); /* don't display errors for now,
unless 'debug' is set. */
EXTERN int info_message INIT(= FALSE); /* printing informative message */
EXTERN int msg_hist_off INIT(= FALSE); /* don't add messages to history */
EXTERN int need_clr_eos INIT(= FALSE); /* need to clear text before
displaying a message. */
EXTERN int emsg_skip INIT(= 0); /* don't display errors for
expression that is skipped */
EXTERN int emsg_severe INIT(= FALSE); /* use message of next of several
emsg() calls for throw */
EXTERN int did_endif INIT(= FALSE); /* just had ":endif" */
EXTERN dict_T vimvardict; /* Dictionary with v: variables */
EXTERN dict_T globvardict; /* Dictionary with g: variables */
EXTERN int did_emsg; /* set by emsg() when the message
is displayed or thrown */
EXTERN char_u *keep_msg INIT(= NULL); // msg to be shown after redraw
EXTERN int keep_msg_attr INIT(= 0); // highlight attr for keep_msg
EXTERN int keep_msg_more INIT(= false); // keep_msg was set by msgmore()
EXTERN int need_fileinfo INIT(= false); // do fileinfo() after redraw
EXTERN int msg_scroll INIT(= false); // msg_start() will scroll
EXTERN int msg_didout INIT(= false); // msg_outstr() was used in line
EXTERN int msg_didany INIT(= false); // msg_outstr() was used at all
EXTERN int msg_nowait INIT(= false); // don't wait for this msg
EXTERN int emsg_off INIT(= 0); // don't display errors for now,
// unless 'debug' is set.
EXTERN int info_message INIT(= false); // printing informative message
EXTERN int msg_hist_off INIT(= false); // don't add messages to history
EXTERN int need_clr_eos INIT(= false); // need to clear text before
// displaying a message.
EXTERN int emsg_skip INIT(= 0); // don't display errors for
// expression that is skipped
EXTERN int emsg_severe INIT(= false); // use message of next of several
// emsg() calls for throw
EXTERN int did_endif INIT(= false); // just had ":endif"
EXTERN dict_T vimvardict; // Dictionary with v: variables
EXTERN dict_T globvardict; // Dictionary with g: variables
EXTERN int did_emsg; // set by emsg() when the message
// is displayed or thrown
EXTERN bool called_vim_beep; // set if vim_beep() is called
EXTERN int did_emsg_syntax; /* did_emsg set because of a
syntax error */
EXTERN int called_emsg; /* always set by emsg() */
EXTERN int ex_exitval INIT(= 0); /* exit value for ex mode */
EXTERN int emsg_on_display INIT(= FALSE); /* there is an error message */
EXTERN int rc_did_emsg INIT(= FALSE); /* vim_regcomp() called emsg() */
EXTERN int did_emsg_syntax; // did_emsg set because of a
// syntax error
EXTERN int called_emsg; // always set by emsg()
EXTERN int ex_exitval INIT(= 0); // exit value for ex mode
EXTERN int emsg_on_display INIT(= false); // there is an error message
EXTERN int rc_did_emsg INIT(= false); // vim_regcomp() called emsg()
EXTERN int no_wait_return INIT(= 0); /* don't wait for return for now */
EXTERN int need_wait_return INIT(= 0); /* need to wait for return later */
EXTERN int did_wait_return INIT(= FALSE); /* wait_return() was used and
nothing written since then */
EXTERN int need_maketitle INIT(= TRUE); /* call maketitle() soon */
EXTERN int no_wait_return INIT(= 0); // don't wait for return for now
EXTERN int need_wait_return INIT(= 0); // need to wait for return later
EXTERN int did_wait_return INIT(= false); // wait_return() was used and
// nothing written since then
EXTERN int need_maketitle INIT(= true); // call maketitle() soon
EXTERN int quit_more INIT(= false); // 'q' hit at "--more--" msg
EXTERN int ex_keep_indent INIT(= false); // getexmodeline(): keep indent
EXTERN int vgetc_busy INIT(= 0); // when inside vgetc() then > 0
EXTERN int didset_vim INIT(= FALSE); /* did set $VIM ourselves */
EXTERN int didset_vimruntime INIT(= FALSE); /* idem for $VIMRUNTIME */
EXTERN int didset_vim INIT(= false); // did set $VIM ourselves
EXTERN int didset_vimruntime INIT(= false); // idem for $VIMRUNTIME
/// Lines left before a "more" message. Ex mode needs to be able to reset this
/// after you type something.
@ -250,8 +242,8 @@ EXTERN int lines_left INIT(= -1); // lines left for listing
EXTERN int msg_no_more INIT(= false); // don't use more prompt, truncate
// messages
EXTERN char_u *sourcing_name INIT( = NULL); /* name of error message source */
EXTERN linenr_T sourcing_lnum INIT(= 0); /* line number of the source file */
EXTERN char_u *sourcing_name INIT(= NULL); // name of error message source
EXTERN linenr_T sourcing_lnum INIT(= 0); // line number of the source file
EXTERN int ex_nesting_level INIT(= 0); // nesting level
EXTERN int debug_break_level INIT(= -1); // break below this level
@ -282,11 +274,11 @@ EXTERN int check_cstack INIT(= false);
/// commands).
EXTERN int trylevel INIT(= 0);
/// When "force_abort" is TRUE, always skip commands after an error message,
/// When "force_abort" is true, always skip commands after an error message,
/// even after the outermost ":endif", ":endwhile" or ":endfor" or for a
/// function without the "abort" flag. It is set to TRUE when "trylevel" is
/// function without the "abort" flag. It is set to true when "trylevel" is
/// non-zero (and ":silent!" was not used) or an exception is being thrown at
/// the time an error is detected. It is set to FALSE when "trylevel" gets
/// the time an error is detected. It is set to false when "trylevel" gets
/// zero again and there was no error or interrupt or throw.
EXTERN int force_abort INIT(= false);
@ -357,41 +349,38 @@ EXTERN int provider_call_nesting INIT(= 0);
EXTERN int t_colors INIT(= 256); // int value of T_CCO
/*
* When highlight_match is TRUE, highlight a match, starting at the cursor
* position. Search_match_lines is the number of lines after the match (0 for
* a match within one line), search_match_endcol the column number of the
* character just after the match in the last line.
*/
EXTERN int highlight_match INIT(= FALSE); /* show search match pos */
EXTERN linenr_T search_match_lines; /* lines of of matched string */
EXTERN colnr_T search_match_endcol; /* col nr of match end */
// When highlight_match is true, highlight a match, starting at the cursor
// position. Search_match_lines is the number of lines after the match (0 for
// a match within one line), search_match_endcol the column number of the
// character just after the match in the last line.
EXTERN int highlight_match INIT(= false); // show search match pos
EXTERN linenr_T search_match_lines; // lines of of matched string
EXTERN colnr_T search_match_endcol; // col nr of match end
EXTERN int no_smartcase INIT(= FALSE); /* don't use 'smartcase' once */
EXTERN int no_smartcase INIT(= false); // don't use 'smartcase' once
EXTERN int need_check_timestamps INIT(= FALSE); /* need to check file
timestamps asap */
EXTERN int did_check_timestamps INIT(= FALSE); /* did check timestamps
recently */
EXTERN int no_check_timestamps INIT(= 0); /* Don't check timestamps */
EXTERN int need_check_timestamps INIT(= false); // need to check file
// timestamps asap
EXTERN int did_check_timestamps INIT(= false); // did check timestamps
// recently
EXTERN int no_check_timestamps INIT(= 0); // Don't check timestamps
EXTERN int autocmd_busy INIT(= FALSE); /* Is apply_autocmds() busy? */
EXTERN int autocmd_no_enter INIT(= FALSE); /* *Enter autocmds disabled */
EXTERN int autocmd_no_leave INIT(= FALSE); /* *Leave autocmds disabled */
EXTERN int modified_was_set; /* did ":set modified" */
EXTERN int did_filetype INIT(= FALSE); /* FileType event found */
EXTERN int keep_filetype INIT(= FALSE); /* value for did_filetype when
starting to execute
autocommands */
EXTERN int autocmd_busy INIT(= false); // Is apply_autocmds() busy?
EXTERN int autocmd_no_enter INIT(= false); // *Enter autocmds disabled
EXTERN int autocmd_no_leave INIT(= false); // *Leave autocmds disabled
EXTERN int modified_was_set; // did ":set modified"
EXTERN int did_filetype INIT(= false); // FileType event found
// value for did_filetype when starting to execute autocommands
EXTERN int keep_filetype INIT(= false);
// When deleting the current buffer, another one must be loaded.
// If we know which one is preferred, au_new_curbuf is set to it.
EXTERN bufref_T au_new_curbuf INIT(= { NULL, 0, 0 });
// When deleting a buffer/window and autocmd_busy is TRUE, do not free the
// When deleting a buffer/window and autocmd_busy is true, do not free the
// buffer/window. but link it in the list starting with
// au_pending_free_buf/ap_pending_free_win, using b_next/w_next.
// Free the buffer/window when autocmd_busy is being set to FALSE.
// Free the buffer/window when autocmd_busy is being set to false.
EXTERN buf_T *au_pending_free_buf INIT(= NULL);
EXTERN win_T *au_pending_free_win INIT(= NULL);
@ -399,31 +388,27 @@ EXTERN win_T *au_pending_free_win INIT(= NULL);
EXTERN int mouse_grid;
EXTERN int mouse_row;
EXTERN int mouse_col;
EXTERN bool mouse_past_bottom INIT(= false); /* mouse below last line */
EXTERN bool mouse_past_eol INIT(= false); /* mouse right of line */
EXTERN int mouse_dragging INIT(= 0); /* extending Visual area with
mouse dragging */
EXTERN bool mouse_past_bottom INIT(= false); // mouse below last line
EXTERN bool mouse_past_eol INIT(= false); // mouse right of line
EXTERN int mouse_dragging INIT(= 0); // extending Visual area with
// mouse dragging
/* The root of the menu hierarchy. */
// The root of the menu hierarchy.
EXTERN vimmenu_T *root_menu INIT(= NULL);
/*
* While defining the system menu, sys_menu is TRUE. This avoids
* overruling of menus that the user already defined.
*/
EXTERN int sys_menu INIT(= FALSE);
// While defining the system menu, sys_menu is true. This avoids
// overruling of menus that the user already defined.
EXTERN int sys_menu INIT(= false);
/* While redrawing the screen this flag is set. It means the screen size
* ('lines' and 'rows') must not be changed. */
EXTERN int updating_screen INIT(= FALSE);
// While redrawing the screen this flag is set. It means the screen size
// ('lines' and 'rows') must not be changed.
EXTERN int updating_screen INIT(= 0);
/*
* All windows are linked in a list. firstwin points to the first entry,
* lastwin to the last entry (can be the same as firstwin) and curwin to the
* currently active window.
*/
EXTERN win_T *firstwin; /* first window */
EXTERN win_T *lastwin; /* last window */
EXTERN win_T *prevwin INIT(= NULL); /* previous window */
// All windows are linked in a list. firstwin points to the first entry,
// lastwin to the last entry (can be the same as firstwin) and curwin to the
// currently active window.
EXTERN win_T *firstwin; // first window
EXTERN win_T *lastwin; // last window
EXTERN win_T *prevwin INIT(= NULL); // previous window
# define ONE_WINDOW (firstwin == lastwin)
# define FOR_ALL_FRAMES(frp, first_frame) \
for (frp = first_frame; frp != NULL; frp = frp->fr_next) // NOLINT
@ -439,33 +424,27 @@ EXTERN win_T *prevwin INIT(= NULL); /* previous window */
for (win_T *wp = ((tp) == curtab) \
? firstwin : (tp)->tp_firstwin; wp != NULL; wp = wp->w_next)
EXTERN win_T *curwin; /* currently active window */
EXTERN win_T *curwin; // currently active window
EXTERN win_T *aucmd_win; /* window used in aucmd_prepbuf() */
EXTERN int aucmd_win_used INIT(= FALSE); /* aucmd_win is being used */
EXTERN win_T *aucmd_win; // window used in aucmd_prepbuf()
EXTERN int aucmd_win_used INIT(= false); // aucmd_win is being used
/*
* The window layout is kept in a tree of frames. topframe points to the top
* of the tree.
*/
EXTERN frame_T *topframe; /* top of the window frame tree */
// The window layout is kept in a tree of frames. topframe points to the top
// of the tree.
EXTERN frame_T *topframe; // top of the window frame tree
/*
* Tab pages are alternative topframes. "first_tabpage" points to the first
* one in the list, "curtab" is the current one.
*/
// Tab pages are alternative topframes. "first_tabpage" points to the first
// one in the list, "curtab" is the current one.
EXTERN tabpage_T *first_tabpage;
EXTERN tabpage_T *lastused_tabpage;
EXTERN tabpage_T *curtab;
EXTERN int redraw_tabline INIT(= FALSE); /* need to redraw tabline */
EXTERN int redraw_tabline INIT(= false); // need to redraw tabline
// Iterates over all tabs in the tab list
# define FOR_ALL_TABS(tp) for (tabpage_T *tp = first_tabpage; tp != NULL; tp = tp->tp_next)
/*
* All buffers are linked in a list. 'firstbuf' points to the first entry,
* 'lastbuf' to the last entry and 'curbuf' to the currently active buffer.
*/
// All buffers are linked in a list. 'firstbuf' points to the first entry,
// 'lastbuf' to the last entry and 'curbuf' to the currently active buffer.
EXTERN buf_T *firstbuf INIT(= NULL); // first buffer
EXTERN buf_T *lastbuf INIT(= NULL); // last buffer
EXTERN buf_T *curbuf INIT(= NULL); // currently active buffer
@ -481,23 +460,19 @@ EXTERN buf_T *curbuf INIT(= NULL); // currently active buffer
for (sign = buf->b_signlist; sign != NULL; sign = sign->next) // NOLINT
/*
* List of files being edited (global argument list). curwin->w_alist points
* to this when the window is using the global argument list.
*/
EXTERN alist_T global_alist; /* global argument list */
// List of files being edited (global argument list). curwin->w_alist points
// to this when the window is using the global argument list.
EXTERN alist_T global_alist; // global argument list
EXTERN int max_alist_id INIT(= 0); ///< the previous argument list id
EXTERN bool arg_had_last INIT(= false); // accessed last file in
// global_alist
EXTERN int ru_col; /* column for ruler */
EXTERN int ru_wid; /* 'rulerfmt' width of ruler when non-zero */
EXTERN int sc_col; /* column for shown command */
EXTERN int ru_col; // column for ruler
EXTERN int ru_wid; // 'rulerfmt' width of ruler when non-zero
EXTERN int sc_col; // column for shown command
//
// When starting or exiting some things are done differently (e.g. screen
// updating).
//
// First NO_SCREEN, then NO_BUFFERS, then 0 when startup finished.
EXTERN int starting INIT(= NO_SCREEN);
@ -546,98 +521,78 @@ EXTERN int VIsual_select INIT(= false);
EXTERN int VIsual_reselect;
/// Type of Visual mode.
EXTERN int VIsual_mode INIT(= 'v');
/// TRUE when redoing Visual.
/// true when redoing Visual.
EXTERN int redo_VIsual_busy INIT(= false);
/// When pasting text with the middle mouse button in visual mode with
/// restart_edit set, remember where it started so we can set Insstart.
EXTERN pos_T where_paste_started;
/*
* This flag is used to make auto-indent work right on lines where only a
* <RETURN> or <ESC> is typed. It is set when an auto-indent is done, and
* reset when any other editing is done on the line. If an <ESC> or <RETURN>
* is received, and did_ai is TRUE, the line is truncated.
*/
// This flag is used to make auto-indent work right on lines where only a
// <RETURN> or <ESC> is typed. It is set when an auto-indent is done, and
// reset when any other editing is done on the line. If an <ESC> or <RETURN>
// is received, and did_ai is true, the line is truncated.
EXTERN bool did_ai INIT(= false);
/*
* Column of first char after autoindent. 0 when no autoindent done. Used
* when 'backspace' is 0, to avoid backspacing over autoindent.
*/
// Column of first char after autoindent. 0 when no autoindent done. Used
// when 'backspace' is 0, to avoid backspacing over autoindent.
EXTERN colnr_T ai_col INIT(= 0);
/*
* This is a character which will end a start-middle-end comment when typed as
* the first character on a new line. It is taken from the last character of
* the "end" comment leader when the COM_AUTO_END flag is given for that
* comment end in 'comments'. It is only valid when did_ai is TRUE.
*/
// This is a character which will end a start-middle-end comment when typed as
// the first character on a new line. It is taken from the last character of
// the "end" comment leader when the COM_AUTO_END flag is given for that
// comment end in 'comments'. It is only valid when did_ai is true.
EXTERN int end_comment_pending INIT(= NUL);
/*
* This flag is set after a ":syncbind" to let the check_scrollbind() function
* know that it should not attempt to perform scrollbinding due to the scroll
* that was a result of the ":syncbind." (Otherwise, check_scrollbind() will
* undo some of the work done by ":syncbind.") -ralston
*/
EXTERN int did_syncbind INIT(= FALSE);
// This flag is set after a ":syncbind" to let the check_scrollbind() function
// know that it should not attempt to perform scrollbinding due to the scroll
// that was a result of the ":syncbind." (Otherwise, check_scrollbind() will
// undo some of the work done by ":syncbind.") -ralston
EXTERN int did_syncbind INIT(= false);
/*
* This flag is set when a smart indent has been performed. When the next typed
* character is a '{' the inserted tab will be deleted again.
*/
// This flag is set when a smart indent has been performed. When the next typed
// character is a '{' the inserted tab will be deleted again.
EXTERN bool did_si INIT(= false);
/*
* This flag is set after an auto indent. If the next typed character is a '}'
* one indent will be removed.
*/
// This flag is set after an auto indent. If the next typed character is a '}'
// one indent will be removed.
EXTERN bool can_si INIT(= false);
/*
* This flag is set after an "O" command. If the next typed character is a '{'
* one indent will be removed.
*/
// This flag is set after an "O" command. If the next typed character is a '{'
// one indent will be removed.
EXTERN bool can_si_back INIT(= false);
// w_cursor before formatting text.
EXTERN pos_T saved_cursor INIT(= { 0, 0, 0 });
/*
* Stuff for insert mode.
*/
EXTERN pos_T Insstart; /* This is where the latest
* insert/append mode started. */
// Stuff for insert mode.
EXTERN pos_T Insstart; // This is where the latest
// insert/append mode started.
// This is where the latest insert/append mode started. In contrast to
// Insstart, this won't be reset by certain keys and is needed for
// op_insert(), to detect correctly where inserting by the user started.
EXTERN pos_T Insstart_orig;
/*
* Stuff for VREPLACE mode.
*/
EXTERN int orig_line_count INIT(= 0); /* Line count when "gR" started */
EXTERN int vr_lines_changed INIT(= 0); /* #Lines changed by "gR" so far */
// Stuff for VREPLACE mode.
EXTERN int orig_line_count INIT(= 0); // Line count when "gR" started
EXTERN int vr_lines_changed INIT(= 0); // #Lines changed by "gR" so far
// increase around internal delete/replace
EXTERN int inhibit_delete_count INIT(= 0);
/*
* These flags are set based upon 'fileencoding'.
* Note that "enc_utf8" is also set for "unicode", because the characters are
* internally stored as UTF-8 (to avoid trouble with NUL bytes).
*/
# define DBCS_JPN 932 /* japan */
# define DBCS_JPNU 9932 /* euc-jp */
# define DBCS_KOR 949 /* korea */
# define DBCS_KORU 9949 /* euc-kr */
# define DBCS_CHS 936 /* chinese */
# define DBCS_CHSU 9936 /* euc-cn */
# define DBCS_CHT 950 /* taiwan */
# define DBCS_CHTU 9950 /* euc-tw */
# define DBCS_2BYTE 1 /* 2byte- */
// These flags are set based upon 'fileencoding'.
// Note that "enc_utf8" is also set for "unicode", because the characters are
// internally stored as UTF-8 (to avoid trouble with NUL bytes).
# define DBCS_JPN 932 // japan
# define DBCS_JPNU 9932 // euc-jp
# define DBCS_KOR 949 // korea
# define DBCS_KORU 9949 // euc-kr
# define DBCS_CHS 936 // chinese
# define DBCS_CHSU 9936 // euc-cn
# define DBCS_CHT 950 // taiwan
# define DBCS_CHTU 9950 // euc-tw
# define DBCS_2BYTE 1 // 2byte-
# define DBCS_DEBUG -1
// mbyte flags that used to depend on 'encoding'. These are now deprecated, as
@ -678,40 +633,40 @@ EXTERN int u_sync_once INIT(= 0); // Call u_sync() once when evaluating
EXTERN bool force_restart_edit INIT(= false); // force restart_edit after
// ex_normal returns
EXTERN int restart_edit INIT(= 0); /* call edit when next cmd finished */
EXTERN int arrow_used; /* Normally FALSE, set to TRUE after
* hitting cursor key in insert mode.
* Used by vgetorpeek() to decide when
* to call u_sync() */
EXTERN int ins_at_eol INIT(= FALSE); /* put cursor after eol when
restarting edit after CTRL-O */
EXTERN int restart_edit INIT(= 0); // call edit when next cmd finished
EXTERN int arrow_used; // Normally false, set to true after
// hitting cursor key in insert mode.
// Used by vgetorpeek() to decide when
// to call u_sync()
EXTERN int ins_at_eol INIT(= false); // put cursor after eol when
// restarting edit after CTRL-O
EXTERN char_u *edit_submode INIT(= NULL); // msg for CTRL-X submode
EXTERN char_u *edit_submode_pre INIT(= NULL); // prepended to edit_submode
EXTERN char_u *edit_submode_extra INIT(= NULL); // appended to edit_submode
EXTERN hlf_T edit_submode_highl; // highl. method for extra info
EXTERN int no_abbr INIT(= TRUE); /* TRUE when no abbreviations loaded */
EXTERN int no_abbr INIT(= true); // true when no abbreviations loaded
EXTERN int mapped_ctrl_c INIT(= 0); // Modes where CTRL-C is mapped.
EXTERN cmdmod_T cmdmod; /* Ex command modifiers */
EXTERN cmdmod_T cmdmod; // Ex command modifiers
EXTERN int msg_silent INIT(= 0); // don't print messages
EXTERN int emsg_silent INIT(= 0); // don't print error messages
EXTERN bool emsg_noredir INIT(= false); // don't redirect error messages
EXTERN bool cmd_silent INIT(= false); // don't echo the command line
/* Values for swap_exists_action: what to do when swap file already exists */
#define SEA_NONE 0 /* don't use dialog */
#define SEA_DIALOG 1 /* use dialog when possible */
#define SEA_QUIT 2 /* quit editing the file */
#define SEA_RECOVER 3 /* recover the file */
// Values for swap_exists_action: what to do when swap file already exists
#define SEA_NONE 0 // don't use dialog
#define SEA_DIALOG 1 // use dialog when possible
#define SEA_QUIT 2 // quit editing the file
#define SEA_RECOVER 3 // recover the file
EXTERN int swap_exists_action INIT(= SEA_NONE);
/* For dialog when swap file already
* exists. */
EXTERN int swap_exists_did_quit INIT(= FALSE);
/* Selected "quit" at the dialog. */
// For dialog when swap file already
// exists.
EXTERN int swap_exists_did_quit INIT(= false);
// Selected "quit" at the dialog.
EXTERN char_u IObuff[IOSIZE]; ///< Buffer for sprintf, I/O, etc.
EXTERN char_u NameBuff[MAXPATHL]; ///< Buffer for expanding file names
@ -724,11 +679,11 @@ IOSIZE
#endif
];
/* When non-zero, postpone redrawing. */
// When non-zero, postpone redrawing.
EXTERN int RedrawingDisabled INIT(= 0);
EXTERN int readonlymode INIT(= FALSE); /* Set to TRUE for "view" */
EXTERN int recoverymode INIT(= FALSE); /* Set to TRUE for "-r" option */
EXTERN int readonlymode INIT(= false); // Set to true for "view"
EXTERN int recoverymode INIT(= false); // Set to true for "-r" option
// typeahead buffer
EXTERN typebuf_T typebuf INIT(= { NULL, NULL, 0, 0, 0, 0, 0, 0, 0 });
@ -738,7 +693,7 @@ EXTERN int ex_normal_lock INIT(= 0); // forbid use of ex_normal()
EXTERN int ignore_script INIT(= false); // ignore script input
EXTERN int stop_insert_mode; // for ":stopinsert" and 'insertmode'
EXTERN bool KeyTyped; // true if user typed current char
EXTERN int KeyStuffed; // TRUE if current char from stuffbuf
EXTERN int KeyStuffed; // true if current char from stuffbuf
EXTERN int maptick INIT(= 0); // tick for each non-mapped char
EXTERN int must_redraw INIT(= 0); // type of redraw necessary
@ -754,15 +709,15 @@ EXTERN FILE *scriptout INIT(= NULL); ///< Stream to write script to.
// volatile because it is used in a signal handler.
EXTERN volatile int got_int INIT(= false); // set to true when interrupt
// signal occurred
EXTERN int bangredo INIT(= FALSE); /* set to TRUE with ! command */
EXTERN int searchcmdlen; /* length of previous search cmd */
EXTERN int reg_do_extmatch INIT(= 0); /* Used when compiling regexp:
* REX_SET to allow \z\(...\),
* REX_USE to allow \z\1 et al. */
EXTERN reg_extmatch_T *re_extmatch_in INIT(= NULL); /* Used by vim_regexec():
* strings for \z\1...\z\9 */
EXTERN reg_extmatch_T *re_extmatch_out INIT(= NULL); /* Set by vim_regexec()
* to store \z\(...\) matches */
EXTERN int bangredo INIT(= false); // set to true with ! command
EXTERN int searchcmdlen; // length of previous search cmd
EXTERN int reg_do_extmatch INIT(= 0); // Used when compiling regexp:
// REX_SET to allow \z\(...\),
// REX_USE to allow \z\1 et al.
// Used by vim_regexec(): strings for \z\1...\z\9
EXTERN reg_extmatch_T *re_extmatch_in INIT(= NULL);
// Set by vim_regexec() to store \z\(...\) matches
EXTERN reg_extmatch_T *re_extmatch_out INIT(= NULL);
EXTERN int did_outofmem_msg INIT(= false);
// set after out of memory msg
@ -781,11 +736,11 @@ EXTERN int autocmd_bufnr INIT(= 0); // fnum for <abuf> on cmdline
EXTERN char_u *autocmd_match INIT(= NULL); // name for <amatch> on cmdline
EXTERN int did_cursorhold INIT(= false); // set when CursorHold t'gerd
EXTERN int postponed_split INIT(= 0); /* for CTRL-W CTRL-] command */
EXTERN int postponed_split_flags INIT(= 0); /* args for win_split() */
EXTERN int postponed_split_tab INIT(= 0); /* cmdmod.tab */
EXTERN int g_do_tagpreview INIT(= 0); /* for tag preview commands:
height of preview window */
EXTERN int postponed_split INIT(= 0); // for CTRL-W CTRL-] command
EXTERN int postponed_split_flags INIT(= 0); // args for win_split()
EXTERN int postponed_split_tab INIT(= 0); // cmdmod.tab
EXTERN int g_do_tagpreview INIT(= 0); // for tag preview commands:
// height of preview window
EXTERN int g_tag_at_cursor INIT(= false); // whether the tag command comes
// from the command line (0) or was
// invoked as a normal command (1)
@ -793,15 +748,13 @@ EXTERN int g_tag_at_cursor INIT(= false); // whether the tag command comes
EXTERN int replace_offset INIT(= 0); // offset for replace_push()
EXTERN char_u *escape_chars INIT(= (char_u *)" \t\\\"|");
/* need backslash in cmd line */
// need backslash in cmd line
EXTERN int keep_help_flag INIT(= FALSE); /* doing :ta from help file */
EXTERN int keep_help_flag INIT(= false); // doing :ta from help file
/*
* When a string option is NULL (which only happens in out-of-memory
* situations), it is set to empty_option, to avoid having to check for NULL
* everywhere.
*/
// When a string option is NULL (which only happens in out-of-memory
// situations), it is set to empty_option, to avoid having to check for NULL
// everywhere.
EXTERN char_u *empty_option INIT(= (char_u *)"");
EXTERN int redir_off INIT(= false); // no redirection for a moment
@ -810,10 +763,10 @@ EXTERN int redir_reg INIT(= 0); // message redirection register
EXTERN int redir_vname INIT(= 0); // message redirection variable
EXTERN garray_T *capture_ga INIT(= NULL); // captured output for execute()
EXTERN char_u langmap_mapchar[256]; /* mapping for language keys */
EXTERN char_u langmap_mapchar[256]; // mapping for language keys
EXTERN int save_p_ls INIT(= -1); /* Save 'laststatus' setting */
EXTERN int save_p_wmh INIT(= -1); /* Save 'winminheight' setting */
EXTERN int save_p_ls INIT(= -1); // Save 'laststatus' setting
EXTERN int save_p_wmh INIT(= -1); // Save 'winminheight' setting
EXTERN int wild_menu_showing INIT(= 0);
enum {
WM_SHOWN = 1, ///< wildmenu showing
@ -822,10 +775,8 @@ enum {
};
/*
* Some file names are stored in pathdef.c, which is generated from the
* Makefile to make their value depend on the Makefile.
*/
// Some file names are stored in pathdef.c, which is generated from the
// Makefile to make their value depend on the Makefile.
#ifdef HAVE_PATHDEF
extern char *default_vim_dir;
extern char *default_vimruntime_dir;
@ -834,14 +785,14 @@ extern char_u *compiled_user;
extern char_u *compiled_sys;
#endif
/* When a window has a local directory, the absolute path of the global
* current directory is stored here (in allocated memory). If the current
* directory is not a local directory, globaldir is NULL. */
// When a window has a local directory, the absolute path of the global
// current directory is stored here (in allocated memory). If the current
// directory is not a local directory, globaldir is NULL.
EXTERN char_u *globaldir INIT(= NULL);
/* Whether 'keymodel' contains "stopsel" and "startsel". */
EXTERN int km_stopsel INIT(= FALSE);
EXTERN int km_startsel INIT(= FALSE);
// Whether 'keymodel' contains "stopsel" and "startsel".
EXTERN int km_stopsel INIT(= false);
EXTERN int km_startsel INIT(= false);
EXTERN int cedit_key INIT(= -1); ///< key value of 'cedit' option
EXTERN int cmdwin_type INIT(= 0); ///< type of cmdline window or 0
@ -850,18 +801,16 @@ EXTERN int cmdwin_level INIT(= 0); ///< cmdline recursion level
EXTERN char_u 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 linenr_T sub_nlines; /* total number of lines changed */
// 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 linenr_T sub_nlines; // total number of lines changed
/* table to store parsed 'wildmode' */
// table to store parsed 'wildmode'
EXTERN char_u wim_flags[4];
/* whether titlestring and iconstring contains statusline syntax */
// whether titlestring and iconstring contains statusline syntax
# define STL_IN_ICON 1
# define STL_IN_TITLE 2
EXTERN int stl_syntax INIT(= 0);
@ -869,7 +818,7 @@ EXTERN int stl_syntax INIT(= 0);
// don't use 'hlsearch' temporarily
EXTERN bool no_hlsearch INIT(= false);
/* Page number used for %N in 'pageheader' and 'guitablabel'. */
// Page number used for %N in 'pageheader' and 'guitablabel'.
EXTERN linenr_T printer_page_num;
@ -887,18 +836,16 @@ EXTERN char pseps[2] INIT(= { '\\', 0 }); // normal path separator string
// kNone when no operator is being executed, kFalse otherwise.
EXTERN TriState virtual_op INIT(= kNone);
/* Display tick, incremented for each call to update_screen() */
// Display tick, incremented for each call to update_screen()
EXTERN disptick_T display_tick INIT(= 0);
/* Line in which spell checking wasn't highlighted because it touched the
* cursor position in Insert mode. */
// Line in which spell checking wasn't highlighted because it touched the
// cursor position in Insert mode.
EXTERN linenr_T spell_redraw_lnum INIT(= 0);
/*
* The error messages that can be shared are included here.
* Excluded are errors that are only used once and debugging messages.
*/
// The error messages that can be shared are included here.
// Excluded are errors that are only used once and debugging messages.
EXTERN char_u e_abort[] INIT(= N_("E470: Command aborted"));
EXTERN char_u e_afterinit[] INIT(= N_(
"E905: Cannot set this option after startup"));
@ -1070,7 +1017,7 @@ EXTERN char line_msg[] INIT(= N_(" line "));
// For undo we need to know the lowest time possible.
EXTERN time_t starttime;
EXTERN FILE *time_fd INIT(= NULL); /* where to write startup timing */
EXTERN FILE *time_fd INIT(= NULL); // where to write startup timing
// Some compilers warn for not using a return value, but in some situations we
// can't do anything useful with the value. Assign to this variable to avoid
@ -1106,4 +1053,4 @@ typedef enum {
#define MIN_CD_SCOPE kCdScopeWindow
#define MAX_CD_SCOPE kCdScopeGlobal
#endif /* NVIM_GLOBALS_H */
#endif // NVIM_GLOBALS_H

View File

@ -3372,11 +3372,9 @@ term_again:
continue;
}
/*
* Are we at the start of a cpp base class declaration or
* constructor initialization?
*/ /* XXX */
n = false;
// Are we at the start of a cpp base class declaration or
// constructor initialization? XXX
n = 0;
if (curbuf->b_ind_cpp_baseclass != 0 && theline[0] != '{') {
n = cin_is_cpp_baseclass(&cache_cpp_baseclass);
l = get_cursor_line_ptr();
@ -3409,7 +3407,6 @@ term_again:
* } foo,
* bar;
*/
n = 0;
if (cin_ends_in(l, (char_u *)",", NULL)
|| (*l != NUL && (n = l[STRLEN(l) - 1]) == '\\')) {
/* take us back to opening paren */

View File

@ -849,7 +849,8 @@ bool marktree_splice(MarkTree *b,
bool same_line = old_extent.row == 0 && new_extent.row == 0;
unrelative(start, &old_extent);
unrelative(start, &new_extent);
MarkTreeIter itr[1], enditr[1];
MarkTreeIter itr[1] = { 0 };
MarkTreeIter enditr[1] = { 0 };
mtpos_t oldbase[MT_MAX_DEPTH];
@ -1003,7 +1004,7 @@ void marktree_move_region(MarkTree *b,
mtpos_t start = { start_row, start_col }, size = { extent_row, extent_col };
mtpos_t end = size;
unrelative(start, &end);
MarkTreeIter itr[1];
MarkTreeIter itr[1] = { 0 };
marktree_itr_get_ext(b, start, itr, false, true, NULL);
kvec_t(mtkey_t) saved = KV_INITIAL_VALUE;
while (itr->node) {

View File

@ -842,6 +842,15 @@ static bool is_append_register(int regname)
return ASCII_ISUPPER(regname);
}
/// @see get_yank_register
/// @returns true when register should be inserted literally
/// (selection or clipboard)
static inline bool is_literal_register(int regname)
FUNC_ATTR_CONST
{
return regname == '*' || regname == '+';
}
/// Returns a copy of contents in register `name`
/// for use in do_put. Should be freed by caller.
yankreg_T *copy_register(int name)
@ -1152,11 +1161,12 @@ static int put_in_typebuf(
*/
int insert_reg(
int regname,
int literally /* insert literally, not as if typed */
bool literally_arg // insert literally, not as if typed
)
{
int retval = OK;
bool allocated;
const bool literally = literally_arg || is_literal_register(regname);
/*
* It is possible to get into an endless loop by having CTRL-R a in
@ -1326,12 +1336,14 @@ bool get_spec_reg(
/// register contents will be interpreted as commands.
///
/// @param regname Register name.
/// @param literally Insert text literally instead of "as typed".
/// @param literally_arg Insert text literally instead of "as typed".
/// @param remcr When true, don't add CR characters.
///
/// @returns FAIL for failure, OK otherwise
bool cmdline_paste_reg(int regname, bool literally, bool remcr)
bool cmdline_paste_reg(int regname, bool literally_arg, bool remcr)
{
const bool literally = literally_arg || is_literal_register(regname);
yankreg_T *reg = get_yank_register(regname, YREG_PASTE);
if (reg->y_array == NULL)
return FAIL;
@ -2534,7 +2546,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
case kMTCharWise:
{
colnr_T startcol = 0, endcol = MAXCOL;
int is_oneChar = FALSE;
int is_oneChar = false;
colnr_T cs, ce;
p = ml_get(lnum);
bd.startspaces = 0;
@ -2565,8 +2577,8 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
&& utf_head_off(p, p + endcol) == 0)) {
if (oap->start.lnum == oap->end.lnum
&& oap->start.col == oap->end.col) {
/* Special case: inside a single char */
is_oneChar = TRUE;
// Special case: inside a single char
is_oneChar = true;
bd.startspaces = oap->end.coladd
- oap->start.coladd + oap->inclusive;
endcol = startcol;
@ -4425,8 +4437,8 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum,
bdp->textlen = 0;
bdp->start_vcol = 0;
bdp->end_vcol = 0;
bdp->is_short = FALSE;
bdp->is_oneChar = FALSE;
bdp->is_short = false;
bdp->is_oneChar = false;
bdp->pre_whitesp = 0;
bdp->pre_whitesp_c = 0;
bdp->end_char_vcols = 0;
@ -4452,9 +4464,10 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum,
bdp->start_char_vcols = incr;
if (bdp->start_vcol < oap->start_vcol) { /* line too short */
bdp->end_vcol = bdp->start_vcol;
bdp->is_short = TRUE;
if (!is_del || oap->op_type == OP_APPEND)
bdp->is_short = true;
if (!is_del || oap->op_type == OP_APPEND) {
bdp->endspaces = oap->end_vcol - oap->start_vcol + 1;
}
} else {
/* notice: this converts partly selected Multibyte characters to
* spaces, too. */
@ -4463,11 +4476,11 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum,
bdp->startspaces = bdp->start_char_vcols - bdp->startspaces;
pend = pstart;
bdp->end_vcol = bdp->start_vcol;
if (bdp->end_vcol > oap->end_vcol) { /* it's all in one character */
bdp->is_oneChar = TRUE;
if (oap->op_type == OP_INSERT)
if (bdp->end_vcol > oap->end_vcol) { // it's all in one character
bdp->is_oneChar = true;
if (oap->op_type == OP_INSERT) {
bdp->endspaces = bdp->start_char_vcols - bdp->startspaces;
else if (oap->op_type == OP_APPEND) {
} else if (oap->op_type == OP_APPEND) {
bdp->startspaces += oap->end_vcol - oap->start_vcol + 1;
bdp->endspaces = bdp->start_char_vcols - bdp->startspaces;
} else {
@ -4492,17 +4505,16 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum,
if (bdp->end_vcol <= oap->end_vcol
&& (!is_del
|| oap->op_type == OP_APPEND
|| oap->op_type == OP_REPLACE)) { /* line too short */
bdp->is_short = TRUE;
/* Alternative: include spaces to fill up the block.
* Disadvantage: can lead to trailing spaces when the line is
* short where the text is put */
/* if (!is_del || oap->op_type == OP_APPEND) */
if (oap->op_type == OP_APPEND || virtual_op)
|| oap->op_type == OP_REPLACE)) { // line too short
bdp->is_short = true;
// Alternative: include spaces to fill up the block.
// Disadvantage: can lead to trailing spaces when the line is
// short where the text is put
// if (!is_del || oap->op_type == OP_APPEND)
if (oap->op_type == OP_APPEND || virtual_op) {
bdp->endspaces = oap->end_vcol - bdp->end_vcol
+ oap->inclusive;
else
bdp->endspaces = 0; /* replace doesn't add characters */
}
} else if (bdp->end_vcol > oap->end_vcol) {
bdp->endspaces = bdp->end_vcol - oap->end_vcol - 1;
if (!is_del && bdp->endspaces) {

View File

@ -6073,10 +6073,8 @@ void buf_copy_options(buf_T *buf, int flags)
save_p_isk = buf->b_p_isk;
buf->b_p_isk = NULL;
}
/*
* Always free the allocated strings.
* If not already initialized, set 'readonly' and copy 'fileformat'.
*/
// Always free the allocated strings. If not already initialized,
// reset 'readonly' and copy 'fileformat'.
if (!buf->b_p_initialized) {
free_buf_options(buf, true);
buf->b_p_ro = false; // don't copy readonly

View File

@ -448,7 +448,6 @@ int os_expand_wildcards(int num_pat, char_u **pat, int *num_file,
} else {
buffer[len] = NUL;
}
i = 0;
for (p = buffer; p < buffer + len; p++) {
if (*p == NUL || (*p == ' ' && check_spaces)) { // count entry
i++;

View File

@ -334,10 +334,10 @@ int update_screen(int type)
}
return FAIL;
}
updating_screen = 1;
updating_screen = TRUE;
++display_tick; /* let syntax code know we're in a next round of
* display updating */
display_tick++; // let syntax code know we're in a next round of
// display updating
// Tricky: vim code can reset msg_scrolled behind our back, so need
// separate bookkeeping for now.
@ -565,7 +565,7 @@ int update_screen(int type)
wp->w_buffer->b_mod_set = false;
}
updating_screen = FALSE;
updating_screen = 0;
/* Clear or redraw the command line. Done last, because scrolling may
* mess up the command line. */
@ -2215,9 +2215,10 @@ win_line (
int n_skip = 0; /* nr of chars to skip for 'nowrap' */
int fromcol = 0, tocol = 0; // start/end of inverting
int fromcol = -10; // start of inverting
int tocol = MAXCOL; // end of inverting
int fromcol_prev = -2; // start of inverting after cursor
int noinvcur = false; // don't invert the cursor
bool noinvcur = false; // don't invert the cursor
pos_T *top, *bot;
int lnum_in_visual_area = false;
pos_T pos;
@ -2416,27 +2417,26 @@ win_line (
capcol_lnum = 0;
}
//
// handle visual active in this window
//
fromcol = -10;
tocol = MAXCOL;
// handle Visual active in this window
if (VIsual_active && wp->w_buffer == curwin->w_buffer) {
// Visual is after curwin->w_cursor
if (ltoreq(curwin->w_cursor, VIsual)) {
// Visual is after curwin->w_cursor
top = &curwin->w_cursor;
bot = &VIsual;
} else { // Visual is before curwin->w_cursor
} else {
// Visual is before curwin->w_cursor
top = &VIsual;
bot = &curwin->w_cursor;
}
lnum_in_visual_area = (lnum >= top->lnum && lnum <= bot->lnum);
if (VIsual_mode == Ctrl_V) { // block mode
if (VIsual_mode == Ctrl_V) {
// block mode
if (lnum_in_visual_area) {
fromcol = wp->w_old_cursor_fcol;
tocol = wp->w_old_cursor_lcol;
}
} else { // non-block mode
} else {
// non-block mode
if (lnum > top->lnum && lnum <= bot->lnum) {
fromcol = 0;
} else if (lnum == top->lnum) {

View File

@ -198,7 +198,7 @@ static void insert_sign(
// column for signs.
if (buf->b_signlist == NULL) {
redraw_buf_later(buf, NOT_VALID);
changed_cline_bef_curs();
changed_line_abv_curs();
}
// first sign in signlist
@ -265,6 +265,81 @@ dict_T * sign_get_info(signlist_T *sign)
return d;
}
// Sort the signs placed on the same line as "sign" by priority. Invoked after
// changing the priority of an already placed sign. Assumes the signs in the
// buffer are sorted by line number and priority.
static void sign_sort_by_prio_on_line(buf_T *buf, signlist_T *sign)
FUNC_ATTR_NONNULL_ALL
{
// If there is only one sign in the buffer or only one sign on the line or
// the sign is already sorted by priority, then return.
if ((sign->prev == NULL
|| sign->prev->lnum != sign->lnum
|| sign->prev->priority > sign->priority)
&& (sign->next == NULL
|| sign->next->lnum != sign->lnum
|| sign->next->priority < sign->priority)) {
return;
}
// One or more signs on the same line as 'sign'
// Find a sign after which 'sign' should be inserted
// First search backward for a sign with higher priority on the same line
signlist_T *p = sign;
while (p->prev != NULL
&& p->prev->lnum == sign->lnum
&& p->prev->priority <= sign->priority) {
p = p->prev;
}
if (p == sign) {
// Sign not found. Search forward for a sign with priority just before
// 'sign'.
p = sign->next;
while (p->next != NULL
&& p->next->lnum == sign->lnum
&& p->next->priority > sign->priority) {
p = p->next;
}
}
// Remove 'sign' from the list
if (buf->b_signlist == sign) {
buf->b_signlist = sign->next;
}
if (sign->prev != NULL) {
sign->prev->next = sign->next;
}
if (sign->next != NULL) {
sign->next->prev = sign->prev;
}
sign->prev = NULL;
sign->next = NULL;
// Re-insert 'sign' at the right place
if (p->priority <= sign->priority) {
// 'sign' has a higher priority and should be inserted before 'p'
sign->prev = p->prev;
sign->next = p;
p->prev = sign;
if (sign->prev != NULL) {
sign->prev->next = sign;
}
if (buf->b_signlist == p) {
buf->b_signlist = sign;
}
} else {
// 'sign' has a lower priority and should be inserted after 'p'
sign->prev = p;
sign->next = p->next;
p->next = sign;
if (sign->next != NULL) {
sign->next->prev = sign;
}
}
}
/// Add the sign into the signlist. Find the right spot to do it though.
void buf_addsign(
buf_T *buf, // buffer to store sign in
@ -284,6 +359,8 @@ void buf_addsign(
&& sign_in_group(sign, groupname)) {
// Update an existing sign
sign->typenr = typenr;
sign->priority = prio;
sign_sort_by_prio_on_line(buf, sign);
return;
} else if (lnum < sign->lnum) {
insert_sign_by_lnum_prio(buf, prev, id, groupname, prio, lnum, typenr);
@ -418,11 +495,11 @@ linenr_T buf_delsign(
}
}
// When deleted the last sign needs to redraw the windows to remove the
// sign column.
// When deleting the last sign the cursor position may change, because the
// sign columns no longer shows. And the 'signcolumn' may be hidden.
if (buf->b_signlist == NULL) {
redraw_buf_later(buf, NOT_VALID);
changed_cline_bef_curs();
changed_line_abv_curs();
}
return lnum;
@ -495,7 +572,7 @@ void buf_delete_signs(buf_T *buf, char_u *group)
// When deleting the last sign need to redraw the windows to remove the
// sign column. Not when curwin is NULL (this means we're exiting).
if (buf->b_signlist != NULL && curwin != NULL) {
changed_cline_bef_curs();
changed_line_abv_curs();
}
lastp = &buf->b_signlist;
@ -754,6 +831,14 @@ int sign_define_by_name(
} else {
sp_prev->sn_next = sp;
}
} else {
// Signs may already exist, a redraw is needed in windows with a
// non-empty sign list.
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_buffer->b_signlist != NULL) {
redraw_buf_later(wp->w_buffer, NOT_VALID);
}
}
}
// set values for a defined sign.
@ -1531,10 +1616,44 @@ static enum
EXP_SUBCMD, // expand :sign sub-commands
EXP_DEFINE, // expand :sign define {name} args
EXP_PLACE, // expand :sign place {id} args
EXP_LIST, // expand :sign place args
EXP_UNPLACE, // expand :sign unplace"
EXP_SIGN_NAMES // expand with name of placed signs
EXP_SIGN_NAMES, // expand with name of placed signs
EXP_SIGN_GROUPS, // expand with name of placed sign groups
} expand_what;
// Return the n'th sign name (used for command line completion)
static char_u *get_nth_sign_name(int idx)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
// Complete with name of signs already defined
int current_idx = 0;
for (sign_T *sp = first_sign; sp != NULL; sp = sp->sn_next) {
if (current_idx++ == idx) {
return sp->sn_name;
}
}
return NULL;
}
// Return the n'th sign group name (used for command line completion)
static char_u *get_nth_sign_group_name(int idx)
{
// Complete with name of sign groups already defined
int current_idx = 0;
int todo = (int)sg_table.ht_used;
for (hashitem_T *hi = sg_table.ht_array; todo > 0; hi++) {
if (!HASHITEM_EMPTY(hi)) {
todo--;
if (current_idx++ == idx) {
signgroup_T *const group = HI2SG(hi);
return group->sg_name;
}
}
}
return NULL;
}
/// Function given to ExpandGeneric() to obtain the sign command
/// expansion.
char_u * get_sign_name(expand_T *xp, int idx)
@ -1552,20 +1671,18 @@ char_u * get_sign_name(expand_T *xp, int idx)
"buffer=", NULL };
return (char_u *)place_arg[idx];
}
case EXP_LIST: {
char *list_arg[] = { "group=", "file=", "buffer=", NULL };
return (char_u *)list_arg[idx];
}
case EXP_UNPLACE: {
char *unplace_arg[] = { "group=", "file=", "buffer=", NULL };
return (char_u *)unplace_arg[idx];
}
case EXP_SIGN_NAMES: {
// Complete with name of signs already defined
int current_idx = 0;
for (sign_T *sp = first_sign; sp != NULL; sp = sp->sn_next) {
if (current_idx++ == idx) {
return sp->sn_name;
}
}
}
return NULL;
case EXP_SIGN_NAMES:
return get_nth_sign_name(idx);
case EXP_SIGN_GROUPS:
return get_nth_sign_group_name(idx);
default:
return NULL;
}
@ -1574,7 +1691,6 @@ char_u * get_sign_name(expand_T *xp, int idx)
/// Handle command line completion for :sign command.
void set_context_in_sign_cmd(expand_T *xp, char_u *arg)
{
char_u *p;
char_u *end_subcmd;
char_u *last;
int cmd_idx;
@ -1598,26 +1714,6 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg)
// |
// begin_subcmd_args
begin_subcmd_args = skipwhite(end_subcmd);
p = skiptowhite(begin_subcmd_args);
if (*p == NUL) {
//
// Expand first argument of subcmd when possible.
// For ":jump {id}" and ":unplace {id}", we could
// possibly expand the ids of all signs already placed.
//
xp->xp_pattern = begin_subcmd_args;
switch (cmd_idx) {
case SIGNCMD_LIST:
case SIGNCMD_UNDEFINE:
// :sign list <CTRL-D>
// :sign undefine <CTRL-D>
expand_what = EXP_SIGN_NAMES;
break;
default:
xp->xp_context = EXPAND_NOTHING;
}
return;
}
// Expand last argument of subcmd.
//
@ -1626,6 +1722,7 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg)
// p
// Loop until reaching last argument.
char_u *p = begin_subcmd_args;
do {
p = skipwhite(p);
last = p;
@ -1645,7 +1742,20 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg)
expand_what = EXP_DEFINE;
break;
case SIGNCMD_PLACE:
expand_what = EXP_PLACE;
// List placed signs
if (ascii_isdigit(*begin_subcmd_args)) {
// :sign place {id} {args}...
expand_what = EXP_PLACE;
} else {
// :sign place {args}...
expand_what = EXP_LIST;
}
break;
case SIGNCMD_LIST:
case SIGNCMD_UNDEFINE:
// :sign list <CTRL-D>
// :sign undefine <CTRL-D>
expand_what = EXP_SIGN_NAMES;
break;
case SIGNCMD_JUMP:
case SIGNCMD_UNPLACE:
@ -1659,19 +1769,33 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg)
xp->xp_pattern = p + 1;
switch (cmd_idx) {
case SIGNCMD_DEFINE:
if (STRNCMP(last, "texthl", p - last) == 0
|| STRNCMP(last, "linehl", p - last) == 0
|| STRNCMP(last, "numhl", p - last) == 0) {
if (STRNCMP(last, "texthl", 6) == 0
|| STRNCMP(last, "linehl", 6) == 0
|| STRNCMP(last, "numhl", 5) == 0) {
xp->xp_context = EXPAND_HIGHLIGHT;
} else if (STRNCMP(last, "icon", p - last) == 0) {
} else if (STRNCMP(last, "icon", 4) == 0) {
xp->xp_context = EXPAND_FILES;
} else {
xp->xp_context = EXPAND_NOTHING;
}
break;
case SIGNCMD_PLACE:
if (STRNCMP(last, "name", p - last) == 0) {
if (STRNCMP(last, "name", 4) == 0) {
expand_what = EXP_SIGN_NAMES;
} else if (STRNCMP(last, "group", 5) == 0) {
expand_what = EXP_SIGN_GROUPS;
} else if (STRNCMP(last, "file", 4) == 0) {
xp->xp_context = EXPAND_BUFFERS;
} else {
xp->xp_context = EXPAND_NOTHING;
}
break;
case SIGNCMD_UNPLACE:
case SIGNCMD_JUMP:
if (STRNCMP(last, "group", 5) == 0) {
expand_what = EXP_SIGN_GROUPS;
} else if (STRNCMP(last, "file", 4) == 0) {
xp->xp_context = EXPAND_BUFFERS;
} else {
xp->xp_context = EXPAND_NOTHING;
}

View File

@ -252,3 +252,14 @@ func Test_numberwidth_adjusted()
call s:compare_lines(expect, lines)
call s:close_windows()
endfunc
" This was causing a memcheck error
func Test_relativenumber_uninitialised()
new
set rnu
call setline(1, ["a", "b"])
redraw
call feedkeys("j", 'xt')
redraw
bwipe!
endfunc

View File

@ -511,3 +511,11 @@ func Test_shortmess_F2()
bwipe
bwipe
endfunc
func Test_visualbell()
set belloff=
set visualbell
call assert_beeps('normal 0h')
set novisualbell
set belloff=all
endfunc

View File

@ -0,0 +1,103 @@
" Test for "rvim" or "vim -Z"
source shared.vim
"if has('win32') && has('gui')
" " Win32 GUI shows a dialog instead of displaying the error in the last line.
" finish
"endif
func Test_restricted()
call Run_restricted_test('!ls', 'E145:')
endfunc
func Run_restricted_test(ex_cmd, error)
let cmd = GetVimCommand('Xrestricted')
if cmd == ''
return
endif
" Use a VimEnter autocommand to avoid that the error message is displayed in
" a dialog with an OK button.
call writefile([
\ "func Init()",
\ " silent! " . a:ex_cmd,
\ " call writefile([v:errmsg], 'Xrestrout')",
\ " qa!",
\ "endfunc",
\ "au VimEnter * call Init()",
\ ], 'Xrestricted')
call system(cmd . ' -Z')
call assert_match(a:error, join(readfile('Xrestrout')))
call delete('Xrestricted')
call delete('Xrestrout')
endfunc
func Test_restricted_lua()
if !has('lua')
throw 'Skipped: Lua is not supported'
endif
call Run_restricted_test('lua print("Hello, Vim!")', 'E981:')
call Run_restricted_test('luado return "hello"', 'E981:')
call Run_restricted_test('luafile somefile', 'E981:')
call Run_restricted_test('call luaeval("expression")', 'E145:')
endfunc
func Test_restricted_mzscheme()
if !has('mzscheme')
throw 'Skipped: MzScheme is not supported'
endif
call Run_restricted_test('mzscheme statement', 'E981:')
call Run_restricted_test('mzfile somefile', 'E981:')
call Run_restricted_test('call mzeval("expression")', 'E145:')
endfunc
func Test_restricted_perl()
if !has('perl')
throw 'Skipped: Perl is not supported'
endif
" TODO: how to make Safe mode fail?
" call Run_restricted_test('perl system("ls")', 'E981:')
" call Run_restricted_test('perldo system("hello")', 'E981:')
" call Run_restricted_test('perlfile somefile', 'E981:')
" call Run_restricted_test('call perleval("system(\"ls\")")', 'E145:')
endfunc
func Test_restricted_python()
if !has('python')
throw 'Skipped: Python is not supported'
endif
call Run_restricted_test('python print "hello"', 'E981:')
call Run_restricted_test('pydo return "hello"', 'E981:')
call Run_restricted_test('pyfile somefile', 'E981:')
call Run_restricted_test('call pyeval("expression")', 'E145:')
endfunc
func Test_restricted_python3()
if !has('python3')
throw 'Skipped: Python3 is not supported'
endif
call Run_restricted_test('py3 print "hello"', 'E981:')
call Run_restricted_test('py3do return "hello"', 'E981:')
call Run_restricted_test('py3file somefile', 'E981:')
call Run_restricted_test('call py3eval("expression")', 'E145:')
endfunc
func Test_restricted_ruby()
if !has('ruby')
throw 'Skipped: Ruby is not supported'
endif
call Run_restricted_test('ruby print "Hello"', 'E981:')
call Run_restricted_test('rubydo print "Hello"', 'E981:')
call Run_restricted_test('rubyfile somefile', 'E981:')
endfunc
func Test_restricted_tcl()
if !has('tcl')
throw 'Skipped: Tcl is not supported'
endif
call Run_restricted_test('tcl puts "Hello"', 'E981:')
call Run_restricted_test('tcldo puts "Hello"', 'E981:')
call Run_restricted_test('tclfile somefile', 'E981:')
endfunc

View File

@ -698,3 +698,9 @@ func Test_search_display_pattern()
set norl
endif
endfunc
func Test_search_special()
" this was causing illegal memory access and an endless loop
set t_PE=
exe "norm /\x80PS"
endfunc

View File

@ -4,6 +4,8 @@ if !has('signs')
finish
endif
source screendump.vim
func Test_sign()
new
call setline(1, ['a', 'b', 'c', 'd'])
@ -210,13 +212,16 @@ func Test_sign_completion()
call assert_equal('"sign define Sign linehl=SpellBad SpellCap ' .
\ 'SpellLocal SpellRare', @:)
call writefile(['foo'], 'XsignOne')
call writefile(['bar'], 'XsignTwo')
call feedkeys(":sign define Sign texthl=Spell\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign define Sign texthl=SpellBad SpellCap ' .
\ 'SpellLocal SpellRare', @:)
call writefile(repeat(["Sun is shining"], 30), "XsignOne")
call writefile(repeat(["Sky is blue"], 30), "XsignTwo")
call feedkeys(":sign define Sign icon=Xsig\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign define Sign icon=XsignOne XsignTwo', @:)
call delete('XsignOne')
call delete('XsignTwo')
" Test for completion of arguments to ':sign undefine'
call feedkeys(":sign undefine \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign undefine Sign1 Sign2', @:)
@ -227,17 +232,70 @@ func Test_sign_completion()
call feedkeys(":sign place 1 name=\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign place 1 name=Sign1 Sign2', @:)
edit XsignOne
sign place 1 name=Sign1 line=5
sign place 1 name=Sign1 group=g1 line=10
edit XsignTwo
sign place 1 name=Sign2 group=g2 line=15
" Test for completion of group= and file= arguments to ':sign place'
call feedkeys(":sign place 1 name=Sign1 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign place 1 name=Sign1 file=XsignOne XsignTwo', @:)
call feedkeys(":sign place 1 name=Sign1 group=\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign place 1 name=Sign1 group=g1 g2', @:)
" Test for completion of arguments to 'sign place' without sign identifier
call feedkeys(":sign place \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign place buffer= file= group=', @:)
call feedkeys(":sign place file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign place file=XsignOne XsignTwo', @:)
call feedkeys(":sign place group=\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign place group=g1 g2', @:)
call feedkeys(":sign place group=g1 file=\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign place group=g1 file=XsignOne XsignTwo', @:)
" Test for completion of arguments to ':sign unplace'
call feedkeys(":sign unplace 1 \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign unplace 1 buffer= file= group=', @:)
call feedkeys(":sign unplace 1 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign unplace 1 file=XsignOne XsignTwo', @:)
call feedkeys(":sign unplace 1 group=\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign unplace 1 group=g1 g2', @:)
call feedkeys(":sign unplace 1 group=g2 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign unplace 1 group=g2 file=XsignOne XsignTwo', @:)
" Test for completion of arguments to ':sign list'
call feedkeys(":sign list \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign list Sign1 Sign2', @:)
" Test for completion of arguments to ':sign jump'
call feedkeys(":sign jump 1 \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign jump 1 buffer= file= group=', @:)
call feedkeys(":sign jump 1 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign jump 1 file=XsignOne XsignTwo', @:)
call feedkeys(":sign jump 1 group=\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign jump 1 group=g1 g2', @:)
" Error cases
call feedkeys(":sign here\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign here', @:)
call feedkeys(":sign define Sign here=\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"sign define Sign here=\<C-A>", @:)
call feedkeys(":sign place 1 here=\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"sign place 1 here=\<C-A>", @:)
call feedkeys(":sign jump 1 here=\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"sign jump 1 here=\<C-A>", @:)
call feedkeys(":sign here there\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"sign here there\<C-A>", @:)
call feedkeys(":sign here there=\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"sign here there=\<C-A>", @:)
sign unplace * group=*
sign undefine Sign1
sign undefine Sign2
enew
call delete('XsignOne')
call delete('XsignTwo')
endfunc
func Test_sign_invalid_commands()
@ -1127,6 +1185,319 @@ func Test_sign_priority()
\ 'priority' : 10}],
\ s[0].signs)
call sign_unplace('*')
" Three signs on different lines with changing priorities
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 11, 'priority' : 50})
call sign_place(2, '', 'sign2', 'Xsign',
\ {'lnum' : 12, 'priority' : 60})
call sign_place(3, '', 'sign3', 'Xsign',
\ {'lnum' : 13, 'priority' : 70})
call sign_place(2, '', 'sign2', 'Xsign',
\ {'lnum' : 12, 'priority' : 40})
call sign_place(3, '', 'sign3', 'Xsign',
\ {'lnum' : 13, 'priority' : 30})
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 11, 'priority' : 50})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 11, 'group' : '',
\ 'priority' : 50},
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 12, 'group' : '',
\ 'priority' : 40},
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 13, 'group' : '',
\ 'priority' : 30}],
\ s[0].signs)
call sign_unplace('*')
" Two signs on the same line with changing priorities
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 20})
call sign_place(2, '', 'sign2', 'Xsign',
\ {'lnum' : 4, 'priority' : 30})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 30},
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 20}],
\ s[0].signs)
" Change the priority of the last sign to highest
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 40})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 40},
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 30}],
\ s[0].signs)
" Change the priority of the first sign to lowest
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 25})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 30},
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 25}],
\ s[0].signs)
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 45})
call sign_place(2, '', 'sign2', 'Xsign',
\ {'lnum' : 4, 'priority' : 55})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 55},
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 45}],
\ s[0].signs)
call sign_unplace('*')
" Three signs on the same line with changing priorities
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 40})
call sign_place(2, '', 'sign2', 'Xsign',
\ {'lnum' : 4, 'priority' : 30})
call sign_place(3, '', 'sign3', 'Xsign',
\ {'lnum' : 4, 'priority' : 20})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 40},
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 30},
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 20}],
\ s[0].signs)
" Change the priority of the middle sign to the highest
call sign_place(2, '', 'sign2', 'Xsign',
\ {'lnum' : 4, 'priority' : 50})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 50},
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 40},
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 20}],
\ s[0].signs)
" Change the priority of the middle sign to the lowest
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 15})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 50},
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 15}],
\ s[0].signs)
" Change the priority of the last sign to the highest
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 55})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 55},
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 50},
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 20}],
\ s[0].signs)
" Change the priority of the first sign to the lowest
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 15})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 50},
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 15}],
\ s[0].signs)
call sign_unplace('*')
" Three signs on the same line with changing priorities along with other
" signs
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 2, 'priority' : 10})
call sign_place(2, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 30})
call sign_place(3, '', 'sign2', 'Xsign',
\ {'lnum' : 4, 'priority' : 20})
call sign_place(4, '', 'sign3', 'Xsign',
\ {'lnum' : 4, 'priority' : 25})
call sign_place(5, '', 'sign2', 'Xsign',
\ {'lnum' : 6, 'priority' : 80})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
\ 'priority' : 10},
\ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 30},
\ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 25},
\ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
\ 'priority' : 80}],
\ s[0].signs)
" Change the priority of the first sign to lowest
call sign_place(2, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 15})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
\ 'priority' : 10},
\ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 25},
\ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 15},
\ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
\ 'priority' : 80}],
\ s[0].signs)
" Change the priority of the last sign to highest
call sign_place(2, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 30})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
\ 'priority' : 10},
\ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 30},
\ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 25},
\ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
\ 'priority' : 80}],
\ s[0].signs)
" Change the priority of the middle sign to lowest
call sign_place(4, '', 'sign3', 'Xsign',
\ {'lnum' : 4, 'priority' : 15})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
\ 'priority' : 10},
\ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 30},
\ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 15},
\ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
\ 'priority' : 80}],
\ s[0].signs)
" Change the priority of the middle sign to highest
call sign_place(3, '', 'sign2', 'Xsign',
\ {'lnum' : 4, 'priority' : 35})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
\ 'priority' : 10},
\ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 35},
\ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 30},
\ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 15},
\ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
\ 'priority' : 80}],
\ s[0].signs)
call sign_unplace('*')
" Multiple signs with the same priority on the same line
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 20})
call sign_place(2, '', 'sign2', 'Xsign',
\ {'lnum' : 4, 'priority' : 20})
call sign_place(3, '', 'sign3', 'Xsign',
\ {'lnum' : 4, 'priority' : 20})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 20}],
\ s[0].signs)
" Place the last sign again with the same priority
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 20})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 20}],
\ s[0].signs)
" Place the first sign again with the same priority
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 20})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 20}],
\ s[0].signs)
" Place the middle sign again with the same priority
call sign_place(3, '', 'sign3', 'Xsign',
\ {'lnum' : 4, 'priority' : 20})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 20}],
\ s[0].signs)
call sign_unplace('*')
" Place multiple signs with same id on a line with different priority
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 5, 'priority' : 20})
call sign_place(1, '', 'sign2', 'Xsign',
\ {'lnum' : 5, 'priority' : 10})
let s = sign_getplaced('Xsign', {'lnum' : 5})
call assert_equal([
\ {'id' : 1, 'name' : 'sign2', 'lnum' : 5, 'group' : '',
\ 'priority' : 10}],
\ s[0].signs)
call sign_place(1, '', 'sign2', 'Xsign',
\ {'lnum' : 5, 'priority' : 5})
let s = sign_getplaced('Xsign', {'lnum' : 5})
call assert_equal([
\ {'id' : 1, 'name' : 'sign2', 'lnum' : 5, 'group' : '',
\ 'priority' : 5}],
\ s[0].signs)
" Error case
call assert_fails("call sign_place(1, 'g1', 'sign1', 'Xsign',
\ [])", 'E715:')
@ -1339,3 +1710,35 @@ func Test_sign_jump_func()
sign undefine sign1
enew! | only!
endfunc
" Test for correct cursor position after the sign column appears or disappears.
func Test_sign_cursor_position()
if !CanRunVimInTerminal()
throw 'Skipped: cannot make screendumps'
endif
let lines =<< trim END
call setline(1, [repeat('x', 75), 'mmmm', 'yyyy'])
call cursor(2,1)
sign define s1 texthl=Search text==>
redraw
sign place 10 line=2 name=s1
END
call writefile(lines, 'XtestSigncolumn')
let buf = RunVimInTerminal('-S XtestSigncolumn', {'rows': 6})
call VerifyScreenDump(buf, 'Test_sign_cursor_1', {})
" Change the sign text
call term_sendkeys(buf, ":sign define s1 text=-)\<CR>")
call VerifyScreenDump(buf, 'Test_sign_cursor_2', {})
" update cursor position calculation
call term_sendkeys(buf, "lh")
call term_sendkeys(buf, ":sign unplace 10\<CR>")
call VerifyScreenDump(buf, 'Test_sign_cursor_3', {})
" clean up
call StopVimInTerminal(buf)
call delete('XtestSigncolumn')
endfunc

View File

@ -70,6 +70,40 @@ describe('expand file name', function()
call assert_match('\~', expand('%:p'))
bwipe!
endfunc
func Test_expandcmd()
let $FOO = 'Test'
call assert_equal('e x/Test/y', expandcmd('e x/$FOO/y'))
unlet $FOO
new
edit Xfile1
call assert_equal('e Xfile1', expandcmd('e %'))
edit Xfile2
edit Xfile1
call assert_equal('e Xfile2', expandcmd('e #'))
edit Xfile2
edit Xfile3
edit Xfile4
let bnum = bufnr('Xfile2')
call assert_equal('e Xfile2', expandcmd('e #' . bnum))
call setline('.', 'Vim!@#')
call assert_equal('e Vim', expandcmd('e <cword>'))
call assert_equal('e Vim!@#', expandcmd('e <cWORD>'))
enew!
edit Xfile.java
call assert_equal('e Xfile.py', expandcmd('e %:r.py'))
call assert_equal('make abc.java', expandcmd('make abc.%:e'))
call assert_equal('make Xabc.java', expandcmd('make %:s?file?abc?'))
edit a1a2a3.rb
call assert_equal('make b1b2b3.rb a1a2a3 Xfile.o', expandcmd('make %:gs?a?b? %< #<.o'))
call assert_fails('call expandcmd("make <afile>")', 'E495:')
call assert_fails('call expandcmd("make <afile>")', 'E495:')
enew
call assert_fails('call expandcmd("make %")', 'E499:')
close
endfunc
]])
end)
@ -87,4 +121,9 @@ describe('expand file name', function()
call('Test_expand_tilde_filename')
expected_empty()
end)
it('works with expandcmd()', function()
call('Test_expandcmd')
expected_empty()
end)
end)