Merge pull request #3753 from watiko/vim-7.4.790

Vim 7.4.{786,787,789,790}
This commit is contained in:
Justin M. Keyes 2015-12-12 17:43:23 -05:00
commit cc203e4b93
9 changed files with 413 additions and 13 deletions

View File

@ -258,6 +258,7 @@ Name triggered by ~
|Syntax| when the 'syntax' option has been set |Syntax| when the 'syntax' option has been set
|EncodingChanged| after the 'encoding' option has been changed |EncodingChanged| after the 'encoding' option has been changed
|TermChanged| after the value of 'term' has changed |TermChanged| after the value of 'term' has changed
|OptionSet| after setting any option
Startup and exit Startup and exit
|VimEnter| after doing all the startup stuff |VimEnter| after doing all the startup stuff
@ -745,6 +746,24 @@ MenuPopup Just before showing the popup menu (under the
o Operator-pending o Operator-pending
i Insert i Insert
c Command line c Command line
*OptionSet*
OptionSet After setting an option. The pattern is
matched against the long option name.
The |v:option_old| variable indicates the
old option value, |v:option_new| variable
indicates the newly set value, the
|v:option_type| variable indicates whether
it's global or local scoped and |<amatch>|
indicates what option has been set.
Note: It's a bad idea, to reset an option
during this autocommand, since this will
probably break plugins. You can always use
|noa| to prevent triggering this autocommand.
Could be used, to check for existence of the
'backupdir' and 'undodir' options and create
directories, if they don't exist yet.
*QuickFixCmdPre* *QuickFixCmdPre*
QuickFixCmdPre Before a quickfix command is run (|:make|, QuickFixCmdPre Before a quickfix command is run (|:make|,
|:lmake|, |:grep|, |:lgrep|, |:grepadd|, |:lmake|, |:grep|, |:lgrep|, |:grepadd|,

View File

@ -1535,6 +1535,15 @@ v:oldfiles List of file names that is loaded from the |shada| file on
than String this will cause trouble. than String this will cause trouble.
{only when compiled with the |+shada| feature} {only when compiled with the |+shada| feature}
*v:option_new*
v:option_new New value of the option. Valid while executing an |OptionSet|
autocommand.
*v:option_old*
v:option_old Old value of the option. Valid while executing an |OptionSet|
autocommand.
*v:option_type*
v:option_type Scope of the set command. Valid while executing an
|OptionSet| autocommand. Can be either "global" or "local"
*v:operator* *operator-variable* *v:operator* *operator-variable*
v:operator The last operator given in Normal mode. This is a single v:operator The last operator given in Normal mode. This is a single
character except for commands starting with <g> or <z>, character except for commands starting with <g> or <z>,

View File

@ -57,6 +57,7 @@ return {
'InsertLeave', -- when leaving Insert mode 'InsertLeave', -- when leaving Insert mode
'JobActivity', -- when job sent some data 'JobActivity', -- when job sent some data
'MenuPopup', -- just before popup menu is displayed 'MenuPopup', -- just before popup menu is displayed
'OptionSet', -- after setting any option
'QuickFixCmdPost', -- after :make, :grep etc. 'QuickFixCmdPost', -- after :make, :grep etc.
'QuickFixCmdPre', -- before :make, :grep etc. 'QuickFixCmdPre', -- before :make, :grep etc.
'QuitPre', -- before :quit 'QuitPre', -- before :quit

View File

@ -373,6 +373,9 @@ static struct vimvar {
{VV_NAME("progpath", VAR_STRING), VV_RO}, {VV_NAME("progpath", VAR_STRING), VV_RO},
{VV_NAME("command_output", VAR_STRING), 0}, {VV_NAME("command_output", VAR_STRING), 0},
{VV_NAME("completed_item", VAR_DICT), VV_RO}, {VV_NAME("completed_item", VAR_DICT), VV_RO},
{VV_NAME("option_new", VAR_STRING), VV_RO},
{VV_NAME("option_old", VAR_STRING), VV_RO},
{VV_NAME("option_type", VAR_STRING), VV_RO},
{VV_NAME("msgpack_types", VAR_DICT), VV_RO}, {VV_NAME("msgpack_types", VAR_DICT), VV_RO},
}; };
@ -21238,9 +21241,13 @@ void ex_oldfiles(exarg_T *eap)
} }
} }
// reset v:option_new, v:option_old and v:option_type
void reset_v_option_vars(void)
{
set_vim_var_string(VV_OPTION_NEW, NULL, -1);
set_vim_var_string(VV_OPTION_OLD, NULL, -1);
set_vim_var_string(VV_OPTION_TYPE, NULL, -1);
}
/* /*
* Adjust a filename, according to a string of modifiers. * Adjust a filename, according to a string of modifiers.

View File

@ -108,6 +108,9 @@ enum {
VV_PROGPATH, VV_PROGPATH,
VV_COMMAND_OUTPUT, VV_COMMAND_OUTPUT,
VV_COMPLETED_ITEM, VV_COMPLETED_ITEM,
VV_OPTION_NEW,
VV_OPTION_OLD,
VV_OPTION_TYPE,
VV_MSGPACK_TYPES, VV_MSGPACK_TYPES,
VV_LEN, /* number of v: vars */ VV_LEN, /* number of v: vars */
}; };

View File

@ -6407,7 +6407,7 @@ apply_autocmds_group (
* invalid. * invalid.
*/ */
if (fname_io == NULL) { if (fname_io == NULL) {
if (event == EVENT_COLORSCHEME) if (event == EVENT_COLORSCHEME || event == EVENT_OPTIONSET)
autocmd_fname = NULL; autocmd_fname = NULL;
else if (fname != NULL && *fname != NUL) else if (fname != NULL && *fname != NUL)
autocmd_fname = fname; autocmd_fname = fname;
@ -6457,6 +6457,7 @@ apply_autocmds_group (
if (event == EVENT_COLORSCHEME if (event == EVENT_COLORSCHEME
|| event == EVENT_FILETYPE || event == EVENT_FILETYPE
|| event == EVENT_FUNCUNDEFINED || event == EVENT_FUNCUNDEFINED
|| event == EVENT_OPTIONSET
|| event == EVENT_QUICKFIXCMDPOST || event == EVENT_QUICKFIXCMDPOST
|| event == EVENT_QUICKFIXCMDPRE || event == EVENT_QUICKFIXCMDPRE
|| event == EVENT_REMOTEREPLY || event == EVENT_REMOTEREPLY

View File

@ -1503,9 +1503,10 @@ do_set (
} else if (opt_idx >= 0) { /* string */ } else if (opt_idx >= 0) { /* string */
char_u *save_arg = NULL; char_u *save_arg = NULL;
char_u *s = NULL; char_u *s = NULL;
char_u *oldval; /* previous value if *varp */ char_u *oldval = NULL; // previous value if *varp
char_u *newval; char_u *newval;
char_u *origval; char_u *origval = NULL;
char_u *saved_origval = NULL;
unsigned newlen; unsigned newlen;
int comma; int comma;
int bs; int bs;
@ -1772,14 +1773,37 @@ do_set (
/* Set the new value. */ /* Set the new value. */
*(char_u **)(varp) = newval; *(char_u **)(varp) = newval;
if (!starting && origval != NULL) {
// origval may be freed by
// did_set_string_option(), make a copy.
saved_origval = vim_strsave(origval);
}
/* Handle side effects, and set the global value for /* Handle side effects, and set the global value for
* ":set" on local options. */ * ":set" on local options. */
errmsg = did_set_string_option(opt_idx, (char_u **)varp, errmsg = did_set_string_option(opt_idx, (char_u **)varp,
new_value_alloced, oldval, errbuf, opt_flags); new_value_alloced, oldval, errbuf, opt_flags);
/* If error detected, print the error message. */ // If error detected, print the error message.
if (errmsg != NULL) if (errmsg != NULL) {
xfree(saved_origval);
goto skip; goto skip;
}
if (saved_origval != NULL) {
char_u buf_type[7];
vim_snprintf((char *)buf_type, ARRAY_SIZE(buf_type), "%s",
(opt_flags & OPT_LOCAL) ? "local" : "global");
set_vim_var_string(VV_OPTION_NEW,
*(char_u **)varp, -1);
set_vim_var_string(VV_OPTION_OLD, saved_origval, -1);
set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
apply_autocmds(EVENT_OPTIONSET,
(char_u *)options[opt_idx].fullname,
NULL, false, NULL);
reset_v_option_vars();
xfree(saved_origval);
}
} else { } else {
// key code option(FIXME(tarruda): Show a warning or something // key code option(FIXME(tarruda): Show a warning or something
// similar) // similar)
@ -2329,6 +2353,7 @@ set_string_option (
char_u *s; char_u *s;
char_u **varp; char_u **varp;
char_u *oldval; char_u *oldval;
char_u *saved_oldval = NULL;
char_u *r = NULL; char_u *r = NULL;
if (options[opt_idx].var == NULL) /* don't set hidden option */ if (options[opt_idx].var == NULL) /* don't set hidden option */
@ -2342,10 +2367,30 @@ set_string_option (
: opt_flags); : opt_flags);
oldval = *varp; oldval = *varp;
*varp = s; *varp = s;
if ((r = did_set_string_option(opt_idx, varp, TRUE, oldval, NULL,
if (!starting) {
saved_oldval = vim_strsave(oldval);
}
if ((r = did_set_string_option(opt_idx, varp, (int)true, oldval, NULL,
opt_flags)) == NULL) opt_flags)) == NULL)
did_set_option(opt_idx, opt_flags, TRUE); did_set_option(opt_idx, opt_flags, TRUE);
// call autocommand after handling side effects
if (saved_oldval != NULL) {
char_u buf_type[7];
vim_snprintf((char *)buf_type, ARRAY_SIZE(buf_type), "%s",
(opt_flags & OPT_LOCAL) ? "local" : "global");
set_vim_var_string(VV_OPTION_NEW, *varp, -1);
set_vim_var_string(VV_OPTION_OLD, saved_oldval, -1);
set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
apply_autocmds(EVENT_OPTIONSET,
(char_u *)options[opt_idx].fullname,
NULL, false, NULL);
reset_v_option_vars();
xfree(saved_oldval);
}
return r; return r;
} }
@ -3814,8 +3859,29 @@ set_bool_option (
* End of handling side effects for bool options. * End of handling side effects for bool options.
*/ */
// after handling side effects, call autocommand
options[opt_idx].flags |= P_WAS_SET; options[opt_idx].flags |= P_WAS_SET;
if (!starting) {
char_u buf_old[2];
char_u buf_new[2];
char_u buf_type[7];
vim_snprintf((char *)buf_old, ARRAY_SIZE(buf_old), "%d",
old_value ? true: false);
vim_snprintf((char *)buf_new, ARRAY_SIZE(buf_new), "%d",
value ? true: false);
vim_snprintf((char *)buf_type, ARRAY_SIZE(buf_type), "%s",
(opt_flags & OPT_LOCAL) ? "local" : "global");
set_vim_var_string(VV_OPTION_NEW, buf_new, -1);
set_vim_var_string(VV_OPTION_OLD, buf_old, -1);
set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
apply_autocmds(EVENT_OPTIONSET,
(char_u *) options[opt_idx].fullname,
NULL, false, NULL);
reset_v_option_vars();
}
comp_col(); /* in case 'ruler' or 'showcmd' changed */ comp_col(); /* in case 'ruler' or 'showcmd' changed */
if (curwin->w_curswant != MAXCOL if (curwin->w_curswant != MAXCOL
&& (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0) && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0)
@ -4187,6 +4253,23 @@ set_num_option (
options[opt_idx].flags |= P_WAS_SET; options[opt_idx].flags |= P_WAS_SET;
if (!starting && errmsg == NULL) {
char_u buf_old[NUMBUFLEN];
char_u buf_new[NUMBUFLEN];
char_u buf_type[7];
vim_snprintf((char *)buf_old, ARRAY_SIZE(buf_old), "%ld", old_value);
vim_snprintf((char *)buf_new, ARRAY_SIZE(buf_new), "%ld", value);
vim_snprintf((char *)buf_type, ARRAY_SIZE(buf_type), "%s",
(opt_flags & OPT_LOCAL) ? "local" : "global");
set_vim_var_string(VV_OPTION_NEW, buf_new, -1);
set_vim_var_string(VV_OPTION_OLD, buf_old, -1);
set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
apply_autocmds(EVENT_OPTIONSET,
(char_u *) options[opt_idx].fullname,
NULL, false, NULL);
reset_v_option_vars();
}
comp_col(); /* in case 'columns' or 'ls' changed */ comp_col(); /* in case 'columns' or 'ls' changed */
if (curwin->w_curswant != MAXCOL if (curwin->w_curswant != MAXCOL
&& (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0) && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0)

View File

@ -206,11 +206,11 @@ static int included_patches[] = {
793, 793,
// 792, // 792,
791, 791,
// 790, 790,
// 789, 789,
// 788 NA // 788 NA
// 787, 787,
// 786, 786,
// 785, // 785,
784, 784,
// 783 NA // 783 NA

View File

@ -0,0 +1,277 @@
local helpers = require('test.functional.helpers')
local nvim = helpers.meths
local clear, eq, neq = helpers.clear, helpers.eq, helpers.neq
local curbuf, buf = helpers.curbuf, helpers.bufmeths
local source, execute = helpers.source, helpers.execute
local function declare_hook_function()
source([[
fu! AutoCommand(match, bufnr, winnr)
let l:acc = {
\ 'option' : a:match,
\ 'oldval' : v:option_old,
\ 'newval' : v:option_new,
\ 'scope' : v:option_type,
\ 'attr' : {
\ 'bufnr' : a:bufnr,
\ 'winnr' : a:winnr,
\ }
\ }
call add(g:ret, l:acc)
endfu
]])
end
local function set_hook(pattern)
execute(
'au OptionSet '
.. pattern ..
' :call AutoCommand(expand("<amatch>"), bufnr("%"), winnr())'
)
end
local function init_var()
execute('let g:ret = []')
end
local function get_result()
local ret = nvim.get_var('ret')
init_var()
return ret
end
local function expected_table(option, oldval, newval, scope, attr)
return {
option = option,
oldval = tostring(oldval),
newval = tostring(newval),
scope = scope,
attr = attr,
}
end
local function expected_combination(...)
local args = {...}
local ret = get_result()
if not (#args == #ret) then
local expecteds = {}
for _, v in pairs(args) do
table.insert(expecteds, expected_table(unpack(v)))
end
eq(expecteds, ret)
return
end
for i, v in ipairs(args) do
local attr = v[5]
if not attr then
-- remove attr entries
ret[i].attr = nil
else
-- remove attr entries which are not required
for k in pairs(ret[i].attr) do
if not attr[k] then
ret[i].attr[k] = nil
end
end
end
eq(expected_table(unpack(v)), ret[i])
end
end
local function expected_empty()
eq({}, get_result())
end
local function make_buffer()
local old_buf = curbuf()
execute('new')
local new_buf = curbuf()
execute('wincmd p') -- move previous window
neq(old_buf, new_buf)
eq(old_buf, curbuf())
return new_buf
end
describe('au OptionSet', function()
describe('with any opton (*)', function()
before_each(function()
clear()
declare_hook_function()
init_var()
set_hook('*')
end)
it('should be called in setting number option', function()
execute('set nu')
expected_combination({'number', 0, 1, 'global'})
execute('setlocal nonu')
expected_combination({'number', 1, 0, 'local'})
execute('setglobal nonu')
expected_combination({'number', 1, 0, 'global'})
end)
it('should be called in setting autoindent option',function()
execute('setlocal ai')
expected_combination({'autoindent', 0, 1, 'local'})
execute('setglobal ai')
expected_combination({'autoindent', 0, 1, 'global'})
execute('set noai')
expected_combination({'autoindent', 1, 0, 'global'})
end)
it('should be called in inverting global autoindent option',function()
execute('set ai!')
expected_combination({'autoindent', 0, 1, 'global'})
end)
it('should be called in being unset local autoindent option',function()
execute('setlocal ai')
expected_combination({'autoindent', 0, 1, 'local'})
execute('setlocal ai<')
expected_combination({'autoindent', 1, 0, 'local'})
end)
it('should be called in setting global list and number option at the same time',function()
execute('set list nu')
expected_combination(
{'list', 0, 1, 'global'},
{'number', 0, 1, 'global'}
)
end)
it('should not print anything, use :noa', function()
execute('noa set nolist nonu')
expected_empty()
end)
it('should be called in setting local acd', function()
execute('setlocal acd')
expected_combination({'autochdir', 0, 1, 'local'})
end)
it('should be called in setting autoread', function()
execute('set noar')
expected_combination({'autoread', 1, 0, 'global'})
execute('setlocal ar')
expected_combination({'autoread', 0, 1, 'local'})
end)
it('should be called in inverting global autoread', function()
execute('setglobal invar')
expected_combination({'autoread', 1, 0, 'global'})
end)
it('should be called in setting backspace option through :let', function()
execute('let &bs=""')
expected_combination({'backspace', 'indent,eol,start', '', 'global'})
end)
describe('being set by setbufvar()', function()
it('should not trigger because option name is invalid', function()
execute('call setbufvar(1, "&l:bk", 1)')
expected_empty()
end)
it('should trigger using correct option name', function()
execute('call setbufvar(1, "&backup", 1)')
expected_combination({'backup', 0, 1, 'local'})
end)
it('should trigger if the current buffer is different from the targetted buffer', function()
local new_buffer = make_buffer()
local new_bufnr = buf.get_number(new_buffer)
execute('call setbufvar(' .. new_bufnr .. ', "&buftype", "nofile")')
expected_combination({'buftype', '', 'nofile', 'local', {bufnr = new_bufnr}})
end)
end)
end)
describe('with specific option', function()
before_each(function()
clear()
declare_hook_function()
init_var()
end)
it('should be called iff setting readonly', function()
set_hook('readonly')
execute('set nu')
expected_empty()
execute('setlocal ro')
expected_combination({'readonly', 0, 1, 'local'})
execute('setglobal ro')
expected_combination({'readonly', 0, 1, 'global'})
execute('set noro')
expected_combination({'readonly', 1, 0, 'global'})
end)
describe('being set by setbufvar()', function()
it('should not trigger because option name does not match with backup', function()
set_hook('backup')
execute('call setbufvar(1, "&l:bk", 1)')
expected_empty()
end)
it('should trigger, use correct option name backup', function()
set_hook('backup')
execute('call setbufvar(1, "&backup", 1)')
expected_combination({'backup', 0, 1, 'local'})
end)
it('should trigger if the current buffer is different from the targetted buffer', function()
set_hook('buftype')
local new_buffer = make_buffer()
local new_bufnr = buf.get_number(new_buffer)
execute('call setbufvar(' .. new_bufnr .. ', "&buftype", "nofile")')
expected_combination({'buftype', '', 'nofile', 'local', {bufnr = new_bufnr}})
end)
end)
describe('being set by neovim api', function()
it('should trigger if a boolean option be set globally', function()
set_hook('autochdir')
nvim.set_option('autochdir', true)
eq(true, nvim.get_option('autochdir'))
expected_combination({'autochdir', '0', '1', 'global'})
end)
it('should trigger if a number option be set globally', function()
set_hook('cmdheight')
nvim.set_option('cmdheight', 5)
eq(5, nvim.get_option('cmdheight'))
expected_combination({'cmdheight', 1, 5, 'global'})
end)
it('should trigger if a string option be set globally', function()
set_hook('ambiwidth')
nvim.set_option('ambiwidth', 'double')
eq('double', nvim.get_option('ambiwidth'))
expected_combination({'ambiwidth', 'single', 'double', 'global'})
end)
end)
end)
end)