On Thursday, September 5, 2013 10:53:39 AM UTC-7, kans wrote:
> On Thursday, September 5, 2013 9:08:16 AM UTC-7, Ben Fritz wrote:
> > On Thursday, September 5, 2013 8:44:15 AM UTC-5, Bjorn Tipling wrote:
> > > > As someone already mentioned: If the command takes too much time, Vim 
> > > > will get stuck.  E.g. when it reads from a socket.  It might be 
> > > > possible 
> > > > to have this kind of work done in another thread, e.g. using Python. 
> > > 
> > > 
> > > Hey check this out:
> > > 
> > > au CursorHold * call BlockForever()
> > > 
> > > 
> > > " Blocks forever
> > > function! BlockForever()
> > >   let c = 1
> > >   while c >= 0
> > >     let c += 1
> > >   endwhile
> > > endfunction
> > > 
> > > You can already do this blocking, I've already experienced it with 
> > > plugins I've removed. I ask again why  setTimeout should be treated 
> > > differently than CursorHold? You can cntrl-c out of CursorHold, but just 
> > > then make that a requirement for settimeout.
> > > 
> > 
> > Exactly. I think as long as you can interrupt the timer with a keystroke it 
> > should be fine. But since you call your timer in between waiting for a 
> > keystroke, won't that prevent CTRL-C from interrupting it? Maybe it 
> > won't...I haven't tried it. 
> 
> ctrl-c works (in this patch) because the OS converts it into a SIGINT which 
> vim knows how to handle.  
> 
> >There might be two types: One that has high priority, and gets handled
> even when the user has typed something.  Another that has lower
> priority, only gets handled when waiting for the user to type. 
> 
> As mattn pointed out, this won't work unless the internals of vim are 
> threadsafe.  
> 
> > It must be possible to get a list of these commands, so that they can be
> >
> > cancelled without having the id.
> 
> This wouldn't be much work, but to my knowledge, no other implementation has 
> this ability.
> 
> > I don't see the need for 'ticktime'.  The remaining time until the next
> >
> > timeout can be computed.  If it's smaller than 'updatetime' then wait
> >
> > for that long.
> 
> This is true.  ticktime is only useful for end users if they want to trade 
> off efficiency for a better timer function.  50ms is probably a sane default 
> that is good enough (and once again, no other implementation lets this bubble 
> up to user land).
> 
> 
> Does anyone have any feedback on how this implemented; ie, putting this logic 
> in mch_inchar vs. RealWaitForChar?  Another issue is that vim makes other 
> blocking calls that will block the timers.

I've attached our latest patch.  We moved some of the logic down to the level 
of poll/select (RealWaitForChar) using MAY_LOOP which is similar to what the 
scheme bindings do; it is cleaner and works better.  We also changed the eval 
call to use do_cmdline_cmd which is far more convenient.  Now, the timeouts 
don't have to be user defined functions.  Also, all timeouts can now be 
disabled by setting 'ticktime' to -1.  We discussed disabling intervals that 
fail, but we ultimately decided that the onus should be on programmers to make 
sane plugins and canceling intervals is unexpected behavior.  Finally, the new 
features are now documented.  Please let us know what you think.

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
>From 6d6545fb9b4cffb34d7ca2fe10ce70ad6d16759b Mon Sep 17 00:00:00 2001
From: Geoff Greer <ge...@greer.fm>
Date: Tue, 10 Sep 2013 03:54:58 -0700
Subject: [PATCH 1/2] Add asynchronous functions to Vim: settimeout,
 setinterval, and canceltimeout.

---
 Filelist      |   2 ++
 src/Makefile  |   5 +++
 src/async.c   |  60 +++++++++++++++++++++++++++++++++
 src/async.h   |   5 +++
 src/eval.c    | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/feature.h |   7 ++++
 src/gui.c     |  30 ++++++++++-------
 src/option.c  |   5 +++
 src/option.h  |   3 ++
 src/os_unix.c |  21 +++++++++++-
 src/structs.h |  14 ++++++++
 src/vim.h     |   4 +++
 12 files changed, 247 insertions(+), 13 deletions(-)
 create mode 100644 src/async.c
 create mode 100644 src/async.h

diff --git a/Filelist b/Filelist
index b324933..cfbf0b3 100644
--- a/Filelist
+++ b/Filelist
@@ -7,6 +7,8 @@ SRC_ALL =	\
 		src/arabic.c \
 		src/arabic.h \
 		src/ascii.h \
+		src/async.c \
+		src/async.h \
 		src/blowfish.c \
 		src/buffer.c \
 		src/charset.c \
diff --git a/src/Makefile b/src/Makefile
index c830378..73439e7 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1424,6 +1424,7 @@ DEST_MAN_RU_U = $(DEST_MAN_TOP)/ru.UTF-8$(MAN1DIR)
 TAGS_INCL = *.h
 
 BASIC_SRC = \
+	async.c \
 	blowfish.c \
 	buffer.c \
 	charset.c \
@@ -1513,6 +1514,7 @@ LINT_SRC = $(BASIC_SRC) $(GUI_SRC) $(HANGULIN_SRC) $(PYTHON_SRC) $(PYTHON3_SRC)
 #LINT_SRC = $(BASIC_SRC)
 
 OBJ_COMMON = \
+	objects/async.o \
 	objects/buffer.o \
 	objects/blowfish.o \
 	objects/charset.o \
@@ -2484,6 +2486,9 @@ auto/pathdef.c: Makefile auto/config.mk
 objects:
 	mkdir objects
 
+objects/async.o: async.c
+	$(CCC) -o $@ async.c
+
 objects/blowfish.o: blowfish.c
 	$(CCC) -o $@ blowfish.c
 
diff --git a/src/async.c b/src/async.c
new file mode 100644
index 0000000..27ee02d
--- /dev/null
+++ b/src/async.c
@@ -0,0 +1,60 @@
+#include "vim.h"
+
+#ifdef FEAT_ASYNC
+
+/*
+ * Insert a new timeout into the timeout linked list.
+ * This is called by set_timeout() in eval.c
+ */
+    void
+insert_timeout(to)
+    timeout_T *to;  /* timeout to insert */
+{
+    timeout_T *cur = timeouts;
+    timeout_T *prev = NULL;
+
+    if (timeouts == NULL) {
+        timeouts = to;
+        return;
+    }
+    while (cur != NULL) {
+        if (cur->tm > to->tm) {
+            if (prev) {
+                prev->next = to;
+            } else {
+                timeouts = to;
+            }
+            to->next = cur;
+            return;
+        }
+        prev = cur;
+        cur = cur->next;
+    }
+}
+
+/*
+ * Execute timeouts that are due.
+ * This is called every ticktime milliseconds by low-level input functions.
+ */
+    void
+call_timeouts() {
+    struct timeval now;
+    gettimeofday(&now, NULL);
+    unsigned long tm = now.tv_sec * 1000 + now.tv_usec/1000;
+    timeout_T *tmp;
+
+    while (timeouts != NULL && timeouts->tm < tm) {
+        do_cmdline_cmd(timeouts->cmd);
+        tmp = timeouts;
+        timeouts = timeouts->next;
+        if (tmp->interval == -1) {
+            free(tmp->cmd);
+            free(tmp);
+        } else {
+            tmp->tm = tm + tmp->interval;
+            insert_timeout(tmp);
+        }
+    }
+}
+
+#endif
diff --git a/src/async.h b/src/async.h
new file mode 100644
index 0000000..600a5ba
--- /dev/null
+++ b/src/async.h
@@ -0,0 +1,5 @@
+
+EXTERN timeout_T *timeouts INIT(= NULL);
+
+void insert_timeout(timeout_T *to);
+void call_timeouts();
diff --git a/src/eval.c b/src/eval.c
index 807efe2..368b3d6 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -674,6 +674,11 @@ struct funccall_S
 static void f_setloclist __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_setmatches __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_setpos __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_ASYNC
+static void f_canceltimeout __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_setinterval __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_settimeout __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
 static void f_setqflist __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_setreg __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_settabvar __ARGS((typval_T *argvars, typval_T *rettv));
@@ -7861,6 +7866,9 @@ struct funccall_S
     {"byte2line",	1, 1, f_byte2line},
     {"byteidx",		2, 2, f_byteidx},
     {"call",		2, 3, f_call},
+#ifdef FEAT_ASYNC
+    {"canceltimeout", 1, 1, f_canceltimeout},
+#endif
 #ifdef FEAT_FLOAT
     {"ceil",		1, 1, f_ceil},
 #endif
@@ -8059,6 +8067,9 @@ struct funccall_S
     {"serverlist",	0, 0, f_serverlist},
     {"setbufvar",	3, 3, f_setbufvar},
     {"setcmdpos",	1, 1, f_setcmdpos},
+#ifdef FEAT_ASYNC
+    {"setinterval",    2, 2, f_setinterval},
+#endif
     {"setline",		2, 2, f_setline},
     {"setloclist",	2, 3, f_setloclist},
     {"setmatches",	1, 1, f_setmatches},
@@ -8067,6 +8078,9 @@ struct funccall_S
     {"setreg",		2, 3, f_setreg},
     {"settabvar",	3, 3, f_settabvar},
     {"settabwinvar",	4, 4, f_settabwinvar},
+#ifdef FEAT_ASYNC
+    {"settimeout",    2, 2, f_settimeout},
+#endif
     {"setwinvar",	3, 3, f_setwinvar},
 #ifdef FEAT_CRYPT
     {"sha256",		1, 1, f_sha256},
@@ -12416,6 +12430,9 @@ struct funccall_S
 #ifdef FEAT_RELTIME
 	"reltime",
 #endif
+#ifdef FEAT_ASYNC
+    "async",
+#endif
 #ifdef FEAT_QUICKFIX
 	"quickfix",
 #endif
@@ -16589,6 +16606,93 @@ struct funccall_S
 #endif
 }
 
+#ifdef FEAT_ASYNC
+static int timeout_id = 0;
+
+    static void
+set_timeout(argvars, rettv, interval)
+    typval_T    *argvars;
+    typval_T    *rettv;
+    int interval;
+{
+    long i = get_tv_number(&argvars[0]);
+    char_u *cmd = get_tv_string(&argvars[1]);
+    struct timeval now;
+    rettv->v_type = VAR_NUMBER;
+
+    if (i < 0) {
+        rettv->vval.v_number = -1;
+        EMSG2(_(e_invarg2), "Interval cannot be negative.");
+        return;
+    }
+
+    gettimeofday(&now, NULL);
+    timeout_T *to = malloc(sizeof(timeout_T));
+    to->id = timeout_id++;
+    rettv->vval.v_number = to->id;
+    to->tm = now.tv_sec * 1000 + now.tv_usec/1000 + i;
+    to->cmd = (char_u*)strdup((char*)cmd);
+    to->interval = interval ? i : -1;
+    to->next = NULL;
+
+    insert_timeout(to);
+}
+
+    static void
+f_setinterval(argvars, rettv)
+    typval_T    *argvars;
+    typval_T    *rettv;
+{
+    set_timeout(argvars, rettv, TRUE);
+}
+
+    static void
+f_settimeout(argvars, rettv)
+    typval_T    *argvars;
+    typval_T    *rettv;
+{
+    set_timeout(argvars, rettv, FALSE);
+}
+
+    static void
+f_canceltimeout(argvars, rettv)
+    typval_T    *argvars;
+    typval_T    *rettv;
+{
+    long id = get_tv_number(&argvars[0]);
+    if (id < 0) {
+        rettv->vval.v_number = -1;
+        EMSG2(_(e_invarg2), "Timeout id cannot be negative.");
+        return;
+    }
+
+    timeout_T *tmp = timeouts;
+    timeout_T *prev = NULL;
+    timeout_T *next;
+    while (tmp != NULL) {
+        next = tmp->next;
+        if (tmp->id == id) {
+            if (prev) {
+                prev->next = next;
+            } else {
+                timeouts = next;
+            }
+            free(tmp->cmd);
+            free(tmp);
+            rettv->vval.v_number = 0;
+            rettv->v_type = VAR_NUMBER;
+            return;
+        } else {
+            prev = tmp;
+        }
+        tmp = next;
+    }
+    rettv->vval.v_number = 1;
+    rettv->v_type = VAR_NUMBER;
+    EMSG2(_(e_invarg2), "Timeout id not found.");
+}
+#endif
+
 /*
  * "setpos()" function
  */
diff --git a/src/feature.h b/src/feature.h
index d4b9aea..80feb37 100644
--- a/src/feature.h
+++ b/src/feature.h
@@ -467,6 +467,13 @@
 #endif
 
 /*
+ * +async		settimeout and setinterval functions.
+ */
+#if defined(FEAT_NORMAL)
+# define FEAT_ASYNC
+#endif
+
+/*
  * +diff		Displaying diffs in a nice way.
  *			Requires +windows and +autocmd.
  */
diff --git a/src/gui.c b/src/gui.c
index b667ba3..a754709 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -2898,18 +2898,31 @@ enum {
     gui_mch_start_blink();
 
     retval = FAIL;
+
+    int i = 0;
+    while (i < p_ut) {
+#ifdef FEAT_ASYNC
+		retval = gui_mch_wait_for_chars(p_tt);
+		call_timeouts();
+		i += p_tt;
+#else
+		retval = gui_mch_wait_for_chars(p_ut);
+		i += p_ut;
+#endif
+		if (retval == OK) {
+			break;
+		}
+    }
+
+#ifdef FEAT_AUTOCMD
     /*
      * We may want to trigger the CursorHold event.  First wait for
      * 'updatetime' and if nothing is typed within that time put the
      * K_CURSORHOLD key in the input buffer.
      */
-    if (gui_mch_wait_for_chars(p_ut) == OK)
-	retval = OK;
-#ifdef FEAT_AUTOCMD
-    else if (trigger_cursorhold())
+    if (retval == FAIL && trigger_cursorhold())
     {
 	char_u	buf[3];
-
 	/* Put K_CURSORHOLD in the input buffer. */
 	buf[0] = CSI;
 	buf[1] = KS_EXTRA;
@@ -2920,13 +2933,6 @@ enum {
     }
 #endif
 
-    if (retval == FAIL)
-    {
-	/* Blocking wait. */
-	before_blocking();
-	retval = gui_mch_wait_for_chars(-1L);
-    }
-
     gui_mch_stop_blink();
     return retval;
 }
diff --git a/src/option.c b/src/option.c
index bf65556..e8ef4a3 100644
--- a/src/option.c
+++ b/src/option.c
@@ -2590,6 +2590,11 @@ struct vimoption
 			    (char_u *)NULL, PV_NONE,
 #endif
 			    {(char_u *)"", (char_u *)0L} SCRIPTID_INIT},
+#ifdef FEAT_ASYNC
+    {"ticktime",  "tt",   P_NUM|P_VI_DEF,
+			    (char_u *)&p_tt, PV_NONE,
+			    {(char_u *)100L, (char_u *)0L} SCRIPTID_INIT},
+#endif
     {"tildeop",	    "top",  P_BOOL|P_VI_DEF|P_VIM,
 			    (char_u *)&p_to, PV_NONE,
 			    {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT},
diff --git a/src/option.h b/src/option.h
index 167b562..ae2ba22 100644
--- a/src/option.h
+++ b/src/option.h
@@ -795,6 +795,9 @@
 #ifdef FEAT_INS_EXPAND
 EXTERN char_u	*p_tsr;		/* 'thesaurus' */
 #endif
+#ifdef FEAT_ASYNC
+EXTERN long	p_tt;		/* 'ticktime' */
+#endif
 EXTERN int	p_ttimeout;	/* 'ttimeout' */
 EXTERN long	p_ttm;		/* 'ttimeoutlen' */
 EXTERN int	p_tbi;		/* 'ttybuiltin' */
diff --git a/src/os_unix.c b/src/os_unix.c
index cc02653..4aa4a25 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -5057,7 +5057,7 @@ sigcont_handler SIGDEFARG(sigarg)
 #ifdef FEAT_NETBEANS_INTG
     int		nb_fd = netbeans_filedesc();
 #endif
-#if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME)
+#if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME) || defined(FEAT_ASYNC)
     static int	busy = FALSE;
 
     /* May retry getting characters after an event was handled. */
@@ -5085,6 +5085,9 @@ sigcont_handler SIGDEFARG(sigarg)
 #  ifdef FEAT_MZSCHEME
 	(mzthreads_allowed() && p_mzq > 0)
 #  endif
+#  ifdef FEAT_ASYNC
+	TRUE
+#  endif
 	    ))
 	gettimeofday(&start_tv, NULL);
 # endif
@@ -5130,6 +5133,12 @@ sigcont_handler SIGDEFARG(sigarg)
 	    mzquantum_used = TRUE;
 	}
 # endif
+# ifdef FEAT_ASYNC
+	call_timeouts();
+	if (p_tt > 0 && (msec < 0 || msec > p_tt)) {
+		towait = p_tt;
+	}
+# endif
 	fds[0].fd = fd;
 	fds[0].events = POLLIN;
 	nfd = 1;
@@ -5257,6 +5266,12 @@ sigcont_handler SIGDEFARG(sigarg)
 	    mzquantum_used = TRUE;
 	}
 # endif
+# ifdef FEAT_ASYNC
+	call_timeouts();
+	if (p_tt > 0 && (msec < 0 || msec > p_tt)) {
+		towait = p_tt;
+	}
+# endif
 # ifdef __EMX__
 	/* don't check for incoming chars if not in raw mode, because select()
 	 * always returns TRUE then (in some version of emx.dll) */
@@ -5369,6 +5384,10 @@ sigcont_handler SIGDEFARG(sigarg)
 	    /* loop if MzThreads must be scheduled and timeout occurred */
 	    finished = FALSE;
 # endif
+# ifdef FEAT_ASYNC
+	if (ret == 0 && msec > p_tt)
+	    finished = FALSE;
+# endif
 
 # ifdef FEAT_SNIFF
 	if (ret < 0 )
diff --git a/src/structs.h b/src/structs.h
index f74d218..360252f 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -2540,3 +2540,17 @@ struct VimMenu
   UINT32_T state[8];
   char_u   buffer[64];
 } context_sha256_T;
+
+#ifdef FEAT_ASYNC
+/*
+ * Used for async settimeout/interval.
+ */
+struct timeout_T {
+    int id;                     /* timeout/interval id */
+    int interval;               /* interval period if interval, otherwise -1 */
+    unsigned long tm;           /* time to fire (epoch milliseconds) */
+    char_u *cmd;                /* vim command to run */
+    struct timeout_T *next;     /* pointer to next timeout in linked list */
+};
+typedef struct timeout_T timeout_T;
+#endif
diff --git a/src/vim.h b/src/vim.h
index 3d61f3a..0afa0b1 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -2123,6 +2123,10 @@ enum auto_event
 # endif
 #endif
 
+#ifdef FEAT_ASYNC
+# include "async.h"
+#endif
+
 #if defined(FEAT_BROWSE) && defined(GTK_CHECK_VERSION)
 # if GTK_CHECK_VERSION(2,4,0)
 #  define USE_FILE_CHOOSER
-- 
1.8.4


>From 68a71b534e875733c3b2865c8b96b28946c9296d Mon Sep 17 00:00:00 2001
From: Geoff Greer <ge...@greer.fm>
Date: Tue, 10 Sep 2013 14:37:27 -0700
Subject: [PATCH 2/2] docs

---
 runtime/doc/eval.txt    | 45 ++++++++++++++++++++++++++++++++++++++++++++-
 runtime/doc/options.txt |  9 +++++++++
 runtime/doc/tags        |  5 +++++
 src/version.c           |  5 +++++
 4 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 60b01a8..a0dd86a 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1,4 +1,4 @@
-*eval.txt*	For Vim version 7.4.  Last change: 2013 Aug 24
+*eval.txt*	For Vim version 7.4.  Last change: 2013 Sep 10
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -1926,6 +1926,7 @@ server2client( {clientid}, {string})
 serverlist()			String	get a list of available servers
 setbufvar( {expr}, {varname}, {val})	set {varname} in buffer {expr} to {val}
 setcmdpos( {pos})		Number	set cursor position in command-line
+setinterval( {nr},{string})   Number  evaluate the expression {string} every {nr} milliseconds
 setline( {lnum}, {line})	Number	set line {lnum} to {line}
 setloclist( {nr}, {list}[, {action}])
 				Number	modify location list using {list}
@@ -1936,6 +1937,7 @@ setreg( {n}, {v}[, {opt}])	Number	set register to value and type
 settabvar( {nr}, {varname}, {val})	set {varname} in tab page {nr} to {val}
 settabwinvar( {tabnr}, {winnr}, {varname}, {val})    set {varname} in window
 					{winnr} in tab page {tabnr} to {val}
+settimeout(	{nr}, {string})	Number  evaluate the expression {string} after {nr} milliseconds
 setwinvar( {nr}, {varname}, {val})	set {varname} in window {nr} to {val}
 sha256( {string})		String	SHA256 checksum of {string}
 shellescape( {string} [, {special}])
@@ -2281,6 +2283,15 @@ call({func}, {arglist} [, {dict}])			*call()* *E699*
 		{dict} is for functions with the "dict" attribute.  It will be
 		used to set the local variable "self". |Dictionary-function|
 
+canceltimeout({nr})					*canceltimeout()*
+		Cancel the timeout or interval with id, {nr}, preventing it 
+		from every firing.
+		Also see |settimeout()| and |setinterval()|.
+		{only available when compiled with the |+async| feature}
+		Examples: >
+			let timeout_id = settimeout(5000, 'echo(2)')
+			echo canceltimeout(timeout_id)
+
 ceil({expr})							*ceil()*
 		Return the smallest integral value greater than or equal to
 		{expr} as a |Float| (round up).
@@ -5187,6 +5198,23 @@ setcmdpos({pos})					*setcmdpos()*
 		Returns 0 when successful, 1 when not editing the command
 		line.
 
+setinterval({nr}, {string})				*setinterval()*
+		Immediately returns an interval id and evaluate the expression, 
+		{string}, every {nr} milliseconds. Intervals do not pile up.  
+		The timer's resolution defaults to 100ms and can be changed by 
+		setting |ticktime|.  Intervals can be canceled by calling 
+		|canceltimeout({interval_id})|.
+		NOTE: Vim is single-threaded and all expressions are run within 
+		the main thread.  Therefore, expressions should return control 
+		flow within	a short amount of time.
+		Also see |settimeout()| and |canceltimeout()|.
+		{only available when compiled with the |+async| feature}
+		Examples: >
+			:call setinterval(1000, "call echo(2)")
+<		2
+		2
+		2
+
 setline({lnum}, {text})					*setline()*
 		Set line {lnum} of the current buffer to {text}.  To insert
 		lines use |append()|.
@@ -5356,6 +5384,21 @@ settabwinvar({tabnr}, {winnr}, {varname}, {val})	*settabwinvar()*
 			:call settabwinvar(3, 2, "myvar", "foobar")
 <		This function is not available in the |sandbox|.
 
+settimeout({nr}, {string})				*settimeout()*
+		Immediately returns an interval id and evaluate the expression, 
+		{string}, once after {nr} milliseconds. The timer's
+		resolution defaults to 100ms and can be changed by setting 
+		|ticktime|.  Timeouts can be canceled by calling 
+		|canceltimeout({interval_id})|.
+		NOTE: Vim is single-threaded and all expressions are run within 
+		the main thread.  Therefore, expressions should return control 
+		flow within	a short amount of time.  
+		Also see |setinterval()| and |canceltimeout()|.
+		{only available when compiled with the |+async| feature}
+		Examples: >
+			:call settimeout(1000, "call echo(2)")
+<		2
+
 setwinvar({nr}, {varname}, {val})			*setwinvar()*
 		Like |settabwinvar()| for the current tab page.
 		Examples: >
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 0688fcc..e010f3e 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -7253,6 +7253,15 @@ A jump table for the options with a short description can be found at |Q_op|.
 	uses another default.
 	Backticks cannot be used in this option for security reasons.
 
+						*'ticktime'* *'tt'*
+'ticktime' 'tt'	number	(default 100)
+			global
+			{not in Vi}
+	This is the resolution for all timers set with |setinterval()| and 
+	|settimeout()|.  Decreasing this number will make the timers
+	more accurate but will also make Vim less efficient.  To globally
+	disable all timers for debugging, set |ticktime| to -1.
+
 			     *'tildeop'* *'top'* *'notildeop'* *'notop'*
 'tildeop' 'top'		boolean	(default off)
 			global
diff --git a/runtime/doc/tags b/runtime/doc/tags
index f32ea6f..3e8e0f7 100644
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -1014,6 +1014,7 @@ $VIMRUNTIME	starting.txt	/*$VIMRUNTIME*
 'tf'	options.txt	/*'tf'*
 'tgst'	options.txt	/*'tgst'*
 'thesaurus'	options.txt	/*'thesaurus'*
+'ticktime'	options.txt	/*'ticktime'*
 'tildeop'	options.txt	/*'tildeop'*
 'timeout'	options.txt	/*'timeout'*
 'timeoutlen'	options.txt	/*'timeoutlen'*
@@ -1032,6 +1033,7 @@ $VIMRUNTIME	starting.txt	/*$VIMRUNTIME*
 'ts'	options.txt	/*'ts'*
 'tsl'	options.txt	/*'tsl'*
 'tsr'	options.txt	/*'tsr'*
+'tt'	options.txt	/*'tt'*
 'ttimeout'	options.txt	/*'ttimeout'*
 'ttimeoutlen'	options.txt	/*'ttimeoutlen'*
 'ttm'	options.txt	/*'ttm'*
@@ -4987,6 +4989,7 @@ c_Up	cmdline.txt	/*c_Up*
 c_digraph	cmdline.txt	/*c_digraph*
 c_wildchar	cmdline.txt	/*c_wildchar*
 call()	eval.txt	/*call()*
+canceltimeout()	eval.txt	/*canceltimeout()*
 carriage-return	intro.txt	/*carriage-return*
 case	change.txt	/*case*
 catch-all	eval.txt	/*catch-all*
@@ -7653,6 +7656,7 @@ set-option	options.txt	/*set-option*
 set-spc-auto	spell.txt	/*set-spc-auto*
 setbufvar()	eval.txt	/*setbufvar()*
 setcmdpos()	eval.txt	/*setcmdpos()*
+setinterval()	eval.txt	/*setinterval()*
 setline()	eval.txt	/*setline()*
 setloclist()	eval.txt	/*setloclist()*
 setmatches()	eval.txt	/*setmatches()*
@@ -7661,6 +7665,7 @@ setqflist()	eval.txt	/*setqflist()*
 setreg()	eval.txt	/*setreg()*
 settabvar()	eval.txt	/*settabvar()*
 settabwinvar()	eval.txt	/*settabwinvar()*
+settimeout()	eval.txt	/*settimeout()*
 setting-guifont	gui.txt	/*setting-guifont*
 setting-guitablabel	tabpage.txt	/*setting-guitablabel*
 setting-tabline	tabpage.txt	/*setting-tabline*
diff --git a/src/version.c b/src/version.c
index ef3f9b1..f98a1b5 100644
--- a/src/version.c
+++ b/src/version.c
@@ -77,6 +77,11 @@
 #else
 	"-arabic",
 #endif
+#ifdef FEAT_ASYNC
+	"+async",
+#else
+	"-async",
+#endif
 #ifdef FEAT_AUTOCMD
 	"+autocmd",
 #else
-- 
1.8.4

Raspunde prin e-mail lui