aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt16
-rw-r--r--config/config.h.in1
-rw-r--r--runtime/doc/eval.txt45
-rw-r--r--runtime/doc/help.txt12
-rw-r--r--runtime/doc/index.txt10
-rw-r--r--runtime/doc/map.txt16
-rw-r--r--runtime/doc/spell.txt10
-rw-r--r--runtime/doc/usr_02.txt253
-rw-r--r--runtime/doc/usr_03.txt6
-rw-r--r--runtime/doc/various.txt2
-rw-r--r--runtime/ftplugin/hgcommit.vim16
-rw-r--r--runtime/indent/lua.vim4
-rw-r--r--runtime/syntax/aptconf.vim135
-rw-r--r--runtime/syntax/rst.vim6
-rw-r--r--runtime/syntax/sh.vim12
-rw-r--r--runtime/syntax/sshconfig.vim18
-rw-r--r--runtime/syntax/sshdconfig.vim11
-rwxr-xr-xscripts/gendeclarations.lua2
-rw-r--r--scripts/msgpack-gen.lua11
-rw-r--r--src/nvim/CMakeLists.txt4
-rw-r--r--src/nvim/api/ui.c (renamed from src/nvim/msgpack_rpc/remote_ui.c)78
-rw-r--r--src/nvim/api/ui.h11
-rw-r--r--src/nvim/api/vim.c4
-rw-r--r--src/nvim/eval.c168
-rw-r--r--src/nvim/event/time.c5
-rw-r--r--src/nvim/event/time.h1
-rw-r--r--src/nvim/ex_docmd.c6
-rw-r--r--src/nvim/ex_getln.c1
-rw-r--r--src/nvim/func_attr.h3
-rw-r--r--src/nvim/message.c24
-rw-r--r--src/nvim/msgpack_rpc/channel.c2
-rw-r--r--src/nvim/msgpack_rpc/remote_ui.h9
-rw-r--r--src/nvim/spell.c70
-rw-r--r--src/nvim/testdir/Makefile1
-rw-r--r--src/nvim/testdir/runtest.vim3
-rw-r--r--src/nvim/testdir/test_timers.vim32
-rw-r--r--src/nvim/testdir/test_viml.vim39
-rw-r--r--src/nvim/ui.c25
-rw-r--r--src/nvim/ui_bridge.c4
-rw-r--r--src/nvim/version.c22
-rw-r--r--test/functional/eval/timer_spec.lua129
-rw-r--r--test/functional/legacy/061_undo_tree_spec.lua13
-rw-r--r--test/functional/legacy/assert_spec.lua18
-rw-r--r--test/functional/legacy/quickfix_spec.lua296
-rw-r--r--test/functional/provider/python_spec.lua82
-rw-r--r--test/functional/ui/screen.lua6
-rw-r--r--third-party/cmake/BuildLuarocks.cmake9
47 files changed, 1364 insertions, 287 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 317d2a1a5b..953e210397 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -300,11 +300,19 @@ include_directories(SYSTEM ${LIBUV_INCLUDE_DIRS})
find_package(Msgpack 1.0.0 REQUIRED)
include_directories(SYSTEM ${MSGPACK_INCLUDE_DIRS})
-find_package(Unibilium REQUIRED)
-include_directories(SYSTEM ${UNIBILIUM_INCLUDE_DIRS})
+if(UNIX)
+ option(FEAT_TUI "Enable the Terminal UI" ON)
+else()
+ option(FEAT_TUI "Enable the Terminal UI" OFF)
+endif()
-find_package(LibTermkey REQUIRED)
-include_directories(SYSTEM ${LIBTERMKEY_INCLUDE_DIRS})
+if(FEAT_TUI)
+ find_package(Unibilium REQUIRED)
+ include_directories(SYSTEM ${UNIBILIUM_INCLUDE_DIRS})
+
+ find_package(LibTermkey REQUIRED)
+ include_directories(SYSTEM ${LIBTERMKEY_INCLUDE_DIRS})
+endif()
find_package(LibVterm REQUIRED)
include_directories(SYSTEM ${LIBVTERM_INCLUDE_DIRS})
diff --git a/config/config.h.in b/config/config.h.in
index 5c5b008f7e..c2f52d8c7e 100644
--- a/config/config.h.in
+++ b/config/config.h.in
@@ -50,6 +50,7 @@
#cmakedefine USE_FNAME_CASE
#define FEAT_CSCOPE
+#cmakedefine FEAT_TUI
#ifndef UNIT_TESTING
#cmakedefine HAVE_JEMALLOC
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index eebdabd154..a8504e2a2a 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1789,6 +1789,7 @@ argv({nr}) String {nr} entry of the argument list
argv() List the argument list
assert_equal({exp}, {act} [, {msg}]) none assert {exp} equals {act}
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_true({actual} [, {msg}]) none assert {actual} is true
asin({expr}) Float arc sine of {expr}
@@ -2114,9 +2115,12 @@ tabpagewinnr({tabarg}[, {arg}])
Number number of current window in tab page
taglist({expr}) List list of tags matching {expr}
tagfiles() List tags files used
-tempname() String name for a temporary file
tan({expr}) Float tangent of {expr}
tanh({expr}) Float hyperbolic tangent of {expr}
+tempname() String name for a temporary file
+timer_start({time}, {callback} [, {options}])
+ Number create a timer
+timer_stop({timer}) none stop a timer
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}
@@ -2260,6 +2264,11 @@ assert_exception({error} [, {msg}]) *assert_exception()*
call assert_exception('E492:')
endtry
+assert_fails({cmd} [, {error}]) *assert_fails()*
+ Run {cmd} and add an error message to |v:errors| if it does
+ NOT produce an error.
+ When {error} is given it must match |v:errmsg|.
+
assert_false({actual} [, {msg}]) *assert_false()*
When {actual} is not false an error message is added to
|v:errors|, like with |assert_equal()|.
@@ -3573,7 +3582,7 @@ getcmdwintype() *getcmdwintype()*
*getcurpos()*
getcurpos() Get the position of the cursor. This is like getpos('.'), but
includes an extra item in the list:
- [bufnum, lnum, col, off, curswant]
+ [bufnum, lnum, col, off, curswant] ~
The "curswant" number is the preferred column when moving the
cursor vertically.
This can be used to save and restore the cursor position: >
@@ -6840,6 +6849,37 @@ tanh({expr}) *tanh()*
< -0.761594
+ *timer_start()*
+timer_start({time}, {callback} [, {options}])
+ Create a timer and return the timer ID.
+
+ {time} is the waiting time in milliseconds. This is the
+ minimum time before invoking the callback. When the system is
+ busy or Vim is not waiting for input the time will be longer.
+
+ {callback} is the function to call. It can be the name of a
+ function or a Funcref. It is called with one argument, which
+ is the timer ID. The callback is only invoked when Vim is
+ waiting for input.
+
+ {options} is a dictionary. Supported entries:
+ "repeat" Number of times to repeat calling the
+ callback. -1 means forever.
+
+ Example: >
+ func MyHandler(timer)
+ echo 'Handler called'
+ endfunc
+ let timer = timer_start(500, 'MyHandler',
+ \ {'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()*
+ Stop a timer. {timer} is an ID returned by timer_start().
+ The timer callback will no longer be invoked.
+
tolower({expr}) *tolower()*
The result is a copy of the String given, with all uppercase
characters turned into lowercase (just like applying |gu| to
@@ -7323,6 +7363,7 @@ termresponse Compiled with support for |t_RV| and |v:termresponse|.
textobjects Compiled with support for |text-objects|.
tgetent Compiled with tgetent support, able to use a termcap
or terminfo file.
+timers Compiled with |timer_start()| support.
title Compiled with window title support |'title'|.
toolbar Compiled with support for |gui-toolbar|.
unix Unix version of Vim.
diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt
index 19bcb35da8..342c475f9b 100644
--- a/runtime/doc/help.txt
+++ b/runtime/doc/help.txt
@@ -1,4 +1,4 @@
-*help.txt* For Vim version 7.4. Last change: 2015 Apr 15
+*help.txt* For Vim version 7.4. Last change: 2016 Jan 10
VIM - main help file
k
@@ -9,14 +9,14 @@ Close this window: Use ":q<Enter>".
Jump to a subject: Position the cursor on a tag (e.g. |bars|) and hit CTRL-].
With the mouse: Double-click the left mouse button on a tag, e.g. |bars|.
- Jump back: Type CTRL-T or CTRL-O (repeat to go further back).
+ Jump back: Type CTRL-T or CTRL-O. Repeat to go further back.
Get specific help: It is possible to go directly to whatever you want help
on, by giving an argument to the |:help| command.
- It is possible to further specify the context:
- *help-context*
+ Prepend something to specify the context: *help-context*
+
WHAT PREPEND EXAMPLE ~
- Normal mode command (nothing) :help x
+ Normal mode command :help x
Visual mode command v_ :help v_u
Insert mode command i_ :help i_<Esc>
Command-line command : :help :quit
@@ -24,6 +24,8 @@ Get specific help: It is possible to go directly to whatever you want help
Vim command argument - :help -r
Option ' :help 'textwidth'
Regular expression / :help /[
+ See |help-summary| for more contexts and an explanation.
+
Search for help: Type ":help word", then hit CTRL-D to see matching
help entries for "word".
Or use ":helpgrep word". |:helpgrep|
diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt
index e6c1ccc0cf..e98f0400c4 100644
--- a/runtime/doc/index.txt
+++ b/runtime/doc/index.txt
@@ -1,4 +1,4 @@
-*index.txt* For Vim version 7.4. Last change: 2016 Jan 03
+*index.txt* For Vim version 7.4. Last change: 2016 Jan 10
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1171,7 +1171,7 @@ tag command action ~
|:cpfile| :cpf[ile] go to last error in previous file
|:cquit| :cq[uit] quit Vim with an error code
|:crewind| :cr[ewind] go to the specified error, default first one
-|:cscope| :cs[cope] execute cscope command
+|:cscope| :cs[cope] execute cscope command
|:cstag| :cst[ag] use cscope to jump to a tag
|:cunmap| :cu[nmap] like ":unmap" but for Command-line mode
|:cunabbrev| :cuna[bbrev] like ":unabbrev" but for Command-line mode
@@ -1290,7 +1290,7 @@ tag command action ~
|:lcd| :lc[d] change directory locally
|:lchdir| :lch[dir] change directory locally
|:lclose| :lcl[ose] close location window
-|:lcscope| :lcs[cope] like ":cscope" but uses location list
+|:lcscope| :lcs[cope] like ":cscope" but uses location list
|:ldo| :ld[o] execute command in valid location list entries
|:lfdo| :lfd[o] execute command in each file in location list
|:left| :le[ft] left align lines
@@ -1341,7 +1341,7 @@ tag command action ~
|:marks| :marks list all marks
|:match| :mat[ch] define a match to highlight
|:menu| :me[nu] enter a new menu item
-|:menutranslate| :menut[ranslate] add a menu translation item
+|:menutranslate| :menut[ranslate] add a menu translation item
|:messages| :mes[sages] view previously displayed messages
|:mkexrc| :mk[exrc] write current mappings and settings to a file
|:mksession| :mks[ession] write session info to a file
@@ -1494,7 +1494,7 @@ tag command action ~
|:stop| :st[op] suspend the editor or escape to a shell
|:stag| :sta[g] split window and jump to a tag
|:startinsert| :star[tinsert] start Insert mode
-|:startgreplace| :startg[replace] start Virtual Replace mode
+|:startgreplace| :startg[replace] start Virtual Replace mode
|:startreplace| :startr[eplace] start Replace mode
|:stopinsert| :stopi[nsert] stop Insert mode
|:stjump| :stj[ump] do ":tjump" and split window
diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt
index 464c700a4d..31c3198f72 100644
--- a/runtime/doc/map.txt
+++ b/runtime/doc/map.txt
@@ -1,4 +1,4 @@
-*map.txt* For Vim version 7.4. Last change: 2014 Dec 08
+*map.txt* For Vim version 7.4. Last change: 2016 Jan 10
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -481,7 +481,7 @@ internal code is written to the script file.
1.6 SPECIAL CHARACTERS *:map-special-chars*
- *map_backslash*
+ *map_backslash* *map-backslash*
Note that only CTRL-V is mentioned here as a special character for mappings
and abbreviations. When 'cpoptions' does not contain 'B', a backslash can
also be used like CTRL-V. The <> notation can be fully used then |<>|. But
@@ -492,21 +492,21 @@ To map a backslash, or use a backslash literally in the {rhs}, the special
sequence "<Bslash>" can be used. This avoids the need to double backslashes
when using nested mappings.
- *map_CTRL-C*
+ *map_CTRL-C* *map-CTRL-C*
Using CTRL-C in the {lhs} is possible, but it will only work when Vim is
waiting for a key, not when Vim is busy with something. When Vim is busy
CTRL-C interrupts/breaks the command.
When using the GUI version on MS-Windows CTRL-C can be mapped to allow a Copy
command to the clipboard. Use CTRL-Break to interrupt Vim.
- *map_space_in_lhs*
+ *map_space_in_lhs* *map-space_in_lhs*
To include a space in {lhs} precede it with a CTRL-V (type two CTRL-Vs for
each space).
- *map_space_in_rhs*
+ *map_space_in_rhs* *map-space_in_rhs*
If you want a {rhs} that starts with a space, use "<Space>". To be fully Vi
compatible (but unreadable) don't use the |<>| notation, precede {rhs} with a
single CTRL-V (you have to type CTRL-V two times).
- *map_empty_rhs*
+ *map_empty_rhs* *map-empty-rhs*
You can create an empty {rhs} by typing nothing after a single CTRL-V (you
have to type CTRL-V two times). Unfortunately, you cannot do this in a vimrc
file.
@@ -581,7 +581,7 @@ Upper and lowercase differences are ignored.
It is not possible to put a comment after these commands, because the '"'
character is considered to be part of the {lhs} or {rhs}.
- *map_bar*
+ *map_bar* *map-bar*
Since the '|' character is used to separate a map command from the next
command, you will have to do something special to include a '|' in {rhs}.
There are three methods:
@@ -599,7 +599,7 @@ When 'b' is present in 'cpoptions', "\|" will be recognized as a mapping
ending in a '\' and then another command. This is Vi compatible, but
illogical when compared to other commands.
- *map_return*
+ *map_return* *map-return*
When you have a mapping that contains an Ex command, you need to put a line
terminator after it to have it executed. The use of <CR> is recommended for
this (see |<>|). Example: >
diff --git a/runtime/doc/spell.txt b/runtime/doc/spell.txt
index 752444a3bd..a767f6cbbf 100644
--- a/runtime/doc/spell.txt
+++ b/runtime/doc/spell.txt
@@ -1,4 +1,4 @@
-*spell.txt* For Vim version 7.4. Last change: 2014 Sep 19
+*spell.txt* For Vim version 7.4. Last change: 2016 Jan 08
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1373,6 +1373,14 @@ the item name. Case is always ignored.
The Hunspell feature to use three arguments and flags is not supported.
+ *spell-NOCOMPOUNDSUGS*
+This item indicates that using compounding to make suggestions is not a good
+idea. Use this when compounding is used with very short or one-character
+words. E.g. to make numbers out of digits. Without this flag creating
+suggestions would spend most time trying all kind of weird compound words.
+
+ NOCOMPOUNDSUGS ~
+
*spell-SYLLABLE*
The SYLLABLE item defines characters or character sequences that are used to
count the number of syllables in a word. Example:
diff --git a/runtime/doc/usr_02.txt b/runtime/doc/usr_02.txt
index 6a288f8965..1c536c1eda 100644
--- a/runtime/doc/usr_02.txt
+++ b/runtime/doc/usr_02.txt
@@ -1,4 +1,4 @@
-*usr_02.txt* For Vim version 7.4. Last change: 2015 Apr 12
+*usr_02.txt* For Vim version 7.4. Last change: 2016 Jan 15
VIM USER MANUAL - by Bram Moolenaar
@@ -397,7 +397,15 @@ original version of the file.
Everything you always wanted to know can be found in the Vim help files.
Don't be afraid to ask!
- To get generic help use this command: >
+
+If you know what you are looking for, it is usually easier to search for it
+using the help system, instead of using Google. Because the subjects follow
+a certain style guide.
+
+Also the help has the advantage of belonging to your particular Vim version.
+You won't see help for commands added later. These would not work for you.
+
+To get generic help use this command: >
:help
@@ -471,7 +479,7 @@ example, use the following command: >
:help 'number'
-The table with all mode prefixes can be found here: |help-context|.
+The table with all mode prefixes can be found below: |help-summary|.
Special keys are enclosed in angle brackets. To find help on the up-arrow key
in Insert mode, for instance, use this command: >
@@ -488,64 +496,187 @@ You can use the error ID at the start to find help about it: >
Summary: *help-summary* >
- :help
-< Gives you very general help. Scroll down to see a list of all
- helpfiles, including those added locally (i.e. not distributed
- with Vim). >
- :help user-toc.txt
-< Table of contents of the User Manual. >
- :help :subject
-< Ex-command "subject", for instance the following: >
- :help :help
-< Help on getting help. >
- :help abc
-< normal-mode command "abc". >
- :help CTRL-B
-< Control key <C-B> in Normal mode. >
- :help i_abc
- :help i_CTRL-B
-< The same in Insert mode. >
- :help v_abc
- :help v_CTRL-B
-< The same in Visual mode. >
- :help c_abc
- :help c_CTRL-B
-< The same in Command-line mode. >
- :help 'subject'
-< Option 'subject'. >
- :help subject()
-< Function "subject". >
- :help -subject
-< Command-line argument "-subject". >
- :help +subject
-< Compile-time feature "+subject". >
- :help /*
-< Regular expression item "*" >
- :help EventName
-< Autocommand event "EventName". >
- :help digraphs.txt
-< The top of the helpfile "digraph.txt".
- Similarly for any other helpfile. >
- :help pattern<Tab>
-< Find a help tag starting with "pattern". Repeat <Tab> for
- others. >
- :help pattern<Ctrl-D>
-< See all possible help tag matches "pattern" at once. >
- :helpgrep pattern
-< Search the whole text of all help files for pattern "pattern".
- Jumps to the first match. Jump to other matches with: >
- :cn
-< next match >
- :cprev
- :cN
-< previous match >
- :cfirst
- :clast
-< first or last match >
- :copen
- :cclose
-< open/close the quickfix window; press <Enter> to jump
- to the item under the cursor
+
+1) Use Ctrl-D after typing a topic and let Vim show all available topics.
+ Or press Tab to complete: >
+ :help some<Tab>
+< More information on how to use the help: >
+ :help helphelp
+
+2) Follow the links in bars to related help. You can go from the detailed
+ help to the user documentation, which describes certain commands more from
+ a user perspective and less detailed. E.g. after: >
+ :help pattern.txt
+< You can see the user guide topics |03.9| and |usr_27.txt| in the
+ introduction.
+
+3) Options are enclosed in single apostrophes. To go to the help topic for the
+ list option: >
+ :help 'list'
+< If you only know you are looking for a certain option, you can also do: >
+ :help options.txt
+< to open the help page which describes all option handling and then search
+ using regular expressions, e.g. textwidth.
+ Certain options have their own namespace, e.g.: >
+ :help cpo-<letter>
+< for the corresponding flag of the 'cpoptions' settings, substitute <letter>
+ by a specific flag, e.g.: >
+ :help cpo-;
+< And for the guioption flags: >
+ :help go-<letter>
+
+4) Normal mode commands do not have a prefix. To go to the help page for the
+ "gt" command: >
+ :help gt
+
+5) Insert mode commands start with i_. Help for deleting a word: >
+ :help i_CTRL-W
+
+6) Visual mode commands start with v_. Help for jumping to the other side of
+ the Visual area: >
+ :help v_o
+
+7) Command line editing and arguments start with c_. Help for using the
+ command argument %: >
+ :help c_%
+
+8) Ex-commands always start with ":", so to go to the :s command help: >
+ :help :s
+
+9) Key combinations. They usually start with a single letter indicating
+ the mode for which they can be used. E.g.: >
+ :help i_CTRL-X
+< takes you to the family of Ctrl-X commands for insert mode which can be
+ used to auto complete different things. Note, that certain keys will
+ always be written the same, e.g. Control will always be CTRL.
+ For normal mode commands there is no prefix and the topic is available at
+ :h CTRL-<Letter>. E.g. >
+ :help CTRL-W
+< In contrast >
+ :help c_CTRL-R
+< will describe what the Ctrl-R does when entering commands in the Command
+ line and >
+ :help v_Ctrl-A
+< talks about incrementing numbers in visual mode and >
+ :help g_CTRL-A
+< talks about the g<C-A> command (e.g. you have to press "g" then <Ctrl-A>).
+ Here the "g" stand for the normal command "g" which always expects a second
+ key before doing something similar to the commands starting with "z"
+
+10) Regexp items always start with /. So to get help for the "\+" quantifier
+ in Vim regexes: >
+ :help /\+
+< If you need to know everything about regular expressions, start reading
+ at: >
+ :help pattern.txt
+
+11) Registers always start with "quote". To find out about the special ":"
+ register: >
+ :help quote:
+
+12) Vim Script (VimL) is available at >
+ :help eval.txt
+< Certain aspects of the language are available at :h expr-X where "X" is a
+ single letter. E.g. >
+ :help expr-!
+< will take you to the topic describing the "!" (Not) operator for
+ VimScript.
+ Also important is >
+ :help function-list
+< to find a short description of all functions available. Help topics for
+ VimL functions always include the "()", so: >
+ :help append()
+< talks about the append VimL function rather than how to append text in the
+ current buffer.
+
+13) Mappings are talked about in the help page :h |map.txt|. Use >
+ :help mapmode-i
+< to find out about the |:imap| command. Also use :map-topic
+ to find out about certain subtopics particular for mappings. e.g: >
+ :help :map-local
+< for buffer-local mappings or >
+ :help map-bar
+< for how the '|' is handled in mappings.
+
+14) Command definitions are talked about :h command-topic, so use >
+ :help command-bar
+< to find out about the '!' argument for custom commands.
+
+15) Window management commands always start with CTRL-W, so you find the
+ corresponding help at :h CTRL-W_letter. E.g. >
+ :help CTRL-W_p
+< for moving the previous accessed window). You can also access >
+ :help windows.txt
+< and read your way through if you are looking for window handling
+ commands.
+
+16) Use |:helpgrep| to search in all help pages (and also of any installed
+ plugins). See |:helpgrep| for how to use it.
+ To search for a topic: >
+ :helpgrep topic
+< This takes you to the first match. To go to the next one: >
+ :cnext
+< All matches are available in the quickfix window which can be opened
+ with: >
+ :copen
+< Move around to the match you like and press Enter to jump to that help.
+
+17) The user manual. This describes help topics for beginners in a rather
+ friendly way. Start at |usr_toc.txt| to find the table of content (as you
+ might have guessed): >
+ :help usr_toc.txt
+< Skim over the contents to find interesting topics. The "Digraphs" and
+ "Entering special characters" items are in chapter 24, so to go to that
+ particular help page: >
+ :help usr_24.txt
+< Also if you want to access a certain chapter in the help, the chapter
+ number can be accessed directly like this: >
+ :help 10.1
+< goes to chapter 10.1 in |usr_10.txt| and talks about recording macros.
+
+18) Highlighting groups. Always start with hl-groupname. E.g. >
+ :help hl-WarningMsg
+< talks about the WarningMsg highlighting group.
+
+19) Syntax highlighting is namespaced to :syn-topic e.g. >
+ :help :syn-conceal
+< talks about the conceal argument for the :syn command.
+
+20) Quickfix commands usually start with :c while location list commands
+ usually start with :l
+
+21) Autocommand events can be found by their name: >
+ :help BufWinLeave
+< To see all possible events: >
+ :help autocommands-events
+
+22) Command-line switches always start with "-". So for the help of the -f
+ command switch of Vim use: >
+ :help -f
+
+23) Optional features always start with "+". To find out about the
+ conceal feature use: >
+ :help +conceal
+
+24) Documentation for included filetype specific functionality is usually
+ available in the form ft-<filetype>-<functionality>. So >
+ :help ft-c-syntax
+< talks about the C syntax file and the option it provides. Sometimes,
+ additional sections for omni completion >
+ :help ft-php-omni
+< or filetype plugins >
+ :help ft-tex-plugin
+< are available.
+
+25) Error and Warning codes can be looked up directly in the help. So >
+ :help E297
+< takes you exactly to the description of the swap error message and >
+ :help W10
+< talks about the warning "Changing a readonly file".
+ Sometimes however, those error codes are not described, but rather are
+ listed at the Vim command that usually causes this. So: >
+ :help E128
+< takes you to the |:function| command
==============================================================================
diff --git a/runtime/doc/usr_03.txt b/runtime/doc/usr_03.txt
index b8f65d9309..943d7b528c 100644
--- a/runtime/doc/usr_03.txt
+++ b/runtime/doc/usr_03.txt
@@ -1,4 +1,4 @@
-*usr_03.txt* For Vim version 7.4. Last change: 2015 Dec 12
+*usr_03.txt* For Vim version 7.4. Last change: 2016 Jan 05
VIM USER MANUAL - by Bram Moolenaar
@@ -414,8 +414,8 @@ in "the" use: >
/the\>
The "\>" item is a special marker that only matches at the end of a word.
-Similarly "\<" only matches at the begin of a word. Thus to search for the
-word "the" only: >
+Similarly "\<" only matches at the beginning of a word. Thus to search for
+the word "the" only: >
/\<the\>
diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt
index af4224993f..293cfe6e00 100644
--- a/runtime/doc/various.txt
+++ b/runtime/doc/various.txt
@@ -1,4 +1,4 @@
-*various.txt* For Vim version 7.4. Last change: 2015 Nov 15
+*various.txt* For Vim version 7.4. Last change: 2016 Jan 10
VIM REFERENCE MANUAL by Bram Moolenaar
diff --git a/runtime/ftplugin/hgcommit.vim b/runtime/ftplugin/hgcommit.vim
new file mode 100644
index 0000000000..d5a6c0a383
--- /dev/null
+++ b/runtime/ftplugin/hgcommit.vim
@@ -0,0 +1,16 @@
+" Vim filetype plugin file
+" Language: hg (Mercurial) commit file
+" Maintainer: Ken Takata <kentkt at csc dot jp>
+" Last Change: 2016 Jan 6
+" Filenames: hg-editor-*.txt
+" License: VIM License
+" URL: https://github.com/k-takata/hg-vim
+
+if exists("b:did_ftplugin")
+ finish
+endif
+let b:did_ftplugin = 1
+
+setlocal nomodeline
+
+let b:undo_ftplugin = 'setl modeline<'
diff --git a/runtime/indent/lua.vim b/runtime/indent/lua.vim
index 393994c590..d1d2c0d600 100644
--- a/runtime/indent/lua.vim
+++ b/runtime/indent/lua.vim
@@ -2,7 +2,7 @@
" Language: Lua script
" Maintainer: Marcus Aurelius Farias <marcus.cf 'at' bol.com.br>
" First Author: Max Ischenko <mfi 'at' ukr.net>
-" Last Change: 2014 Nov 12
+" Last Change: 2016 Jan 10
" Only load this indent file when no other was loaded.
if exists("b:did_indent")
@@ -52,7 +52,7 @@ function! GetLuaIndent()
endif
endif
- " Subtract a 'shiftwidth' on end, else (and elseif), until and '}'
+ " Subtract a 'shiftwidth' on end, else, elseif, until and '}'
" This is the part that requires 'indentkeys'.
let midx = match(getline(v:lnum), '^\s*\%(end\>\|else\>\|elseif\>\|until\>\|}\)')
if midx != -1 && synIDattr(synID(v:lnum, midx + 1, 1), "name") != "luaComment"
diff --git a/runtime/syntax/aptconf.vim b/runtime/syntax/aptconf.vim
index 0607ca10f5..7a31b2d15e 100644
--- a/runtime/syntax/aptconf.vim
+++ b/runtime/syntax/aptconf.vim
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: APT config file
" Maintainer: Yann Amar <quidame@poivron.org>
-" Last Change: 2013 Apr 12
+" Last Change: 2015 Dec 22
" For version 5.x: Clear all syntax items
" For version 6.x and 7.x: Quit when a syntax file was already loaded
@@ -38,22 +38,22 @@ setlocal iskeyword+=/,-,.,_,+
" Incomplete keywords will be treated differently than completely bad strings:
syn keyword aptconfGroupIncomplete
- \ a[cquire] a[ptitude] d[ebtags] d[ebug] d[ir] d[pkg] d[select]
- \ o[rderlist] p[ackagemanager] p[kgcachegen] q[uiet] r[pm]
- \ u[nattended-upgrade]
+ \ a[cquire] a[dequate] a[ptitude] a[ptlistbugs] d[ebtags] d[ebug]
+ \ d[ir] d[pkg] d[select] o[rderlist] p[ackagemanager] p[kgcachegen]
+ \ q[uiet] r[pm] s[ynaptic] u[nattended-upgrade] w[hatmaps]
" Only the following keywords can be used at toplevel (to begin an option):
syn keyword aptconfGroup
- \ acquire apt aptitude debtags debug dir dpkg dselect
- \ orderlist packagemanager pkgcachegen quiet rpm
- \ unattended-upgrade
+ \ acquire adequate apt aptitude aptlistbugs debtags debug
+ \ dir dpkg dselect orderlist packagemanager pkgcachegen
+ \ quiet rpm synaptic unattended-upgrade whatmaps
" Possible options for each group:
" Acquire: {{{
syn keyword aptconfAcquire contained
- \ cdrom Check-Valid-Until CompressionTypes ForceHash ftp gpgv
- \ GzipIndexes http https Languages Max-ValidTime Min-ValidTime PDiffs
- \ Queue-Mode Retries Source-Symlinks
+ \ cdrom Check-Valid-Until CompressionTypes ForceHash ForceIPv4
+ \ ForceIPv6 ftp gpgv GzipIndexes http https Languages Max-ValidTime
+ \ Min-ValidTime PDiffs Queue-Mode Retries Source-Symlinks
syn keyword aptconfAcquireCDROM contained
\ AutoDetect CdromOnly Mount UMount
@@ -62,14 +62,15 @@ syn keyword aptconfAcquireCompressionTypes contained
\ bz2 lzma gz Order
syn keyword aptconfAcquireFTP contained
- \ Passive Proxy ProxyLogin Timeout
+ \ ForceExtended Passive Proxy ProxyLogin Timeout
syn keyword aptconfAcquireHTTP contained
\ AllowRedirect Dl-Limit Max-Age No-Cache No-Store Pipeline-Depth
- \ Proxy Timeout User-Agent
+ \ Proxy ProxyAutoDetect Proxy-Auto-Detect Timeout User-Agent
syn keyword aptconfAcquireHTTPS contained
- \ CaInfo CaPath CrlFile IssuerCert SslCert SslForceVersion SslKey
+ \ AllowRedirect CaInfo CaPath CrlFile Dl-Limit IssuerCert Max-Age
+ \ No-Cache No-Store Proxy SslCert SslForceVersion SslKey Timeout
\ Verify-Host Verify-Peer
syn keyword aptconfAcquireMaxValidTime contained
@@ -83,14 +84,21 @@ syn cluster aptconfAcquire_ contains=aptconfAcquire,
\ aptconfAcquireHTTP,aptconfAcquireHTTPS,aptconfAcquireMaxValidTime,
\ aptconfAcquirePDiffs
" }}}
+" Adequate: {{{
+syn keyword aptconfAdequate contained
+ \ Enabled
+
+syn cluster aptconfAdequate_ contains=aptconfAdequate
+" }}}
" Apt: {{{
syn keyword aptconfApt contained
\ Architecture Architectures Archive Authentication AutoRemove
- \ Build-Essential Cache Cache-Grow Cache-Limit Cache-Start CDROM
- \ Changelogs Clean-Installed Compressor Default-Release
- \ Force-LoopBreak Get Ignore-Hold Immediate-Configure
+ \ Build-Essential Build-Profiles Cache Cache-Grow Cache-Limit
+ \ Cache-Start CDROM Changelogs Clean-Installed Compressor
+ \ Default-Release Force-LoopBreak Get Ignore-Hold Immediate-Configure
\ Install-Recommends Install-Suggests Keep-Fds List-Cleanup
- \ NeverAutoRemove Never-MarkAuto-Sections Periodic Status-Fd Update
+ \ Move-Autobit-Sections NeverAutoRemove Never-MarkAuto-Sections
+ \ Periodic Status-Fd Update VersionedKernelPackages
syn keyword aptconfAptAuthentication contained
\ TrustCDROM
@@ -124,11 +132,12 @@ syn keyword aptconfAptGet contained
syn keyword aptconfAptPeriodic contained
\ AutocleanInterval BackupArchiveInterval BackupLevel
- \ Download-Upgradeable-Packages MaxAge MaxSize MinAge
- \ Unattended-Upgrade Update-Package-Lists Verbose
+ \ Download-Upgradeable-Packages Download-Upgradeable-Packages-Debdelta
+ \ Enable MaxAge MaxSize MinAge Unattended-Upgrade Update-Package-Lists
+ \ Verbose
syn keyword aptconfAptUpdate contained
- \ Pre-Invoke Post-Invoke Post-Invoke-Success
+ \ List-Refresh Pre-Invoke Post-Invoke Post-Invoke-Success
syn cluster aptconfApt_ contains=aptconfApt,
\ aptconfAptAuthentication,aptconfAptAutoRemove,aptconfAptCache,
@@ -240,6 +249,12 @@ syn cluster aptconfAptitude_ contains=aptconfAptitude,
\ aptconfAptitudeUIKeyBindings,aptconfAptitudeUIStyles,
\ aptconfAptitudeUIStylesElements
" }}}
+" AptListbugs: {{{
+syn keyword aptconfAptListbugs contained
+ \ IgnoreRegexp Severities
+
+syn cluster aptconfAptListbugs_ contains=aptconfAptListbugs
+" }}}
" DebTags: {{{
syn keyword aptconfDebTags contained
\ Vocabulary
@@ -251,7 +266,8 @@ syn keyword aptconfDebug contained
\ Acquire aptcdrom BuildDeps Hashes IdentCdrom Nolocking
\ pkgAcquire pkgAutoRemove pkgCacheGen pkgDepCache pkgDPkgPM
\ pkgDPkgProgressReporting pkgInitialize pkgOrderList
- \ pkgPackageManager pkgPolicy pkgProblemResolver sourceList
+ \ pkgPackageManager pkgPolicy pkgProblemResolver RunScripts
+ \ sourceList
syn keyword aptconfDebugAcquire contained
\ cdrom Ftp gpgv Http Https netrc
@@ -295,7 +311,7 @@ syn keyword aptconfDirMedia contained
\ MountPath
syn keyword aptconfDirState contained
- \ cdroms extended_states Lists mirrors status
+ \ cdroms extended_states Lists mirrors preferences status
syn cluster aptconfDir_ contains=aptconfDir,
\ aptconfDirAptitude,aptconfDirBin,aptconfDirCache,aptconfDirEtc,
@@ -303,15 +319,16 @@ syn cluster aptconfDir_ contains=aptconfDir,
" }}}
" DPkg: {{{
syn keyword aptconfDPkg contained
- \ Build-Options Chroot-Directory ConfigurePending FlushSTDIN MaxArgs
- \ MaxBytes NoTriggers options Pre-Install-Pkgs Pre-Invoke Post-Invoke
+ \ Build-Options Chroot-Directory ConfigurePending FlushSTDIN
+ \ MaxArgBytes MaxArgs MaxBytes NoTriggers options
+ \ Pre-Install-Pkgs Pre-Invoke Post-Invoke
\ Run-Directory StopOnError Tools TriggersPending
syn keyword aptconfDPkgTools contained
- \ Options Version
+ \ adequate InfoFD Options Version
syn cluster aptconfDPkg_ contains=aptconfDPkg,
- \ aptconfDPkgOrderList,aptconfDPkgOrderListScore,aptconfDPkgTools
+ \ aptconfDPkgTools
" }}}
" DSelect: {{{
syn keyword aptconfDSelect contained
@@ -353,23 +370,59 @@ syn keyword aptconfRpm contained
syn cluster aptconfRpm_ contains=aptconfRpm
" }}}
-" Unattened Upgrade: {{{
+" Synaptic: {{{
+syn keyword aptconfSynaptic contained
+ \ AskQuitOnProceed AskRelated AutoCleanCache CleanCache DefaultDistro
+ \ delAction delHistory Download-Only ftpProxy ftpProxyPort httpProxy
+ \ httpProxyPort Install-Recommends LastSearchType Maximized noProxy
+ \ OneClickOnStatusActions ShowAllPkgInfoInMain showWelcomeDialog
+ \ ToolbarState undoStackSize update upgradeType useProxy UseStatusColors
+ \ UseTerminal useUserFont useUserTerminalFont ViewMode
+ \ availVerColumnPos availVerColumnVisible componentColumnPos
+ \ componentColumnVisible descrColumnPos descrColumnVisible
+ \ downloadSizeColumnPos downloadSizeColumnVisible hpanedPos
+ \ instVerColumnPos instVerColumnVisible instSizeColumnPos
+ \ instSizeColumnVisible nameColumnPos nameColumnVisible
+ \ sectionColumnPos sectionColumnVisible statusColumnPos
+ \ statusColumnVisible supportedColumnPos supportedColumnVisible
+ \ vpanedPos windowWidth windowHeight windowX windowY closeZvt
+ \ color-available color-available-locked color-broken color-downgrade
+ \ color-install color-installed-locked color-installed-outdated
+ \ color-installed-updated color-new color-purge color-reinstall
+ \ color-remove color-upgrade
+
+syn keyword aptconfSynapticUpdate contained
+ \ last type
+
+syn cluster aptconfSynaptic_ contains=aptconfSynaptic,
+ \ aptconfSynapticUpdate
+" }}}
+" Unattended Upgrade: {{{
syn keyword aptconfUnattendedUpgrade contained
- \ AutoFixInterruptedDpkg Automatic-Reboot InstallOnShutdown Mail
- \ MailOnlyOnError MinimalSteps Origins-Pattern Package-Blacklist
+ \ AutoFixInterruptedDpkg Automatic-Reboot Automatic-Reboot-Time
+ \ Automatic-Reboot-WithUsers InstallOnShutdown Mail MailOnlyOnError
+ \ MinimalSteps Origins-Pattern Package-Blacklist
\ Remove-Unused-Dependencies
syn cluster aptconfUnattendedUpgrade_ contains=aptconfUnattendedUpgrade
" }}}
+" Whatmaps: {{{
+syn keyword aptconfWhatmaps contained
+ \ Enable-Restart Security-Update-Origins
+
+syn cluster aptconfWhatmaps_ contains=aptconfWhatmaps
+" }}}
syn case match
" Now put all the keywords (and 'valid' options) in a single cluster:
syn cluster aptconfOptions contains=aptconfRegexpOpt,
- \ @aptconfAcquire_,@aptconfApt_,@aptconfAptitude_,@aptconfDebTags_,
- \ @aptconfDebug_,@aptconfDir_,@aptconfDPkg_,@aptconfDSelect_,
- \ @aptconfOrderList_,@aptconfPackageManager_,@aptconfPkgCacheGen_,
- \ @aptconfQuiet_,@aptconfRpm_,@aptconfUnattendedUpgrade_
+ \ @aptconfAcquire_,@aptconfAdequate_,@aptconfApt_,@aptconfAptitude_,
+ \ @aptconfAptListbugs_,@aptconfDebTags_,@aptconfDebug_,@aptconfDir_,
+ \ @aptconfDPkg_,@aptconfDSelect_,@aptconfOrderList_,
+ \ @aptconfPackageManager_,@aptconfPkgCacheGen_,@aptconfQuiet_,
+ \ @aptconfRpm_,@aptconfSynaptic_,@aptconfUnattendedUpgrade_,
+ \ @aptconfWhatmaps_
" Syntax:
syn match aptconfSemiColon ';'
@@ -382,8 +435,11 @@ syn region aptconfInclude matchgroup=aptconfOperator start='::' end='::\|\s'me=
" Basic Syntax Errors: XXX avoid to generate false positives !!!
"
-" * Invalid comment format (seems to not cause errors, but...):
-syn match aptconfAsError display '^#.*'
+" * Undocumented inline comment. Since it is currently largely used, and does
+" not seem to cause trouble ('apt-config dump' never complains when # is used
+" the same way than //) it has been moved to aptconfComment group. But it
+" still needs to be defined here (i.e. before #clear and #include directives)
+syn match aptconfComment '#.*' contains=@aptconfCommentSpecial
"
" * When a semicolon is missing after a double-quoted string:
" There are some cases (for example in the Dir group of options, but not only)
@@ -445,6 +501,8 @@ hi def link aptconfAcquireHTTPS aptconfOption
hi def link aptconfAcquireMaxValidTime aptconfOption
hi def link aptconfAcquirePDiffs aptconfOption
+hi def link aptconfAdequate aptconfOption
+
hi def link aptconfApt aptconfOption
hi def link aptconfAptAuthentication aptconfOption
hi def link aptconfAptAutoRemove aptconfOption
@@ -471,6 +529,8 @@ hi def link aptconfAptitudeUIKeyBindings aptconfOption
hi def link aptconfAptitudeUIStyles aptconfOption
hi def link aptconfAptitudeUIStylesElements aptconfOption
+hi def link aptconfAptListbugs aptconfOption
+
hi def link aptconfDebTags aptconfOption
hi def link aptconfDebug aptconfOption
@@ -504,8 +564,13 @@ hi def link aptconfQuiet aptconfOption
hi def link aptconfRpm aptconfOption
+hi def link aptconfSynaptic aptconfOption
+hi def link aptconfSynapticUpdate aptconfOption
+
hi def link aptconfUnattendedUpgrade aptconfOption
+hi def link aptconfWhatmaps aptconfOption
+
let b:current_syntax = "aptconf"
let &cpo = s:cpo_save
diff --git a/runtime/syntax/rst.vim b/runtime/syntax/rst.vim
index 8b17104be4..b3c89f8352 100644
--- a/runtime/syntax/rst.vim
+++ b/runtime/syntax/rst.vim
@@ -2,7 +2,7 @@
" Language: reStructuredText documentation format
" Maintainer: Marshall Ward <marshall.ward@gmail.com>
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2015-09-07
+" Latest Revision: 2016-01-05
if exists("b:current_syntax")
finish
@@ -13,8 +13,6 @@ set cpo&vim
syn case ignore
-syn match rstSections "^\%(\([=`:.'"~^_*+#-]\)\1\+\n\)\=.\+\n\([=`:.'"~^_*+#-]\)\2\+$"
-
syn match rstTransition /^[=`:.'"~^_*+#-]\{4,}\s*$/
syn cluster rstCruft contains=rstEmphasis,rstStrongEmphasis,
@@ -123,6 +121,8 @@ call s:DefineInlineMarkup('InlineLiteral', '``', "", '``')
call s:DefineInlineMarkup('SubstitutionReference', '|', '|', '|_\{0,2}')
call s:DefineInlineMarkup('InlineInternalTargets', '_`', '`', '`')
+syn match rstSections "^\%(\([=`:.'"~^_*+#-]\)\1\+\n\)\=.\+\n\([=`:.'"~^_*+#-]\)\2\+$"
+
" TODO: Can’t remember why these two can’t be defined like the ones above.
execute 'syn match rstFootnoteReference contains=@NoSpell' .
\ ' +\[\%(\d\+\|#\%(' . s:ReferenceName . '\)\=\|\*\)\]_+'
diff --git a/runtime/syntax/sh.vim b/runtime/syntax/sh.vim
index efe0bcb461..909ead81f1 100644
--- a/runtime/syntax/sh.vim
+++ b/runtime/syntax/sh.vim
@@ -2,8 +2,8 @@
" Language: shell (sh) Korn shell (ksh) bash (sh)
" Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz>
" Previous Maintainer: Lennart Schultz <Lennart.Schultz@ecmwf.int>
-" Last Change: Nov 09, 2015
-" Version: 142
+" Last Change: Dec 11, 2015
+" Version: 143
" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SH
" For options and settings, please use: :help ft-sh-syntax
" This file includes many ideas from Eric Brunet (eric.brunet@ens.fr)
@@ -119,7 +119,7 @@ syn cluster shCaseList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSu
syn cluster shCommandSubList contains=shAlias,shArithmetic,shComment,shCmdParenRegion,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shEcho,shEscape,shExDoubleQuote,shExpr,shExSingleQuote,shNumber,shOperator,shOption,shPosnParm,shSingleQuote,shSpecial,shStatement,shSubSh,shTest,shVariable
syn cluster shCurlyList contains=shNumber,shComma,shDeref,shDerefSimple,shDerefSpecial
syn cluster shDblQuoteList contains=shCommandSub,shDeref,shDerefSimple,shEscape,shPosnParm,shCtrlSeq,shSpecial
-syn cluster shDerefList contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial,shDerefWordError,shDerefPPS
+syn cluster shDerefList contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial,shDerefWordError,shDerefPSR,shDerefPPS
syn cluster shDerefVarList contains=shDerefOp,shDerefVarArray,shDerefOpError
syn cluster shEchoList contains=shArithmetic,shCommandSub,shDeref,shDerefSimple,shEscape,shExpr,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shCtrlSeq,shEchoQuote
syn cluster shExprList1 contains=shCharClass,shNumber,shOperator,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shExpr,shDblBrace,shDeref,shDerefSimple,shCtrlSeq
@@ -493,6 +493,11 @@ if exists("b:is_bash")
syn match shDerefPPS contained '/\{1,2}' nextgroup=shDerefPPSleft
syn region shDerefPPSleft contained start='.' skip=@\%(\\\\\)*\\/@ matchgroup=shDerefOp end='/' end='\ze}' nextgroup=shDerefPPSright contains=@shCommandSubList
syn region shDerefPPSright contained start='.' skip=@\%(\\\\\)\+@ end='\ze}' contains=@shCommandSubList
+
+ " bash : ${parameter/#substring/replacement}
+ syn match shDerefPSR contained '/#' nextgroup=shDerefPSRleft
+ syn region shDerefPSRleft contained start='.' skip=@\%(\\\\\)*\\/@ matchgroup=shDerefOp end='/' end='\ze}' nextgroup=shDerefPSRright
+ syn region shDerefPSRright contained start='.' skip=@\%(\\\\\)\+@ end='\ze}'
endif
" Arithmetic Parenthesized Expressions: {{{1
@@ -563,6 +568,7 @@ hi def link shColon shComment
hi def link shDerefOp shOperator
hi def link shDerefPOL shDerefOp
hi def link shDerefPPS shDerefOp
+hi def link shDerefPSR shDerefOp
hi def link shDeref shShellVariables
hi def link shDerefDelim shOperator
hi def link shDerefSimple shDeref
diff --git a/runtime/syntax/sshconfig.vim b/runtime/syntax/sshconfig.vim
index 479277e17f..ef2ca07976 100644
--- a/runtime/syntax/sshconfig.vim
+++ b/runtime/syntax/sshconfig.vim
@@ -2,9 +2,10 @@
" Language: OpenSSH client configuration file (ssh_config)
" Author: David Necas (Yeti)
" Maintainer: Dominik Fischer <d dot f dot fischer at web dot de>
-" Contributor: Leonard Ehrenfried <leonard.ehrenfried@web.de>
-" Last Change: 2015 Dec 3
-" SSH Version: 7.0
+" Contributor: Leonard Ehrenfried <leonard.ehrenfried@web.de>
+" Contributor: Karsten Hopp <karsten@redhat.com>
+" Last Change: 2016 Jan 15
+" SSH Version: 7.1
"
" Setup
@@ -69,8 +70,8 @@ syn keyword sshconfigSysLogFacility DAEMON USER AUTH AUTHPRIV LOCAL0 LOCAL1
syn keyword sshconfigSysLogFacility LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7
syn keyword sshconfigAddressFamily inet inet6
-syn match sshconfigIPQoS "af1[1234]"
-syn match sshconfigIPQoS "af2[23]"
+syn match sshconfigIPQoS "af1[123]"
+syn match sshconfigIPQoS "af2[123]"
syn match sshconfigIPQoS "af3[123]"
syn match sshconfigIPQoS "af4[123]"
syn match sshconfigIPQoS "cs[0-7]"
@@ -106,6 +107,10 @@ syn keyword sshconfigMatch canonical exec host originalhost user localuser all
syn keyword sshconfigKeyword AddressFamily
syn keyword sshconfigKeyword BatchMode
syn keyword sshconfigKeyword BindAddress
+syn keyword sshconfigKeyword CanonicalDomains
+syn keyword sshconfigKeyword CanonicalizeFallbackLocal
+syn keyword sshconfigKeyword CanonicalizeHostname
+syn keyword sshconfigKeyword CanonicalizeMaxDots
syn keyword sshconfigKeyword ChallengeResponseAuthentication
syn keyword sshconfigKeyword CheckHostIP
syn keyword sshconfigKeyword Cipher
@@ -145,6 +150,8 @@ syn keyword sshconfigKeyword HostbasedKeyTypes
syn keyword sshconfigKeyword IPQoS
syn keyword sshconfigKeyword IdentitiesOnly
syn keyword sshconfigKeyword IdentityFile
+syn keyword sshconfigKeyword IgnoreUnknown
+syn keyword sshconfigKeyword IPQoS
syn keyword sshconfigKeyword KbdInteractiveAuthentication
syn keyword sshconfigKeyword KbdInteractiveDevices
syn keyword sshconfigKeyword KexAlgorithms
@@ -182,6 +189,7 @@ syn keyword sshconfigKeyword UseBlacklistedKeys
syn keyword sshconfigKeyword UsePrivilegedPort
syn keyword sshconfigKeyword User
syn keyword sshconfigKeyword UserKnownHostsFile
+syn keyword sshconfigKeyword UseRoaming
syn keyword sshconfigKeyword VerifyHostKeyDNS
syn keyword sshconfigKeyword VisualHostKey
syn keyword sshconfigKeyword XAuthLocation
diff --git a/runtime/syntax/sshdconfig.vim b/runtime/syntax/sshdconfig.vim
index ac90a80aa5..4203047d2c 100644
--- a/runtime/syntax/sshdconfig.vim
+++ b/runtime/syntax/sshdconfig.vim
@@ -4,9 +4,10 @@
" Maintainer: Dominik Fischer <d dot f dot fischer at web dot de>
" Contributor: Thilo Six
" Contributor: Leonard Ehrenfried <leonard.ehrenfried@web.de>
+" Contributor: Karsten Hopp <karsten@redhat.com>
" Originally: 2009-07-09
-" Last Change: 2015 Dec 3
-" SSH Version: 7.0
+" Last Change: 2016 Jan 12
+" SSH Version: 7.1
"
" Setup
@@ -65,8 +66,8 @@ syn keyword sshdconfigSysLogFacility LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7
syn keyword sshdconfigCompression delayed
-syn match sshdconfigIPQoS "af1[1234]"
-syn match sshdconfigIPQoS "af2[23]"
+syn match sshdconfigIPQoS "af1[123]"
+syn match sshdconfigIPQoS "af2[123]"
syn match sshdconfigIPQoS "af3[123]"
syn match sshdconfigIPQoS "af4[123]"
syn match sshdconfigIPQoS "cs[0-7]"
@@ -109,6 +110,7 @@ syn keyword sshdconfigKeyword AllowGroups
syn keyword sshdconfigKeyword AllowStreamLocalForwarding
syn keyword sshdconfigKeyword AllowTcpForwarding
syn keyword sshdconfigKeyword AllowUsers
+syn keyword sshdconfigKeyword AuthenticationMethods
syn keyword sshdconfigKeyword AuthorizedKeysFile
syn keyword sshdconfigKeyword AuthorizedKeysCommand
syn keyword sshdconfigKeyword AuthorizedKeysCommandUser
@@ -132,6 +134,7 @@ syn keyword sshdconfigKeyword GSSAPIStrictAcceptorCheck
syn keyword sshdconfigKeyword GatewayPorts
syn keyword sshdconfigKeyword HostCertificate
syn keyword sshdconfigKeyword HostKey
+syn keyword sshdconfigKeyword HostKeyAgent
syn keyword sshdconfigKeyword HostKeyAlgorithms
syn keyword sshdconfigKeyword HostbasedAcceptedKeyTypes
syn keyword sshdconfigKeyword HostbasedAuthentication
diff --git a/scripts/gendeclarations.lua b/scripts/gendeclarations.lua
index 4e74e4e301..ff69b18ae4 100755
--- a/scripts/gendeclarations.lua
+++ b/scripts/gendeclarations.lua
@@ -143,7 +143,7 @@ local pattern = concat(
lit(')'),
any_amount(concat( -- optional attributes
spaces,
- lit('FUNC_ATTR_'),
+ lit('FUNC_'),
any_amount(aw),
one_or_no(concat( -- attribute argument
spaces,
diff --git a/scripts/msgpack-gen.lua b/scripts/msgpack-gen.lua
index c726db3920..190af636dc 100644
--- a/scripts/msgpack-gen.lua
+++ b/scripts/msgpack-gen.lua
@@ -35,7 +35,8 @@ c_proto = Ct(
Cg(c_type, 'return_type') * Cg(c_id, 'name') *
fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') *
Cg(Cc(false), 'async') *
- (fill * Cg((P('FUNC_ATTR_ASYNC') * Cc(true)), 'async') ^ -1) *
+ (fill * Cg((P('FUNC_API_ASYNC') * Cc(true)), 'async') ^ -1) *
+ (fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1) *
fill * P(';')
)
grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1)
@@ -62,8 +63,11 @@ for i = 1, #arg - 1 do
local input = io.open(full_path, 'rb')
local tmp = grammar:match(input:read('*all'))
for i = 1, #tmp do
- functions[#functions + 1] = tmp[i]
local fn = tmp[i]
+ if fn.noexport then
+ goto continue
+ end
+ functions[#functions + 1] = tmp[i]
if #fn.parameters ~= 0 and fn.parameters[1][2] == 'channel_id' then
-- this function should receive the channel id
fn.receives_channel_id = true
@@ -77,6 +81,7 @@ for i = 1, #arg - 1 do
-- for specifying errors
fn.parameters[#fn.parameters] = nil
end
+ ::continue::
end
input:close()
end
@@ -217,7 +222,7 @@ for i = 1, #functions do
if fn.receives_channel_id then
-- if the function receives the channel id, pass it as first argument
- if #args > 0 then
+ if #args > 0 or fn.can_fail then
output:write('channel_id, '..call_args)
else
output:write('channel_id')
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index 172643091a..ab6f69f66c 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -55,6 +55,10 @@ foreach(subdir
event
eval
)
+ if(${subdir} MATCHES "tui" AND NOT FEAT_TUI)
+ continue()
+ endif()
+
file(MAKE_DIRECTORY ${GENERATED_DIR}/${subdir})
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/${subdir})
file(GLOB sources ${subdir}/*.c)
diff --git a/src/nvim/msgpack_rpc/remote_ui.c b/src/nvim/api/ui.c
index 6ffcffe2e1..1703d49296 100644
--- a/src/nvim/msgpack_rpc/remote_ui.c
+++ b/src/nvim/api/ui.c
@@ -7,13 +7,12 @@
#include "nvim/ui.h"
#include "nvim/memory.h"
#include "nvim/map.h"
-#include "nvim/msgpack_rpc/remote_ui.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "msgpack_rpc/remote_ui.c.generated.h"
+# include "api/ui.c.generated.h"
#endif
typedef struct {
@@ -24,21 +23,13 @@ typedef struct {
static PMap(uint64_t) *connected_uis = NULL;
void remote_ui_init(void)
+ FUNC_API_NOEXPORT
{
connected_uis = pmap_new(uint64_t)();
- // Add handler for "attach_ui"
- String method = cstr_as_string("ui_attach");
- MsgpackRpcRequestHandler handler = {.fn = remote_ui_attach, .async = false};
- msgpack_rpc_add_method_handler(method, handler);
- method = cstr_as_string("ui_detach");
- handler.fn = remote_ui_detach;
- msgpack_rpc_add_method_handler(method, handler);
- method = cstr_as_string("ui_try_resize");
- handler.fn = remote_ui_try_resize;
- msgpack_rpc_add_method_handler(method, handler);
}
void remote_ui_disconnect(uint64_t channel_id)
+ FUNC_API_NOEXPORT
{
UI *ui = pmap_get(uint64_t)(connected_uis, channel_id);
if (!ui) {
@@ -49,34 +40,30 @@ void remote_ui_disconnect(uint64_t channel_id)
api_free_array(data->buffer);
pmap_del(uint64_t)(connected_uis, channel_id);
xfree(ui->data);
- ui_detach(ui);
+ ui_detach_impl(ui);
xfree(ui);
}
-static Object remote_ui_attach(uint64_t channel_id, uint64_t request_id,
- Array args, Error *error)
+void ui_attach(uint64_t channel_id, Integer width, Integer height,
+ Boolean enable_rgb, Error *err)
{
if (pmap_has(uint64_t)(connected_uis, channel_id)) {
- api_set_error(error, Exception, _("UI already attached for channel"));
- return NIL;
+ api_set_error(err, Exception, _("UI already attached for channel"));
+ return;
}
- if (args.size != 3 || args.items[0].type != kObjectTypeInteger
- || args.items[1].type != kObjectTypeInteger
- || args.items[2].type != kObjectTypeBoolean
- || args.items[0].data.integer <= 0 || args.items[1].data.integer <= 0) {
- api_set_error(error, Validation,
- _("Invalid arguments. Expected: "
- "(uint width > 0, uint height > 0, bool enable_rgb)"));
- return NIL;
+ if (width <= 0 || height <= 0) {
+ api_set_error(err, Validation,
+ _("Expected width > 0 and height > 0"));
+ return;
}
UIData *data = xmalloc(sizeof(UIData));
data->channel_id = channel_id;
data->buffer = (Array)ARRAY_DICT_INIT;
UI *ui = xcalloc(1, sizeof(UI));
- ui->width = (int)args.items[0].data.integer;
- ui->height = (int)args.items[1].data.integer;
- ui->rgb = args.items[2].data.boolean;
+ ui->width = (int)width;
+ ui->height = (int)height;
+ ui->rgb = enable_rgb;
ui->data = data;
ui->resize = remote_ui_resize;
ui->clear = remote_ui_clear;
@@ -102,45 +89,38 @@ static Object remote_ui_attach(uint64_t channel_id, uint64_t request_id,
ui->set_title = remote_ui_set_title;
ui->set_icon = remote_ui_set_icon;
pmap_put(uint64_t)(connected_uis, channel_id, ui);
- ui_attach(ui);
- return NIL;
+ ui_attach_impl(ui);
+ return;
}
-static Object remote_ui_detach(uint64_t channel_id, uint64_t request_id,
- Array args, Error *error)
+void ui_detach(uint64_t channel_id, Error *err)
{
if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
- api_set_error(error, Exception, _("UI is not attached for channel"));
+ api_set_error(err, Exception, _("UI is not attached for channel"));
}
remote_ui_disconnect(channel_id);
-
- return NIL;
}
-static Object remote_ui_try_resize(uint64_t channel_id, uint64_t request_id,
- Array args, Error *error)
+Object ui_try_resize(uint64_t channel_id, Integer width,
+ Integer height, Error *err)
{
if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
- api_set_error(error, Exception, _("UI is not attached for channel"));
+ api_set_error(err, Exception, _("UI is not attached for channel"));
}
- if (args.size != 2 || args.items[0].type != kObjectTypeInteger
- || args.items[1].type != kObjectTypeInteger
- || args.items[0].data.integer <= 0 || args.items[1].data.integer <= 0) {
- api_set_error(error, Validation,
- _("Invalid arguments. Expected: "
- "(uint width > 0, uint height > 0)"));
+ if (width <= 0 || height <= 0) {
+ api_set_error(err, Validation,
+ _("Expected width > 0 and height > 0"));
return NIL;
}
UI *ui = pmap_get(uint64_t)(connected_uis, channel_id);
- ui->width = (int)args.items[0].data.integer;
- ui->height = (int)args.items[1].data.integer;
+ ui->width = (int)width;
+ ui->height = (int)height;
ui_refresh();
return NIL;
}
-
static void push_call(UI *ui, char *name, Array args)
{
Array call = ARRAY_DICT_INIT;
@@ -236,7 +216,7 @@ static void remote_ui_mode_change(UI *ui, int mode)
}
static void remote_ui_set_scroll_region(UI *ui, int top, int bot, int left,
- int right)
+ int right)
{
Array args = ARRAY_DICT_INIT;
ADD(args, INTEGER_OBJ(top));
@@ -297,7 +277,7 @@ static void remote_ui_highlight_set(UI *ui, HlAttrs attrs)
static void remote_ui_put(UI *ui, uint8_t *data, size_t size)
{
Array args = ARRAY_DICT_INIT;
- String str = {.data = xmemdupz(data, size), .size = size};
+ String str = { .data = xmemdupz(data, size), .size = size };
ADD(args, STRING_OBJ(str));
push_call(ui, "put", args);
}
diff --git a/src/nvim/api/ui.h b/src/nvim/api/ui.h
new file mode 100644
index 0000000000..b3af14f8a8
--- /dev/null
+++ b/src/nvim/api/ui.h
@@ -0,0 +1,11 @@
+#ifndef NVIM_API_UI_H
+#define NVIM_API_UI_H
+
+#include <stdint.h>
+
+#include "nvim/api/private/defs.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "api/ui.h.generated.h"
+#endif
+#endif // NVIM_API_UI_H
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 46ac3c9022..46d72b847d 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -98,7 +98,7 @@ void vim_feedkeys(String keys, String mode, Boolean escape_csi)
/// @return The number of bytes actually written, which can be lower than
/// requested if the buffer becomes full.
Integer vim_input(String keys)
- FUNC_ATTR_ASYNC
+ FUNC_API_ASYNC
{
return (Integer)input_enqueue(keys);
}
@@ -618,7 +618,7 @@ Dictionary vim_get_color_map(void)
Array vim_get_api_info(uint64_t channel_id)
- FUNC_ATTR_ASYNC
+ FUNC_API_ASYNC
{
Array rv = ARRAY_DICT_INIT;
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 96c008b0e0..420a712e3e 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -79,6 +79,7 @@
#include "nvim/event/pty_process.h"
#include "nvim/event/rstream.h"
#include "nvim/event/wstream.h"
+#include "nvim/event/time.h"
#include "nvim/os/time.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/msgpack_rpc/server.h"
@@ -428,6 +429,14 @@ typedef struct {
int status;
} JobEvent;
+typedef struct {
+ TimeWatcher tw;
+ int timer_id;
+ int repeat_count;
+ bool stopped;
+ ufunc_T *callback;
+} timer_T;
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval.c.generated.h"
#endif
@@ -438,6 +447,9 @@ typedef struct {
static uint64_t current_job_id = 1;
static PMap(uint64_t) *jobs = NULL;
+static uint64_t last_timer_id = 0;
+static PMap(uint64_t) *timers = NULL;
+
static const char *const msgpack_type_names[] = {
[kMPNil] = "nil",
[kMPBoolean] = "boolean",
@@ -469,6 +481,7 @@ void eval_init(void)
vimvars[VV_VERSION].vv_nr = VIM_VERSION_100;
jobs = pmap_new(uint64_t)();
+ timers = pmap_new(uint64_t)();
struct vimvar *p;
init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE);
@@ -6667,6 +6680,7 @@ static struct fst {
{ "asin", 1, 1, f_asin }, // WJMc
{ "assert_equal", 2, 3, f_assert_equal },
{ "assert_exception", 1, 2, f_assert_exception },
+ { "assert_fails", 1, 2, f_assert_fails },
{ "assert_false", 1, 2, f_assert_false },
{ "assert_true", 1, 2, f_assert_true },
{ "atan", 1, 1, f_atan },
@@ -6930,6 +6944,8 @@ static struct fst {
{ "tempname", 0, 0, f_tempname },
{ "termopen", 1, 2, f_termopen },
{ "test", 1, 1, f_test },
+ { "timer_start", 2, 3, f_timer_start },
+ { "timer_stop", 1, 1, f_timer_stop },
{ "tolower", 1, 1, f_tolower },
{ "toupper", 1, 1, f_toupper },
{ "tr", 3, 3, f_tr },
@@ -7652,6 +7668,43 @@ static void f_assert_exception(typval_T *argvars, typval_T *rettv)
}
}
+/// "assert_fails(cmd [, error])" function
+static void f_assert_fails(typval_T *argvars, typval_T *rettv)
+{
+ char_u *cmd = get_tv_string_chk(&argvars[0]);
+ garray_T ga;
+
+ called_emsg = false;
+ suppress_errthrow = true;
+ emsg_silent = true;
+ do_cmdline_cmd((char *)cmd);
+ if (!called_emsg) {
+ prepare_assert_error(&ga);
+ ga_concat(&ga, (char_u *)"command did not fail: ");
+ ga_concat(&ga, cmd);
+ assert_error(&ga);
+ ga_clear(&ga);
+ } else if (argvars[1].v_type != VAR_UNKNOWN) {
+ char_u buf[NUMBUFLEN];
+ char *error = (char *)get_tv_string_buf_chk(&argvars[1], buf);
+
+ if (error == NULL
+ || strstr((char *)vimvars[VV_ERRMSG].vv_str, error) == NULL) {
+ prepare_assert_error(&ga);
+ fill_assert_error(&ga, &argvars[2], NULL, &argvars[1],
+ &vimvars[VV_ERRMSG].vv_tv);
+ assert_error(&ga);
+ ga_clear(&ga);
+ }
+ }
+
+ called_emsg = false;
+ suppress_errthrow = false;
+ emsg_silent = false;
+ emsg_on_display = false;
+ set_vim_var_string(VV_ERRMSG, NULL, 0);
+}
+
// Common for assert_true() and assert_false().
static void assert_bool(typval_T *argvars, bool is_true)
{
@@ -10688,6 +10741,7 @@ static void f_has(typval_T *argvars, typval_T *rettv)
"termguicolors",
"termresponse",
"textobjects",
+ "timers",
"title",
"user-commands", /* was accidentally included in 5.4 */
"user_commands",
@@ -16441,6 +16495,119 @@ static void f_tanh(typval_T *argvars, typval_T *rettv)
float_op_wrapper(argvars, rettv, &tanh);
}
+
+/// "timer_start(timeout, callback, opts)" function
+static void f_timer_start(typval_T *argvars, typval_T *rettv)
+{
+ long timeout = get_tv_number(&argvars[0]);
+ timer_T *timer;
+ int repeat = 1;
+ dict_T *dict;
+
+ rettv->vval.v_number = -1;
+
+ if (argvars[2].v_type != VAR_UNKNOWN) {
+ if (argvars[2].v_type != VAR_DICT
+ || (dict = argvars[2].vval.v_dict) == NULL) {
+ EMSG2(_(e_invarg2), get_tv_string(&argvars[2]));
+ return;
+ }
+ if (dict_find(dict, (char_u *)"repeat", -1) != NULL) {
+ repeat = get_dict_number(dict, (char_u *)"repeat");
+ }
+ }
+
+ if (argvars[1].v_type != VAR_FUNC && argvars[1].v_type != VAR_STRING) {
+ EMSG2(e_invarg2, "funcref");
+ return;
+ }
+ ufunc_T *func = find_ufunc(argvars[1].vval.v_string);
+ if (!func) {
+ // Invalid function name. Error already reported by `find_ufunc`.
+ return;
+ }
+ func->uf_refcount++;
+
+ timer = xmalloc(sizeof *timer);
+ timer->stopped = false;
+ timer->repeat_count = repeat;
+ timer->timer_id = last_timer_id++;
+ timer->callback = func;
+
+ time_watcher_init(&loop, &timer->tw, timer);
+ timer->tw.events = queue_new_child(loop.events);
+ // if main loop is blocked, don't queue up multiple events
+ timer->tw.blockable = true;
+ time_watcher_start(&timer->tw, timer_due_cb, timeout,
+ timeout * (repeat != 1));
+
+ pmap_put(uint64_t)(timers, timer->timer_id, timer);
+ rettv->vval.v_number = timer->timer_id;
+}
+
+
+// "timer_stop(timerid)" function
+static void f_timer_stop(typval_T *argvars, typval_T *rettv)
+{
+ if (argvars[0].v_type != VAR_NUMBER) {
+ EMSG(_(e_number_exp));
+ return;
+ }
+
+ timer_T *timer = pmap_get(uint64_t)(timers, get_tv_number(&argvars[0]));
+
+ if (timer == NULL) {
+ return;
+ }
+
+ timer_stop(timer);
+}
+
+// invoked on the main loop
+static void timer_due_cb(TimeWatcher *tw, void *data)
+{
+ timer_T *timer = (timer_T *)data;
+ if (timer->stopped) {
+ return;
+ }
+ // if repeat was negative repeat forever
+ if (timer->repeat_count >= 0 && --timer->repeat_count == 0) {
+ timer_stop(timer);
+ }
+
+ typval_T argv[1];
+ init_tv(argv);
+ argv[0].v_type = VAR_NUMBER;
+ argv[0].vval.v_number = timer->timer_id;
+ typval_T rettv;
+
+ init_tv(&rettv);
+ call_user_func(timer->callback, ARRAY_SIZE(argv), argv, &rettv,
+ curwin->w_cursor.lnum, curwin->w_cursor.lnum, NULL);
+ clear_tv(&rettv);
+}
+
+static void timer_stop(timer_T *timer)
+{
+ if (timer->stopped) {
+ // avoid double free
+ return;
+ }
+ timer->stopped = true;
+ time_watcher_stop(&timer->tw);
+ time_watcher_close(&timer->tw, timer_free_cb);
+}
+
+// invoked on next event loop tick, so queue is empty
+static void timer_free_cb(TimeWatcher *tw, void *data)
+{
+ timer_T *timer = (timer_T *)data;
+ queue_free(timer->tw.events);
+ user_func_unref(timer->callback);
+ pmap_del(uint64_t)(timers, timer->timer_id);
+ xfree(timer);
+}
+
/*
* "tolower(string)" function
*/
@@ -21851,6 +22018,7 @@ static void script_host_eval(char *name, typval_T *argvars, typval_T *rettv)
if (argvars[0].v_type != VAR_STRING) {
EMSG(_(e_invarg));
+ return;
}
list_T *args = list_alloc();
diff --git a/src/nvim/event/time.c b/src/nvim/event/time.c
index 7bf333bcea..f68a66345f 100644
--- a/src/nvim/event/time.c
+++ b/src/nvim/event/time.c
@@ -17,6 +17,7 @@ void time_watcher_init(Loop *loop, TimeWatcher *watcher, void *data)
watcher->uv.data = watcher;
watcher->data = data;
watcher->events = loop->fast_events;
+ watcher->blockable = false;
}
void time_watcher_start(TimeWatcher *watcher, time_cb cb, uint64_t timeout,
@@ -50,6 +51,10 @@ static void time_watcher_cb(uv_timer_t *handle)
FUNC_ATTR_NONNULL_ALL
{
TimeWatcher *watcher = handle->data;
+ if (watcher->blockable && !queue_empty(watcher->events)) {
+ // the timer blocked and there already is an unprocessed event waiting
+ return;
+ }
CREATE_EVENT(watcher->events, time_event, 1, watcher);
}
diff --git a/src/nvim/event/time.h b/src/nvim/event/time.h
index 7882b2b627..14df176ea3 100644
--- a/src/nvim/event/time.h
+++ b/src/nvim/event/time.h
@@ -13,6 +13,7 @@ struct time_watcher {
void *data;
time_cb cb, close_cb;
Queue *events;
+ bool blockable;
};
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 870284a0f7..59962c153b 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -6989,10 +6989,10 @@ static void ex_sleep(exarg_T *eap)
*/
void do_sleep(long msec)
{
- long done;
ui_flush(); // flush before waiting
- for (done = 0; !got_int && done < msec; done += 1000L) {
- os_delay(msec - done > 1000L ? 1000L : msec - done, true);
+ for (long left = msec; !got_int && left > 0; left -= 1000L) {
+ int next = left > 1000l ? 1000 : (int)left;
+ LOOP_PROCESS_EVENTS_UNTIL(&loop, loop.events, (int)next, got_int);
os_breakcheck();
}
}
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index a4e5a4dcd7..db21fddedb 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -359,6 +359,7 @@ static int command_line_execute(VimState *state, int key)
if (s->c == K_EVENT) {
queue_process_events(loop.events);
+ redrawcmdline();
return 1;
}
diff --git a/src/nvim/func_attr.h b/src/nvim/func_attr.h
index c31d21ec6d..af8558d40d 100644
--- a/src/nvim/func_attr.h
+++ b/src/nvim/func_attr.h
@@ -179,7 +179,8 @@
#endif
#ifdef DEFINE_FUNC_ATTRIBUTES
- #define FUNC_ATTR_ASYNC
+ #define FUNC_API_ASYNC
+ #define FUNC_API_NOEXPORT
#define FUNC_ATTR_MALLOC REAL_FATTR_MALLOC
#define FUNC_ATTR_ALLOC_SIZE(x) REAL_FATTR_ALLOC_SIZE(x)
#define FUNC_ATTR_ALLOC_SIZE_PROD(x,y) REAL_FATTR_ALLOC_SIZE_PROD(x,y)
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 47f246fc76..521db85cf0 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -785,11 +785,13 @@ void wait_return(int redraw)
State = HITRETURN;
setmouse();
- /* Avoid the sequence that the user types ":" at the hit-return prompt
- * to start an Ex command, but the file-changed dialog gets in the
- * way. */
- if (need_check_timestamps)
- check_timestamps(FALSE);
+ cmdline_row = msg_row;
+ // Avoid the sequence that the user types ":" at the hit-return prompt
+ // to start an Ex command, but the file-changed dialog gets in the
+ // way.
+ if (need_check_timestamps) {
+ check_timestamps(false);
+ }
hit_return_msg();
@@ -1970,6 +1972,7 @@ static void msg_puts_printf(char *str, int maxlen)
*/
static int do_more_prompt(int typed_char)
{
+ static bool entered = false;
int used_typed_char = typed_char;
int oldState = State;
int c;
@@ -1979,6 +1982,13 @@ static int do_more_prompt(int typed_char)
msgchunk_T *mp;
int i;
+ // We get called recursively when a timer callback outputs a message. In
+ // that case don't show another prompt. Also when at the hit-Enter prompt.
+ if (entered || State == HITRETURN) {
+ return false;
+ }
+ entered = true;
+
if (typed_char == 'G') {
/* "g<": Find first line on the last page. */
mp_last = msg_sb_start(last_msgchunk);
@@ -2153,9 +2163,11 @@ static int do_more_prompt(int typed_char)
if (quit_more) {
msg_row = Rows - 1;
msg_col = 0;
- } else if (cmdmsg_rl)
+ } else if (cmdmsg_rl) {
msg_col = Columns - 1;
+ }
+ entered = false;
return retval;
}
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 34ff7c6374..3a6d7c1434 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -7,8 +7,8 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/vim.h"
+#include "nvim/api/ui.h"
#include "nvim/msgpack_rpc/channel.h"
-#include "nvim/msgpack_rpc/remote_ui.h"
#include "nvim/event/loop.h"
#include "nvim/event/libuv_process.h"
#include "nvim/event/rstream.h"
diff --git a/src/nvim/msgpack_rpc/remote_ui.h b/src/nvim/msgpack_rpc/remote_ui.h
deleted file mode 100644
index 8af86dc1b8..0000000000
--- a/src/nvim/msgpack_rpc/remote_ui.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef NVIM_MSGPACK_RPC_REMOTE_UI_H
-#define NVIM_MSGPACK_RPC_REMOTE_UI_H
-
-#include "nvim/ui.h"
-
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "msgpack_rpc/remote_ui.h.generated.h"
-#endif
-#endif // NVIM_MSGPACK_RPC_REMOTE_UI_H
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 0acaa9ae2b..84906a3548 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -45,6 +45,9 @@
// Use SPELL_PRINTTREE for debugging: dump the word tree after adding a word.
// Only use it for small word lists!
+// Use SPELL_COMPRESS_ALLWAYS for debugging: compress the word tree after
+// adding a word. Only use it for small word lists!
+
// Use DEBUG_TRIEWALK to print the changes made in suggest_trie_walk() for a
// specific word.
@@ -156,6 +159,8 @@
//
// sectionID == SN_NOSPLITSUGS: nothing
//
+// sectionID == SN_NOCOMPOUNDSUGS: nothing
+//
// sectionID == SN_WORDS: <word> ...
// <word> N bytes NUL terminated common word
//
@@ -482,7 +487,7 @@ struct slang_S {
regprog_T **sl_prefprog; // table with regprogs for prefixes
garray_T sl_rep; // list of fromto_T entries from REP lines
- short sl_rep_first[256]; // indexes where byte first appears, -1 if
+ int16_t sl_rep_first[256]; // indexes where byte first appears, -1 if
// there is none
garray_T sl_sal; // list of salitem_T entries from SAL lines
salfirst_T sl_sal_first[256]; // indexes where byte first appears, -1 if
@@ -494,8 +499,9 @@ struct slang_S {
// "sl_sal_first" maps chars, when has_mbyte
// "sl_sal" is a list of wide char lists.
garray_T sl_repsal; // list of fromto_T entries from REPSAL lines
- short sl_repsal_first[256]; // sl_rep_first for REPSAL lines
- bool sl_nosplitsugs; // don't suggest splitting a word
+ int16_t sl_repsal_first[256]; // sl_rep_first for REPSAL lines
+ bool sl_nosplitsugs; // don't suggest splitting a word
+ bool sl_nocompoundsugs; // don't suggest compounding
// Info from the .sug file. Loaded on demand.
time_t sl_sugtime; // timestamp for .sug file
@@ -558,6 +564,7 @@ typedef struct langp_S {
#define SN_WORDS 13 // common words
#define SN_NOSPLITSUGS 14 // don't split word for suggestions
#define SN_INFO 15 // info section
+#define SN_NOCOMPOUNDSUGS 16 // don't compound for suggestions
#define SN_END 255 // end of sections
#define SNF_REQUIRED 1 // <sectionflags>: required section
@@ -948,6 +955,7 @@ typedef struct spellinfo_S {
char_u *si_sofoto; // SOFOTO text
int si_nosugfile; // NOSUGFILE item found
int si_nosplitsugs; // NOSPLITSUGS item found
+ int si_nocompoundsugs; // NOCOMPOUNDSUGS item found
int si_followup; // soundsalike: ?
int si_collapse; // soundsalike: ?
hashtab_T si_commonwords; // hashtable for common words
@@ -2666,7 +2674,11 @@ spell_load_file (
break;
case SN_NOSPLITSUGS:
- lp->sl_nosplitsugs = true; // <timestamp>
+ lp->sl_nosplitsugs = true;
+ break;
+
+ case SN_NOCOMPOUNDSUGS:
+ lp->sl_nocompoundsugs = true;
break;
case SN_COMPOUND:
@@ -2868,7 +2880,7 @@ static int read_prefcond_section(FILE *fd, slang_T *lp)
// Read REP or REPSAL items section from "fd": <repcount> <rep> ...
// Return SP_*ERROR flags.
-static int read_rep_section(FILE *fd, garray_T *gap, short *first)
+static int read_rep_section(FILE *fd, garray_T *gap, int16_t *first)
{
int cnt;
fromto_T *ftp;
@@ -4266,9 +4278,9 @@ static void spell_print_node(wordnode_T *node, int depth)
PRINTSOME(line1, depth, "(%d)", node->wn_nr, 0);
PRINTSOME(line2, depth, " ", 0, 0);
PRINTSOME(line3, depth, " ", 0, 0);
- msg(line1);
- msg(line2);
- msg(line3);
+ msg((char_u *)line1);
+ msg((char_u *)line2);
+ msg((char_u *)line3);
} else {
node->wn_u1.index = TRUE;
@@ -4289,9 +4301,9 @@ static void spell_print_node(wordnode_T *node, int depth)
PRINTSOME(line3, depth, " ", 0, 0);
if (node->wn_byte == NUL) {
- msg(line1);
- msg(line2);
- msg(line3);
+ msg((char_u *)line1);
+ msg((char_u *)line2);
+ msg((char_u *)line3);
}
// do the children
@@ -4633,6 +4645,8 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
spin->si_nobreak = true;
} else if (is_aff_rule(items, itemcnt, "NOSPLITSUGS", 1)) {
spin->si_nosplitsugs = true;
+ } else if (is_aff_rule(items, itemcnt, "NOCOMPOUNDSUGS", 1)) {
+ spin->si_nocompoundsugs = true;
} else if (is_aff_rule(items, itemcnt, "NOSUGFILE", 1)) {
spin->si_nosugfile = true;
} else if (is_aff_rule(items, itemcnt, "PFXPOSTPONE", 1)) {
@@ -6289,7 +6303,7 @@ static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int
node = *prev;
}
#ifdef SPELL_PRINTTREE
- smsg("Added \"%s\"", word);
+ smsg((char_u *)"Added \"%s\"", word);
spell_print_tree(root->wn_sibling);
#endif
@@ -6312,8 +6326,8 @@ static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int
// 3. When compressed before, added "compress_added" words
// (si_compress_cnt == 1) and the number of free nodes drops below the
// maximum word length.
-#ifndef SPELL_PRINTTREE
- if (spin->si_compress_cnt == 1
+#ifndef SPELL_COMPRESS_ALLWAYS
+ if (spin->si_compress_cnt == 1 // NOLINT(readability/braces)
? spin->si_free_count < MAXWLEN
: spin->si_blocks_cnt >= compress_start)
#endif
@@ -6857,6 +6871,15 @@ static int write_vim_spell(spellinfo_T *spin, char_u *fname)
put_bytes(fd, 0, 4); // <sectionlen>
}
+ // SN_NOCOMPUNDSUGS: nothing
+ // This is used to notify that no suggestions with compounds are to be
+ // made.
+ if (spin->si_nocompoundsugs) {
+ putc(SN_NOCOMPOUNDSUGS, fd); // <sectionID>
+ putc(0, fd); // <sectionflags>
+ put_bytes(fd, 0, 4); // <sectionlen>
+ }
+
// SN_COMPOUND: compound info.
// We don't mark it required, when not supported all compound words will
// be bad words.
@@ -9771,6 +9794,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// be possible to compound another (short) word.
try_compound = false;
if (!soundfold
+ && !slang->sl_nocompoundsugs
&& slang->sl_compprog != NULL
&& ((unsigned)flags >> 24) != 0
&& sp->ts_twordlen - sp->ts_splitoff
@@ -9791,21 +9815,21 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// For NOBREAK we never try splitting, it won't make any word
// valid.
- if (slang->sl_nobreak)
+ if (slang->sl_nobreak && !slang->sl_nocompoundsugs) {
try_compound = true;
-
- // If we could add a compound word, and it's also possible to
- // split at this point, do the split first and set
- // TSF_DIDSPLIT to avoid doing it again.
- else if (!fword_ends
- && try_compound
- && (sp->ts_flags & TSF_DIDSPLIT) == 0) {
+ } else if (!fword_ends
+ && try_compound
+ && (sp->ts_flags & TSF_DIDSPLIT) == 0) {
+ // If we could add a compound word, and it's also possible to
+ // split at this point, do the split first and set
+ // TSF_DIDSPLIT to avoid doing it again.
try_compound = false;
sp->ts_flags |= TSF_DIDSPLIT;
--sp->ts_curi; // do the same NUL again
compflags[sp->ts_complen] = NUL;
- } else
+ } else {
sp->ts_flags &= ~TSF_DIDSPLIT;
+ }
if (try_split || try_compound) {
if (!try_compound && (!fword_ends || !goodword_ends)) {
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index 18ecabeade..867cab9fbf 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -39,6 +39,7 @@ NEW_TESTS = \
test_cursor_func.res \
test_help_tagjump.res \
test_menu.res \
+ test_timers.res \
test_viml.res \
test_alot.res
diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim
index 5b34b4fc31..2712fb9371 100644
--- a/src/nvim/testdir/runtest.vim
+++ b/src/nvim/testdir/runtest.vim
@@ -65,7 +65,8 @@ function /^Test_
redir END
let tests = split(substitute(@q, 'function \(\k*()\)', '\1', 'g'))
-for test in tests
+" Execute the tests in alphabetical order.
+for test in sort(tests)
if exists("*SetUp")
call SetUp()
endif
diff --git a/src/nvim/testdir/test_timers.vim b/src/nvim/testdir/test_timers.vim
new file mode 100644
index 0000000000..9f58a35909
--- /dev/null
+++ b/src/nvim/testdir/test_timers.vim
@@ -0,0 +1,32 @@
+" Test for timers
+
+if !has('timers')
+ finish
+endif
+
+func MyHandler(timer)
+ let s:val += 1
+endfunc
+
+func Test_oneshot()
+ let s:val = 0
+ let timer = timer_start(50, 'MyHandler')
+ sleep 200m
+ call assert_equal(1, s:val)
+endfunc
+
+func Test_repeat_three()
+ let s:val = 0
+ let timer = timer_start(50, 'MyHandler', {'repeat': 3})
+ sleep 500m
+ call assert_equal(3, s:val)
+endfunc
+
+func Test_repeat_many()
+ let s: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)
+endfunc
diff --git a/src/nvim/testdir/test_viml.vim b/src/nvim/testdir/test_viml.vim
index 9f0618bd45..2d989cdad9 100644
--- a/src/nvim/testdir/test_viml.vim
+++ b/src/nvim/testdir/test_viml.vim
@@ -922,6 +922,45 @@ func Test_curlies()
call assert_equal(77, g:a['t'])
endfunc
+"-------------------------------------------------------------------------------
+" Test 91: using type(). {{{1
+"-------------------------------------------------------------------------------
+
+func Test_type()
+ call assert_equal(0, type(0))
+ call assert_equal(1, type(""))
+ call assert_equal(2, type(function("tr")))
+ call assert_equal(3, type([]))
+ call assert_equal(4, type({}))
+ call assert_equal(5, type(0.0))
+ call assert_equal(6, type(v:false))
+ call assert_equal(6, type(v:true))
+ call assert_equal(7, type(v:null))
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 92: skipping code {{{1
+"-------------------------------------------------------------------------------
+
+func Test_skip()
+ let Fn = function('Test_type')
+ call assert_false(0 && Fn[1])
+ call assert_false(0 && string(Fn))
+ call assert_false(0 && len(Fn))
+ let l = []
+ call assert_false(0 && l[1])
+ call assert_false(0 && string(l))
+ call assert_false(0 && len(l))
+ let f = 1.0
+ call assert_false(0 && f[1])
+ call assert_false(0 && string(f))
+ call assert_false(0 && len(f))
+ let sp = v:null
+ call assert_false(0 && sp[1])
+ call assert_false(0 && string(sp))
+ call assert_false(0 && len(sp))
+
+endfunc
"-------------------------------------------------------------------------------
" Modelines {{{1
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 05322a6f64..ae38754c1e 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -30,7 +30,11 @@
#include "nvim/screen.h"
#include "nvim/syntax.h"
#include "nvim/window.h"
-#include "nvim/tui/tui.h"
+#ifdef FEAT_TUI
+# include "nvim/tui/tui.h"
+#else
+# include "nvim/msgpack_rpc/server.h"
+#endif
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ui.c.generated.h"
@@ -83,7 +87,22 @@ static int height, width;
void ui_builtin_start(void)
{
+#ifdef FEAT_TUI
tui_start();
+#else
+ fprintf(stderr, "Neovim was built without a Terminal UI," \
+ "press Ctrl+C to exit\n");
+
+ size_t len;
+ char **addrs = server_address_list(&len);
+ if (addrs != NULL) {
+ fprintf(stderr, "currently listening on the following address(es)\n");
+ for (size_t i = 0; i < len; i++) {
+ fprintf(stderr, "\t%s\n", addrs[i]);
+ }
+ xfree(addrs);
+ }
+#endif
}
void ui_builtin_stop(void)
@@ -188,7 +207,7 @@ void ui_mouse_off(void)
UI_CALL(mouse_off);
}
-void ui_attach(UI *ui)
+void ui_attach_impl(UI *ui)
{
if (ui_count == MAX_UI_COUNT) {
abort();
@@ -198,7 +217,7 @@ void ui_attach(UI *ui)
ui_refresh();
}
-void ui_detach(UI *ui)
+void ui_detach_impl(UI *ui)
{
size_t shift_index = MAX_UI_COUNT;
diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c
index fd9d4671e3..d17fa4a782 100644
--- a/src/nvim/ui_bridge.c
+++ b/src/nvim/ui_bridge.c
@@ -71,7 +71,7 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler)
}
uv_mutex_unlock(&rv->mutex);
- ui_attach(&rv->bridge);
+ ui_attach_impl(&rv->bridge);
return &rv->bridge;
}
@@ -105,7 +105,7 @@ static void ui_bridge_stop(UI *b)
uv_thread_join(&bridge->ui_thread);
uv_mutex_destroy(&bridge->mutex);
uv_cond_destroy(&bridge->cond);
- ui_detach(b);
+ ui_detach_impl(b);
xfree(b);
}
static void ui_bridge_stop_event(void **argv)
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 23bfca6221..c491021328 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -64,12 +64,19 @@ static char *features[] = {
#else
"-jemalloc",
#endif
+
+#ifdef FEAT_TUI
+ "+tui",
+#else
+ "-tui",
+#endif
NULL
};
// clang-format off
static int included_patches[] = {
1832,
+ 1831,
1809,
1808,
1806,
@@ -82,6 +89,7 @@ static int included_patches[] = {
1652,
1643,
1641,
+ // 1624 NA
// 1600 NA
// 1599 NA
@@ -106,7 +114,7 @@ static int included_patches[] = {
// 1581,
// 1580,
// 1579,
- // 1578,
+ 1578,
// 1577,
1576,
// 1575 NA
@@ -117,7 +125,7 @@ static int included_patches[] = {
1570,
1569,
1568,
- // 1567,
+ 1567,
// 1566 NA
// 1565,
// 1564,
@@ -403,7 +411,7 @@ static int included_patches[] = {
1284,
// 1283 NA
1282,
- // 1281,
+ 1281,
// 1280 NA
// 1279 NA
// 1278 NA
@@ -588,7 +596,7 @@ static int included_patches[] = {
// 1099 NA
// 1098 NA
// 1097,
- // 1096,
+ 1096,
// 1095 NA
// 1094,
1093,
@@ -613,14 +621,14 @@ static int included_patches[] = {
// 1074 NA,
// 1073,
1072,
- // 1071,
+ 1071,
// 1070 NA
// 1069 NA
// 1068,
// 1067 NA
// 1066 NA
1065,
- // 1064,
+ 1064,
// 1063 NA
// 1062 NA
1061,
@@ -631,7 +639,7 @@ static int included_patches[] = {
// 1056,
1055,
1054,
- // 1053,
+ 1053,
1052,
// 1051,
1050,
diff --git a/test/functional/eval/timer_spec.lua b/test/functional/eval/timer_spec.lua
new file mode 100644
index 0000000000..611113f560
--- /dev/null
+++ b/test/functional/eval/timer_spec.lua
@@ -0,0 +1,129 @@
+local helpers = require('test.functional.helpers')
+local Screen = require('test.functional.ui.screen')
+local ok, feed, eq, eval = helpers.ok, helpers.feed, helpers.eq, helpers.eval
+local source, nvim_async, run = helpers.source, helpers.nvim_async, helpers.run
+local clear, execute, funcs = helpers.clear, helpers.execute, helpers.funcs
+
+describe('timers', function()
+ before_each(function()
+ clear()
+ source([[
+ let g:val = 0
+ func MyHandler(timer)
+ let g:val += 1
+ endfunc
+ ]])
+ end)
+
+ it('works one-shot', function()
+ execute("call timer_start(50, 'MyHandler')")
+ eq(0,eval("g:val"))
+ run(nil, nil, nil, 200)
+ eq(1,eval("g:val"))
+ end)
+
+ it('works with repeat two', function()
+ execute("call timer_start(50, 'MyHandler', {'repeat': 2})")
+ eq(0,eval("g:val"))
+ run(nil, nil, nil, 300)
+ eq(2,eval("g:val"))
+ end)
+
+ it('are triggered during sleep', function()
+ execute("call timer_start(50, 'MyHandler', {'repeat': 2})")
+ nvim_async("command", "sleep 10")
+ eq(0,eval("g:val"))
+ run(nil, nil, nil, 300)
+ eq(2,eval("g:val"))
+ end)
+
+ it('can be started during sleep', function()
+ nvim_async("command", "sleep 10")
+ -- this also tests that remote requests works during sleep
+ eval("timer_start(50, 'MyHandler', {'repeat': 2})")
+ eq(0,eval("g:val"))
+ run(nil, nil, nil, 300)
+ eq(2,eval("g:val"))
+ end)
+
+ it('are paused when event processing is disabled', function()
+ -- this is not the intended behavior, but at least there will
+ -- not be a burst of queued up callbacks
+ execute("call timer_start(50, 'MyHandler', {'repeat': 2})")
+ run(nil, nil, nil, 100)
+ local count = eval("g:val")
+ nvim_async("command", "let g:c = getchar()")
+ run(nil, nil, nil, 300)
+ feed("c")
+ local diff = eval("g:val") - count
+ ok(0 <= diff and diff <= 2)
+ eq(99, eval("g:c"))
+ end)
+
+ it('can be stopped', function()
+ local t = eval("timer_start(50, 'MyHandler', {'repeat': -1})")
+ eq(0,eval("g:val"))
+ run(nil, nil, nil, 300)
+ funcs.timer_stop(t)
+ local count = eval("g:val")
+ run(nil, nil, nil, 300)
+ local count2 = eval("g:val")
+ ok(4 <= count and count <= 7)
+ -- when count is eval:ed after timer_stop this should be non-racy
+ eq(count, count2)
+ end)
+
+ it('can be stopped from the handler', function()
+ source([[
+ func! MyHandler(timer)
+ let g:val += 1
+ if g:val == 3
+ call timer_stop(a:timer)
+ " check double stop is ignored
+ call timer_stop(a:timer)
+ endif
+ endfunc
+ ]])
+ execute("call timer_start(50, 'MyHandler', {'repeat': -1})")
+ eq(0,eval("g:val"))
+ run(nil, nil, nil, 300)
+ eq(3,eval("g:val"))
+ end)
+
+ it('can have two timers', function()
+ source([[
+ let g:val2 = 0
+ func! MyHandler2(timer)
+ let g:val2 += 1
+ endfunc
+ ]])
+ execute("call timer_start(50, 'MyHandler', {'repeat': 3})")
+ execute("call timer_start(100, 'MyHandler2', {'repeat': 2})")
+ run(nil, nil, nil, 300)
+ eq(3,eval("g:val"))
+ eq(2,eval("g:val2"))
+ end)
+
+ it("doesn't mess up the cmdline", function()
+ local screen = Screen.new(40, 6)
+ screen:attach()
+ screen:set_default_attr_ignore({{bold=true, foreground=Screen.colors.Blue}})
+ source([[
+ func! MyHandler(timer)
+ echo "evil"
+ endfunc
+ ]])
+ execute("call timer_start(100, 'MyHandler', {'repeat': 1})")
+ feed(":good")
+ screen:sleep(200)
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ :good^ |
+ ]])
+ end)
+
+end)
diff --git a/test/functional/legacy/061_undo_tree_spec.lua b/test/functional/legacy/061_undo_tree_spec.lua
index 6db37bf1ff..350a77b2c5 100644
--- a/test/functional/legacy/061_undo_tree_spec.lua
+++ b/test/functional/legacy/061_undo_tree_spec.lua
@@ -1,10 +1,9 @@
-- Tests for undo tree and :earlier and :later.
local helpers = require('test.functional.helpers')
-local feed, source, eq, eval, clear, execute, expect, wait, write_file =
- helpers.feed, helpers.source, helpers.eq, helpers.eval,
- helpers.clear, helpers.execute, helpers.expect, helpers.wait,
- helpers.write_file
+local expect, feed, source = helpers.expect, helpers.feed, helpers.source
+local eval, clear, execute = helpers.eval, helpers.clear, helpers.execute
+local write_file, command, eq = helpers.write_file, helpers.command, helpers.eq
local function expect_empty_buffer()
-- The space will be removed by helpers.dedent but is needed because dedent
@@ -57,8 +56,7 @@ describe('undo tree:', function()
-- Delete three other characters and go back in time step by step.
feed('$xxx')
expect_line('123456')
- execute('sleep 1')
- wait()
+ command('sleep 1')
feed('g-')
expect_line('1234567')
feed('g-')
@@ -79,8 +77,7 @@ describe('undo tree:', function()
expect_line('123456')
-- Delay for two seconds and go some seconds forward and backward.
- execute('sleep 2')
- wait()
+ command('sleep 2')
feed('Aa<esc>')
feed('Ab<esc>')
feed('Ac<esc>')
diff --git a/test/functional/legacy/assert_spec.lua b/test/functional/legacy/assert_spec.lua
index 1ce665360d..63699387c1 100644
--- a/test/functional/legacy/assert_spec.lua
+++ b/test/functional/legacy/assert_spec.lua
@@ -142,4 +142,22 @@ describe('assert function:', function()
})
end)
end)
+
+ -- assert_fails({cmd}, [, {error}])
+ describe('assert_fails', function()
+ it('should change v:errors when error does not match v:errmsg', function()
+ execute([[call assert_fails('xxx', {})]])
+ expected_errors({"Expected {} but got 'E731: using Dictionary as a String'"})
+ end)
+
+ it('should not change v:errors when cmd errors', function()
+ call('assert_fails', 'NonexistentCmd')
+ expected_empty()
+ end)
+
+ it('should change v:errors when cmd succeeds', function()
+ call('assert_fails', 'call empty("")')
+ expected_errors({'command did not fail: call empty("")'})
+ end)
+ end)
end)
diff --git a/test/functional/legacy/quickfix_spec.lua b/test/functional/legacy/quickfix_spec.lua
index 88f86815b3..315b8ca682 100644
--- a/test/functional/legacy/quickfix_spec.lua
+++ b/test/functional/legacy/quickfix_spec.lua
@@ -2,11 +2,264 @@
local helpers = require('test.functional.helpers')
local source, clear = helpers.source, helpers.clear
+local eq, nvim, call = helpers.eq, helpers.meths, helpers.call
+
+local function expected_empty()
+ eq({}, nvim.get_vvar('errors'))
+end
describe('helpgrep', function()
- before_each(clear)
+ before_each(function()
+ clear()
- it('works', function()
+ source([[
+ " Tests for the :clist and :llist commands
+ function XlistTests(cchar)
+ let Xlist = a:cchar . 'list'
+ let Xgetexpr = a:cchar . 'getexpr'
+
+ " With an empty list, command should return error
+ exe Xgetexpr . ' []'
+ exe 'silent! ' . Xlist
+ call assert_true(v:errmsg ==# 'E42: No Errors')
+
+ " Populate the list and then try
+ exe Xgetexpr . " ['non-error 1', 'Xtestfile1:1:3:Line1',
+ \ 'non-error 2', 'Xtestfile2:2:2:Line2',
+ \ 'non-error 3', 'Xtestfile3:3:1:Line3']"
+
+ " List only valid entries
+ redir => result
+ exe 'silent ' . Xlist
+ redir END
+ let l = split(result, "\n")
+ call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
+ \ ' 4 Xtestfile2:2 col 2: Line2',
+ \ ' 6 Xtestfile3:3 col 1: Line3'], l)
+
+ " List all the entries
+ redir => result
+ exe 'silent ' . Xlist . "!"
+ redir END
+ let l = split(result, "\n")
+ call assert_equal([' 1: non-error 1', ' 2 Xtestfile1:1 col 3: Line1',
+ \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2',
+ \ ' 5: non-error 3', ' 6 Xtestfile3:3 col 1: Line3'], l)
+
+ " List a range of errors
+ redir => result
+ exe 'silent '. Xlist . " 3,6"
+ redir END
+ let l = split(result, "\n")
+ call assert_equal([' 4 Xtestfile2:2 col 2: Line2',
+ \ ' 6 Xtestfile3:3 col 1: Line3'], l)
+
+ redir => result
+ exe 'silent ' . Xlist . "! 3,4"
+ redir END
+ let l = split(result, "\n")
+ call assert_equal([' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
+
+ redir => result
+ exe 'silent ' . Xlist . " -6,-4"
+ redir END
+ let l = split(result, "\n")
+ call assert_equal([' 2 Xtestfile1:1 col 3: Line1'], l)
+
+ redir => result
+ exe 'silent ' . Xlist . "! -5,-3"
+ redir END
+ let l = split(result, "\n")
+ call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
+ \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
+ endfunction
+
+ " Tests for the :colder, :cnewer, :lolder and :lnewer commands
+ " Note that this test assumes that a quickfix/location list is
+ " already set by the caller
+ function XageTests(cchar)
+ let Xolder = a:cchar . 'older'
+ let Xnewer = a:cchar . 'newer'
+ let Xgetexpr = a:cchar . 'getexpr'
+ if a:cchar == 'c'
+ let Xgetlist = 'getqflist()'
+ else
+ let Xgetlist = 'getloclist(0)'
+ endif
+
+ " Jumping to a non existent list should return error
+ exe 'silent! ' . Xolder . ' 99'
+ call assert_true(v:errmsg ==# 'E380: At bottom of quickfix stack')
+
+ exe 'silent! ' . Xnewer . ' 99'
+ call assert_true(v:errmsg ==# 'E381: At top of quickfix stack')
+
+ " Add three quickfix/location lists
+ exe Xgetexpr . " ['Xtestfile1:1:3:Line1']"
+ exe Xgetexpr . " ['Xtestfile2:2:2:Line2']"
+ exe Xgetexpr . " ['Xtestfile3:3:1:Line3']"
+
+ " Go back two lists
+ exe Xolder
+ exe 'let l = ' . Xgetlist
+ call assert_equal('Line2', l[0].text)
+
+ " Go forward two lists
+ exe Xnewer
+ exe 'let l = ' . Xgetlist
+ call assert_equal('Line3', l[0].text)
+
+ " Test for the optional count argument
+ exe Xolder . ' 2'
+ exe 'let l = ' . Xgetlist
+ call assert_equal('Line1', l[0].text)
+
+ exe Xnewer . ' 2'
+ exe 'let l = ' . Xgetlist
+ call assert_equal('Line3', l[0].text)
+ endfunction
+
+ " Tests for the :cwindow, :lwindow :cclose, :lclose, :copen and :lopen
+ " commands
+ function XwindowTests(cchar)
+ let Xwindow = a:cchar . 'window'
+ let Xclose = a:cchar . 'close'
+ let Xopen = a:cchar . 'open'
+ let Xgetexpr = a:cchar . 'getexpr'
+
+ " Create a list with no valid entries
+ exe Xgetexpr . " ['non-error 1', 'non-error 2', 'non-error 3']"
+
+ " Quickfix/Location window should not open with no valid errors
+ exe Xwindow
+ call assert_true(winnr('$') == 1)
+
+ " Create a list with valid entries
+ exe Xgetexpr . " ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2',
+ \ 'Xtestfile3:3:1:Line3']"
+
+ " Open the window
+ exe Xwindow
+ call assert_true(winnr('$') == 2 && winnr() == 2 &&
+ \ getline('.') ==# 'Xtestfile1|1 col 3| Line1')
+
+ " Close the window
+ exe Xclose
+ call assert_true(winnr('$') == 1)
+
+ " Create a list with no valid entries
+ exe Xgetexpr . " ['non-error 1', 'non-error 2', 'non-error 3']"
+
+ " Open the window
+ exe Xopen . ' 5'
+ call assert_true(winnr('$') == 2 && getline('.') ==# '|| non-error 1'
+ \ && winheight('.') == 5)
+
+ " Opening the window again, should move the cursor to that window
+ wincmd t
+ exe Xopen . ' 7'
+ call assert_true(winnr('$') == 2 && winnr() == 2 &&
+ \ winheight('.') == 7 &&
+ \ getline('.') ==# '|| non-error 1')
+
+
+ " Calling cwindow should close the quickfix window with no valid errors
+ exe Xwindow
+ call assert_true(winnr('$') == 1)
+ endfunction
+
+ " Tests for the :cfile, :lfile, :caddfile, :laddfile, :cgetfile and :lgetfile
+ " commands.
+ function XfileTests(cchar)
+ let Xfile = a:cchar . 'file'
+ let Xgetfile = a:cchar . 'getfile'
+ let Xaddfile = a:cchar . 'addfile'
+ if a:cchar == 'c'
+ let Xgetlist = 'getqflist()'
+ else
+ let Xgetlist = 'getloclist(0)'
+ endif
+
+ call writefile(['Xtestfile1:700:10:Line 700',
+ \ 'Xtestfile2:800:15:Line 800'], 'Xqftestfile1')
+
+ enew!
+ exe Xfile . ' Xqftestfile1'
+ exe 'let l = ' . Xgetlist
+ call assert_true(len(l) == 2 &&
+ \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' &&
+ \ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800')
+
+ " Run cfile/lfile from a modified buffer
+ enew!
+ silent! put ='Quickfix'
+ exe 'silent! ' . Xfile . ' Xqftestfile1'
+ call assert_true(v:errmsg ==# 'E37: No write since last change (add ! to override)')
+
+ call writefile(['Xtestfile3:900:30:Line 900'], 'Xqftestfile1')
+ exe Xaddfile . ' Xqftestfile1'
+ exe 'let l = ' . Xgetlist
+ call assert_true(len(l) == 3 &&
+ \ l[2].lnum == 900 && l[2].col == 30 && l[2].text ==# 'Line 900')
+
+ call writefile(['Xtestfile1:222:77:Line 222',
+ \ 'Xtestfile2:333:88:Line 333'], 'Xqftestfile1')
+
+ enew!
+ exe Xgetfile . ' Xqftestfile1'
+ exe 'let l = ' . Xgetlist
+ call assert_true(len(l) == 2 &&
+ \ l[0].lnum == 222 && l[0].col == 77 && l[0].text ==# 'Line 222' &&
+ \ l[1].lnum == 333 && l[1].col == 88 && l[1].text ==# 'Line 333')
+
+ call delete('Xqftestfile1')
+ endfunction
+
+ " Tests for the :cbuffer, :lbuffer, :caddbuffer, :laddbuffer, :cgetbuffer and
+ " :lgetbuffer commands.
+ function XbufferTests(cchar)
+ let Xbuffer = a:cchar . 'buffer'
+ let Xgetbuffer = a:cchar . 'getbuffer'
+ let Xaddbuffer = a:cchar . 'addbuffer'
+ if a:cchar == 'c'
+ let Xgetlist = 'getqflist()'
+ else
+ let Xgetlist = 'getloclist(0)'
+ endif
+
+ enew!
+ silent! call setline(1, ['Xtestfile7:700:10:Line 700',
+ \ 'Xtestfile8:800:15:Line 800'])
+ exe Xbuffer . "!"
+ exe 'let l = ' . Xgetlist
+ call assert_true(len(l) == 2 &&
+ \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' &&
+ \ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800')
+
+ enew!
+ silent! call setline(1, ['Xtestfile9:900:55:Line 900',
+ \ 'Xtestfile10:950:66:Line 950'])
+ exe Xgetbuffer
+ exe 'let l = ' . Xgetlist
+ call assert_true(len(l) == 2 &&
+ \ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900' &&
+ \ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950')
+
+ enew!
+ silent! call setline(1, ['Xtestfile11:700:20:Line 700',
+ \ 'Xtestfile12:750:25:Line 750'])
+ exe Xaddbuffer
+ exe 'let l = ' . Xgetlist
+ call assert_true(len(l) == 4 &&
+ \ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950' &&
+ \ l[2].lnum == 700 && l[2].col == 20 && l[2].text ==# 'Line 700' &&
+ \ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750')
+
+ endfunction
+ ]])
+ end)
+
+ it('copen/cclose work', function()
source([[
helpgrep quickfix
copen
@@ -14,4 +267,43 @@ describe('helpgrep', function()
cclose
]])
end)
+
+ it('clist/llist work', function()
+ call('XlistTests', 'c')
+ expected_empty()
+ call('XlistTests', 'l')
+ expected_empty()
+ end)
+
+ it('colder/cnewer and lolder/lnewer work', function()
+ local list = {{bufnr = 1, lnum = 1}}
+ call('setqflist', list)
+ call('XageTests', 'c')
+ expected_empty()
+
+ call('setloclist', 0, list)
+ call('XageTests', 'l')
+ expected_empty()
+ end)
+
+ it('quickfix/location list window commands work', function()
+ call('XwindowTests', 'c')
+ expected_empty()
+ call('XwindowTests', 'l')
+ expected_empty()
+ end)
+
+ it('quickfix/location list file commands work', function()
+ call('XfileTests', 'c')
+ expected_empty()
+ call('XfileTests', 'l')
+ expected_empty()
+ end)
+
+ it('quickfix/location list buffer commands work', function()
+ call('XbufferTests', 'c')
+ expected_empty()
+ call('XbufferTests', 'l')
+ expected_empty()
+ end)
end)
diff --git a/test/functional/provider/python_spec.lua b/test/functional/provider/python_spec.lua
index da45d6aa00..06fdbef669 100644
--- a/test/functional/provider/python_spec.lua
+++ b/test/functional/provider/python_spec.lua
@@ -1,12 +1,22 @@
local helpers = require('test.functional.helpers')
-local eval, command, feed = helpers.eval, helpers.command, helpers.feed
-local eq, clear, insert = helpers.eq, helpers.clear, helpers.insert
-local expect, write_file = helpers.expect, helpers.write_file
+
+local eq = helpers.eq
+local neq = helpers.neq
+local feed = helpers.feed
+local clear = helpers.clear
+local funcs = helpers.funcs
+local meths = helpers.meths
+local insert = helpers.insert
+local expect = helpers.expect
+local command = helpers.command
+local exc_exec = helpers.exc_exec
+local write_file = helpers.write_file
+local curbufmeths = helpers.curbufmeths
do
clear()
command('let [g:interp, g:errors] = provider#pythonx#Detect(2)')
- local errors = eval('g:errors')
+ local errors = meths.get_var('errors')
if errors ~= '' then
pending(
'Python 2 (or the Python 2 neovim module) is broken or missing:\n' .. errors,
@@ -15,49 +25,58 @@ do
end
end
-describe('python commands and functions', function()
- before_each(function()
- clear()
- command('python import vim')
- end)
+before_each(function()
+ clear()
+ command('python import vim')
+end)
- it('feature test', function()
- eq(1, eval('has("python")'))
+describe('python feature test', function()
+ it('works', function()
+ eq(1, funcs.has('python'))
end)
+end)
- it('python_execute', function()
+describe(':python command', function()
+ it('works with a line', function()
command('python vim.vars["set_by_python"] = [100, 0]')
- eq({100, 0}, eval('g:set_by_python'))
+ eq({100, 0}, meths.get_var('set_by_python'))
end)
- it('python_execute with nested commands', function()
+ -- TODO(ZyX-I): works with << EOF
+ -- TODO(ZyX-I): works with execute 'python' line1."\n".line2."\n"…
+
+ it('supports nesting', function()
command([[python vim.command('python vim.command("python vim.command(\'let set_by_nested_python = 555\')")')]])
- eq(555, eval('g:set_by_nested_python'))
+ eq(555, meths.get_var('set_by_nested_python'))
end)
- it('python_execute with range', function()
+ it('supports range', function()
insert([[
line1
line2
line3
line4]])
feed('ggjvj:python vim.vars["range"] = vim.current.range[:]<CR>')
- eq({'line2', 'line3'}, eval('g:range'))
+ eq({'line2', 'line3'}, meths.get_var('range'))
end)
+end)
- it('pyfile', function()
+describe(':pyfile command', function()
+ it('works', function()
local fname = 'pyfile.py'
write_file(fname, 'vim.command("let set_by_pyfile = 123")')
command('pyfile pyfile.py')
- eq(123, eval('g:set_by_pyfile'))
+ eq(123, meths.get_var('set_by_pyfile'))
os.remove(fname)
end)
+end)
- it('pydo', function()
+describe(':pydo command', function()
+ it('works', function()
-- :pydo 42 returns None for all lines,
-- the buffer should not be changed
command('normal :pydo 42')
- eq(0, eval('&mod'))
+ eq(false, curbufmeths.get_option('modified'))
-- insert some text
insert('abc\ndef\nghi')
expect([[
@@ -71,8 +90,25 @@ describe('python commands and functions', function()
2
ghi]])
end)
+end)
+
+describe('pyeval()', function()
+ it('works', function()
+ eq({1, 2, {['key'] = 'val'}}, funcs.pyeval('[1, 2, {"key": "val"}]'))
+ end)
+
+ it('errors out when given non-string', function()
+ eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(10)'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:_null_dict)'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:_null_list)'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(0.0)'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(function("tr"))'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:true)'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:false)'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:null)'))
+ end)
- it('pyeval', function()
- eq({1, 2, {['key'] = 'val'}}, eval([[pyeval('[1, 2, {"key": "val"}]')]]))
+ it('accepts NULL string', function()
+ neq(0, exc_exec('call pyeval($XXX_NONEXISTENT_VAR_XXX)'))
end)
end)
diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua
index 6372cbe081..99b85caf10 100644
--- a/test/functional/ui/screen.lua
+++ b/test/functional/ui/screen.lua
@@ -290,6 +290,10 @@ If everything else fails, use Screen:redraw_debug to help investigate what is
end
end
+function Screen:sleep(ms)
+ pcall(function() self:wait(function() return "error" end, ms) end)
+end
+
function Screen:_redraw(updates)
for _, update in ipairs(updates) do
-- print('--')
@@ -501,7 +505,7 @@ end
function Screen:snapshot_util(attrs, ignore)
-- util to generate screen test
- pcall(function() self:wait(function() return "error" end, 250) end)
+ self:sleep(250)
self:print_snapshot(attrs, ignore)
end
diff --git a/third-party/cmake/BuildLuarocks.cmake b/third-party/cmake/BuildLuarocks.cmake
index 1662f89b24..069c94ea2e 100644
--- a/third-party/cmake/BuildLuarocks.cmake
+++ b/third-party/cmake/BuildLuarocks.cmake
@@ -114,6 +114,15 @@ add_custom_target(lpeg
list(APPEND THIRD_PARTY_DEPS lpeg)
+add_custom_command(OUTPUT ${HOSTDEPS_LIB_DIR}/luarocks/rocks/inspect
+ COMMAND ${LUAROCKS_BINARY}
+ ARGS build inspect ${LUAROCKS_BUILDARGS}
+ DEPENDS mpack)
+add_custom_target(inspect
+ DEPENDS ${HOSTDEPS_LIB_DIR}/luarocks/rocks/inspect)
+
+list(APPEND THIRD_PARTY_DEPS inspect)
+
if(USE_BUNDLED_BUSTED)
add_custom_command(OUTPUT ${HOSTDEPS_BIN_DIR}/busted
COMMAND ${LUAROCKS_BINARY}