summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-11-25 00:05:32 +0100
committerBram Moolenaar <Bram@vim.org>2019-11-25 00:05:32 +0100
commit67a2deb9cb4ac2224cb1e4d240a5d0659f036264 (patch)
tree024c2f55f38fb92a7da3c6887dbd0c510c7ae6cb
parenta106e6cde682bda4ad10ed745acb51975fcb02e0 (diff)
downloadvim-git-67a2deb9cb4ac2224cb1e4d240a5d0659f036264.tar.gz
patch 8.1.2341: not so easy to interrupt a script programaticallyv8.1.2341
Problem: Not so easy to interrupt a script programatically. Solution: Add the interrupt() function. (Yasuhiro Matsumoto, closes #2834)
-rw-r--r--runtime/doc/eval.txt16
-rw-r--r--src/evalfunc.c11
-rw-r--r--src/ex_eval.c1
-rw-r--r--src/testdir/Make_all.mak2
-rw-r--r--src/testdir/test_interrupt.vim27
-rw-r--r--src/version.c2
6 files changed, 58 insertions, 1 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 7c8c8d30f..a6f56eb91 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1,4 +1,4 @@
-*eval.txt* For Vim version 8.1. Last change: 2019 Nov 21
+*eval.txt* For Vim version 8.1. Last change: 2019 Nov 24
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -2531,6 +2531,7 @@ inputrestore() Number restore typeahead
inputsave() Number save and clear typeahead
inputsecret({prompt} [, {text}]) String like input() but hiding the text
insert({object}, {item} [, {idx}]) List insert {item} in {object} [before {idx}]
+interrupt() none interrupt script execution
invert({expr}) Number bitwise invert
isdirectory({directory}) Number |TRUE| if {directory} is a directory
isinf({expr}) Number determine if {expr} is infinity value
@@ -6181,6 +6182,19 @@ insert({object}, {item} [, {idx}]) *insert()*
Can also be used as a |method|: >
mylist->insert(item)
+interrupt() *interrupt()*
+ Interrupt script execution. It works more or less like the
+ user typing CTRL-C, most commands won't execute and control
+ returns to the user. This is useful to abort execution
+ from lower down, e.g. in an autocommand. Example: >
+ :function s:check_typoname(file)
+ : if fnamemodify(a:file, ':t') == '['
+ : echomsg 'Maybe typo'
+ : call interrupt()
+ : endif
+ :endfunction
+ :au BufWritePre * call s:check_typoname(expand('<amatch>'))
+
invert({expr}) *invert()*
Bitwise invert. The argument is converted to a number. A
List, Dict or Float argument causes an error. Example: >
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 6a9f9d637..075ef1bf1 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -114,6 +114,7 @@ static void f_inputlist(typval_T *argvars, typval_T *rettv);
static void f_inputrestore(typval_T *argvars, typval_T *rettv);
static void f_inputsave(typval_T *argvars, typval_T *rettv);
static void f_inputsecret(typval_T *argvars, typval_T *rettv);
+static void f_interrupt(typval_T *argvars, typval_T *rettv);
static void f_invert(typval_T *argvars, typval_T *rettv);
static void f_islocked(typval_T *argvars, typval_T *rettv);
#if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
@@ -509,6 +510,7 @@ static funcentry_T global_functions[] =
{"inputsave", 0, 0, 0, f_inputsave},
{"inputsecret", 1, 2, FEARG_1, f_inputsecret},
{"insert", 2, 3, FEARG_1, f_insert},
+ {"interrupt", 0, 0, 0, f_interrupt},
{"invert", 1, 1, FEARG_1, f_invert},
{"isdirectory", 1, 1, FEARG_1, f_isdirectory},
#if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
@@ -4152,6 +4154,15 @@ f_inputsecret(typval_T *argvars, typval_T *rettv)
}
/*
+ * "interrupt()" function
+ */
+ static void
+f_interrupt(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
+{
+ got_int = TRUE;
+}
+
+/*
* "invert(expr)" function
*/
static void
diff --git a/src/ex_eval.c b/src/ex_eval.c
index f1a8b97fc..097280a67 100644
--- a/src/ex_eval.c
+++ b/src/ex_eval.c
@@ -85,6 +85,7 @@ static int cause_abort = FALSE;
* until the throw point for error messages has been reached. That is, during
* cancellation of an expression evaluation after an aborting function call or
* due to a parsing error, aborting() always returns the same value.
+ * "got_int" is also set by calling interrupt().
*/
int
aborting(void)
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
index 6b86b37ec..ac254202a 100644
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -154,6 +154,7 @@ NEW_TESTS = \
test_increment \
test_increment_dbcs \
test_ins_complete \
+ test_interrupt \
test_job_fails \
test_join \
test_json \
@@ -361,6 +362,7 @@ NEW_TESTS_RES = \
test_increment.res \
test_increment_dbcs.res \
test_ins_complete.res \
+ test_interrupt.res \
test_job_fails.res \
test_json.res \
test_jumplist.res \
diff --git a/src/testdir/test_interrupt.vim b/src/testdir/test_interrupt.vim
new file mode 100644
index 000000000..111752d16
--- /dev/null
+++ b/src/testdir/test_interrupt.vim
@@ -0,0 +1,27 @@
+" Test behavior of interrupt()
+
+let s:bufwritepre_called = 0
+let s:bufwritepost_called = 0
+
+func s:bufwritepre()
+ let s:bufwritepre_called = 1
+ call interrupt()
+endfunction
+
+func s:bufwritepost()
+ let s:bufwritepost_called = 1
+endfunction
+
+func Test_interrupt()
+ new Xfile
+ let n = 0
+ try
+ au BufWritePre Xfile call s:bufwritepre()
+ au BufWritePost Xfile call s:bufwritepost()
+ w!
+ catch /^Vim:Interrupt$/
+ endtry
+ call assert_equal(1, s:bufwritepre_called)
+ call assert_equal(0, s:bufwritepost_called)
+ call assert_equal(0, filereadable('Xfile'))
+endfunc
diff --git a/src/version.c b/src/version.c
index bebf22003..bbc71be6e 100644
--- a/src/version.c
+++ b/src/version.c
@@ -738,6 +738,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2341,
+/**/
2340,
/**/
2339,