From 2ff8b64679242e73248774a388d54931c9ce49bd Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 24 May 2016 10:46:45 +0200 Subject: [PATCH 01/11] patch 7.4.1833 Problem: Cannot use an Ex command for 'keywordprg'. Solution: Accept an Ex command. (Nelo-Thara Wallus) --- runtime/doc/options.txt | 10 ++++++---- src/normal.c | 17 +++++++++++++++-- src/version.c | 2 ++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index aefbdbffbc..3f3764939a 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -4587,16 +4587,18 @@ A jump table for the options with a short description can be found at |Q_op|. *'keywordprg'* *'kp'* 'keywordprg' 'kp' string (default "man" or "man -s", DOS: ":help", - OS/2: "view /", VMS: "help") + VMS: "help") global or local to buffer |global-local| {not in Vi} Program to use for the |K| command. Environment variables are expanded |:set_env|. ":help" may be used to access the Vim internal help. (Note that previously setting the global option to the empty value did this, which is now deprecated.) - When "man" is used, Vim will automatically translate a count for the - "K" command to a section number. Also for "man -s", in which case the - "-s" is removed when there is no count. + When the first character is ":", the command is invoked as a Vim + Ex command prefixed with [count]. + When "man", "man -s" or an Ex command is used, Vim will automatically + translate a count for the "K" command and pass it as the first + argument. For "man -s" the "-s" is removed when there is no count. See |option-backslash| about including spaces and backslashes. Example: > :set keywordprg=man\ -s diff --git a/src/normal.c b/src/normal.c index 7c15c15521..d9948ec594 100644 --- a/src/normal.c +++ b/src/normal.c @@ -5485,10 +5485,12 @@ nv_ident(cmdarg_T *cap) { char_u *ptr = NULL; char_u *buf; + unsigned buflen; char_u *newbuf; char_u *p; char_u *kp; /* value of 'keywordprg' */ - int kp_help; /* 'keywordprg' is ":help" */ + int kp_help; /* 'keywordprg' is ":he" */ + int kp_ex; /* 'keywordprg' starts with ":" */ int n = 0; /* init for GCC */ int cmdchar; int g_cmd; /* "g" command */ @@ -5536,7 +5538,9 @@ nv_ident(cmdarg_T *cap) kp = (*curbuf->b_p_kp == NUL ? p_kp : curbuf->b_p_kp); kp_help = (*kp == NUL || STRCMP(kp, ":he") == 0 || STRCMP(kp, ":help") == 0); - buf = alloc((unsigned)(n * 2 + 30 + STRLEN(kp))); + kp_ex = (*kp == ':'); + buflen = (unsigned)(n * 2 + 30 + STRLEN(kp)); + buf = alloc(buflen); if (buf == NULL) return; buf[0] = NUL; @@ -5562,6 +5566,15 @@ nv_ident(cmdarg_T *cap) case 'K': if (kp_help) STRCPY(buf, "he! "); + else if (kp_ex) + { + if (cap->count0 != 0) + vim_snprintf((char *)buf, buflen, "%s %ld", + kp, cap->count0); + else + STRCPY(buf, kp); + STRCAT(buf, " "); + } else { /* An external command will probably use an argument starting diff --git a/src/version.c b/src/version.c index 863a58f199..eaa3e8ec91 100644 --- a/src/version.c +++ b/src/version.c @@ -753,6 +753,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1833, /**/ 1832, /**/ From 908be438794619f10ef7fa25e24e5893b2ae0189 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 24 May 2016 10:51:30 +0200 Subject: [PATCH 02/11] patch 7.4.1834 Problem: Possible crash when conceal is active. Solution: Check for the screen to be valid when redrawing a line. --- src/screen.c | 4 ++++ src/version.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/screen.c b/src/screen.c index a72bffa536..2e425cba4c 100644 --- a/src/screen.c +++ b/src/screen.c @@ -801,6 +801,10 @@ update_single_line(win_T *wp, linenr_T lnum) int row; int j; + /* Don't do anything if the screen structures are (not yet) valid. */ + if (!screen_valid(TRUE)) + return; + if (lnum >= wp->w_topline && lnum < wp->w_botline && foldedCount(wp, lnum, &win_foldinfo) == 0) { diff --git a/src/version.c b/src/version.c index eaa3e8ec91..417a3aa57e 100644 --- a/src/version.c +++ b/src/version.c @@ -753,6 +753,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1834, /**/ 1833, /**/ From 991dea3ab185fb35e577ab0bdfd443cd4b43ccc6 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 24 May 2016 11:31:32 +0200 Subject: [PATCH 03/11] patch 7.4.1835 Problem: When splitting and closing a window the status height changes. Solution: Compute the frame height correctly. (Hirohito Higashi) --- src/testdir/test_alot.vim | 1 + src/testdir/test_window_cmd.vim | 37 +++++++++++++++++++++++++++++++++ src/version.c | 2 ++ src/window.c | 18 ++++++++-------- 4 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 src/testdir/test_window_cmd.vim diff --git a/src/testdir/test_alot.vim b/src/testdir/test_alot.vim index 6bfd81eaf9..d8d460aec4 100644 --- a/src/testdir/test_alot.vim +++ b/src/testdir/test_alot.vim @@ -32,3 +32,4 @@ source test_tagjump.vim source test_timers.vim source test_undolevels.vim source test_unlet.vim +source test_window_cmd.vim diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim new file mode 100644 index 0000000000..d2e42720d2 --- /dev/null +++ b/src/testdir/test_window_cmd.vim @@ -0,0 +1,37 @@ +" Tests for window cmd (:wincmd, :split, :vsplit, :resize and etc...) + +func Test_window_cmd_ls0_with_split() + set ls=0 + set splitbelow + split + quit + call assert_equal(0, &lines - &cmdheight - winheight(0)) + new | only! + " + set splitbelow&vim + botright split + quit + call assert_equal(0, &lines - &cmdheight - winheight(0)) + new | only! + set ls&vim +endfunc + +func Test_window_cmd_cmdwin_with_vsp() + let efmt='Expected 0 but got %d (in ls=%d, %s window)' + for v in range(0, 2) + exec "set ls=" . v + vsplit + call feedkeys("q:\") + let ac = &lines - (&cmdheight + winheight(0) + !!v) + let emsg = printf(efmt, ac, v, 'left') + call assert_equal(0, ac, emsg) + wincmd w + let ac = &lines - (&cmdheight + winheight(0) + !!v) + let emsg = printf(efmt, ac, v, 'right') + call assert_equal(0, ac, emsg) + new | only! + endfor + set ls&vim +endfunc + +" vim: sw=2 et diff --git a/src/version.c b/src/version.c index 417a3aa57e..166a9de507 100644 --- a/src/version.c +++ b/src/version.c @@ -753,6 +753,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1835, /**/ 1834, /**/ diff --git a/src/window.c b/src/window.c index bbd0a527c0..01da765b46 100644 --- a/src/window.c +++ b/src/window.c @@ -1165,8 +1165,13 @@ win_split_ins( * one row for the status line */ win_new_height(wp, new_size); if (flags & (WSP_TOP | WSP_BOT)) - frame_new_height(curfrp, curfrp->fr_height - - (new_size + STATUS_HEIGHT), flags & WSP_TOP, FALSE); + { + int new_fr_height = curfrp->fr_height - new_size; + + if (!((flags & WSP_BOT) && p_ls == 0)) + new_fr_height -= STATUS_HEIGHT; + frame_new_height(curfrp, new_fr_height, flags & WSP_TOP, FALSE); + } else win_new_height(oldwin, oldwin_height - (new_size + STATUS_HEIGHT)); if (before) /* new window above current one */ @@ -1179,18 +1184,13 @@ win_split_ins( { wp->w_winrow = oldwin->w_winrow + oldwin->w_height + STATUS_HEIGHT; wp->w_status_height = oldwin->w_status_height; - /* Don't set the status_height for oldwin yet, this might break - * frame_fix_height(oldwin), therefore will be set below. */ + if (!(flags & WSP_BOT)) + oldwin->w_status_height = STATUS_HEIGHT; } if (flags & WSP_BOT) frame_add_statusline(curfrp); frame_fix_height(wp); frame_fix_height(oldwin); - - if (!before) - /* new window above current one, set the status_height after - * frame_fix_height(oldwin) */ - oldwin->w_status_height = STATUS_HEIGHT; } if (flags & (WSP_TOP | WSP_BOT)) From 1d429610bf9e99a6252be8abbc910d6667e4d1da Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 24 May 2016 15:44:17 +0200 Subject: [PATCH 04/11] patch 7.4.1836 Problem: When using a partial on a dictionary it always gets bound to that dictionary. Solution: Make a difference between binding a function to a dictionary explicitly or automatically. --- runtime/doc/eval.txt | 42 +++++++++++++++++++++++++++++++++++- src/eval.c | 30 ++++++++++++++++---------- src/structs.h | 2 ++ src/testdir/test_partial.vim | 22 +++++++++++++++++++ src/version.c | 2 ++ 5 files changed, 86 insertions(+), 12 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index a1c1505cf9..19957fc29f 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 7.4. Last change: 2016 May 20 +*eval.txt* For Vim version 7.4. Last change: 2016 May 24 VIM REFERENCE MANUAL by Bram Moolenaar @@ -59,6 +59,9 @@ Dictionary An associative, unordered array: Each entry has a key and a Funcref A reference to a function |Funcref|. Example: function("strlen") + It can be bound to a dictionary and arguments, it then works + like a Partial. + Example: function("Callback", [arg], myDict) Special |v:false|, |v:true|, |v:none| and |v:null|. *Special* @@ -150,6 +153,43 @@ The name of the referenced function can be obtained with |string()|. > You can use |call()| to invoke a Funcref and use a list variable for the arguments: > :let r = call(Fn, mylist) +< + *Partial* +A Funcref optionally binds a Dictionary and/or arguments. This is also called +a Partial. This is created by passing the Dictionary and/or arguments to +function(). When calling the function the Dictionary and/or arguments will be +passed to the function. Example: > + + let Cb = function('Callback', ['foo'], myDict) + call Cb() + +This will invoke the function as if using: > + call myDict.Callback('foo') + +This is very useful when passing a function around, e.g. in the arguments of +|ch_open()|. + +Note that binding a function to a Dictionary also happens when the function is +a member of the Dictionary: > + + let myDict.myFunction = MyFunction + call myDict.myFunction() + +Here MyFunction() will get myDict passed as "self". This happens when the +"myFunction" member is accessed. When making assigning "myFunction" to +otherDict and calling it, it will be bound to otherDict: > + + let otherDict.myFunction = myDict.myFunction + call otherDict.myFunction() + +Now "self" will be "otherDict". But when the dictionary was bound explicitly +this won't happen: > + + let myDict.myFunction = function(MyFunction, myDict) + let otherDict.myFunction = myDict.myFunction + call otherDict.myFunction() + +Here "self" will be "myDict", because it was bound explitly. 1.3 Lists ~ diff --git a/src/eval.c b/src/eval.c index 005485dd9c..ce83143cee 100644 --- a/src/eval.c +++ b/src/eval.c @@ -9069,14 +9069,12 @@ call_func( if (partial != NULL) { - if (partial->pt_dict != NULL) - { - /* When the function has a partial with a dict and there is a dict - * argument, use the dict argument. That is backwards compatible. - */ - if (selfdict_in == NULL) - selfdict = partial->pt_dict; - } + /* When the function has a partial with a dict and there is a dict + * argument, use the dict argument. That is backwards compatible. + * When the dict was bound explicitly use the one from the partial. */ + if (partial->pt_dict != NULL + && (selfdict_in == NULL || !partial->pt_auto)) + selfdict = partial->pt_dict; if (error == ERROR_NONE && partial->pt_argc > 0) { for (argv_clear = 0; argv_clear < partial->pt_argc; ++argv_clear) @@ -12330,12 +12328,16 @@ f_function(typval_T *argvars, typval_T *rettv) * use "dict". That is backwards compatible. */ if (dict_idx > 0) { + /* The dict is bound explicitly, pt_auto is FALSE. */ pt->pt_dict = argvars[dict_idx].vval.v_dict; ++pt->pt_dict->dv_refcount; } else if (arg_pt != NULL) { + /* If the dict was bound automatically the result is also + * bound automatically. */ pt->pt_dict = arg_pt->pt_dict; + pt->pt_auto = arg_pt->pt_auto; if (pt->pt_dict != NULL) ++pt->pt_dict->dv_refcount; } @@ -22279,8 +22281,14 @@ handle_subscript( } } - if ((rettv->v_type == VAR_FUNC || rettv->v_type == VAR_PARTIAL) - && selfdict != NULL) + /* Turn "dict.Func" into a partial for "Func" bound to "dict". + * Don't do this when "Func" is already a partial that was bound + * explicitly (pt_auto is FALSE). */ + if (selfdict != NULL + && (rettv->v_type == VAR_FUNC + || (rettv->v_type == VAR_PARTIAL + && (rettv->vval.v_partial->pt_auto + || rettv->vval.v_partial->pt_dict == NULL)))) { char_u *fname = rettv->v_type == VAR_FUNC ? rettv->vval.v_string : rettv->vval.v_partial->pt_name; @@ -22294,7 +22302,6 @@ handle_subscript( fp = find_func(fname); vim_free(tofree); - /* Turn "dict.Func" into a partial for "Func" with "dict". */ if (fp != NULL && (fp->uf_flags & FC_DICT)) { partial_T *pt = (partial_T *)alloc_clear(sizeof(partial_T)); @@ -22303,6 +22310,7 @@ handle_subscript( { pt->pt_refcount = 1; pt->pt_dict = selfdict; + pt->pt_auto = TRUE; selfdict = NULL; if (rettv->v_type == VAR_FUNC) { diff --git a/src/structs.h b/src/structs.h index 24d819bf5d..12a8a43878 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1261,6 +1261,8 @@ struct partial_S { int pt_refcount; /* reference count */ char_u *pt_name; /* function name */ + int pt_auto; /* when TRUE the partial was created for using + dict.member in handle_subscript() */ int pt_argc; /* number of arguments */ typval_T *pt_argv; /* arguments in allocated array */ dict_T *pt_dict; /* dict for "self" */ diff --git a/src/testdir/test_partial.vim b/src/testdir/test_partial.vim index 5f4a48faf8..8b11200d2b 100644 --- a/src/testdir/test_partial.vim +++ b/src/testdir/test_partial.vim @@ -257,3 +257,25 @@ func Test_ref_job_partial_dict() call job_setoptions(g:ref_job, {'exit_cb': function('string', [], d)}) endif endfunc + +func Test_auto_partial_rebind() + let dict1 = {'name': 'dict1'} + func! dict1.f1() + return self.name + endfunc + let dict1.f2 = function(dict1.f1, dict1) + + call assert_equal('dict1', dict1.f1()) + call assert_equal('dict1', dict1['f1']()) + call assert_equal('dict1', dict1.f2()) + call assert_equal('dict1', dict1['f2']()) + + let dict2 = {'name': 'dict2'} + let dict2.f1 = dict1.f1 + let dict2.f2 = dict1.f2 + + call assert_equal('dict2', dict2.f1()) + call assert_equal('dict2', dict2['f1']()) + call assert_equal('dict1', dict2.f2()) + call assert_equal('dict1', dict2['f2']()) +endfunc diff --git a/src/version.c b/src/version.c index 166a9de507..8b92714340 100644 --- a/src/version.c +++ b/src/version.c @@ -753,6 +753,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1836, /**/ 1835, /**/ From c67e89213476b5f4756d92208b57ce9ef4a4cf24 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 24 May 2016 16:07:40 +0200 Subject: [PATCH 05/11] patch 7.4.1837 Problem: The BufUnload event is triggered twice, when :bunload is used with set to or . Solution: Do not trigger the event when ml_mfp is NULL. (Hirohito Higashi) --- src/buffer.c | 9 +++-- src/testdir/test_autocmd.vim | 69 +++++++++++++++++++++++++----------- src/version.c | 2 ++ 3 files changed, 56 insertions(+), 24 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index e884f55dd7..b0e3a22b50 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -574,9 +574,12 @@ buf_freeall(buf_T *buf, int flags) int is_curbuf = (buf == curbuf); buf->b_closing = TRUE; - apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, FALSE, buf); - if (!buf_valid(buf)) /* autocommands may delete the buffer */ - return; + if (buf->b_ml.ml_mfp != NULL) + { + apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, FALSE, buf); + if (!buf_valid(buf)) /* autocommands may delete the buffer */ + return; + } if ((flags & BFA_DEL) && buf->b_p_bl) { apply_autocmds(EVENT_BUFDELETE, buf->b_fname, buf->b_fname, FALSE, buf); diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim index d3e0981025..1dceb70cd4 100644 --- a/src/testdir/test_autocmd.vim +++ b/src/testdir/test_autocmd.vim @@ -7,29 +7,56 @@ func Test_vim_did_enter() " becomes one. endfunc -if !has('timers') - finish +if has('timers') + func ExitInsertMode(id) + call feedkeys("\") + endfunc + + func Test_cursorhold_insert() + let g:triggered = 0 + au CursorHoldI * let g:triggered += 1 + set updatetime=20 + call timer_start(100, 'ExitInsertMode') + call feedkeys('a', 'x!') + call assert_equal(1, g:triggered) + endfunc + + func Test_cursorhold_insert_ctrl_x() + let g:triggered = 0 + au CursorHoldI * let g:triggered += 1 + set updatetime=20 + call timer_start(100, 'ExitInsertMode') + " CursorHoldI does not trigger after CTRL-X + call feedkeys("a\", 'x!') + call assert_equal(0, g:triggered) + endfunc endif -func ExitInsertMode(id) - call feedkeys("\") -endfunc +function Test_bufunload() + augroup test_bufunload_group + autocmd! + autocmd BufUnload * call add(s:li, "bufunload") + autocmd BufDelete * call add(s:li, "bufdelete") + autocmd BufWipeout * call add(s:li, "bufwipeout") + augroup END -func Test_cursorhold_insert() - let g:triggered = 0 - au CursorHoldI * let g:triggered += 1 - set updatetime=20 - call timer_start(100, 'ExitInsertMode') - call feedkeys('a', 'x!') - call assert_equal(1, g:triggered) -endfunc + let s:li=[] + new + setlocal bufhidden= + bunload + call assert_equal(["bufunload", "bufdelete"], s:li) -func Test_cursorhold_insert_ctrl_x() - let g:triggered = 0 - au CursorHoldI * let g:triggered += 1 - set updatetime=20 - call timer_start(100, 'ExitInsertMode') - " CursorHoldI does not trigger after CTRL-X - call feedkeys("a\", 'x!') - call assert_equal(0, g:triggered) + let s:li=[] + new + setlocal bufhidden=delete + bunload + call assert_equal(["bufunload", "bufdelete"], s:li) + + let s:li=[] + new + setlocal bufhidden=unload + bwipeout + call assert_equal(["bufunload", "bufdelete", "bufwipeout"], s:li) + + augroup! test_bufunload_group endfunc diff --git a/src/version.c b/src/version.c index 8b92714340..f1bbbdd774 100644 --- a/src/version.c +++ b/src/version.c @@ -753,6 +753,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1837, /**/ 1836, /**/ From 574860b5ee9da281c875dad07a607454e135eaee Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 24 May 2016 17:33:34 +0200 Subject: [PATCH 06/11] patch 7.4.1838 Problem: Functions specifically for testing do not sort together. Solution: Rename garbagecollect_for_testing() to test_garbagecollect_now(). Add test_null_list(), test_null_dict(), etc. --- runtime/doc/eval.txt | 66 +++++++++++++----- src/eval.c | 125 ++++++++++++++++++++++------------- src/testdir/test_channel.vim | 4 +- src/testdir/test_expr.vim | 2 +- src/version.c | 2 + 5 files changed, 134 insertions(+), 65 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 19957fc29f..8dbc5b0c39 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1955,7 +1955,6 @@ foreground() Number bring the Vim window to the foreground function({name} [, {arglist}] [, {dict}]) Funcref reference to function {name} garbagecollect([{atexit}]) none free memory, breaking cyclic references -garbagecollect_for_testing() none free memory right now get({list}, {idx} [, {def}]) any get item {idx} from {list} or {def} get({dict}, {key} [, {def}]) any get item {key} from {dict} or {def} getbufline({expr}, {lnum} [, {end}]) @@ -2203,6 +2202,13 @@ tagfiles() List tags files used tan({expr}) Float tangent of {expr} tanh({expr}) Float hyperbolic tangent of {expr} tempname() String name for a temporary file +test_garbagecollect_now() none free memory right now for testing +test_null_channel() Channel null value for testing +test_null_dict() Dict null value for testing +test_null_job() Job null value for testing +test_null_list() List null value for testing +test_null_partial() Funcref null value for testing +test_null_string() String null value for testing timer_start({time}, {callback} [, {options}]) Number create a timer timer_stop({timer}) none stop a timer @@ -3752,11 +3758,10 @@ garbagecollect([{atexit}]) *garbagecollect()* collection will also be done when exiting Vim, if it wasn't done before. This is useful when checking for memory leaks. -garbagecollect_for_testing() *garbagecollect_for_testing()* - Like garbagecollect(), but executed right away. This must - only be called directly to avoid any structure to exist - internally, and |v:testing| must have been set before calling - any function. + The garbage collection is not done immediately but only when + it's safe to perform. This is when waiting for the user to + type a character. To force garbage collection immediately use + |test_garbagecollect_now()|. get({list}, {idx} [, {default}]) *get()* Get item {idx} from |List| {list}. When this item is not @@ -7165,17 +7170,6 @@ taglist({expr}) *taglist()* located by Vim. Refer to |tags-file-format| for the format of the tags file generated by the different ctags tools. -tempname() *tempname()* *temp-file-name* - The result is a String, which is the name of a file that - doesn't exist. It can be used for a temporary file. The name - is different for at least 26 consecutive calls. Example: > - :let tmpfile = tempname() - :exe "redir > " . tmpfile -< For Unix, the file will be in a private directory |tempfile|. - For MS-Windows forward slashes are used when the 'shellslash' - option is set or when 'shellcmdflag' starts with '-'. - - tan({expr}) *tan()* Return the tangent of {expr}, measured in radians, as a |Float| in the range [-inf, inf]. @@ -7200,6 +7194,44 @@ tanh({expr}) *tanh()* {only available when compiled with the |+float| feature} +tempname() *tempname()* *temp-file-name* + The result is a String, which is the name of a file that + doesn't exist. It can be used for a temporary file. The name + is different for at least 26 consecutive calls. Example: > + :let tmpfile = tempname() + :exe "redir > " . tmpfile +< For Unix, the file will be in a private directory |tempfile|. + For MS-Windows forward slashes are used when the 'shellslash' + option is set or when 'shellcmdflag' starts with '-'. + + +test_garbagecollect_now() *test_garbagecollect_now()* + Like garbagecollect(), but executed right away. This must + only be called directly to avoid any structure to exist + internally, and |v:testing| must have been set before calling + any function. + +test_null_channel() *test_null_channel()* + Return a Channel that is null. Only useful for testing. + {only available when compiled with the +channel feature} + +test_null_dict() *test_null_dict()* + Return a Dict that is null. Only useful for testing. + +test_null_job() *test_null_job()* + Return a Job that is null. Only useful for testing. + {only available when compiled with the +job feature} + +test_null_list() *test_null_list()* + Return a List that is null. Only useful for testing. + +test_null_partial() *test_null_partial()* + Return a Partial that is null. Only useful for testing. + +test_null_string() *test_null_string()* + Return a String that is null. Only useful for testing. + + *timer_start()* timer_start({time}, {callback} [, {options}]) Create a timer and return the timer ID. diff --git a/src/eval.c b/src/eval.c index ce83143cee..a653b89f72 100644 --- a/src/eval.c +++ b/src/eval.c @@ -583,7 +583,6 @@ static void f_foldtextresult(typval_T *argvars, typval_T *rettv); static void f_foreground(typval_T *argvars, typval_T *rettv); static void f_function(typval_T *argvars, typval_T *rettv); static void f_garbagecollect(typval_T *argvars, typval_T *rettv); -static void f_garbagecollect_for_testing(typval_T *argvars, typval_T *rettv); static void f_get(typval_T *argvars, typval_T *rettv); static void f_getbufline(typval_T *argvars, typval_T *rettv); static void f_getbufvar(typval_T *argvars, typval_T *rettv); @@ -806,7 +805,17 @@ static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv); static void f_taglist(typval_T *argvars, typval_T *rettv); static void f_tagfiles(typval_T *argvars, typval_T *rettv); static void f_tempname(typval_T *argvars, typval_T *rettv); -static void f_test(typval_T *argvars, typval_T *rettv); +static void f_test_garbagecollect_now(typval_T *argvars, typval_T *rettv); +#ifdef FEAT_JOB_CHANNEL +static void f_test_null_channel(typval_T *argvars, typval_T *rettv); +#endif +static void f_test_null_dict(typval_T *argvars, typval_T *rettv); +#ifdef FEAT_JOB_CHANNEL +static void f_test_null_job(typval_T *argvars, typval_T *rettv); +#endif +static void f_test_null_list(typval_T *argvars, typval_T *rettv); +static void f_test_null_partial(typval_T *argvars, typval_T *rettv); +static void f_test_null_string(typval_T *argvars, typval_T *rettv); #ifdef FEAT_FLOAT static void f_tan(typval_T *argvars, typval_T *rettv); static void f_tanh(typval_T *argvars, typval_T *rettv); @@ -6925,7 +6934,7 @@ static garray_T funcargs = GA_EMPTY; /* * Do garbage collection for lists and dicts. - * When "testing" is TRUE this is called from garbagecollect_for_testing(). + * When "testing" is TRUE this is called from test_garbagecollect_now(). * Return TRUE if some memory was freed. */ int @@ -8451,7 +8460,6 @@ static struct fst {"foreground", 0, 0, f_foreground}, {"function", 1, 3, f_function}, {"garbagecollect", 0, 1, f_garbagecollect}, - {"garbagecollect_for_testing", 0, 0, f_garbagecollect_for_testing}, {"get", 2, 3, f_get}, {"getbufline", 2, 3, f_getbufline}, {"getbufvar", 2, 3, f_getbufvar}, @@ -8681,7 +8689,17 @@ static struct fst {"tanh", 1, 1, f_tanh}, #endif {"tempname", 0, 0, f_tempname}, - {"test", 1, 1, f_test}, + {"test_garbagecollect_now", 0, 0, f_test_garbagecollect_now}, +#ifdef FEAT_JOB_CHANNEL + {"test_null_channel", 0, 0, f_test_null_channel}, +#endif + {"test_null_dict", 0, 0, f_test_null_dict}, +#ifdef FEAT_JOB_CHANNEL + {"test_null_job", 0, 0, f_test_null_job}, +#endif + {"test_null_list", 0, 0, f_test_null_list}, + {"test_null_partial", 0, 0, f_test_null_partial}, + {"test_null_string", 0, 0, f_test_null_string}, #ifdef FEAT_TIMERS {"timer_start", 2, 3, f_timer_start}, {"timer_stop", 1, 1, f_timer_stop}, @@ -12373,17 +12391,6 @@ f_garbagecollect(typval_T *argvars, typval_T *rettv UNUSED) garbage_collect_at_exit = TRUE; } -/* - * "garbagecollect_for_testing()" function - */ - static void -f_garbagecollect_for_testing(typval_T *argvars UNUSED, typval_T *rettv UNUSED) -{ - /* This is dangerous, any Lists and Dicts used internally may be freed - * while still in use. */ - garbage_collect(TRUE); -} - /* * "get()" function */ @@ -20602,35 +20609,6 @@ f_tempname(typval_T *argvars UNUSED, typval_T *rettv) } while (x == 'I' || x == 'O'); } -/* - * "test(list)" function: Just checking the walls... - */ - static void -f_test(typval_T *argvars UNUSED, typval_T *rettv UNUSED) -{ - /* Used for unit testing. Change the code below to your liking. */ -#if 0 - listitem_T *li; - list_T *l; - char_u *bad, *good; - - if (argvars[0].v_type != VAR_LIST) - return; - l = argvars[0].vval.v_list; - if (l == NULL) - return; - li = l->lv_first; - if (li == NULL) - return; - bad = get_tv_string(&li->li_tv); - li = li->li_next; - if (li == NULL) - return; - good = get_tv_string(&li->li_tv); - rettv->vval.v_number = test_edit_score(bad, good); -#endif -} - #ifdef FEAT_FLOAT /* * "tan()" function @@ -20663,6 +20641,63 @@ f_tanh(typval_T *argvars, typval_T *rettv) } #endif +/* + * "test_garbagecollect_now()" function + */ + static void +f_test_garbagecollect_now(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ + /* This is dangerous, any Lists and Dicts used internally may be freed + * while still in use. */ + garbage_collect(TRUE); +} + +#ifdef FEAT_JOB_CHANNEL + static void +f_test_null_channel(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ + rettv->v_type = VAR_CHANNEL; + rettv->vval.v_channel = NULL; +} +#endif + + static void +f_test_null_dict(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ + rettv->v_type = VAR_DICT; + rettv->vval.v_dict = NULL; +} + +#ifdef FEAT_JOB_CHANNEL + static void +f_test_null_job(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ + rettv->v_type = VAR_JOB; + rettv->vval.v_job = NULL; +} +#endif + + static void +f_test_null_list(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ + rettv->v_type = VAR_LIST; + rettv->vval.v_list = NULL; +} + + static void +f_test_null_partial(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ + rettv->v_type = VAR_PARTIAL; + rettv->vval.v_partial = NULL; +} + + static void +f_test_null_string(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ + rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; +} + #if defined(FEAT_JOB_CHANNEL) || defined(FEAT_TIMERS) || defined(PROTO) /* * Get a callback from "arg". It can be a Funcref or a function name. diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim index 8e29d32354..363b5cd9e1 100644 --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -183,7 +183,7 @@ func s:communicate(port) call assert_equal('got it', s:responseMsg) " Collect garbage, tests that our handle isn't collected. - call garbagecollect_for_testing() + call test_garbagecollect_now() " check setting options (without testing the effect) call ch_setoptions(handle, {'callback': 's:NotUsed'}) @@ -1302,7 +1302,7 @@ endfunc func Test_using_freed_memory() let g:a = job_start(['ls']) sleep 10m - call garbagecollect_for_testing() + call test_garbagecollect_now() endfunc diff --git a/src/testdir/test_expr.vim b/src/testdir/test_expr.vim index 2cd9625adc..142455bfe1 100644 --- a/src/testdir/test_expr.vim +++ b/src/testdir/test_expr.vim @@ -85,7 +85,7 @@ func Test_getreg_empty_list() endfunc func Test_loop_over_null_list() - let null_list = submatch(1, 1) + let null_list = test_null_list() for i in null_list call assert_true(0, 'should not get here') endfor diff --git a/src/version.c b/src/version.c index f1bbbdd774..46aff53914 100644 --- a/src/version.c +++ b/src/version.c @@ -753,6 +753,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1838, /**/ 1837, /**/ From 2bbf8eff6fab16d86e7bcfc0da1962d31bec7891 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 24 May 2016 18:37:12 +0200 Subject: [PATCH 07/11] patch 7.4.1839 Problem: Cannot get the items stored in a partial. Solution: Support using get() on a partial. --- runtime/doc/eval.txt | 6 ++++++ src/eval.c | 39 ++++++++++++++++++++++++++++++++++++ src/testdir/test_partial.vim | 9 +++++++++ src/version.c | 2 ++ 4 files changed, 56 insertions(+) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 8dbc5b0c39..36133d839f 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -3771,6 +3771,12 @@ get({dict}, {key} [, {default}]) Get item with key {key} from |Dictionary| {dict}. When this item is not available return {default}. Return zero when {default} is omitted. +get({partial}, {what}) + Get an item with from Funcref {partial}. Possible values for + {what} are: + 'func' The function + 'dict' The dictionary + 'args' The list with arguments *getbufline()* getbufline({expr}, {lnum} [, {end}]) diff --git a/src/eval.c b/src/eval.c index a653b89f72..99b948c7d8 100644 --- a/src/eval.c +++ b/src/eval.c @@ -12423,6 +12423,45 @@ f_get(typval_T *argvars, typval_T *rettv) tv = &di->di_tv; } } + else if (argvars[0].v_type == VAR_PARTIAL) + { + partial_T *pt = argvars[0].vval.v_partial; + + if (pt != NULL) + { + char_u *what = get_tv_string(&argvars[1]); + + if (STRCMP(what, "func") == 0) + { + rettv->v_type = VAR_STRING; + if (pt->pt_name == NULL) + rettv->vval.v_string = NULL; + else + rettv->vval.v_string = vim_strsave(pt->pt_name); + } + else if (STRCMP(what, "dict") == 0) + { + rettv->v_type = VAR_DICT; + rettv->vval.v_dict = pt->pt_dict; + if (pt->pt_dict != NULL) + ++pt->pt_dict->dv_refcount; + } + else if (STRCMP(what, "args") == 0) + { + rettv->v_type = VAR_LIST; + if (rettv_list_alloc(rettv) == OK) + { + int i; + + for (i = 0; i < pt->pt_argc; ++i) + list_append_tv(rettv->vval.v_list, &pt->pt_argv[i]); + } + } + else + EMSG2(_(e_invarg2), what); + return; + } + } else EMSG2(_(e_listdictarg), "get()"); diff --git a/src/testdir/test_partial.vim b/src/testdir/test_partial.vim index 8b11200d2b..30e1df99e7 100644 --- a/src/testdir/test_partial.vim +++ b/src/testdir/test_partial.vim @@ -279,3 +279,12 @@ func Test_auto_partial_rebind() call assert_equal('dict1', dict2.f2()) call assert_equal('dict1', dict2['f2']()) endfunc + +func Test_get_partial_items() + let dict = {'name': 'hello'} + let Cb = function('MyDictFunc', ["foo", "bar"], dict) + call assert_equal('MyDictFunc', get(Cb, 'func')) + call assert_equal(["foo", "bar"], get(Cb, 'args')) + call assert_equal(dict, get(Cb, 'dict')) + call assert_fails('call get(Cb, "xxx")', 'E475:') +endfunc diff --git a/src/version.c b/src/version.c index 46aff53914..b53a744264 100644 --- a/src/version.c +++ b/src/version.c @@ -753,6 +753,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1839, /**/ 1838, /**/ From a57024453115592b8847af40ddd965a33898e390 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 24 May 2016 19:37:29 +0200 Subject: [PATCH 08/11] patch 7.4.1840 Problem: When using packages an "after" directory cannot be used. Solution: Add the "after" directory of the package to 'runtimepath' if it exists. --- src/ex_cmds2.c | 23 ++++++++++++++++++----- src/testdir/test_packadd.vim | 4 +++- src/version.c | 2 ++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c index 256acec7c4..a90fe7d8c6 100644 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -3326,13 +3326,15 @@ add_pack_plugin(char_u *fname, void *cookie) int keep; int oldlen; int addlen; + char_u *afterdir; + int afterlen = 0; char_u *ffname = fix_fname(fname); if (ffname == NULL) return; if (cookie != &APP_LOAD && strstr((char *)p_rtp, (char *)ffname) == NULL) { - /* directory not in 'runtimepath', add it */ + /* directory is not yet in 'runtimepath', add it */ p4 = p3 = p2 = p1 = get_past_head(ffname); for (p = p1; *p; mb_ptr_adv(p)) if (vim_ispathsep_nocolon(*p)) @@ -3360,20 +3362,31 @@ add_pack_plugin(char_u *fname, void *cookie) } *p4 = c; + /* check if rtp/pack/name/start/name/after exists */ + afterdir = concat_fnames(ffname, (char_u *)"after", TRUE); + if (afterdir != NULL && mch_isdir(afterdir)) + afterlen = STRLEN(afterdir) + 1; /* add one for comma */ + oldlen = (int)STRLEN(p_rtp); - addlen = (int)STRLEN(ffname); - new_rtp = alloc(oldlen + addlen + 2); + addlen = (int)STRLEN(ffname) + 1; /* add one for comma */ + new_rtp = alloc(oldlen + addlen + afterlen + 1); /* add one for NUL */ if (new_rtp == NULL) goto theend; keep = (int)(insp - p_rtp); mch_memmove(new_rtp, p_rtp, keep); new_rtp[keep] = ','; - mch_memmove(new_rtp + keep + 1, ffname, addlen + 1); + mch_memmove(new_rtp + keep + 1, ffname, addlen); if (p_rtp[keep] != NUL) - mch_memmove(new_rtp + keep + 1 + addlen, p_rtp + keep, + mch_memmove(new_rtp + keep + addlen, p_rtp + keep, oldlen - keep + 1); + if (afterlen > 0) + { + STRCAT(new_rtp, ","); + STRCAT(new_rtp, afterdir); + } set_option_value((char_u *)"rtp", 0L, new_rtp, 0); vim_free(new_rtp); + vim_free(afterdir); } if (cookie != &APP_ADD_DIR) diff --git a/src/testdir/test_packadd.vim b/src/testdir/test_packadd.vim index 66a344b0dc..eca1560f77 100644 --- a/src/testdir/test_packadd.vim +++ b/src/testdir/test_packadd.vim @@ -13,6 +13,7 @@ endfunc func Test_packadd() call mkdir(s:plugdir . '/plugin/also', 'p') call mkdir(s:plugdir . '/ftdetect', 'p') + call mkdir(s:plugdir . '/after', 'p') set rtp& let rtp = &rtp filetype on @@ -35,7 +36,8 @@ func Test_packadd() call assert_equal(77, g:plugin_also_works) call assert_equal(17, g:ftdetect_works) call assert_true(len(&rtp) > len(rtp)) - call assert_true(&rtp =~ 'testdir/Xdir/pack/mine/opt/mytest\($\|,\)') + call assert_true(&rtp =~ '/testdir/Xdir/pack/mine/opt/mytest\($\|,\)') + call assert_true(&rtp =~ '/testdir/Xdir/pack/mine/opt/mytest/after$') " Check exception call assert_fails("packadd directorynotfound", 'E919:') diff --git a/src/version.c b/src/version.c index b53a744264..eda517ace2 100644 --- a/src/version.c +++ b/src/version.c @@ -753,6 +753,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1840, /**/ 1839, /**/ From 2b2b8ae5ab37b04584633c469265d85825166905 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 24 May 2016 19:59:51 +0200 Subject: [PATCH 09/11] patch 7.4.1841 Problem: The code to reallocate the buffer used for quickfix is repeated. Solution: Move the code to a function. (Yegappan Lakshmanan, closes #831) --- src/quickfix.c | 85 +++++++++++++++-------------------- src/testdir/test_quickfix.vim | 13 +++++- src/version.c | 2 + 3 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/quickfix.c b/src/quickfix.c index 7b6d1bc9ce..a719e4fe0a 100644 --- a/src/quickfix.c +++ b/src/quickfix.c @@ -179,6 +179,31 @@ qf_init( */ #define LINE_MAXLEN 4096 + static char_u * +qf_grow_linebuf(char_u **growbuf, int *growbufsiz, int newsz, int *allocsz) +{ + /* + * If the line exceeds LINE_MAXLEN exclude the last + * byte since it's not a NL character. + */ + *allocsz = newsz > LINE_MAXLEN ? LINE_MAXLEN - 1 : newsz; + if (*growbuf == NULL) + { + *growbuf = alloc(*allocsz + 1); + if (*growbuf == NULL) + return NULL; + *growbufsiz = *allocsz; + } + else if (*allocsz > *growbufsiz) + { + *growbuf = vim_realloc(*growbuf, *allocsz + 1); + if (*growbuf == NULL) + return NULL; + *growbufsiz = *allocsz; + } + return *growbuf; +} + /* * Read the errorfile "efile" into memory, line by line, building the error * list. @@ -538,24 +563,10 @@ qf_init_ext( if (len > IOSIZE - 2) { - /* - * If the line exceeds LINE_MAXLEN exclude the last - * byte since it's not a NL character. - */ - linelen = len > LINE_MAXLEN ? LINE_MAXLEN - 1 : len; - if (growbuf == NULL) - { - growbuf = alloc(linelen + 1); - growbufsiz = linelen; - } - else if (linelen > growbufsiz) - { - growbuf = vim_realloc(growbuf, linelen + 1); - if (growbuf == NULL) - goto qf_init_end; - growbufsiz = linelen; - } - linebuf = growbuf; + linebuf = qf_grow_linebuf(&growbuf, &growbufsiz, len, + &linelen); + if (linebuf == NULL) + goto qf_init_end; } else { @@ -584,22 +595,10 @@ qf_init_ext( len = (int)STRLEN(p_li->li_tv.vval.v_string); if (len > IOSIZE - 2) { - linelen = len; - if (linelen > LINE_MAXLEN) - linelen = LINE_MAXLEN - 1; - if (growbuf == NULL) - { - growbuf = alloc(linelen + 1); - growbufsiz = linelen; - } - else if (linelen > growbufsiz) - { - if ((growbuf = vim_realloc(growbuf, - linelen + 1)) == NULL) - goto qf_init_end; - growbufsiz = linelen; - } - linebuf = growbuf; + linebuf = qf_grow_linebuf(&growbuf, &growbufsiz, len, + &linelen); + if (linebuf == NULL) + goto qf_init_end; } else { @@ -621,20 +620,10 @@ qf_init_ext( linelen = (int)STRLEN(p_buf); if (linelen > IOSIZE - 2) { - if (growbuf == NULL) - { - growbuf = alloc(linelen + 1); - growbufsiz = linelen; - } - else if (linelen > growbufsiz) - { - if (linelen > LINE_MAXLEN) - linelen = LINE_MAXLEN - 1; - if ((growbuf = vim_realloc(growbuf, linelen + 1)) == NULL) - goto qf_init_end; - growbufsiz = linelen; - } - linebuf = growbuf; + linebuf = qf_grow_linebuf(&growbuf, &growbufsiz, len, + &linelen); + if (linebuf == NULL) + goto qf_init_end; } else linebuf = IObuff; diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim index 31ae9df4d7..e002303601 100644 --- a/src/testdir/test_quickfix.vim +++ b/src/testdir/test_quickfix.vim @@ -700,14 +700,14 @@ endfunc " Tests for the setqflist() and setloclist() functions function SetXlistTests(cchar, bnum) + let Xwindow = a:cchar . 'window' + let Xnext = a:cchar . 'next' if a:cchar == 'c' let Xsetlist = function('setqflist') let Xgetlist = function('getqflist') - let Xnext = 'cnext' else let Xsetlist = function('setloclist', [0]) let Xgetlist = function('getloclist', [0]) - let Xnext = 'lnext' endif call Xsetlist([{'bufnr': a:bnum, 'lnum': 1}, @@ -723,6 +723,15 @@ function SetXlistTests(cchar, bnum) exe Xnext call assert_equal(3, line('.')) + " Appending entries to the list should not change the cursor position + " in the quickfix window + exe Xwindow + 1 + call Xsetlist([{'bufnr': a:bnum, 'lnum': 4}, + \ {'bufnr': a:bnum, 'lnum': 5}], 'a') + call assert_equal(1, line('.')) + close + call Xsetlist([{'bufnr': a:bnum, 'lnum': 3}, \ {'bufnr': a:bnum, 'lnum': 4}, \ {'bufnr': a:bnum, 'lnum': 5}], 'r') diff --git a/src/version.c b/src/version.c index eda517ace2..9e31e77321 100644 --- a/src/version.c +++ b/src/version.c @@ -753,6 +753,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1841, /**/ 1840, /**/ From 26852128a2b713ef49341a0c18daba928444e7eb Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 24 May 2016 20:02:38 +0200 Subject: [PATCH 10/11] Update runtime files. --- runtime/doc/channel.txt | 4 ++-- runtime/doc/filetype.txt | 6 +++++- runtime/doc/options.txt | 5 ++++- runtime/doc/repeat.txt | 7 ++++++- runtime/doc/tags | 10 +++++++++- runtime/doc/todo.txt | 40 +++++++++++++++---------------------- runtime/doc/various.txt | 13 +++++++----- runtime/ftplugin/groovy.vim | 19 ++++++++++++++++++ runtime/scripts.vim | 5 +++-- runtime/syntax/groovy.vim | 11 ++++++---- runtime/syntax/scheme.vim | 17 +++++++++++++++- 11 files changed, 95 insertions(+), 42 deletions(-) create mode 100644 runtime/ftplugin/groovy.vim diff --git a/runtime/doc/channel.txt b/runtime/doc/channel.txt index e527086f2e..bfb62f57b2 100644 --- a/runtime/doc/channel.txt +++ b/runtime/doc/channel.txt @@ -1,4 +1,4 @@ -*channel.txt* For Vim version 7.4. Last change: 2016 May 19 +*channel.txt* For Vim version 7.4. Last change: 2016 May 24 VIM REFERENCE MANUAL by Bram Moolenaar @@ -61,7 +61,7 @@ Common combination are: crosss-refrences in a database. ============================================================================== -2. Channel demo *channel-demo* +2. Channel demo *channel-demo* *demoserver.py* This requires Python. The demo program can be found in $VIMRUNTIME/tools/demoserver.py diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt index cc1e53ccb5..995a04965d 100644 --- a/runtime/doc/filetype.txt +++ b/runtime/doc/filetype.txt @@ -1,4 +1,4 @@ -*filetype.txt* For Vim version 7.4. Last change: 2016 Apr 30 +*filetype.txt* For Vim version 7.4. Last change: 2016 May 24 VIM REFERENCE MANUAL by Bram Moolenaar @@ -585,6 +585,10 @@ If you do not like the default folding, use an autocommand to add your desired folding style instead. For example: > autocmd FileType man setlocal foldmethod=indent foldenable +You may also want to set 'keywordprg' to make the |K| command open a manual +page in a Vim window: > + set keywordprg=:Man + MANPAGER *manpager.vim* diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 3f3764939a..a836e53fb0 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 7.4. Last change: 2016 May 10 +*options.txt* For Vim version 7.4. Last change: 2016 May 24 VIM REFERENCE MANUAL by Bram Moolenaar @@ -6065,6 +6065,7 @@ A jump table for the options with a short description can be found at |Q_op|. keymap/ key mapping files |mbyte-keymap| lang/ menu translations |:menutrans| menu.vim GUI menus |menu.vim| + pack/ packages |:packadd| plugin/ plugin scripts |write-plugin| print/ files for printing |postscript-print-encoding| spell/ spell checking files |spell| @@ -6086,6 +6087,8 @@ A jump table for the options with a short description can be found at |Q_op|. personal preferences to overrule or add to the distributed defaults or system-wide settings (rarely needed). + More entries are added when using |packages|. + Note that, unlike 'path', no wildcards like "**" are allowed. Normal wildcards are allowed, but can significantly slow down searching for runtime files. For speed, use as few items as possible and avoid diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt index 92ab58566d..791e7a54ab 100644 --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -1,4 +1,4 @@ -*repeat.txt* For Vim version 7.4. Last change: 2016 Apr 05 +*repeat.txt* For Vim version 7.4. Last change: 2016 May 24 VIM REFERENCE MANUAL by Bram Moolenaar @@ -232,6 +232,8 @@ For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|. pack/*/opt/{name} ~ The directory is added to 'runtimepath' if it wasn't there yet. + If the directory pack/*/opt/{name}/after exists it is + added at the end of 'runtimepath'. Note that {name} is the directory name, not the name of the .vim file. All the files matching the pattern @@ -507,6 +509,9 @@ To load packages earlier, so that 'runtimepath' gets updated: > This also works when loading plugins is disabled. The automatic loading will only happen once. +If the package has an "after" directory, that directory is added to the end of +'runtimepath', so that anything there will be loaded later. + Using a single plugin and loading it automatically ~ diff --git a/runtime/doc/tags b/runtime/doc/tags index a249d2c54d..f181b5065b 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -4589,6 +4589,7 @@ PHP_outdentSLComments indent.txt /*PHP_outdentSLComments* PHP_outdentphpescape indent.txt /*PHP_outdentphpescape* PHP_removeCRwhenUnix indent.txt /*PHP_removeCRwhenUnix* PHP_vintage_case_default_indent indent.txt /*PHP_vintage_case_default_indent* +Partial eval.txt /*Partial* Pattern pattern.txt /*Pattern* Perl if_perl.txt /*Perl* Posix intro.txt /*Posix* @@ -5562,6 +5563,7 @@ delete() eval.txt /*delete()* delete-insert change.txt /*delete-insert* delete-menus gui.txt /*delete-menus* deleting change.txt /*deleting* +demoserver.py channel.txt /*demoserver.py* design-assumptions develop.txt /*design-assumptions* design-compatible develop.txt /*design-compatible* design-decisions develop.txt /*design-decisions* @@ -6351,7 +6353,6 @@ g` motion.txt /*g`* g`a motion.txt /*g`a* ga various.txt /*ga* garbagecollect() eval.txt /*garbagecollect()* -garbagecollect_for_testing() eval.txt /*garbagecollect_for_testing()* gd pattern.txt /*gd* gdb debug.txt /*gdb* ge motion.txt /*ge* @@ -8611,6 +8612,13 @@ terminal-options term.txt /*terminal-options* terminfo term.txt /*terminfo* termresponse-variable eval.txt /*termresponse-variable* test-functions usr_41.txt /*test-functions* +test_garbagecollect_now() eval.txt /*test_garbagecollect_now()* +test_null_channel() eval.txt /*test_null_channel()* +test_null_dict() eval.txt /*test_null_dict()* +test_null_job() eval.txt /*test_null_job()* +test_null_list() eval.txt /*test_null_list()* +test_null_partial() eval.txt /*test_null_partial()* +test_null_string() eval.txt /*test_null_string()* testing-variable eval.txt /*testing-variable* tex-cchar syntax.txt /*tex-cchar* tex-cole syntax.txt /*tex-cole* diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index 6377a7682c..1a118a1b73 100644 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -1,4 +1,4 @@ -*todo.txt* For Vim version 7.4. Last change: 2016 May 20 +*todo.txt* For Vim version 7.4. Last change: 2016 May 24 VIM REFERENCE MANUAL by Bram Moolenaar @@ -42,41 +42,26 @@ Any other callbacks that could be invoked at the wrong moment? If removing buffer that's being read from, close channel? -problem with "Ignore" after adding 'guicolors'. (Charles Campbell, 2016 Apr +Problem with "Ignore" after adding 'guicolors'. (Charles Campbell, 2016 Apr 27) -In test_partial when start_job() has a non-existing command memory leaks. - -Rename garbagecollect_for_testing() to test_garbagecollect_now(). -Add test_get_null_list(), use in test_expr. +In test_partial when start_job() has a non-existing command memory (a dict +item) leaks. Memory leak in test49 Memory leak in test_alot, with matchstrpos() Packages: -- Add the "after" directory to 'runtimepath' only if it exists. +- Add the "after" directory to 'runtimepath', only if it exists. (Greg Hurrell, May 1) - Also keep a list of loaded plugins, skip when encountered again? Vim.org: when a user already has a homepage, do show the field so that it can be deleted. -Patch to fix memory leak (Justin Keyes, 2016 May 16, #811) -Instead free before assigning, set to NULL after free. - Comparing partials doesn't work well. (Nikolai Pavlov, 2016 May 17, #813) Examples in the form of a test (May 19) -Documentation for partials is lacking. -- Add "partial" and "partials" tag. -- Assigning to a dict member creates a partial. - How to store a partial associated with dictA in dictB? Add help for this. - See comments on #812. -- using dict.Func for function() is broken: not true (Nikolai Pavlov, May 20) - -Patch to fix that BufUnload is triggered twice. (Hirohito Higashi, 2016 May -14) - +channel: - Feedback from Ramel Eshed, May 7. Occasional crashes. - Close_cb isn't invoked when output goes to a buffer. (Luc Hermitte) @@ -153,15 +138,14 @@ Regexp problems: Using freed memory in quickfix code. (Dominique, 2016 Mar 21) +User commands: add a <> item to pass on command modifiers, such as ":tab". + jsonencode(): should convert to utf-8. (Nikolai Pavlov, 2016 Jan 23) What if there is an invalid character? Once .exe with updated installer is available: Add remark to download page about /S and /D options (Ken Takata, 2016 Apr 13) -Patch to avoid reallocating buffer for quickfix lines three times. -(Yegappan Lakshmanan, 2016 May 7) - Patch to make cursor blinking work better with GTK3. (Kazunobu Kuriyama, 2016 Apr 19) Need to check this works on Linux. Alternative: @@ -180,14 +164,22 @@ Invalid behavior with NULL list. (Nikolai Pavlov, #768) Patch to fix using CTRL-] on "{address}." in help. (Hirohito Higashi, 2016 May 18, #814) +Patch to reduce number of memory allocations for quickfix lines. +(Yegappan Lakshmanan, 2016 May 22, #831) + +Patch to fix greying popup menu items. (Shane Harper, 2016 May 23, #834) + &t_ut not used with 'termguicolors' is set. (Jacob Niehus, 2016 May 14, #804) Patch to fix this, Jacob Niehus, 2016 May 14, #805) For current Windows build .pdb file is missing. (Gabriele Fava, 2016 May 11) 5) +Problem with whitespace in errorformat. (Gerd Wachsmuth, 2016 May 15, #807) + When 'autochdir' is set, writing new file does not change the current dir. (Dan Church, issue #777) +Patch to fix this. (mister fish (Allen Haim), 2016 May 14, #803) ml_get errors when reloading file. (Chris Desjardins, 2016 Apr 19) Also with latest version. @@ -420,7 +412,7 @@ Value returned by virtcol() changes depending on how lines wrap. This is inconsistent with the documentation. Patch to add filtering of the quickfix list. (Yegappan Lakshmanan, 2016 Mar -13, last version) Update Mar 21., Apr 2. +13, last version) Update May 22, #830. Can we cache the syntax attributes, so that updates for 'relativenumber' and 'cursorline'/'cursorcolumn' are a lot faster? diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index 7510210bd3..067ae6e6ff 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -1,4 +1,4 @@ -*various.txt* For Vim version 7.4. Last change: 2016 May 05 +*various.txt* For Vim version 7.4. Last change: 2016 May 24 VIM REFERENCE MANUAL by Bram Moolenaar @@ -607,13 +607,16 @@ K Run a program to lookup the keyword under the directory of Vim. It is called 'ref' and does a simple spelling check. Special cases: + - If 'keywordprg' begins with ":" it is invoked as + a Vim Ex command with [count]. - If 'keywordprg' is empty, the ":help" command is used. It's a good idea to include more characters in 'iskeyword' then, to be able to find more help. - - When 'keywordprg' is equal to "man", a count before - "K" is inserted after the "man" command and before - the keyword. For example, using "2K" while the - cursor is on "mkdir", results in: > + - When 'keywordprg' is equal to "man" or starts with + ":", a [count] before "K" is inserted after + keywordprg and before the keyword. For example, + using "2K" while the cursor is on "mkdir", results + in: > !man 2 mkdir < - When 'keywordprg' is equal to "man -s", a count before "K" is inserted after the "-s". If there is diff --git a/runtime/ftplugin/groovy.vim b/runtime/ftplugin/groovy.vim new file mode 100644 index 0000000000..cc7d6e35eb --- /dev/null +++ b/runtime/ftplugin/groovy.vim @@ -0,0 +1,19 @@ +" Vim filetype plugin file +" Language: groovy +" Maintainer: Justin M. Keyes +" Last Change: 2016 May 22 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +let s:cpo_save = &cpo +set cpo-=C + +let b:undo_ftplugin = 'setlocal commentstring<' + +setlocal commentstring=//%s + +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/runtime/scripts.vim b/runtime/scripts.vim index 5c136abbb1..276382808b 100644 --- a/runtime/scripts.vim +++ b/runtime/scripts.vim @@ -1,7 +1,7 @@ " Vim support file to detect file types in scripts " " Maintainer: Bram Moolenaar -" Last change: 2014 Aug 24 +" Last change: 2016 May 21 " This file is called by an autocommand for every file that has just been " loaded into a buffer. It checks if the type of file can be recognized by @@ -245,7 +245,8 @@ else set ft=xhtml " HTML (e.g.: ' + " Avoid "doctype html", used by slim. + elseif s:line1 =~? '' set ft=html " PDF diff --git a/runtime/syntax/groovy.vim b/runtime/syntax/groovy.vim index 42fcf4abac..dc39677724 100644 --- a/runtime/syntax/groovy.vim +++ b/runtime/syntax/groovy.vim @@ -2,9 +2,9 @@ " Language: Groovy " Original Author: Alessio Pace " Maintainer: Tobias Rapp -" Version: 0.1.14 +" Version: 0.1.16 " URL: http://www.vim.org/scripts/script.php?script_id=945 -" Last Change: 2015 Apr 21 +" Last Change: 2016 May 23 " THE ORIGINAL AUTHOR'S NOTES: " @@ -255,8 +255,11 @@ syn region groovyString start=+"+ end=+"+ end=+$+ contains=groovySpeci syn region groovyString start=+'+ end=+'+ end=+$+ contains=groovySpecialChar,groovySpecialError,@Spell syn region groovyString start=+"""+ end=+"""+ contains=groovySpecialChar,groovySpecialError,@Spell,groovyELExpr syn region groovyString start=+'''+ end=+'''+ contains=groovySpecialChar,groovySpecialError,@Spell -" regex string -syn region groovyString start='/[^/]' end='/' contains=groovySpecialChar,groovyRegexChar,groovyELExpr +if exists("groovy_regex_strings") + " regex strings interfere with the division operator and thus are disabled + " by default + syn region groovyString start='/[^/*]' end='/' contains=groovySpecialChar,groovyRegexChar,groovyELExpr +endif " syn region groovyELExpr start=+${+ end=+}+ keepend contained syn match groovyELExpr /\${.\{-}}/ contained syn match groovyELExpr /\$[a-zA-Z_][a-zA-Z0-9_.]*/ contained diff --git a/runtime/syntax/scheme.vim b/runtime/syntax/scheme.vim index a210b0c720..c59e09cd17 100644 --- a/runtime/syntax/scheme.vim +++ b/runtime/syntax/scheme.vim @@ -1,6 +1,6 @@ " Vim syntax file " Language: Scheme (R5RS + some R6RS extras) -" Last Change: 2012 May 13 +" Last Change: 2016 May 23 " Maintainer: Sergey Khorev " Original author: Dirk van Deun @@ -245,6 +245,18 @@ if exists("b:is_mzscheme") || exists("is_mzscheme") syn region schemeUnquote matchgroup=Delimiter start="#,@\[" end="\]" contains=ALL syn region schemeQuoted matchgroup=Delimiter start="#['`]" end=![ \t()\[\]";]!me=e-1 contains=ALL syn region schemeQuoted matchgroup=Delimiter start="#['`](" matchgroup=Delimiter end=")" contains=ALL + + " Identifiers are very liberal in MzScheme/Racket + syn match schemeOther ![^()[\]{}",'`;#|\\ ]\+! + + " Language setting + syn match schemeLang "#lang [-+_/A-Za-z0-9]\+\>" + + " Various number forms + syn match schemeNumber "[-+]\=[0-9]\+\(\.[0-9]*\)\=\(e[-+]\=[0-9]\+\)\=\>" + syn match schemeNumber "[-+]\=\.[0-9]\+\(e[-+]\=[0-9]\+\)\=\>" + syn match schemeNumber "[-+]\=[0-9]\+/[0-9]\+\>" + syn match schemeNumber "\([-+]\=\([0-9]\+\(\.[0-9]*\)\=\(e[-+]\=[0-9]\+\)\=\|\.[0-9]\+\(e[-+]\=[0-9]\+\)\=\|[0-9]\+/[0-9]\+\)\)\=[-+]\([0-9]\+\(\.[0-9]*\)\=\(e[-+]\=[0-9]\+\)\=\|\.[0-9]\+\(e[-+]\=[0-9]\+\)\=\|[0-9]\+/[0-9]\+\)\=i\>" endif @@ -321,6 +333,9 @@ if version >= 508 || !exists("did_scheme_syntax_inits") HiLink schemeExtSyntax Type HiLink schemeExtFunc PreProc + + HiLink schemeLang PreProc + delcommand HiLink endif From 03e19a04ac2ca55643663b97b6ab94043233dcbd Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 24 May 2016 22:29:49 +0200 Subject: [PATCH 11/11] patch 7.4.1842 Problem: get() works for Partial but not for Funcref. Solution: Accept Funcref. Also return the function itself. (Nikolai Pavlov) --- runtime/doc/eval.txt | 6 ++++-- src/eval.c | 18 ++++++++++++++---- src/testdir/test_partial.vim | 15 ++++++++++++--- src/version.c | 2 ++ 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 36133d839f..8cc1099cfc 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1957,6 +1957,7 @@ function({name} [, {arglist}] [, {dict}]) garbagecollect([{atexit}]) none free memory, breaking cyclic references get({list}, {idx} [, {def}]) any get item {idx} from {list} or {def} get({dict}, {key} [, {def}]) any get item {key} from {dict} or {def} +get({func}, {what}) any get property of funcref/partial {func} getbufline({expr}, {lnum} [, {end}]) List lines {lnum} to {end} of buffer {expr} getbufvar({expr}, {varname} [, {def}]) @@ -3771,9 +3772,10 @@ get({dict}, {key} [, {default}]) Get item with key {key} from |Dictionary| {dict}. When this item is not available return {default}. Return zero when {default} is omitted. -get({partial}, {what}) - Get an item with from Funcref {partial}. Possible values for +get({func}, {what}) + Get an item with from Funcref {func}. Possible values for {what} are: + 'name' The function name 'func' The function 'dict' The dictionary 'args' The list with arguments diff --git a/src/eval.c b/src/eval.c index 99b948c7d8..41f98d2fa1 100644 --- a/src/eval.c +++ b/src/eval.c @@ -12423,17 +12423,27 @@ f_get(typval_T *argvars, typval_T *rettv) tv = &di->di_tv; } } - else if (argvars[0].v_type == VAR_PARTIAL) + else if (argvars[0].v_type == VAR_PARTIAL || argvars[0].v_type == VAR_FUNC) { - partial_T *pt = argvars[0].vval.v_partial; + partial_T *pt; + partial_T fref_pt; + + if (argvars[0].v_type == VAR_PARTIAL) + pt = argvars[0].vval.v_partial; + else + { + vim_memset(&fref_pt, 0, sizeof(fref_pt)); + fref_pt.pt_name = argvars[0].vval.v_string; + pt = &fref_pt; + } if (pt != NULL) { char_u *what = get_tv_string(&argvars[1]); - if (STRCMP(what, "func") == 0) + if (STRCMP(what, "func") == 0 || STRCMP(what, "name") == 0) { - rettv->v_type = VAR_STRING; + rettv->v_type = (*what == 'f' ? VAR_FUNC : VAR_STRING); if (pt->pt_name == NULL) rettv->vval.v_string = NULL; else diff --git a/src/testdir/test_partial.vim b/src/testdir/test_partial.vim index 30e1df99e7..af6ca6db25 100644 --- a/src/testdir/test_partial.vim +++ b/src/testdir/test_partial.vim @@ -282,9 +282,18 @@ endfunc func Test_get_partial_items() let dict = {'name': 'hello'} - let Cb = function('MyDictFunc', ["foo", "bar"], dict) - call assert_equal('MyDictFunc', get(Cb, 'func')) - call assert_equal(["foo", "bar"], get(Cb, 'args')) + let args = ["foo", "bar"] + let Func = function('MyDictFunc') + let Cb = function('MyDictFunc', args, dict) + + call assert_equal(Func, get(Cb, 'func')) + call assert_equal('MyDictFunc', get(Cb, 'name')) + call assert_equal(args, get(Cb, 'args')) call assert_equal(dict, get(Cb, 'dict')) call assert_fails('call get(Cb, "xxx")', 'E475:') + + call assert_equal(Func, get(Func, 'func')) + call assert_equal('MyDictFunc', get(Func, 'name')) + call assert_equal([], get(Func, 'args')) + call assert_true(empty( get(Func, 'dict'))) endfunc diff --git a/src/version.c b/src/version.c index 9e31e77321..d93be4881e 100644 --- a/src/version.c +++ b/src/version.c @@ -753,6 +753,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1842, /**/ 1841, /**/