From c8ce615299b4d8c1b2e6cf83496f48cd497d8a37 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 7 Aug 2016 13:48:20 +0200 Subject: [PATCH 1/8] patch 7.4.2174 Problem: Adding duplicate flags to 'whichwrap' leaves commas behind. Solution: Also remove the commas. (Naruhiko Nishino) --- src/Makefile | 2 +- src/option.c | 26 +++++++++++++++++++---- src/testdir/Make_all.mak | 1 - src/testdir/test_alot.vim | 1 + src/testdir/test_options.in | 23 --------------------- src/testdir/test_options.ok | 3 --- src/testdir/test_options.vim | 40 ++++++++++++++++++++++++++++++++++++ src/version.c | 2 ++ 8 files changed, 66 insertions(+), 32 deletions(-) delete mode 100644 src/testdir/test_options.in delete mode 100644 src/testdir/test_options.ok create mode 100644 src/testdir/test_options.vim diff --git a/src/Makefile b/src/Makefile index 33d8b8c53c..ada714d279 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2031,7 +2031,6 @@ test1 \ test_mapping \ test_marks \ test_nested_function \ - test_options \ test_search_mbyte \ test_signs \ test_tagcase \ @@ -2101,6 +2100,7 @@ test_arglist \ test_menu \ test_messages \ test_netbeans \ + test_options \ test_packadd \ test_partial \ test_perl \ diff --git a/src/option.c b/src/option.c index b9b59eefd0..ff7973fd40 100644 --- a/src/option.c +++ b/src/option.c @@ -4919,12 +4919,30 @@ do_set( { /* Remove flags that appear twice. */ for (s = newval; *s; ++s) - if ((!(flags & P_COMMA) || *s != ',') - && vim_strchr(s + 1, *s) != NULL) + { + /* if options have P_FLAGLIST and + * P_ONECOMMA such as 'whichwrap' */ + if (flags & P_ONECOMMA) { - STRMOVE(s, s + 1); - --s; + if (*s != ',' && *(s + 1) == ',' + && vim_strchr(s + 2, *s) != NULL) + { + /* Remove the duplicated value and + * the next comma. */ + STRMOVE(s, s + 2); + s -= 2; + } } + else + { + if ((!(flags & P_COMMA) || *s != ',') + && vim_strchr(s + 1, *s) != NULL) + { + STRMOVE(s, s + 1); + --s; + } + } + } } if (save_arg != NULL) /* number for 'whichwrap' */ diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index e7e4c680aa..02f2611086 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -101,7 +101,6 @@ SCRIPTS_ALL = \ test_mapping.out \ test_marks.out \ test_nested_function.out \ - test_options.out \ test_search_mbyte.out \ test_signs.out \ test_tagcase.out \ diff --git a/src/testdir/test_alot.vim b/src/testdir/test_alot.vim index 0245fadb45..8dd698478d 100644 --- a/src/testdir/test_alot.vim +++ b/src/testdir/test_alot.vim @@ -38,3 +38,4 @@ source test_timers.vim source test_true_false.vim source test_unlet.vim source test_window_cmd.vim +source test_options.vim diff --git a/src/testdir/test_options.in b/src/testdir/test_options.in deleted file mode 100644 index 6e56fa2427..0000000000 --- a/src/testdir/test_options.in +++ /dev/null @@ -1,23 +0,0 @@ -Test for ":options". - -STARTTEST -:so small.vim -:let caught = 'ok' -:try - :options -:catch - :let caught = v:throwpoint . "\n" . v:exception -:endtry -:buf 1 -:$put =caught -:" -:" Test that changing 'path' keeps two commas. -:set path=foo,,bar -:set path-=bar -:set path+=bar -:$put =&path -:/^result/,$w! test.out -:qa! -ENDTEST - -result diff --git a/src/testdir/test_options.ok b/src/testdir/test_options.ok deleted file mode 100644 index 07731526bc..0000000000 --- a/src/testdir/test_options.ok +++ /dev/null @@ -1,3 +0,0 @@ -result -ok -foo,,bar diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim new file mode 100644 index 0000000000..cceb180189 --- /dev/null +++ b/src/testdir/test_options.vim @@ -0,0 +1,40 @@ +" Test for options + +function! Test_whichwrap() + set whichwrap=b,s + call assert_equal('b,s', &whichwrap) + + set whichwrap+=h,l + call assert_equal('b,s,h,l', &whichwrap) + + set whichwrap+=h,l + call assert_equal('b,s,h,l', &whichwrap) + + set whichwrap+=h,l + call assert_equal('b,s,h,l', &whichwrap) + + set whichwrap& +endfunction + +function! Test_options() + let caught = 'ok' + try + options + catch + let caught = v:throwpoint . "\n" . v:exception + endtry + call assert_equal('ok', caught) + + " close option-window + close +endfunction + +function! Test_path_keep_commas() + " Test that changing 'path' keeps two commas. + set path=foo,,bar + set path-=bar + set path+=bar + call assert_equal('foo,,bar', &path) + + set path& +endfunction diff --git a/src/version.c b/src/version.c index 9cf031bdff..f2d1c79e33 100644 --- a/src/version.c +++ b/src/version.c @@ -763,6 +763,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2174, /**/ 2173, /**/ From 812ad4f3a2cb33002a24f6b5862c7b375cd68fe4 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 7 Aug 2016 14:03:13 +0200 Subject: [PATCH 2/8] patch 7.4.2175 Problem: Insufficient testing of cscope. Solution: Add more tests. (Dominique Pelle) --- src/testdir/test_cscope.vim | 405 +++++++++++++++++++++++------------- src/version.c | 2 + 2 files changed, 258 insertions(+), 149 deletions(-) diff --git a/src/testdir/test_cscope.vim b/src/testdir/test_cscope.vim index 2c7ed9fcce..e9ed490372 100644 --- a/src/testdir/test_cscope.vim +++ b/src/testdir/test_cscope.vim @@ -4,6 +4,256 @@ if !has('cscope') || !executable('cscope') || !has('quickfix') finish endif +func CscopeSetupOrClean(setup) + if a:setup + noa sp ../memfile_test.c + saveas! Xmemfile_test.c + call system('cscope -bk -fXcscope.out Xmemfile_test.c') + call system('cscope -bk -fXcscope2.out Xmemfile_test.c') + cscope add Xcscope.out + set cscopequickfix=s-,g-,d-,c-,t-,e-,f-,i-,a- + else + cscope kill -1 + for file in ['Xcscope.out', 'Xcscope2.out', 'Xmemfile_test.c'] + call delete(file) + endfo + endif +endfunc + +func Test_cscopeWithCscopeConnections() + call CscopeSetupOrClean(1) + " Test 0: E568: duplicate cscope database not added + try + set nocscopeverbose + cscope add Xcscope.out + set cscopeverbose + catch + call assert_true(0) + endtry + call assert_fails('cscope add', 'E560') + call assert_fails('cscope add Xcscope.out', 'E568') + call assert_fails('cscope add doesnotexist.out', 'E563') + + " Test 1: Find this C-Symbol + for cmd in ['cs find s main', 'cs find 0 main'] + let a=execute(cmd) + " Test 1.1 test where it moves the cursor + call assert_equal('main(void)', getline('.')) + " Test 1.2 test the output of the :cs command + call assert_match('\n(1 of 1): <
> main(void )', a) + endfor + + " Test 2: Find this definition + for cmd in ['cs find g test_mf_hash', 'cs find 1 test_mf_hash'] + exe cmd + call assert_equal(['', '/*', ' * Test mf_hash_*() functions.', ' */', ' static void', 'test_mf_hash(void)', '{'], getline(line('.')-5, line('.')+1)) + endfor + + " Test 3: Find functions called by this function + for cmd in ['cs find d test_mf_hash', 'cs find 2 test_mf_hash'] + let a=execute(cmd) + call assert_match('\n(1 of 42): <> mf_hash_init(&ht);', a) + call assert_equal(' mf_hash_init(&ht);', getline('.')) + endfor + + " Test 4: Find functions calling this function + for cmd in ['cs find c test_mf_hash', 'cs find 3 test_mf_hash'] + let a=execute(cmd) + call assert_match('\n(1 of 1): <
> test_mf_hash();', a) + call assert_equal(' test_mf_hash();', getline('.')) + endfor + + " Test 5: Find this text string + for cmd in ['cs find t Bram', 'cs find 4 Bram'] + let a=execute(cmd) + call assert_match('(1 of 1): <<>> \* VIM - Vi IMproved^Iby Bram Moolenaar', a) + call assert_equal(' * VIM - Vi IMproved by Bram Moolenaar', getline('.')) + endfor + + " Test 6: Find this egrep pattern + " test all matches returned by cscope + for cmd in ['cs find e ^\#includ.', 'cs find 6 ^\#includ.'] + let a=execute(cmd) + call assert_match('\n(1 of 3): <<>> #include ', a) + call assert_equal('#include ', getline('.')) + cnext + call assert_equal('#include "main.c"', getline('.')) + cnext + call assert_equal('#include "memfile.c"', getline('.')) + call assert_fails('cnext', 'E553:') + endfor + + " Test 7: Find the same egrep pattern using lcscope this time. + let a=execute('lcs find e ^\#includ.') + call assert_match('\n(1 of 3): <<>> #include ', a) + call assert_equal('#include ', getline('.')) + lnext + call assert_equal('#include "main.c"', getline('.')) + lnext + call assert_equal('#include "memfile.c"', getline('.')) + call assert_fails('lnext', 'E553:') + + " Test 8: Find this file + for cmd in ['cs find f Xmemfile_test.c', 'cs find 7 Xmemfile_test.c'] + enew + let a=execute(cmd) + call assert_match('\n"Xmemfile_test.c" 143L, 3137C', a) + call assert_equal('Xmemfile_test.c', @%) + endfor + + " Test 9: Find files #including this file + for cmd in ['cs find i assert.h', 'cs find 8 assert.h'] + enew + let a=execute(cmd) + call assert_equal(['','"Xmemfile_test.c" 143L, 3137C','(1 of 1): <> #include '], split(a, '\n', 1)) + call assert_equal('#include ', getline('.')) + endfor + + " Test 10: Invalid find command + call assert_fails('cs find x', 'E560:') + + " Test 11: Find places where this symbol is assigned a value + " this needs a cscope >= 15.8 + " unfortunately, Travis has cscope version 15.7 + let cscope_version=systemlist('cscope --version')[0] + let cs_version=str2float(matchstr(cscope_version, '\d\+\(\.\d\+\)\?')) + if cs_version >= 15.8 + for cmd in ['cs find a item', 'cs find 9 item'] + let a=execute(cmd) + call assert_equal(['', '(1 of 4): <> item = (mf_hashitem_T *)lalloc_clear(sizeof(mf_hashtab_T), FALSE);'], split(a, '\n', 1)) + call assert_equal(' item = (mf_hashitem_T *)lalloc_clear(sizeof(mf_hashtab_T), FALSE);', getline('.')) + cnext + call assert_equal(' item = mf_hash_find(&ht, key);', getline('.')) + cnext + call assert_equal(' item = mf_hash_find(&ht, key);', getline('.')) + cnext + call assert_equal(' item = mf_hash_find(&ht, key);', getline('.')) + endfor + endif + + " Test 12: leading whitespace is not removed for cscope find text + let a=execute('cscope find t test_mf_hash') + call assert_equal(['', '(1 of 1): <<>> test_mf_hash();'], split(a, '\n', 1)) + call assert_equal(' test_mf_hash();', getline('.')) + + " Test 13: test with scscope + let a=execute('scs find t Bram') + call assert_match('(1 of 1): <<>> \* VIM - Vi IMproved^Iby Bram Moolenaar', a) + call assert_equal(' * VIM - Vi IMproved by Bram Moolenaar', getline('.')) + + " Test 14: cscope help + for cmd in ['cs', 'cs help', 'cs xxx'] + let a=execute(cmd) + call assert_match('^cscope commands:\n', a) + call assert_match('\nadd :', a) + call assert_match('\nfind :', a) + call assert_match('\nhelp : Show this message', a) + call assert_match('\nkill : Kill a connection', a) + call assert_match('\nreset: Reinit all connections', a) + call assert_match('\nshow : Show connections', a) + endfor + let a=execute('scscope help') + call assert_match('This cscope command does not support splitting the window\.', a) + + " Test 15: reset connections + let a=execute('cscope reset') + call assert_match('\nAdded cscope database.*Xcscope.out (#0)', a) + call assert_match('\nAll cscope databases reset', a) + + " Test 16: cscope show + let a=execute('cscope show') + call assert_match('\n 0 \d\+.*Xcscope.out\s*', a) + + " Test 17: cstag and 'csto' option + set csto=0 + let a=execute('cstag TEST_COUNT') + call assert_match('(1 of 1): <> #define TEST_COUNT 50000', a) + call assert_equal('#define TEST_COUNT 50000', getline('.')) + set csto=1 + let a=execute('cstag index_to_key') + call assert_match('(1 of 1): <> #define index_to_key(i) ((i) ^ 15167)', a) + call assert_equal('#define index_to_key(i) ((i) ^ 15167)', getline('.')) + call assert_fails('cstag xxx', 'E257:') + call assert_fails('cstag', 'E562:') + + " Test 18: 'cst' option + set nocst + call assert_fails('tag TEST_COUNT', 'E426:') + set cst + let a=execute('tag TEST_COUNT') + call assert_match('(1 of 1): <> #define TEST_COUNT 50000', a) + call assert_equal('#define TEST_COUNT 50000', getline('.')) + let a=execute('tags') + call assert_match('1 1 TEST_COUNT\s\+\d\+\s\+#define index_to_key', a) + + " Test 19: this should trigger call to cs_print_tags() + " Unclear how to check result though, we just exercise the code. + set cst cscopequickfix=s0 + call feedkeys(":cs find s main\", 't') + + " Test 20: cscope kill + call assert_fails('cscope kill 2', 'E261:') + call assert_fails('cscope kill xxx', 'E261:') + + let a=execute('cscope kill 0') + call assert_match('cscope connection 0 closed', a) + + cscope add Xcscope.out + let a=execute('cscope kill Xcscope.out') + call assert_match('cscope connection Xcscope.out closed', a) + + cscope add Xcscope.out . + let a=execute('cscope kill -1') + call assert_match('cscope connection .*Xcscope.out closed', a) + let a=execute('cscope kill -1') + call assert_equal('', a) + + " Test 21: 'csprg' option + call assert_equal('cscope', &csprg) + set csprg=doesnotexist + call assert_fails('cscope add Xcscope2.out', 'E609:') + set csprg=cscope + + " Test 22: multiple cscope connections + cscope add Xcscope.out + cscope add Xcscope2.out . -C + let a=execute('cscope show') + call assert_match('\n 0 \d\+.*Xcscope.out\s*', a) + call assert_match('\n 1 \d\+.*Xcscope2.out\s*\.', a) + + " Test 23: test Ex command line completion + call feedkeys(":cs \\\"\", 'tx') + call assert_equal('"cs add find help kill reset show', @:) + + call feedkeys(":scs \\\"\", 'tx') + call assert_equal('"scs find', @:) + + call feedkeys(":cs find \\\"\", 'tx') + call assert_equal('"cs find a c d e f g i s t', @:) + + call feedkeys(":cs kill \\\"\", 'tx') + call assert_equal('"cs kill -1 0 1', @:) + + call feedkeys(":cs add Xcscope\\\"\", 'tx') + call assert_equal('"cs add Xcscope.out Xcscope2.out', @:) + + " Test 24: cscope_connection() + call assert_equal(cscope_connection(), 1) + call assert_equal(cscope_connection(0, 'out'), 1) + call assert_equal(cscope_connection(0, 'xxx'), 1) + call assert_equal(cscope_connection(1, 'out'), 1) + call assert_equal(cscope_connection(1, 'xxx'), 0) + call assert_equal(cscope_connection(2, 'out'), 0) + call assert_equal(cscope_connection(3, 'xxx', '..'), 0) + call assert_equal(cscope_connection(3, 'out', 'xxx'), 0) + call assert_equal(cscope_connection(3, 'out', '.'), 1) + call assert_equal(cscope_connection(4, 'out', '.'), 0) + + " CleanUp + call CscopeSetupOrClean(0) + +endfunc + func Test_cscopequickfix() set cscopequickfix=s-,g-,d+,c-,t+,e-,f0,i-,a- call assert_equal('s-,g-,d+,c-,t+,e-,f0,i-,a-', &cscopequickfix) @@ -14,156 +264,13 @@ func Test_cscopequickfix() call assert_fails('set cscopequickfix=s-a', 'E474:') endfunc -func CscopeSetupOrClean(setup) - if a:setup - noa sp ../memfile_test.c - saveas! Xmemfile_test.c - call system('cscope -bk -fXcscope.out Xmemfile_test.c') - cscope add Xcscope.out - set cscopequickfix=s-,g-,d-,c-,t-,e-,f-,i-,a- - else - cscope kill -1 - for file in ['Xcscope.out', 'Xmemfile_test.c'] - call delete(file) - endfor - endif +func Test_withoutCscopeConnection() + call assert_equal(cscope_connection(), 0) + + call assert_fails('cscope find s main', 'E567:') + let a=execute('cscope show') + call assert_match('no cscope connections', a) endfunc -func Test_cscope1() - call CscopeSetupOrClean(1) - " Test 0: E568: duplicate cscope database not added - try - set nocscopeverbose - cscope add Xcscope.out - set cscopeverbose - catch - call assert_true(0) - endtry - call assert_fails('cscope add Xcscope.out', 'E568') - call assert_fails('cscope add doesnotexist.out', 'E563') - call assert_fails('cscope kill 2', 'E261') - " Test 1: Find this C-Symbol - let a=execute('cscope find s main') - " Test 1.1 test where it moves the cursor - call assert_equal('main(void)', getline('.')) - " Test 1.2 test the output of the :cs command - call assert_match('\n(1 of 1): <
> main(void )', a) - - " Test 2: Find this definition - cscope find g test_mf_hash - call assert_equal(['', '/*', ' * Test mf_hash_*() functions.', ' */', ' static void', 'test_mf_hash(void)', '{'], getline(line('.')-5, line('.')+1)) - - " Test 3: Find functions called by this function - let a=execute('cscope find d test_mf_hash') - call assert_match('\n(1 of 42): <> mf_hash_init(&ht);', a) - call assert_equal(' mf_hash_init(&ht);', getline('.')) - - " Test 4: Find functions calling this function - let a=execute('cscope find c test_mf_hash') - call assert_match('\n(1 of 1): <
> test_mf_hash();', a) - call assert_equal(' test_mf_hash();', getline('.')) - - " Test 5: Find this text string - let a=execute('cscope find t Bram') - call assert_match('(1 of 1): <<>> \* VIM - Vi IMproved^Iby Bram Moolenaar', a) - call assert_equal(' * VIM - Vi IMproved by Bram Moolenaar', getline('.')) - - " Test 6: Find this egrep pattern - " test all matches returned by cscope - let a=execute('cscope find e ^\#includ.') - call assert_match('\n(1 of 3): <<>> #include ', a) - call assert_equal('#include ', getline('.')) - cnext - call assert_equal('#include "main.c"', getline('.')) - cnext - call assert_equal('#include "memfile.c"', getline('.')) - call assert_fails('cnext', 'E553') - - " Test 7: Find this file - enew - let a=execute('cscope find f Xmemfile_test.c') - call assert_match('\n"Xmemfile_test.c" 143L, 3137C', a) - call assert_equal('Xmemfile_test.c', @%) - - " Test 8: Find files #including this file - enew - let a=execute('cscope find i assert.h') - call assert_equal(['','"Xmemfile_test.c" 143L, 3137C','(1 of 1): <> #include '], split(a, '\n', 1)) - call assert_equal('#include ', getline('.')) - - " Test 9: Invalid find command - call assert_fails('cs find x', 'E560') - - " Test 10: Find places where this symbol is assigned a value - " this needs a cscope >= 15.8 - " unfortunately, Travis has cscope version 15.7 - let cscope_version=systemlist('cscope --version')[0] - let cs_version=str2float(matchstr(cscope_version, '\d\+\(\.\d\+\)\?')) - if cs_version >= 15.8 - let a=execute('cscope find a item') - call assert_equal(['', '(1 of 4): <> item = (mf_hashitem_T *)lalloc_clear(sizeof(mf_hashtab_T), FALSE);'], split(a, '\n', 1)) - call assert_equal(' item = (mf_hashitem_T *)lalloc_clear(sizeof(mf_hashtab_T), FALSE);', getline('.')) - cnext - call assert_equal(' item = mf_hash_find(&ht, key);', getline('.')) - cnext - call assert_equal(' item = mf_hash_find(&ht, key);', getline('.')) - cnext - call assert_equal(' item = mf_hash_find(&ht, key);', getline('.')) - endif - - " Test 11: leading whitespace is not removed for cscope find text - let a=execute('cscope find t test_mf_hash') - call assert_equal(['', '(1 of 1): <<>> test_mf_hash();'], split(a, '\n', 1)) - call assert_equal(' test_mf_hash();', getline('.')) - - " Test 12: cscope help - let a=execute('cscope help') - call assert_match('^cscope commands:\n', a) - call assert_match('\nadd :', a) - call assert_match('\nfind :', a) - call assert_match('\nhelp : Show this message', a) - call assert_match('\nkill : Kill a connection', a) - call assert_match('\nreset: Reinit all connections', a) - call assert_match('\nshow : Show connections', a) - - " Test 13: reset connections - let a=execute('cscope reset') - call assert_match('\nAdded cscope database.*Xcscope.out (#0)', a) - call assert_match('\nAll cscope databases reset', a) - - " Test 14: cscope show - let a=execute('cscope show') - call assert_match('\n 0 \d\+.*Xcscope.out\s*', a) - - " Test 15: cstag and 'csto' option - set csto=0 - let a=execute('cstag TEST_COUNT') - call assert_match('(1 of 1): <> #define TEST_COUNT 50000', a) - call assert_equal('#define TEST_COUNT 50000', getline('.')) - set csto=1 - let a=execute('cstag index_to_key') - call assert_match('(1 of 1): <> #define index_to_key(i) ((i) ^ 15167)', a) - call assert_equal('#define index_to_key(i) ((i) ^ 15167)', getline('.')) - call assert_fails('cstag xxx', 'E257') - call assert_fails('cstag', 'E562') - - " Test 15: 'csprg' option - call assert_equal('cscope', &csprg) - - " Test 16: 'cst' option - set cst - let a=execute('tag TEST_COUNT') - call assert_match('(1 of 1): <> #define TEST_COUNT 50000', a) - call assert_equal('#define TEST_COUNT 50000', getline('.')) - set nocst - call assert_fails('tag TEST_COUNT', 'E426') - - " CleanUp - call CscopeSetupOrClean(0) - - " cscope command should fail after killing scope connection. - call assert_fails('cscope find s main', 'E567') - -endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index f2d1c79e33..944dfa4230 100644 --- a/src/version.c +++ b/src/version.c @@ -763,6 +763,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2175, /**/ 2174, /**/ From a8e691d44937fd9d72dcbad2b8c673682277f13d Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 7 Aug 2016 15:19:26 +0200 Subject: [PATCH 3/8] patch 7.4.2176 Problem: #ifdefs in main() are complicated. Solution: Always define vim_main2(). Move params to the file level. (suggested by Ken Takata) --- src/if_mzsch.c | 13 +++++--- src/main.c | 70 +++++++++++++++++------------------------- src/proto/if_mzsch.pro | 2 +- src/structs.h | 4 ++- src/version.c | 2 ++ src/vim.h | 6 ++-- 6 files changed, 45 insertions(+), 52 deletions(-) diff --git a/src/if_mzsch.c b/src/if_mzsch.c index 7a462ad54b..41388109ea 100644 --- a/src/if_mzsch.c +++ b/src/if_mzsch.c @@ -1009,8 +1009,11 @@ static intptr_t _tls_index = 0; #endif int -mzscheme_main(int argc, char** argv) +mzscheme_main() { + int argc = 0; + char *argv = NULL; + #ifdef DYNAMIC_MZSCHEME /* * Racket requires trampolined startup. We can not load it later. @@ -1019,16 +1022,16 @@ mzscheme_main(int argc, char** argv) if (!mzscheme_enabled(FALSE)) { disabled = TRUE; - return vim_main2(argc, argv); + return vim_main2(); } #endif #ifdef HAVE_TLS_SPACE scheme_register_tls_space(&tls_space, _tls_index); #endif #ifdef TRAMPOLINED_MZVIM_STARTUP - return scheme_main_setup(TRUE, mzscheme_env_main, argc, argv); + return scheme_main_setup(TRUE, mzscheme_env_main, argc, &argv); #else - return mzscheme_env_main(NULL, argc, argv); + return mzscheme_env_main(NULL, argc, &argv); #endif } @@ -1056,7 +1059,7 @@ mzscheme_env_main(Scheme_Env *env, int argc, char **argv) * We trampoline into vim_main2 * Passing argc, argv through from mzscheme_main */ - vim_main_result = vim_main2(argc, argv); + vim_main_result = vim_main2(); #if !defined(TRAMPOLINED_MZVIM_STARTUP) && defined(MZ_PRECISE_GC) /* releasing dummy */ MZ_GC_REG(); diff --git a/src/main.c b/src/main.c index 48e90c27ff..c694532860 100644 --- a/src/main.c +++ b/src/main.c @@ -92,6 +92,9 @@ static char_u *start_dir = NULL; /* current working dir on startup */ static int has_dash_c_arg = FALSE; +/* Various parameters passed between main() and other functions. */ +static mparm_T params; + int # ifdef VIMDLL _export @@ -106,9 +109,6 @@ main # endif (int argc, char **argv) { - char_u *fname = NULL; /* file name from command line */ - mparm_T params; /* various parameters passed between - * main() and other functions. */ #ifdef STARTUPTIME int i; #endif @@ -157,6 +157,7 @@ main #endif #ifdef STARTUPTIME + /* Need to find "--startuptime" before actually parsing arguments. */ for (i = 1; i < argc; ++i) { if (STRICMP(argv[i], "--startuptime") == 0 && i + 1 < argc) @@ -241,7 +242,7 @@ main mch_chdir((char *)start_dir); } #endif - fname = alist_name(&GARGLIST[0]); + params.fname = alist_name(&GARGLIST[0]); } #if defined(WIN32) && defined(FEAT_MBYTE) @@ -263,7 +264,7 @@ main * Hint: to avoid this when typing a command use a forward slash. * If the cd fails, it doesn't matter. */ - (void)vim_chdirfile(fname); + (void)vim_chdirfile(params.fname); if (start_dir != NULL) mch_dirname(start_dir, MAXPATHL); } @@ -281,7 +282,7 @@ main /* * When listing swap file names, don't do cursor positioning et. al. */ - if (recoverymode && fname == NULL) + if (recoverymode && params.fname == NULL) params.want_full_screen = FALSE; /* @@ -312,8 +313,8 @@ main if (getcwd((char *)NameBuff, MAXPATHL) != NULL && STRCMP(NameBuff, "/") == 0) { - if (fname != NULL) - (void)vim_chdirfile(fname); + if (params.fname != NULL) + (void)vim_chdirfile(params.fname); else { expand_env((char_u *)"$HOME", NameBuff, MAXPATHL); @@ -407,37 +408,23 @@ main * Newer version of MzScheme (Racket) require earlier (trampolined) * initialisation via scheme_main_setup. * Implement this by initialising it as early as possible - * and splitting off remaining Vim main into vim_main2 + * and splitting off remaining Vim main into vim_main2(). */ - { - /* Pack up preprocessed command line arguments. - * It is safe because Scheme does not access argc/argv. */ - char *args[2]; - args[0] = (char *)fname; - args[1] = (char *)¶ms; - return mzscheme_main(2, args); - } -} + return mzscheme_main(); +#else + return vim_main2(); #endif +} #endif /* NO_VIM_MAIN */ -/* vim_main2() needs to be produced when FEAT_MZSCHEME is defined even when - * NO_VIM_MAIN is defined. */ -#ifdef FEAT_MZSCHEME +/* + * vim_main2() is needed for FEAT_MZSCHEME, but we define it always to keep + * things simple. + * It is also defined when NO_VIM_MAIN is defined, but then it's empty. + */ int -vim_main2(int argc UNUSED, char **argv UNUSED) +vim_main2(void) { -# ifndef NO_VIM_MAIN - char_u *fname = (char_u *)argv[0]; - mparm_T params; - - memcpy(¶ms, argv[1], sizeof(params)); -# else - return 0; -} -# endif -#endif - #ifndef NO_VIM_MAIN /* Reset 'loadplugins' for "-u NONE" before "--cmd" arguments. * Allows for setting 'loadplugins' there. */ @@ -493,7 +480,7 @@ vim_main2(int argc UNUSED, char **argv UNUSED) * This uses the 'dir' option, therefore it must be after the * initializations. */ - if (recoverymode && fname == NULL) + if (recoverymode && params.fname == NULL) { recover_names(NULL, TRUE, 0, NULL); mch_exit(0); @@ -888,16 +875,17 @@ vim_main2(int argc UNUSED, char **argv UNUSED) */ main_loop(FALSE, FALSE); +#endif /* NO_VIM_MAIN */ + return 0; } -#endif /* NO_VIM_MAIN */ #endif /* PROTO */ /* * Initialisation shared by main() and some tests. */ void -common_init(mparm_T *params) +common_init(mparm_T *paramp) { #ifdef FEAT_MBYTE @@ -914,7 +902,7 @@ common_init(mparm_T *params) #ifdef MAC_OS_CLASSIC /* Prepare for possibly starting GUI sometime */ /* Macintosh needs this before any memory is allocated. */ - gui_prepare(¶ms->argc, params->argv); + gui_prepare(¶mp->argc, paramp->argv); TIME_MSG("GUI prepared"); #endif @@ -963,14 +951,14 @@ common_init(mparm_T *params) * --socketid * --windowid */ - early_arg_scan(params); + early_arg_scan(paramp); #ifdef FEAT_SUN_WORKSHOP - findYourself(params->argv[0]); + findYourself(paramp->argv[0]); #endif #if defined(FEAT_GUI) && !defined(MAC_OS_CLASSIC) /* Prepare for possibly starting GUI sometime */ - gui_prepare(¶ms->argc, params->argv); + gui_prepare(¶mp->argc, paramp->argv); TIME_MSG("GUI prepared"); #endif @@ -985,7 +973,7 @@ common_init(mparm_T *params) * (needed for :! to * work). mch_check_win() will also handle the -d or * -dev argument. */ - params->stdout_isatty = (mch_check_win(params->argc, params->argv) != FAIL); + paramp->stdout_isatty = (mch_check_win(paramp->argc, paramp->argv) != FAIL); TIME_MSG("window checked"); /* diff --git a/src/proto/if_mzsch.pro b/src/proto/if_mzsch.pro index 193bd499ad..bab82cef3f 100644 --- a/src/proto/if_mzsch.pro +++ b/src/proto/if_mzsch.pro @@ -3,7 +3,7 @@ int mzscheme_enabled(int verbose); void mzvim_check_threads(void); void mzvim_reset_timer(void); void mzscheme_end(void); -int mzscheme_main(int argc, char **argv); +int mzscheme_main(void); void mzscheme_buffer_free(buf_T *buf); void mzscheme_window_free(win_T *win); void ex_mzscheme(exarg_T *eap); diff --git a/src/structs.h b/src/structs.h index 5439748286..6cfbb3c25d 100644 --- a/src/structs.h +++ b/src/structs.h @@ -3160,7 +3160,7 @@ struct timer_S timer_T *tr_prev; proftime_T tr_due; /* when the callback is to be invoked */ int tr_repeat; /* number of times to repeat, -1 forever */ - long tr_interval; /* only set when it repeats */ + long tr_interval; /* msec */ char_u *tr_callback; /* allocated */ partial_T *tr_partial; #endif @@ -3180,6 +3180,8 @@ typedef struct int argc; char **argv; + char_u *fname; /* first file to edit */ + int evim_mode; /* started as "evim" */ char_u *use_vimrc; /* vimrc from -u argument */ diff --git a/src/version.c b/src/version.c index 944dfa4230..4d6765f059 100644 --- a/src/version.c +++ b/src/version.c @@ -763,6 +763,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2176, /**/ 2175, /**/ diff --git a/src/vim.h b/src/vim.h index 928a558fba..96cfc6ccad 100644 --- a/src/vim.h +++ b/src/vim.h @@ -2439,10 +2439,8 @@ typedef enum #define JSON_JS 1 /* use JS instead of JSON */ #define JSON_NO_NONE 2 /* v:none item not allowed */ -#ifdef FEAT_MZSCHEME -/* this is in main.c, cproto can't handle it. */ -int vim_main2(int argc, char **argv); -#endif +/* This is in main.c, cproto can't handle it. */ +int vim_main2(void); /* Used for flags of do_in_path() */ #define DIP_ALL 0x01 /* all matches, not just the first one */ From ba98bef1910094179bf90b9467b6e2d2f9462601 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 7 Aug 2016 15:51:39 +0200 Subject: [PATCH 4/8] patch 7.4.2177 Problem: No testing for -C and -N command line flags, file arguments, startuptime. Solution: Add tests. --- src/testdir/shared.vim | 4 +- src/testdir/test_startup.vim | 86 +++++++++++++++++++++++++++++++++++- src/version.c | 2 + 3 files changed, 89 insertions(+), 3 deletions(-) diff --git a/src/testdir/shared.vim b/src/testdir/shared.vim index 5985ff9e1c..a9b090543d 100644 --- a/src/testdir/shared.vim +++ b/src/testdir/shared.vim @@ -130,7 +130,7 @@ func RunVim(before, after, arguments) if !filereadable('vimcmd') return 0 endif - let args = a:arguments + let args = '' if len(a:before) > 0 call writefile(a:before, 'Xbefore.vim') let args .= ' --cmd "so Xbefore.vim"' @@ -145,7 +145,7 @@ func RunVim(before, after, arguments) if cmd !~ '-u NONE' let cmd = cmd . ' -u NONE' endif - exe "silent !" . cmd . ' ' . args + exe "silent !" . cmd . args . ' ' . a:arguments if len(a:before) > 0 call delete('Xbefore.vim') diff --git a/src/testdir/test_startup.vim b/src/testdir/test_startup.vim index f21f4c35be..384dcbe2e0 100644 --- a/src/testdir/test_startup.vim +++ b/src/testdir/test_startup.vim @@ -69,7 +69,7 @@ func Test_help_arg() if RunVim([], [], '--help >Xtestout') let lines = readfile('Xtestout') call assert_true(len(lines) > 20) - call assert_true(lines[0] =~ 'Vi IMproved') + call assert_match('Vi IMproved', lines[0]) " check if couple of lines are there let found = 0 @@ -85,3 +85,87 @@ func Test_help_arg() endif call delete('Xtestout') endfunc + +func Test_compatible_args() + let after = [ + \ 'call writefile([string(&compatible)], "Xtestout")', + \ 'set viminfo+=nviminfo', + \ 'quit', + \ ] + if RunVim([], after, '-C') + let lines = readfile('Xtestout') + call assert_equal('1', lines[0]) + endif + + if RunVim([], after, '-N') + let lines = readfile('Xtestout') + call assert_equal('0', lines[0]) + endif + + call delete('Xtestout') +endfunc + +func Test_file_args() + let after = [ + \ 'call writefile(argv(), "Xtestout")', + \ 'qall', + \ ] + if RunVim([], after, '') + let lines = readfile('Xtestout') + call assert_equal(0, len(lines)) + endif + + if RunVim([], after, 'one') + let lines = readfile('Xtestout') + call assert_equal(1, len(lines)) + call assert_equal('one', lines[0]) + endif + + if RunVim([], after, 'one two three') + let lines = readfile('Xtestout') + call assert_equal(3, len(lines)) + call assert_equal('one', lines[0]) + call assert_equal('two', lines[1]) + call assert_equal('three', lines[2]) + endif + + if RunVim([], after, 'one -c echo two') + let lines = readfile('Xtestout') + call assert_equal(2, len(lines)) + call assert_equal('one', lines[0]) + call assert_equal('two', lines[1]) + endif + + if RunVim([], after, 'one -- -c echo two') + let lines = readfile('Xtestout') + call assert_equal(4, len(lines)) + call assert_equal('one', lines[0]) + call assert_equal('-c', lines[1]) + call assert_equal('echo', lines[2]) + call assert_equal('two', lines[3]) + endif + + call delete('Xtestout') +endfunc + +func Test_startuptime() + if !has('startuptime') + return + endif + let after = ['qall'] + if RunVim([], after, '--startuptime Xtestout one') + let lines = readfile('Xtestout') + let expected = ['--- VIM STARTING ---', 'parsing arguments', + \ 'shell init', 'inits 3', 'start termcap', 'opening buffers'] + let found = [] + for line in lines + for exp in expected + if line =~ exp + call add(found, exp) + endif + endfor + endfor + call assert_equal(expected, found) + endif + call delete('Xtestout') +endfunc diff --git a/src/version.c b/src/version.c index 4d6765f059..29d845fa15 100644 --- a/src/version.c +++ b/src/version.c @@ -763,6 +763,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2177, /**/ 2176, /**/ From 3a938383396d4ab352bbb4d806938302debdae2c Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 7 Aug 2016 16:36:40 +0200 Subject: [PATCH 5/8] patch 7.4.2178 Problem: No test for reading from stdin. Solution: Add a test. --- src/testdir/shared.vim | 16 +++++++++++++--- src/testdir/test_startup.vim | 12 ++++++++++++ src/version.c | 2 ++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/testdir/shared.vim b/src/testdir/shared.vim index a9b090543d..ad8afe1ff2 100644 --- a/src/testdir/shared.vim +++ b/src/testdir/shared.vim @@ -122,11 +122,15 @@ func WaitFor(expr) endfunc " Run Vim, using the "vimcmd" file and "-u NORC". -" "before" is a list of commands to be executed before loading plugins. -" "after" is a list of commands to be executed after loading plugins. +" "before" is a list of Vim commands to be executed before loading plugins. +" "after" is a list of Vim commands to be executed after loading plugins. " Plugins are not loaded, unless 'loadplugins' is set in "before". " Return 1 if Vim could be executed. func RunVim(before, after, arguments) + call RunVimPiped(a:before, a:after, a:arguments, '') +endfunc + +func RunVimPiped(before, after, arguments, pipecmd) if !filereadable('vimcmd') return 0 endif @@ -145,7 +149,13 @@ func RunVim(before, after, arguments) if cmd !~ '-u NONE' let cmd = cmd . ' -u NONE' endif - exe "silent !" . cmd . args . ' ' . a:arguments + + " With pipecmd we can't set VIMRUNTIME. + if a:pipecmd != '' + let cmd = substitute(cmd, 'VIMRUNTIME=.*VIMRUNTIME;', '', '') + endif + + exe "silent !" . a:pipecmd . cmd . args . ' ' . a:arguments if len(a:before) > 0 call delete('Xbefore.vim') diff --git a/src/testdir/test_startup.vim b/src/testdir/test_startup.vim index 384dcbe2e0..652318fb7c 100644 --- a/src/testdir/test_startup.vim +++ b/src/testdir/test_startup.vim @@ -169,3 +169,15 @@ func Test_startuptime() endif call delete('Xtestout') endfunc + +func Test_read_stdin() + let after = [ + \ 'write Xtestout', + \ 'quit!', + \ ] + if RunVimPiped([], after, '-', 'echo something | ') + let lines = readfile('Xtestout') + call assert_equal('something', lines[0]) + endif + call delete('Xtestout') +endfunc diff --git a/src/version.c b/src/version.c index 29d845fa15..d87abe85cb 100644 --- a/src/version.c +++ b/src/version.c @@ -763,6 +763,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2178, /**/ 2177, /**/ From e4a76ad0e74a31bbd9f1b1ac5b816d714d19a412 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 7 Aug 2016 16:50:10 +0200 Subject: [PATCH 6/8] patch 7.4.2179 Problem: Reading from stdin test fails on MS-Windows. Solution: Strip the extra space. --- src/testdir/test_startup.vim | 3 ++- src/version.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_startup.vim b/src/testdir/test_startup.vim index 652318fb7c..0522ecc82e 100644 --- a/src/testdir/test_startup.vim +++ b/src/testdir/test_startup.vim @@ -177,7 +177,8 @@ func Test_read_stdin() \ ] if RunVimPiped([], after, '-', 'echo something | ') let lines = readfile('Xtestout') - call assert_equal('something', lines[0]) + " MS-Windows adds a space after the word + call assert_equal(['something'], split(lines[0])) endif call delete('Xtestout') endfunc diff --git a/src/version.c b/src/version.c index d87abe85cb..c9197f44a3 100644 --- a/src/version.c +++ b/src/version.c @@ -763,6 +763,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2179, /**/ 2178, /**/ From b73598e2f022a22fec512ea681c70d2775e8fd87 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 7 Aug 2016 18:22:53 +0200 Subject: [PATCH 7/8] patch 7.4.2180 Problem: There is no easy way to stop all timers. There is no way to temporary pause a timer. Solution: Add timer_stopall() and timer_pause(). --- runtime/doc/eval.txt | 36 +++++++++++++-- src/evalfunc.c | 32 +++++++++++++ src/ex_cmds2.c | 12 +++++ src/proto/ex_cmds2.pro | 1 + src/structs.h | 1 + src/testdir/shared.vim | 5 +- src/testdir/test_timers.vim | 92 ++++++++++++++++++++++++++++++------- src/version.c | 2 + 8 files changed, 161 insertions(+), 20 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index d6269d5a3d..39765d59e6 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 Aug 06 +*eval.txt* For Vim version 7.4. Last change: 2016 Aug 07 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1969,7 +1969,7 @@ assert_exception({error} [, {msg}]) none assert {error} is in v:exception assert_fails({cmd} [, {error}]) none assert {cmd} fails assert_false({actual} [, {msg}]) none assert {actual} is false assert_inrange({lower}, {upper}, {actual} [, {msg}]) - none assert {actual} is inside the range + none assert {actual} is inside the range assert_match({pat}, {text} [, {msg}]) none assert {pat} matches {text} assert_notequal({exp}, {act} [, {msg}]) none assert {exp} is not equal {act} assert_notmatch({pat}, {text} [, {msg}]) none assert {pat} not matches {text} @@ -2340,9 +2340,11 @@ test_null_partial() Funcref null value for testing test_null_string() String null value for testing test_settime({expr}) none set current time for testing timer_info([{id}]) List information about timers +timer_pause({id}, {pause}) none pause or unpause a timer timer_start({time}, {callback} [, {options}]) Number create a timer timer_stop({timer}) none stop a timer +timer_stopall() none stop all timers tolower({expr}) String the String {expr} switched to lowercase toupper({expr}) String the String {expr} switched to uppercase tr({src}, {fromstr}, {tostr}) String translate chars of {src} in {fromstr} @@ -7555,8 +7557,26 @@ timer_info([{id}]) "time" time the timer was started with "remaining" time until the timer fires "repeat" number of times the timer will still fire; - -1 means forever + -1 means forever "callback" the callback + "paused" 1 if the timer is paused, 0 otherwise + + {only available when compiled with the |+timers| feature} + +timer_pause({timer}, {paused}) *timer_pause()* + Pause or unpause a timer. A paused timer does not invoke its + callback, while the time it would is not changed. Unpausing a + timer may cause the callback to be invoked almost immediately + if enough time has passed. + + Pausing a timer is useful to avoid the callback to be called + for a short time. + + If {paused} evaluates to a non-zero Number or a non-empty + String, then the timer is paused, otherwise it is unpaused. + See |non-zero-arg|. + + {only available when compiled with the |+timers| feature} *timer_start()* timer_start({time}, {callback} [, {options}]) @@ -7583,6 +7603,7 @@ timer_start({time}, {callback} [, {options}]) \ {'repeat': 3}) < This will invoke MyHandler() three times at 500 msec intervals. + {only available when compiled with the |+timers| feature} timer_stop({timer}) *timer_stop()* @@ -7590,6 +7611,15 @@ timer_stop({timer}) *timer_stop()* {timer} is an ID returned by timer_start(), thus it must be a Number. If {timer} does not exist there is no error. + {only available when compiled with the |+timers| feature} + +timer_stopall() *timer_stopall()* + Stop all timers. The timer callbacks will no longer be + invoked. Useful if some timers is misbehaving. If there are + no timers there is no error. + + {only available when compiled with the |+timers| feature} + tolower({expr}) *tolower()* The result is a copy of the String given, with all uppercase characters turned into lowercase (just like applying |gu| to diff --git a/src/evalfunc.c b/src/evalfunc.c index 50fa3bf720..8b5ad22fed 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -397,8 +397,10 @@ static void f_tanh(typval_T *argvars, typval_T *rettv); #endif #ifdef FEAT_TIMERS static void f_timer_info(typval_T *argvars, typval_T *rettv); +static void f_timer_pause(typval_T *argvars, typval_T *rettv); static void f_timer_start(typval_T *argvars, typval_T *rettv); static void f_timer_stop(typval_T *argvars, typval_T *rettv); +static void f_timer_stopall(typval_T *argvars, typval_T *rettv); #endif static void f_tolower(typval_T *argvars, typval_T *rettv); static void f_toupper(typval_T *argvars, typval_T *rettv); @@ -817,8 +819,10 @@ static struct fst {"test_settime", 1, 1, f_test_settime}, #ifdef FEAT_TIMERS {"timer_info", 0, 1, f_timer_info}, + {"timer_pause", 2, 2, f_timer_pause}, {"timer_start", 2, 3, f_timer_start}, {"timer_stop", 1, 1, f_timer_stop}, + {"timer_stopall", 0, 0, f_timer_stopall}, #endif {"tolower", 1, 1, f_tolower}, {"toupper", 1, 1, f_toupper}, @@ -11987,6 +11991,25 @@ f_timer_info(typval_T *argvars, typval_T *rettv) add_timer_info_all(rettv); } +/* + * "timer_pause(timer, paused)" function + */ + static void +f_timer_pause(typval_T *argvars, typval_T *rettv UNUSED) +{ + timer_T *timer = NULL; + int paused = (int)get_tv_number(&argvars[1]); + + if (argvars[0].v_type != VAR_NUMBER) + EMSG(_(e_number_exp)); + else + { + timer = find_timer((int)get_tv_number(&argvars[0])); + if (timer != NULL) + timer->tr_paused = paused; + } +} + /* * "timer_start(time, callback [, options])" function */ @@ -12048,6 +12071,15 @@ f_timer_stop(typval_T *argvars, typval_T *rettv UNUSED) if (timer != NULL) stop_timer(timer); } + +/* + * "timer_stopall()" function + */ + static void +f_timer_stopall(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ + stop_all_timers(); +} #endif /* diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c index 6cf26e9931..73b3a522fd 100644 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -1189,6 +1189,8 @@ check_due_timer(void) next_due = -1; for (timer = first_timer; timer != NULL; timer = timer->tr_next) { + if (timer->tr_paused) + continue; # ifdef WIN3264 this_due = (long)(((double)(timer->tr_due.QuadPart - now.QuadPart) / (double)fr.QuadPart) * 1000); @@ -1251,6 +1253,15 @@ stop_timer(timer_T *timer) free_timer(timer); } + void +stop_all_timers(void) +{ + timer_T *timer; + + while (first_timer != NULL) + stop_timer(first_timer); +} + void add_timer_info(typval_T *rettv, timer_T *timer) { @@ -1283,6 +1294,7 @@ add_timer_info(typval_T *rettv, timer_T *timer) dict_add_nr_str(dict, "repeat", (long)(timer->tr_repeat < 0 ? -1 : timer->tr_repeat + 1), NULL); + dict_add_nr_str(dict, "paused", (long)(timer->tr_paused), NULL); di = dictitem_alloc((char_u *)"callback"); if (di != NULL) diff --git a/src/proto/ex_cmds2.pro b/src/proto/ex_cmds2.pro index 977f5c0de1..f241d377e8 100644 --- a/src/proto/ex_cmds2.pro +++ b/src/proto/ex_cmds2.pro @@ -22,6 +22,7 @@ timer_T *create_timer(long msec, int repeat); long check_due_timer(void); timer_T *find_timer(int id); void stop_timer(timer_T *timer); +void stop_all_timers(void); void add_timer_info(typval_T *rettv, timer_T *timer); void add_timer_info_all(typval_T *rettv); int set_ref_in_timer(int copyID); diff --git a/src/structs.h b/src/structs.h index 6cfbb3c25d..b56282fc29 100644 --- a/src/structs.h +++ b/src/structs.h @@ -3159,6 +3159,7 @@ struct timer_S timer_T *tr_next; timer_T *tr_prev; proftime_T tr_due; /* when the callback is to be invoked */ + int tr_paused; /* when TRUE callback is not invoked */ int tr_repeat; /* number of times to repeat, -1 forever */ long tr_interval; /* msec */ char_u *tr_callback; /* allocated */ diff --git a/src/testdir/shared.vim b/src/testdir/shared.vim index ad8afe1ff2..aba428a46d 100644 --- a/src/testdir/shared.vim +++ b/src/testdir/shared.vim @@ -109,14 +109,17 @@ func s:kill_server(cmd) endfunc " Wait for up to a second for "expr" to become true. +" Return time slept in milliseconds. func WaitFor(expr) + let slept = 0 for i in range(100) try if eval(a:expr) - return + return slept endif catch endtry + let slept += 10 sleep 10m endfor endfunc diff --git a/src/testdir/test_timers.vim b/src/testdir/test_timers.vim index 0969377c87..fb35f61fff 100644 --- a/src/testdir/test_timers.vim +++ b/src/testdir/test_timers.vim @@ -1,11 +1,13 @@ " Test for timers +source shared.vim + if !has('timers') finish endif func MyHandler(timer) - let s:val += 1 + let g:val += 1 endfunc func MyHandlerWithLists(lists, timer) @@ -13,43 +15,101 @@ func MyHandlerWithLists(lists, timer) endfunc func Test_oneshot() - let s:val = 0 + let g:val = 0 let timer = timer_start(50, 'MyHandler') - sleep 200m - call assert_equal(1, s:val) + let slept = WaitFor('g:val == 1') + call assert_equal(1, g:val) + call assert_inrange(30, 100, slept) endfunc func Test_repeat_three() - let s:val = 0 + let g:val = 0 let timer = timer_start(50, 'MyHandler', {'repeat': 3}) - sleep 500m - call assert_equal(3, s:val) + let slept = WaitFor('g:val == 3') + call assert_equal(3, g:val) + call assert_inrange(100, 250, slept) endfunc func Test_repeat_many() - let s:val = 0 + let g:val = 0 let timer = timer_start(50, 'MyHandler', {'repeat': -1}) sleep 200m call timer_stop(timer) - call assert_true(s:val > 1) - call assert_true(s:val < 5) + call assert_inrange(2, 4, g:val) endfunc func Test_with_partial_callback() - let s:val = 0 + let g:val = 0 let s:meow = {} function s:meow.bite(...) - let s:val += 1 + let g:val += 1 endfunction call timer_start(50, s:meow.bite) - sleep 200m - call assert_equal(1, s:val) + let slept = WaitFor('g:val == 1') + call assert_equal(1, g:val) + call assert_inrange(30, 100, slept) endfunc func Test_retain_partial() - call timer_start(100, function('MyHandlerWithLists', [['a']])) + call timer_start(50, function('MyHandlerWithLists', [['a']])) call test_garbagecollect_now() - sleep 200m + sleep 100m endfunc + +func Test_info() + let id = timer_start(1000, 'MyHandler') + let info = timer_info(id) + call assert_equal(id, info[0]['id']) + call assert_equal(1000, info[0]['time']) + call assert_true(info[0]['remaining'] > 500) + call assert_true(info[0]['remaining'] <= 1000) + call assert_equal(1, info[0]['repeat']) + call assert_equal("function('MyHandler')", string(info[0]['callback'])) + + let found = 0 + for info in timer_info() + if info['id'] == id + let found += 1 + endif + endfor + call assert_equal(1, found) + + call timer_stop(id) + call assert_equal([], timer_info(id)) +endfunc + +func Test_stopall() + let id1 = timer_start(1000, 'MyHandler') + let id2 = timer_start(2000, 'MyHandler') + let info = timer_info() + call assert_equal(2, len(info)) + + call timer_stopall() + let info = timer_info() + call assert_equal(0, len(info)) +endfunc + +func Test_paused() + let g:val = 0 + + let id = timer_start(50, 'MyHandler') + let info = timer_info(id) + call assert_equal(0, info[0]['paused']) + + call timer_pause(id, 1) + let info = timer_info(id) + call assert_equal(1, info[0]['paused']) + sleep 100m + call assert_equal(0, g:val) + + call timer_pause(id, 0) + let info = timer_info(id) + call assert_equal(0, info[0]['paused']) + + let slept = WaitFor('g:val == 1') + call assert_equal(1, g:val) + call assert_inrange(0, 10, slept) +endfunc + " vim: ts=2 sw=0 et diff --git a/src/version.c b/src/version.c index c9197f44a3..044546b3d1 100644 --- a/src/version.c +++ b/src/version.c @@ -763,6 +763,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2180, /**/ 2179, /**/ From a772ec5e91efbd5c4b99bb5cf5704a6c6f0baf3f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 7 Aug 2016 20:20:50 +0200 Subject: [PATCH 8/8] patch 7.4.2181 Problem: Compiler warning for unused variable. Solution: Remove it. (Dominique Pelle) --- src/ex_cmds2.c | 2 -- src/version.c | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c index 73b3a522fd..5af2b40588 100644 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -1256,8 +1256,6 @@ stop_timer(timer_T *timer) void stop_all_timers(void) { - timer_T *timer; - while (first_timer != NULL) stop_timer(first_timer); } diff --git a/src/version.c b/src/version.c index 044546b3d1..21f6932846 100644 --- a/src/version.c +++ b/src/version.c @@ -763,6 +763,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2181, /**/ 2180, /**/