diff options
77 files changed, 1411 insertions, 640 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 4aa6a2de32..cb8302deb7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,12 +59,17 @@ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Dev" "Release" "MinSizeRel" "RelWithDebInfo") # If not in a git repo (e.g., a tarball) these tokens define the complete -# version string, else it is combined with the result of `git describe`. +# version string, else they are combined with the result of `git describe`. set(NVIM_VERSION_MAJOR 0) -set(NVIM_VERSION_MINOR 1) -set(NVIM_VERSION_PATCH 6) +set(NVIM_VERSION_MINOR 2) +set(NVIM_VERSION_PATCH 0) set(NVIM_VERSION_PRERELEASE "-dev") # for package maintainers +# API level +set(NVIM_API_LEVEL 1) # Bump this after any API change. +set(NVIM_API_LEVEL_COMPAT 0) # Adjust this after a _breaking_ API change. +set(NVIM_API_PRERELEASE false) + file(TO_CMAKE_PATH ${CMAKE_CURRENT_LIST_DIR}/.git FORCED_GIT_DIR) include(GetGitRevisionDescription) get_git_head_revision(GIT_REFSPEC NVIM_VERSION_COMMIT) diff --git a/config/versiondef.h.in b/config/versiondef.h.in index c91bb29c90..b9565735b3 100644 --- a/config/versiondef.h.in +++ b/config/versiondef.h.in @@ -7,6 +7,10 @@ #define NVIM_VERSION_PRERELEASE "@NVIM_VERSION_PRERELEASE@" #cmakedefine NVIM_VERSION_MEDIUM "@NVIM_VERSION_MEDIUM@" +#define NVIM_API_LEVEL @NVIM_API_LEVEL@ +#define NVIM_API_LEVEL_COMPAT @NVIM_API_LEVEL_COMPAT@ +#define NVIM_API_PRERELEASE @NVIM_API_PRERELEASE@ + #define NVIM_VERSION_CFLAGS "@NVIM_VERSION_CFLAGS@" #define NVIM_VERSION_BUILD_TYPE "@NVIM_VERSION_BUILD_TYPE@" diff --git a/runtime/autoload/health.vim b/runtime/autoload/health.vim index 336adc65e5..cbfd7c76a1 100644 --- a/runtime/autoload/health.vim +++ b/runtime/autoload/health.vim @@ -26,6 +26,7 @@ function! health#check(plugin_names) abort \ : s:to_fn_names(a:plugin_names) tabnew + setlocal wrap breakindent setlocal filetype=markdown bufhidden=wipe call s:enhance_syntax() @@ -35,7 +36,7 @@ function! health#check(plugin_names) abort redraw|echo 'Running healthchecks...' for c in healthchecks let output = '' - call append('$', split(printf("\n%s\n%s", c, repeat('=',80)), "\n")) + call append('$', split(printf("\n%s\n%s", c, repeat('=',72)), "\n")) try let output = "\n\n".execute('call '.c.'()') catch diff --git a/runtime/autoload/health/nvim.vim b/runtime/autoload/health/nvim.vim index 60e56034e1..ea87e4b3ac 100644 --- a/runtime/autoload/health/nvim.vim +++ b/runtime/autoload/health/nvim.vim @@ -1,5 +1,20 @@ +let s:suggest_faq = 'See https://github.com/neovim/neovim/wiki/FAQ' + +function! s:check_config() abort + call health#report_start('Configuration') + let sensible_pi = globpath(&runtimepath, '**/sensible.vim', 1, 1) + if empty(sensible_pi) + call health#report_ok('no issues found') + else + call health#report_info("found sensible.vim plugin:\n".join(sensible_pi, "\n")) + call health#report_error("sensible.vim plugin is not needed; Nvim has the same defaults built-in." + \ ." Also, sensible.vim sets 'ttimeoutlen' to a sub-optimal value.", + \ ["Remove sensible.vim plugin, or wrap it in a `if !has('nvim')` check."]) + endif +endfunction + " Load the remote plugin manifest file and check for unregistered plugins -function! s:check_manifest() abort +function! s:check_rplugin_manifest() abort call health#report_start('Remote Plugins') let existing_rplugins = {} @@ -57,26 +72,54 @@ function! s:check_manifest() abort endif endfunction +function! s:check_performance() abort + call health#report_start('Performance') + + " check buildtype + let buildtype = matchstr(execute('version'), '\v\cbuild type:?\s*[^\n\r\t ]+') + if empty(buildtype) + call health#report_error('failed to get build type from :version') + elseif buildtype =~# '\v(MinSizeRel|Release|RelWithDebInfo)' + call health#report_ok(buildtype) + else + call health#report_info(buildtype) + call health#report_warn( + \ "Non-optimized build-type. Nvim will be slower.", + \ ["Install a different Nvim package, or rebuild with `CMAKE_BUILD_TYPE=RelWithDebInfo`.", + \ s:suggest_faq]) + endif +endfunction + function! s:check_tmux() abort if empty($TMUX) || !executable('tmux') return endif - call health#report_start('tmux configuration') - let suggestions = ["Set escape-time in ~/.tmux.conf: set-option -sg escape-time 10", - \ 'See https://github.com/neovim/neovim/wiki/FAQ'] + call health#report_start('tmux') + + " check escape-time + let suggestions = ["Set escape-time in ~/.tmux.conf:\nset-option -sg escape-time 10", + \ s:suggest_faq] let cmd = 'tmux show-option -qvgs escape-time' let out = system(cmd) let tmux_esc_time = substitute(out, '\v(\s|\r|\n)', '', 'g') - if v:shell_error call health#report_error('command failed: '.cmd."\n".out) elseif empty(tmux_esc_time) call health#report_error('escape-time is not set', suggestions) - elseif tmux_esc_time > 500 + elseif tmux_esc_time > 300 call health#report_error( \ 'escape-time ('.tmux_esc_time.') is higher than 300ms', suggestions) else - call health#report_ok('escape-time = '.tmux_esc_time.'ms') + call health#report_ok('escape-time: '.tmux_esc_time.'ms') + endif + + " check $TERM + call health#report_info('$TERM: '.$TERM) + if $TERM !~# '\v(tmux-256color|screen-256color)' + call health#report_error( + \ '$TERM should be "screen-256color" or "tmux-256color" when running tmux.', + \ ["Set default-terminal in ~/.tmux.conf:\nset-option -g default-terminal \"screen-256color\"", + \ s:suggest_faq]) endif endfunction @@ -90,7 +133,7 @@ function! s:check_terminfo() abort \ .'infocmp $TERM | sed ''s/kbs=^[hH]/kbs=\\177/'' > $TERM.ti' \ ."\n" \ .'tic $TERM.ti', - \ 'See https://github.com/neovim/neovim/wiki/FAQ'] + \ s:suggest_faq] let cmd = 'infocmp -L' let out = system(cmd) let kbs_entry = matchstr(out, 'key_backspace=\S*') @@ -107,7 +150,9 @@ function! s:check_terminfo() abort endfunction function! health#nvim#check() abort - call s:check_manifest() - call s:check_tmux() + call s:check_config() + call s:check_performance() + call s:check_rplugin_manifest() call s:check_terminfo() + call s:check_tmux() endfunction diff --git a/runtime/autoload/health/provider.vim b/runtime/autoload/health/provider.vim index d4b2f07a17..3c40e48b2e 100644 --- a/runtime/autoload/health/provider.vim +++ b/runtime/autoload/health/provider.vim @@ -45,6 +45,19 @@ function! s:download(url) abort return 'missing `curl` and `python`, cannot make pypi request' endfunction +" Check for clipboard tools. +function! s:check_clipboard() abort + call health#report_start('Clipboard') + + let clipboard_tool = provider#clipboard#Executable() + if empty(clipboard_tool) + call health#report_warn( + \ "No clipboard tool found. Using the system clipboard won't work.", + \ ['See ":help clipboard"']) + else + call health#report_ok('Clipboard tool found: '. clipboard_tool) + endif +endfunction " Get the latest Neovim Python client version from PyPI. function! s:latest_pypi_version() abort @@ -371,6 +384,7 @@ function! s:check_ruby() abort endfunction function! health#provider#check() abort + call s:check_clipboard() call s:check_python(2) call s:check_python(3) call s:check_ruby() diff --git a/runtime/autoload/provider/clipboard.vim b/runtime/autoload/provider/clipboard.vim index 0f4aa78ddd..f63ad5730b 100644 --- a/runtime/autoload/provider/clipboard.vim +++ b/runtime/autoload/provider/clipboard.vim @@ -31,34 +31,51 @@ function! s:try_cmd(cmd, ...) endfunction let s:cache_enabled = 1 -if executable('pbcopy') - let s:copy['+'] = 'pbcopy' - let s:paste['+'] = 'pbpaste' - let s:copy['*'] = s:copy['+'] - let s:paste['*'] = s:paste['+'] - let s:cache_enabled = 0 -elseif exists('$DISPLAY') && executable('xsel') - let s:copy['+'] = 'xsel --nodetach -i -b' - let s:paste['+'] = 'xsel -o -b' - let s:copy['*'] = 'xsel --nodetach -i -p' - let s:paste['*'] = 'xsel -o -p' -elseif exists('$DISPLAY') && executable('xclip') - let s:copy['+'] = 'xclip -quiet -i -selection clipboard' - let s:paste['+'] = 'xclip -o -selection clipboard' - let s:copy['*'] = 'xclip -quiet -i -selection primary' - let s:paste['*'] = 'xclip -o -selection primary' -elseif executable('lemonade') - let s:copy['+'] = 'lemonade copy' - let s:paste['+'] = 'lemonade paste' - let s:copy['*'] = 'lemonade copy' - let s:paste['*'] = 'lemonade paste' -elseif executable('doitclient') - let s:copy['+'] = 'doitclient wclip' - let s:paste['+'] = 'doitclient wclip -r' - let s:copy['*'] = s:copy['+'] - let s:paste['*'] = s:paste['+'] -else - echom 'clipboard: No clipboard tool available. See :help clipboard' +let s:err = '' + +function! provider#clipboard#Error() abort + return s:err +endfunction + +function! provider#clipboard#Executable() abort + if executable('pbcopy') + let s:copy['+'] = 'pbcopy' + let s:paste['+'] = 'pbpaste' + let s:copy['*'] = s:copy['+'] + let s:paste['*'] = s:paste['+'] + let s:cache_enabled = 0 + return 'pbcopy' + elseif exists('$DISPLAY') && executable('xsel') + let s:copy['+'] = 'xsel --nodetach -i -b' + let s:paste['+'] = 'xsel -o -b' + let s:copy['*'] = 'xsel --nodetach -i -p' + let s:paste['*'] = 'xsel -o -p' + return 'xsel' + elseif exists('$DISPLAY') && executable('xclip') + let s:copy['+'] = 'xclip -quiet -i -selection clipboard' + let s:paste['+'] = 'xclip -o -selection clipboard' + let s:copy['*'] = 'xclip -quiet -i -selection primary' + let s:paste['*'] = 'xclip -o -selection primary' + return 'xclip' + elseif executable('lemonade') + let s:copy['+'] = 'lemonade copy' + let s:paste['+'] = 'lemonade paste' + let s:copy['*'] = 'lemonade copy' + let s:paste['*'] = 'lemonade paste' + return 'lemonade' + elseif executable('doitclient') + let s:copy['+'] = 'doitclient wclip' + let s:paste['+'] = 'doitclient wclip -r' + let s:copy['*'] = s:copy['+'] + let s:paste['*'] = s:paste['+'] + return 'doitclient' + endif + + let s:err = 'clipboard: No clipboard tool available. See :help clipboard' + return '' +endfunction + +if empty(provider#clipboard#Executable()) finish endif diff --git a/runtime/compiler/tidy.vim b/runtime/compiler/tidy.vim index 56baee2224..75be8b83d9 100644 --- a/runtime/compiler/tidy.vim +++ b/runtime/compiler/tidy.vim @@ -1,7 +1,7 @@ " Vim compiler file " Compiler: HTML Tidy " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2013 Jul 7 +" Last Change: 2016 Apr 21 if exists("current_compiler") finish @@ -12,8 +12,8 @@ if exists(":CompilerSet") != 2 " older Vim always used :setlocal command -nargs=* CompilerSet setlocal <args> endif -CompilerSet makeprg=tidy\ -quiet\ -errors\ --gnu-emacs\ yes\ % +CompilerSet makeprg=tidy\ -quiet\ -errors\ --gnu-emacs\ yes\ %:S -" sample warning: foo.html:8:1: Warning: inserting missing 'foobar' element -" sample error: foo.html:9:2: Error: <foobar> is not recognized! -CompilerSet errorformat=%f:%l:%c:\ Error:%m,%f:%l:%c:\ Warning:%m,%-G%.%# +" foo.html:8:1: Warning: inserting missing 'foobar' element +" foo.html:9:2: Error: <foobar> is not recognized! +CompilerSet errorformat=%f:%l:%c:\ %trror:%m,%f:%l:%c:\ %tarning:%m,%-G%.%# diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index c3d7fdb35b..976b852bdb 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -51,9 +51,10 @@ Tabpage -> enum value kObjectTypeTabpage Nvim exposes metadata about the API as a Dictionary with the following keys: -functions calling signature of the API functions -types The custom handle types defined by Nvim -error_types The possible kinds of errors an API function can exit with. +version Nvim version, API level/compatibility +functions API function signatures +types Custom handle types defined by Nvim +error_types Possible error types returned by API functions This metadata is mostly useful for external programs accessing the API via RPC, see |rpc-api|. diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 3c9b4dafcd..3ce0d1cd87 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 7.4. Last change: 2016 Mar 27 +*eval.txt* For Vim version 7.4. Last change: 2016 May 20 VIM REFERENCE MANUAL by Bram Moolenaar @@ -43,6 +43,7 @@ Number A 32 or 64 bit signed number. |expr-number| *Number* Float A floating point number. |floating-point-format| *Float* Examples: 123.456 1.15e-6 -1.1e3 + *E928* String A NUL terminated string of 8-bit unsigned characters (bytes). |expr-string| Examples: "ab\txx\"--" 'x-z''a,c' @@ -6171,6 +6172,7 @@ setqflist({list} [, {action}[, {title}]]) *setqflist()* Note that the list is not exactly the same as what |getqflist()| returns. + *E927* If {action} is set to 'a', then the items from {list} are added to the existing quickfix list. If there is no existing list, then a new list is created. If {action} is set to 'r', @@ -7048,8 +7050,9 @@ timer_start({time}, {callback} [, {options}]) {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. + Stop a timer. The timer callback will no longer be invoked. + {timer} is an ID returned by timer_start(), thus it must be a + Number. tolower({expr}) *tolower()* The result is a copy of the String given, with all uppercase @@ -7450,7 +7453,11 @@ There are four types of features: Example: > :if has("gui_running") < *has-patch* -3. Included patches. The "patch123" feature means that patch 123 has been +3. {Nvim} version. The "nvim-1.2.3" feature means that the Nvim version is + 1.2.3 or later. Example: > + :if has("nvim-1.2.3") +< +4. Included patches. The "patch123" feature means that patch 123 has been included. Note that this form does not check the version of Vim, you need to inspect |v:version| for that. Example (checking version 6.2.148 or later): > @@ -7458,7 +7465,7 @@ There are four types of features: < Note that it's possible for patch 147 to be omitted even though 148 is included. -4. Beyond a certain version or at a certain version and including a specific +5. Beyond a certain version or at a certain version and including a specific patch. The "patch-7.4.237" feature means that the Vim version is 7.5 or later, or it is version 7.4 and patch 237 was included. Note that this only works for patch 7.4.237 and later, before that you @@ -7530,6 +7537,7 @@ multi_byte Compiled with support for 'encoding' multi_byte_encoding 'encoding' is set to a multi-byte encoding. multi_byte_ime Compiled with support for IME input method. multi_lang Compiled with support for multiple languages. +nvim This is Nvim. |has-patch| ole Compiled with OLE automation support for Win32. path_extra Compiled with up/downwards search in 'path' and 'tags' persistent_undo Compiled with support for persistent undo history. diff --git a/runtime/doc/message.txt b/runtime/doc/message.txt index 7ceddeb674..d3eeecaf7c 100644 --- a/runtime/doc/message.txt +++ b/runtime/doc/message.txt @@ -1,4 +1,4 @@ -*message.txt* For Vim version 7.4. Last change: 2016 Feb 27 +*message.txt* For Vim version 7.4. Last change: 2016 Jul 14 VIM REFERENCE MANUAL by Bram Moolenaar @@ -656,6 +656,12 @@ You must be using an awful lot of buffers. It's now possible that two buffers have the same number, which causes various problems. You might want to exit Vim and restart it. + *E931* > + Buffer cannot be registered + +Out of memory or a duplicate buffer number. May habben after W14. Looking up +a buffer will not always work, better restart Vim. + *E296* *E297* > Seek error in swap file write Write error in swap file diff --git a/runtime/doc/motion.txt b/runtime/doc/motion.txt index 7f84f2d2a3..4d6f0719e3 100644 --- a/runtime/doc/motion.txt +++ b/runtime/doc/motion.txt @@ -1,4 +1,4 @@ -*motion.txt* For Vim version 7.4. Last change: 2015 Jun 06 +*motion.txt* For Vim version 7.4. Last change: 2016 Jul 12 VIM REFERENCE MANUAL by Bram Moolenaar @@ -569,7 +569,7 @@ i[ "inner [] block", select [count] '[' ']' blocks. This When used in Visual mode it is made characterwise. a) *v_a)* *a)* *a(* -a( *v_ab* *v_a(* *ab* +a( *vab* *v_ab* *v_a(* *ab* ab "a block", select [count] blocks, from "[count] [(" to the matching ')', including the '(' and ')' (see |[(|). Does not include white space outside of the @@ -577,7 +577,7 @@ ab "a block", select [count] blocks, from "[count] [(" to When used in Visual mode it is made characterwise. i) *v_i)* *i)* *i(* -i( *v_ib* *v_i(* *ib* +i( *vib* *v_ib* *v_i(* *ib* ib "inner block", select [count] blocks, from "[count] [(" to the matching ')', excluding the '(' and ')' (see |[(|). diff --git a/runtime/doc/msgpack_rpc.txt b/runtime/doc/msgpack_rpc.txt index b3fed9e756..757f5574d4 100644 --- a/runtime/doc/msgpack_rpc.txt +++ b/runtime/doc/msgpack_rpc.txt @@ -168,6 +168,8 @@ API metadata object ~ API clients exist to hide msgpack-rpc details. The API metadata object contains information that makes this task easier (see also |rpc-types|): + - The "version" key contains the Nvim version, API level, and API + backwards-compatibility level. - The "functions" key contains a list of metadata objects for individual functions. - Each function metadata object has |rpc-types| information about the return diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index e8ddc56f7a..5a5999e64c 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 7.4. Last change: 2016 Mar 19 +*options.txt* For Vim version 7.4. Last change: 2016 Jul 12 VIM REFERENCE MANUAL by Bram Moolenaar @@ -497,6 +497,7 @@ For example, to use a modeline only for Vim 7.0: To use a modeline for Vim after version 7.2: /* vim>702: set cole=2: */ ~ There can be no blanks between "vim" and the ":". +The modeline is ignored if {vers} does not fit in an integer. {Nvim} The number of lines that are checked can be set with the 'modelines' option. @@ -2110,11 +2111,17 @@ A jump table for the options with a short description can be found at |Q_op|. Change the way text is displayed. This is comma separated list of flags: lastline When included, as much as possible of the last line - in a window will be displayed. When not included, a - last line that doesn't fit is replaced with "@" lines. + in a window will be displayed. "@@@" is put in the + last columns of the last screen line to indicate the + rest of the line is not displayed. + truncate Like "lastline", but "@@@" is displayed in the first + column of the last screen line. Overrules "lastline". uhex Show unprintable characters hexadecimal as <xx> instead of using ^C and ~C. + When neither "lastline" or "truncate" is included, a last line that + doesn't fit is replaced with "@" lines. + *'eadirection'* *'ead'* 'eadirection' 'ead' string (default "both") global @@ -4943,6 +4950,7 @@ A jump table for the options with a short description can be found at |Q_op|. keymap/ key mapping files |mbyte-keymap| lang/ menu translations |:menutrans| menu.vim GUI menus |menu.vim| + pack/ packages |:packadd| plugin/ plugin scripts |write-plugin| print/ files for printing |postscript-print-encoding| spell/ spell checking files |spell| @@ -4969,6 +4977,8 @@ A jump table for the options with a short description can be found at |Q_op|. ordering. This is for preferences to overrule or add to the distributed defaults or system-wide settings (rarely needed). + More entries are added when using |packages|. + Note that, unlike 'path', no wildcards like "**" are allowed. Normal wildcards are allowed, but can significantly slow down searching for runtime files. For speed, use as few items as possible and avoid @@ -5445,6 +5455,8 @@ A jump table for the options with a short description can be found at |Q_op|. The |FilterReadPre|, |FilterReadPost| and |FilterWritePre|, |FilterWritePost| autocommands event are not triggered when 'shelltemp' is off. + The `system()` function does not respect this option and always uses + temp files. *'shellxescape'* *'sxe'* 'shellxescape' 'sxe' string (default: ""; diff --git a/runtime/doc/pattern.txt b/runtime/doc/pattern.txt index 0fe6106ec5..8e50a67847 100644 --- a/runtime/doc/pattern.txt +++ b/runtime/doc/pattern.txt @@ -1,4 +1,4 @@ -*pattern.txt* For Vim version 7.4. Last change: 2016 Apr 03 +*pattern.txt* For Vim version 7.4. Last change: 2016 Apr 26 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1071,8 +1071,8 @@ x A single character, with no special meaning, matches itself belonging to that character class. The following character classes are supported: Name Contents ~ -*[:alnum:]* [:alnum:] letters and digits -*[:alpha:]* [:alpha:] letters +*[:alnum:]* [:alnum:] ASCII letters and digits +*[:alpha:]* [:alpha:] ASCII letters *[:blank:]* [:blank:] space and tab characters *[:cntrl:]* [:cntrl:] control characters *[:digit:]* [:digit:] decimal digits @@ -1080,7 +1080,7 @@ x A single character, with no special meaning, matches itself *[:lower:]* [:lower:] lowercase letters (all letters when 'ignorecase' is used) *[:print:]* [:print:] printable characters including space -*[:punct:]* [:punct:] punctuation characters +*[:punct:]* [:punct:] ASCII punctuation characters *[:space:]* [:space:] whitespace characters *[:upper:]* [:upper:] uppercase letters (all letters when 'ignorecase' is used) @@ -1097,7 +1097,8 @@ x A single character, with no special meaning, matches itself These items only work for 8-bit characters, except [:lower:] and [:upper:] also work for multi-byte characters when using the new regexp engine. See |two-engines|. In the future these items may - work for multi-byte characters. + work for multi-byte characters. For now, to get all "alpha" + characters you can use: [[:lower:][:upper:]]. */[[=* *[==]* - An equivalence class. This means that characters are matched that have almost the same meaning, e.g., when ignoring accents. This diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt index e84bbe5439..b44761cdb5 100644 --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -223,6 +223,8 @@ For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|. pack/*/opt/{name} ~ The directory is added to 'runtimepath' if it wasn't there yet. + If the directory pack/*/opt/{name}/after exists it is + added at the end of 'runtimepath'. Note that {name} is the directory name, not the name of the .vim file. All the files matching the pattern @@ -492,6 +494,9 @@ To load packages earlier, so that 'runtimepath' gets updated: > This also works when loading plugins is disabled. The automatic loading will only happen once. +If the package has an "after" directory, that directory is added to the end of +'runtimepath', so that anything there will be loaded later. + Using a single plugin and loading it automatically ~ diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index dccbe2562e..bbc0260ffa 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -198,7 +198,8 @@ argument. -Z Restricted mode. All commands that make use of an external shell are disabled. This includes suspending with CTRL-Z, ":sh", filtering, the system() function, backtick expansion, - delete(), rename(), mkdir(), writefile(), libcall(), etc. + delete(), rename(), mkdir(), writefile(), libcall(), + jobstart(), etc. *-e* -e Start Vim in Ex mode |Q|. diff --git a/runtime/doc/tabpage.txt b/runtime/doc/tabpage.txt index 70e6953211..4ab5b3c759 100644 --- a/runtime/doc/tabpage.txt +++ b/runtime/doc/tabpage.txt @@ -83,14 +83,21 @@ In the GUI tab pages line you can use the right mouse button to open menu. Execute {cmd} and when it opens a new window open a new tab page instead. Doesn't work for |:diffsplit|, |:diffpatch|, |:execute| and |:normal|. - When [count] is omitted the tab page appears after the current - one. - When [count] is specified the new tab page comes after tab - page [count]. Use ":0tab cmd" to get the new tab page as the - first one. + If [count] is given the new tab page appears after the tab + page [count] otherwise the new tab page will appear after the + current one. Examples: > - :tab split " opens current buffer in new tab page - :tab help gt " opens tab page with help for "gt" + :tab split " opens current buffer in new tab page + :tab help gt " opens tab page with help for "gt" + :.tab help gt " as above + :+tab help " opens tab page with help after the next + " tab page + :-tab help " opens tab page with help before the + " current one + :0tab help " opens tab page with help before the + " first one + :$tab help " opens tab page with help after the last + " one CTRL-W gf Open a new tab page and edit the file name under the cursor. See |CTRL-W_gf|. @@ -140,7 +147,7 @@ something else. :{count}tabo[nly][!] Close all tab pages except the {count}th one. > - :.tabonly " one + :.tabonly " as above :-tabonly " close all tab pages except the previous one :+tabonly " close all tab pages except the next one :1tabonly " close all tab pages except the first one diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index bb1f993ab6..c8919dbe24 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -105,6 +105,11 @@ Some `CTRL-SHIFT-...` key chords are distinguished from `CTRL-...` variants Options: 'statusline' supports unlimited alignment sections + 'tabline' %@Func@foo%X can call any function on mouse-click + +Variables: + |v:event| + |v:windowid| is always available (for use by external UIs) Commands: |:CheckHealth| @@ -112,18 +117,18 @@ Commands: |:Man| is available by default, with many improvements such as completion Functions: + |dictwatcheradd()| notifies a callback whenever a |Dict| is modified + |dictwatcherdel()| |execute()| works with |:redir| + |msgpackdump()|, |msgpackparse()| provide msgpack de/serialization Events: - |TabNew| |TabNewEntered| - |TabClosed| |TermOpen| |TermClose| |TextYankPost| Highlight groups: - |hl-EndOfBuffer| |hl-QuickFixLine| |hl-TermCursor| |hl-TermCursorNC| diff --git a/runtime/filetype.vim b/runtime/filetype.vim index c5a3577a62..bfb45a3720 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1,7 +1,7 @@ " Vim support file to detect file types " " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2015 Oct 13 +" Last Change: 2016 Jul 12 " Listen very carefully, I will say this only once if exists("did_load_filetypes") @@ -1617,11 +1617,9 @@ au BufNewFile,BufRead */etc/protocols setf protocols " Pyrex au BufNewFile,BufRead *.pyx,*.pxd setf pyrex -" Python -au BufNewFile,BufRead *.py,*.pyw setf python - +" Python, Python Shell Startup Files " Quixote (Python-based web framework) -au BufNewFile,BufRead *.ptl setf python +au BufNewFile,BufRead *.py,*.pyw,.pythonstartup,.pythonrc,*.ptl setf python " Radiance au BufNewFile,BufRead *.rad,*.mat setf radiance diff --git a/runtime/ftplugin/groovy.vim b/runtime/ftplugin/groovy.vim new file mode 100644 index 0000000000..cc7d6e35eb --- /dev/null +++ b/runtime/ftplugin/groovy.vim @@ -0,0 +1,19 @@ +" Vim filetype plugin file +" Language: groovy +" Maintainer: Justin M. Keyes <justinkz@gmail.com> +" Last Change: 2016 May 22 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +let s:cpo_save = &cpo +set cpo-=C + +let b:undo_ftplugin = 'setlocal commentstring<' + +setlocal commentstring=//%s + +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/runtime/plugin/matchit.vim b/runtime/plugin/matchit.vim index 8053b080e1..c0f1f08027 100644 --- a/runtime/plugin/matchit.vim +++ b/runtime/plugin/matchit.vim @@ -123,7 +123,6 @@ function! s:Match_wrapper(word, forward, mode) range " Thanks to Preben "Peppe" Guldberg and Bram Moolenaar for this suggestion! if (match_words != s:last_words) || (&mps != s:last_mps) || \ exists("b:match_debug") - let s:last_words = match_words let s:last_mps = &mps " The next several lines were here before " BF started messing with this script. @@ -135,6 +134,7 @@ function! s:Match_wrapper(word, forward, mode) range \ '\/\*:\*\/,#\s*if\%(def\)\=:#\s*else\>:#\s*elif\>:#\s*endif\>' " s:all = pattern with all the keywords let match_words = match_words . (strlen(match_words) ? "," : "") . default + let s:last_words = match_words if match_words !~ s:notslash . '\\\d' let s:do_BR = 0 let s:pat = match_words diff --git a/runtime/scripts.vim b/runtime/scripts.vim index b62b0a5db8..c2f6d5cff1 100644 --- a/runtime/scripts.vim +++ b/runtime/scripts.vim @@ -1,7 +1,7 @@ " Vim support file to detect file types in scripts " " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last change: 2014 Aug 24 +" Last change: 2016 May 21 " This file is called by an autocommand for every file that has just been " loaded into a buffer. It checks if the type of file can be recognized by @@ -240,7 +240,8 @@ else set ft=xhtml " HTML (e.g.: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN") - elseif s:line1 =~? '\<DOCTYPE\s\+html\>' + " Avoid "doctype html", used by slim. + elseif s:line1 =~? '<!DOCTYPE\s\+html\>' set ft=html " PDF diff --git a/runtime/syntax/awk.vim b/runtime/syntax/awk.vim index 40491eea1a..ae0f217580 100644 --- a/runtime/syntax/awk.vim +++ b/runtime/syntax/awk.vim @@ -1,15 +1,15 @@ " Vim syntax file " Language: awk, nawk, gawk, mawk " Maintainer: Antonio Colombo <azc100@gmail.com> -" Last Change: 2014 Oct 21 +" Last Change: 2016 Jul 15 -" AWK ref. is: Alfred V. Aho, Brian W. Kernighan, Peter J. Weinberger +" AWK ref. is: Alfred V. Aho, Brian W. Kernighan, Peter J. Weinberger " The AWK Programming Language, Addison-Wesley, 1988 " GAWK ref. is: Arnold D. Robbins " Effective AWK Programming, Third Edition, O'Reilly, 2001 " Effective AWK Programming, Fourth Edition, O'Reilly, 2015 -" (also available with the gawk source distribution) +" (also available and updated with the gawk source distribution) " MAWK is a "new awk" meaning it implements AWK ref. " mawk conforms to the Posix 1003.2 (draft 11.3) @@ -19,11 +19,8 @@ " TODO: " Dig into the commented out syntax expressions below. -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syn clear -elseif exists("b:current_syntax") +" Quit when a syntax file was already loaded +if exists("b:current_syntax") finish endif @@ -35,13 +32,13 @@ set cpo&vim syn keyword awkStatement break continue delete exit syn keyword awkStatement function getline next syn keyword awkStatement print printf return -" GAWK ref. Chapter 7 -syn keyword awkStatement nextfile +" GAWK ref. Chapter 7-9 +syn keyword awkStatement switch nextfile +syn keyword awkStatement func " " GAWK ref. Chapter 9, Functions -" " Numeric Functions -syn keyword awkFunction atan2 cos div exp int log rand sin sqrt srand +syn keyword awkFunction atan2 cos exp int intdiv log rand sin sqrt srand " String Manipulation Functions syn keyword awkFunction asort asort1 gensub gsub index length match syn keyword awkFunction patsplit split sprintf strtonum sub substr @@ -52,17 +49,17 @@ syn keyword awkFunction close fflush system syn keyword awkFunction mktime strftime systime " Bit Manipulation Functions syn keyword awkFunction and compl lshift or rshift xor -" Getting Type Function -syn keyword awkFunction isarray +" Getting Type Functions +syn keyword awkFunction isarray typeof " String-Translation Functions syn keyword awkFunction bindtextdomain dcgettext dcngetext syn keyword awkConditional if else -syn keyword awkRepeat while for +syn keyword awkRepeat while for do -syn keyword awkTodo contained TODO +syn keyword awkTodo contained TODO -syn keyword awkPatterns BEGIN END +syn keyword awkPatterns BEGIN END BEGINFILE ENDFILE " GAWK ref. Chapter 7 " Built-in Variables That Control awk @@ -74,20 +71,18 @@ syn keyword awkVariables ARGC ARGV ARGIND ENVIRON ERRNO FILENAME syn keyword awkVariables FNR NF FUNCTAB NR PROCINFO RLENGTH RSTART syn keyword awkVariables RT SYMTAB -syn keyword awkRepeat do " Octal format character. syn match awkSpecialCharacter display contained "\\[0-7]\{1,3\}" -syn keyword awkStatement func nextfile " Hex format character. syn match awkSpecialCharacter display contained "\\x[0-9A-Fa-f]\+" syn match awkFieldVars "\$\d\+" -"catch errors caused by wrong parenthesis -syn region awkParen transparent start="(" end=")" contains=ALLBUT,awkParenError,awkSpecialCharacter,awkArrayElement,awkArrayArray,awkTodo,awkRegExp,awkBrktRegExp,awkBrackets,awkCharClass +" catch errors caused by wrong parenthesis +syn region awkParen transparent start="(" end=")" contains=ALLBUT,awkParenError,awkSpecialCharacter,awkArrayElement,awkArrayArray,awkTodo,awkRegExp,awkBrktRegExp,awkBrackets,awkCharClass,awkComment syn match awkParenError display ")" -syn match awkInParen display contained "[{}]" +"syn match awkInParen display contained "[{}]" " 64 lines for complex &&'s, and ||'s in a big "if" syn sync ccomment awkParen maxlines=64 @@ -141,7 +136,7 @@ syn match awkExpression "?\|:" syn keyword awkExpression in " Boolean Logic (OR, AND, NOT) -"syn match awkBoolLogic "||\|&&\|\!" +syn match awkBoolLogic "||\|&&\|\!" " This is overridden by less-than & greater-than. " Put this above those to override them. @@ -171,63 +166,42 @@ syn region awkArray transparent start="\[" end="\]" contains=awkArray,awkArrayE " (for the few instances where it would be more than "oneline") syn sync ccomment awkArray maxlines=10 -" define the default highlighting -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 || !exists("did_awk_syn_inits") - if version < 508 - let did_awk_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink awkConditional Conditional - HiLink awkFunction Function - HiLink awkRepeat Repeat - HiLink awkStatement Statement - - HiLink awkString String - HiLink awkSpecialPrintf Special - HiLink awkSpecialCharacter Special - - HiLink awkSearch String - HiLink awkBrackets awkRegExp - HiLink awkBrktRegExp awkNestRegExp - HiLink awkCharClass awkNestRegExp - HiLink awkNestRegExp Keyword - HiLink awkRegExp Special - - HiLink awkNumber Number - HiLink awkFloat Float - - HiLink awkFileIO Special - HiLink awkOperator Special - HiLink awkExpression Special - HiLink awkBoolLogic Special - - HiLink awkPatterns Special - HiLink awkVariables Special - HiLink awkFieldVars Special - - HiLink awkLineSkip Special - HiLink awkSemicolon Special - HiLink awkComma Special - "HiLink awkIdentifier Identifier - - HiLink awkComment Comment - HiLink awkTodo Todo - - " Change this if you want nested array names to be highlighted. - HiLink awkArrayArray awkArray - HiLink awkArrayElement Special - - HiLink awkParenError awkError - HiLink awkInParen awkError - HiLink awkError Error - - delcommand HiLink -endif +" Define the default highlighting. +" Only used when an item doesn't have highlighting yet +hi def link awkConditional Conditional +hi def link awkFunction Function +hi def link awkRepeat Repeat +hi def link awkStatement Statement +hi def link awkString String +hi def link awkSpecialPrintf Special +hi def link awkSpecialCharacter Special +hi def link awkSearch String +hi def link awkBrackets awkRegExp +hi def link awkBrktRegExp awkNestRegExp +hi def link awkCharClass awkNestRegExp +hi def link awkNestRegExp Keyword +hi def link awkRegExp Special +hi def link awkNumber Number +hi def link awkFloat Float +hi def link awkFileIO Special +hi def link awkOperator Special +hi def link awkExpression Special +hi def link awkBoolLogic Special +hi def link awkPatterns Special +hi def link awkVariables Special +hi def link awkFieldVars Special +hi def link awkLineSkip Special +hi def link awkSemicolon Special +hi def link awkComma Special +hi def link awkIdentifier Identifier +hi def link awkComment Comment +hi def link awkTodo Todo +" Change this if you want nested array names to be highlighted. +hi def link awkArrayArray awkArray +hi def link awkArrayElement Special +hi def link awkParenError awkError +hi def link awkInParen awkError +hi def link awkError Error let b:current_syntax = "awk" diff --git a/runtime/syntax/dcl.vim b/runtime/syntax/dcl.vim index b08adec31d..73bf577e3e 100644 --- a/runtime/syntax/dcl.vim +++ b/runtime/syntax/dcl.vim @@ -1,8 +1,8 @@ " Vim syntax file " Language: DCL (Digital Command Language - vms) " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> -" Last Change: Jan 20, 2016 -" Version: 8 +" Last Change: May 02, 2016 +" Version: 9 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_DCL " For version 5.x: Clear all syntax items @@ -13,7 +13,7 @@ elseif exists("b:current_syntax") finish endif -if !has("patch-7.4.1141") +if !has("patch-7.4.1142") setlocal iskeyword=$,@,48-57,_ else syn iskeyword $,@,48-57,_ diff --git a/runtime/syntax/debchangelog.vim b/runtime/syntax/debchangelog.vim index 4f1d6d4b11..d0c658c75e 100644 --- a/runtime/syntax/debchangelog.vim +++ b/runtime/syntax/debchangelog.vim @@ -3,7 +3,7 @@ " Maintainer: Debian Vim Maintainers <pkg-vim-maintainers@lists.alioth.debian.org> " Former Maintainers: Gerfried Fuchs <alfie@ist.org> " Wichert Akkerman <wakkerma@debian.org> -" Last Change: 2015 Oct 24 +" Last Change: 2016 Apr 24 " URL: https://anonscm.debian.org/cgit/pkg-vim/vim.git/plain/runtime/syntax/debchangelog.vim " Standard syntax initialization @@ -23,7 +23,7 @@ let binNMU='binary-only=yes' syn match debchangelogName contained "^[[:alnum:]][[:alnum:].+-]\+ " exe 'syn match debchangelogFirstKV contained "; \('.urgency.'\|'.binNMU.'\)"' exe 'syn match debchangelogOtherKV contained ", \('.urgency.'\|'.binNMU.'\)"' -syn match debchangelogTarget contained "\v %(frozen|unstable|sid|%(testing|%(old)=stable)%(-proposed-updates|-security)=|experimental|squeeze-%(backports%(-sloppy)=|volatile|lts|security)|wheezy-%(backports%(-sloppy)=|security)|jessie%(-backports|-security)=|stretch|%(devel|precise|trusty|vivid|wily|xenial)%(-%(security|proposed|updates|backports|commercial|partner))=)+" +syn match debchangelogTarget contained "\v %(frozen|unstable|sid|%(testing|%(old)=stable)%(-proposed-updates|-security)=|experimental|squeeze-%(backports%(-sloppy)=|volatile|lts|security)|wheezy-%(backports%(-sloppy)=|security)|jessie%(-backports|-security)=|stretch|%(devel|precise|trusty|vivid|wily|xenial|yakkety)%(-%(security|proposed|updates|backports|commercial|partner))=)+" syn match debchangelogVersion contained "(.\{-})" syn match debchangelogCloses contained "closes:\_s*\(bug\)\=#\=\_s\=\d\+\(,\_s*\(bug\)\=#\=\_s\=\d\+\)*" syn match debchangelogLP contained "\clp:\s\+#\d\+\(,\s*#\d\+\)*" diff --git a/runtime/syntax/debsources.vim b/runtime/syntax/debsources.vim index e0c5f4075f..d35e24729d 100644 --- a/runtime/syntax/debsources.vim +++ b/runtime/syntax/debsources.vim @@ -2,7 +2,7 @@ " Language: Debian sources.list " Maintainer: Debian Vim Maintainers <pkg-vim-maintainers@lists.alioth.debian.org> " Former Maintainer: Matthijs Mohlmann <matthijs@cacholong.nl> -" Last Change: 2015 Oct 24 +" Last Change: 2016 Apr 24 " URL: https://anonscm.debian.org/cgit/pkg-vim/vim.git/plain/runtime/syntax/debsources.vim " Standard syntax initialization @@ -27,7 +27,7 @@ let s:supported = [ \ 'oldstable', 'stable', 'testing', 'unstable', 'experimental', \ 'squeeze', 'wheezy', 'jessie', 'stretch', 'sid', 'rc-buggy', \ - \ 'precise', 'trusty', 'vivid', 'wily', 'xenial', 'devel' + \ 'precise', 'trusty', 'wily', 'xenial', 'yakkety', 'devel' \ ] let s:unsupported = [ \ 'buzz', 'rex', 'bo', 'hamm', 'slink', 'potato', @@ -36,7 +36,7 @@ let s:unsupported = [ \ 'warty', 'hoary', 'breezy', 'dapper', 'edgy', 'feisty', \ 'gutsy', 'hardy', 'intrepid', 'jaunty', 'karmic', 'lucid', \ 'maverick', 'natty', 'oneiric', 'quantal', 'raring', 'saucy', - \ 'utopic' + \ 'utopic', 'vivid' \ ] let &cpo=s:cpo diff --git a/runtime/syntax/groovy.vim b/runtime/syntax/groovy.vim index 42fcf4abac..dc39677724 100644 --- a/runtime/syntax/groovy.vim +++ b/runtime/syntax/groovy.vim @@ -2,9 +2,9 @@ " Language: Groovy " Original Author: Alessio Pace <billy.corgan@tiscali.it> " Maintainer: Tobias Rapp <yahuxo@gmx.de> -" Version: 0.1.14 +" Version: 0.1.16 " URL: http://www.vim.org/scripts/script.php?script_id=945 -" Last Change: 2015 Apr 21 +" Last Change: 2016 May 23 " THE ORIGINAL AUTHOR'S NOTES: " @@ -255,8 +255,11 @@ syn region groovyString start=+"+ end=+"+ end=+$+ contains=groovySpeci syn region groovyString start=+'+ end=+'+ end=+$+ contains=groovySpecialChar,groovySpecialError,@Spell syn region groovyString start=+"""+ end=+"""+ contains=groovySpecialChar,groovySpecialError,@Spell,groovyELExpr syn region groovyString start=+'''+ end=+'''+ contains=groovySpecialChar,groovySpecialError,@Spell -" regex string -syn region groovyString start='/[^/]' end='/' contains=groovySpecialChar,groovyRegexChar,groovyELExpr +if exists("groovy_regex_strings") + " regex strings interfere with the division operator and thus are disabled + " by default + syn region groovyString start='/[^/*]' end='/' contains=groovySpecialChar,groovyRegexChar,groovyELExpr +endif " syn region groovyELExpr start=+${+ end=+}+ keepend contained syn match groovyELExpr /\${.\{-}}/ contained syn match groovyELExpr /\$[a-zA-Z_][a-zA-Z0-9_.]*/ contained diff --git a/runtime/syntax/lisp.vim b/runtime/syntax/lisp.vim index f496398d50..a402452389 100644 --- a/runtime/syntax/lisp.vim +++ b/runtime/syntax/lisp.vim @@ -1,8 +1,8 @@ " Vim syntax file " Language: Lisp " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> -" Last Change: Jan 20, 2016 -" Version: 24 +" Last Change: May 02, 2016 +" Version: 25 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_LISP " " Thanks to F Xavier Noria for a list of 978 Common Lisp symbols taken from HyperSpec @@ -16,7 +16,7 @@ endif if exists("g:lisp_isk") exe "setl isk=".g:lisp_isk -elseif !has("patch-7.4.1141") +elseif !has("patch-7.4.1142") setl isk=38,42,43,45,47-58,60-62,64-90,97-122,_ else syn iskeyword 38,42,43,45,47-58,60-62,64-90,97-122,_ diff --git a/runtime/syntax/maple.vim b/runtime/syntax/maple.vim index 9a4db26dd8..77b1507b36 100644 --- a/runtime/syntax/maple.vim +++ b/runtime/syntax/maple.vim @@ -1,8 +1,8 @@ " Vim syntax file " Language: Maple V (based on release 4) " Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz> -" Last Change: Jan 20, 2016 -" Version: 12 +" Last Change: May 02, 2016 +" Version: 13 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_MAPLE " " Package Function Selection: {{{1 @@ -30,7 +30,7 @@ elseif exists("b:current_syntax") endif " Iskeyword Effects: {{{1 -if !has("patch-7.4.1141") +if !has("patch-7.4.1142") setl isk=$,48-57,_,a-z,@-Z else syn iskeyword $,48-57,_,a-z,@-Z diff --git a/runtime/syntax/scheme.vim b/runtime/syntax/scheme.vim index a210b0c720..c59e09cd17 100644 --- a/runtime/syntax/scheme.vim +++ b/runtime/syntax/scheme.vim @@ -1,6 +1,6 @@ " Vim syntax file " Language: Scheme (R5RS + some R6RS extras) -" Last Change: 2012 May 13 +" Last Change: 2016 May 23 " Maintainer: Sergey Khorev <sergey.khorev@gmail.com> " Original author: Dirk van Deun <dirk@igwe.vub.ac.be> @@ -245,6 +245,18 @@ if exists("b:is_mzscheme") || exists("is_mzscheme") syn region schemeUnquote matchgroup=Delimiter start="#,@\[" end="\]" contains=ALL syn region schemeQuoted matchgroup=Delimiter start="#['`]" end=![ \t()\[\]";]!me=e-1 contains=ALL syn region schemeQuoted matchgroup=Delimiter start="#['`](" matchgroup=Delimiter end=")" contains=ALL + + " Identifiers are very liberal in MzScheme/Racket + syn match schemeOther ![^()[\]{}",'`;#|\\ ]\+! + + " Language setting + syn match schemeLang "#lang [-+_/A-Za-z0-9]\+\>" + + " Various number forms + syn match schemeNumber "[-+]\=[0-9]\+\(\.[0-9]*\)\=\(e[-+]\=[0-9]\+\)\=\>" + syn match schemeNumber "[-+]\=\.[0-9]\+\(e[-+]\=[0-9]\+\)\=\>" + syn match schemeNumber "[-+]\=[0-9]\+/[0-9]\+\>" + syn match schemeNumber "\([-+]\=\([0-9]\+\(\.[0-9]*\)\=\(e[-+]\=[0-9]\+\)\=\|\.[0-9]\+\(e[-+]\=[0-9]\+\)\=\|[0-9]\+/[0-9]\+\)\)\=[-+]\([0-9]\+\(\.[0-9]*\)\=\(e[-+]\=[0-9]\+\)\=\|\.[0-9]\+\(e[-+]\=[0-9]\+\)\=\|[0-9]\+/[0-9]\+\)\=i\>" endif @@ -321,6 +333,9 @@ if version >= 508 || !exists("did_scheme_syntax_inits") HiLink schemeExtSyntax Type HiLink schemeExtFunc PreProc + + HiLink schemeLang PreProc + delcommand HiLink endif diff --git a/runtime/syntax/sh.vim b/runtime/syntax/sh.vim index 6ef5bf0d16..c51bd9aa45 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: Apr 11, 2016 -" Version: 147 +" Last Change: May 02, 2016 +" Version: 151 " 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) @@ -18,19 +18,25 @@ endif " trying to answer the question: which shell is /bin/sh, really? " If the user has not specified any of g:is_kornshell, g:is_bash, g:is_posix, g:is_sh, then guess. -if !exists("g:is_kornshell") && !exists("g:is_bash") && !exists("g:is_posix") && !exists("g:is_sh") +if getline(1) =~ '\<ksh$' + let b:is_kornshell = 1 +elseif getline(1) =~ '\<bash$' + let b:is_bash = 1 +elseif getline(1) =~ '\<dash$' + let b:is_posix = 1 +elseif !exists("g:is_kornshell") && !exists("g:is_bash") && !exists("g:is_posix") && !exists("g:is_sh") let s:shell = "" if executable("/bin/sh") let s:shell = resolve("/bin/sh") elseif executable("/usr/bin/sh") let s:shell = resolve("/usr/bin/sh") endif - if s:shell =~ 'bash$' - let g:is_bash= 1 - elseif s:shell =~ 'ksh$' - let g:is_kornshell = 1 + if s:shell =~ 'ksh$' + let b:is_kornshell= 1 + elseif s:shell =~ 'bash$' + let b:is_bash = 1 elseif s:shell =~ 'dash$' - let g:is_posix = 1 + let b:is_posix = 1 endif unlet s:shell endif @@ -86,8 +92,12 @@ if g:sh_fold_enabled && &fdm == "manual" endif " set up the syntax-highlighting iskeyword -if has("patch-7.4.1141") - exe "syn iskeyword ".&iskeyword.",-" +if has("patch-7.4.1142") + if exists("b:is_bash") + exe "syn iskeyword ".&iskeyword.",-,:" + else + exe "syn iskeyword ".&iskeyword.",-" + endif endif " Set up folding commands for shell {{{1 @@ -140,6 +150,7 @@ syn cluster shHereListDQ contains=shBeginHere,@shDblQuoteList,shHerePayload syn cluster shIdList contains=shCommandSub,shWrapLineOperator,shSetOption,shDeref,shDerefSimple,shRedir,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shExpr,shCtrlSeq,shStringSpecial,shAtExpr syn cluster shIfList contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey,shFunctionOne,shFunctionTwo syn cluster shLoopList contains=@shCaseList,@shErrorList,shCaseEsac,shConditional,shDblBrace,shExpr,shFor,shForPP,shIf,shOption,shSet,shTest,shTestOpr,shTouch +syn cluster shPPSRightList contains=shComment,shDeref,shDerefSimple,shEscape,shPosnParm syn cluster shSubShList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shIf,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq,shOperator syn cluster shTestList contains=shCharClass,shCommandSub,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shExDoubleQuote,shExpr,shExSingleQuote,shNumber,shOperator,shSingleQuote,shTest,shTestOpr @@ -213,14 +224,15 @@ syn region shSubSh transparent matchgroup=shSubShRegion start="[^(]\zs(" end=")" syn region shExpr matchgroup=shRange start="\[" skip=+\\\\\|\\$\|\[+ end="\]" contains=@shTestList,shSpecial syn region shTest transparent matchgroup=shStatement start="\<test\s" skip=+\\\\\|\\$+ matchgroup=NONE end="[;&|]"me=e-1 end="$" contains=@shExprList1 syn region shNoQuote start='\S' skip='\%(\\\\\)*\\.' end='\ze\s' contained +syn match shAstQuote contained '\*\ze"' nextgroup=shString syn match shTestOpr contained '[^-+/%]\zs=' skipwhite nextgroup=shTestDoubleQuote,shTestSingleQuote,shTestPattern syn match shTestOpr contained "<=\|>=\|!=\|==\|=\~\|-.\>\|-\(nt\|ot\|ef\|eq\|ne\|lt\|le\|gt\|ge\)\>\|[!<>]" syn match shTestPattern contained '\w\+' -syn region shTestDoubleQuote contained start='\%(\%(\\\\\)*\\\)\@<!"' skip=+\\\\\|\\"+ end='"' +syn region shTestDoubleQuote contained start='\%(\%(\\\\\)*\\\)\@<!"' skip=+\\\\\|\\"+ end='"' contains=shDeref,shDerefSimple,shDerefSpecial syn match shTestSingleQuote contained '\\.' syn match shTestSingleQuote contained "'[^']*'" if exists("b:is_kornshell") || exists("b:is_bash") - syn region shDblBrace matchgroup=Delimiter start="\[\[" skip=+\%(\\\\\)*\\$+ end="\]\]" contains=@shTestList,shNoQuote,shComment + syn region shDblBrace matchgroup=Delimiter start="\[\[" skip=+\%(\\\\\)*\\$+ end="\]\]" contains=@shTestList,shAstQuote,shNoQuote,shComment syn region shDblParen matchgroup=Delimiter start="((" skip=+\%(\\\\\)*\\$+ end="))" contains=@shTestList,shComment endif @@ -313,7 +325,9 @@ syn match shSource "^\.\s" syn match shSource "\s\.\s" "syn region shColon start="^\s*:" end="$" end="\s#"me=e-2 contains=@shColonList "syn region shColon start="^\s*\zs:" end="$" end="\s#"me=e-2 -syn match shColon '^\s*\zs:' +if exists("b:is_kornshell") + syn match shColon '^\s*\zs:' +endif " String And Character Constants: {{{1 "================================ @@ -404,21 +418,21 @@ if !exists("g:is_posix") endif if exists("b:is_bash") - ShFoldFunctions syn region shFunctionOne matchgroup=shFunction start="^\s*\h[-a-zA-Z_0-9]*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment - ShFoldFunctions syn region shFunctionTwo matchgroup=shFunction start="\<[^d][^o]\&\h[-a-zA-Z_0-9]*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment - ShFoldFunctions syn region shFunctionThree matchgroup=shFunction start="^\s*\h[-a-zA-Z_0-9]*\s*()\_s*(" end=")" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment - ShFoldFunctions syn region shFunctionFour matchgroup=shFunction start="\<[^d][^o]\&\h[-a-zA-Z_0-9]*\s*\%(()\)\=\_s*)" end=")" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment + ShFoldFunctions syn region shFunctionOne matchgroup=shFunction start="^\s*[A-Za-z_0-9:][-a-zA-Z_0-9:]*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment + ShFoldFunctions syn region shFunctionTwo matchgroup=shFunction start="\%(do\)\@!\&\<[A-Za-z_0-9:][-a-zA-Z_0-9:]*\>\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment + ShFoldFunctions syn region shFunctionThree matchgroup=shFunction start="^\s*[A-Za-z_0-9:][-a-zA-Z_0-9:]*\s*()\_s*(" end=")" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment + ShFoldFunctions syn region shFunctionFour matchgroup=shFunction start="\%(do\)\@!\&\<[A-Za-z_0-9:][-a-zA-Z_0-9:]*\>\s*\%(()\)\=\_s*)" end=")" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment else - ShFoldFunctions syn region shFunctionOne matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment - ShFoldFunctions syn region shFunctionTwo matchgroup=shFunction start="\<[^d][^o]\&\h\w*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment - ShFoldFunctions syn region shFunctionThree matchgroup=shFunction start="^\s*\h\w*\s*()\_s*(" end=")" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment - ShFoldFunctions syn region shFunctionFour matchgroup=shFunction start="\<[^d][^o]\&\h\w*\s*\%(()\)\=\_s*(" end=")" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment + ShFoldFunctions syn region shFunctionOne matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment + ShFoldFunctions syn region shFunctionTwo matchgroup=shFunction start="\%(do\)\@!\&\<\h\w*\>\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment + ShFoldFunctions syn region shFunctionThree matchgroup=shFunction start="^\s*\h\w*\s*()\_s*(" end=")" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment + ShFoldFunctions syn region shFunctionFour matchgroup=shFunction start="\%(do\)\@!\&\<\h\w*\>\s*\%(()\)\=\_s*(" end=")" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment endif " Parameter Dereferencing: {{{1 " ======================== if !exists("g:sh_no_error") - syn match shDerefWordError "[^}$[]" contained + syn match shDerefWordError "[^}$[~]" contained endif syn match shDerefSimple "\$\%(\k\+\|\d\)" syn region shDeref matchgroup=PreProc start="\${" end="}" contains=@shDerefList,shDerefVarArray @@ -498,7 +512,7 @@ if exists("b:is_bash") " bash : ${parameter//pattern} 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 + syn region shDerefPPSright contained start='.' skip=@\%(\\\\\)\+@ end='\ze}' contains=@shPPSRightList " bash : ${parameter/#substring/replacement} syn match shDerefPSR contained '/#' nextgroup=shDerefPSRleft @@ -567,6 +581,7 @@ syn sync match shWhileSync grouphere shRepeat "\<while\>" " Default Highlighting: {{{1 " ===================== hi def link shArithRegion shShellVariables +hi def link shAstQuote shDoubleQuote hi def link shAtExpr shSetList hi def link shBeginHere shRedir hi def link shCaseBar shConditional @@ -597,7 +612,6 @@ hi def link shEmbeddedEcho shString hi def link shEscape shCommandSub hi def link shExDoubleQuote shDoubleQuote hi def link shExSingleQuote shSingleQuote -hi def link shFunction Function hi def link shHereDoc shString hi def link shHerePayload shHereDoc hi def link shLoop shStatement @@ -628,21 +642,17 @@ if exists("b:is_bash") hi def link bashAdminStatement shStatement hi def link bashSpecialVariables shShellVariables hi def link bashStatement shStatement - hi def link shFunctionParen Delimiter - hi def link shFunctionDelim Delimiter hi def link shCharClass shSpecial endif if exists("b:is_kornshell") hi def link kshSpecialVariables shShellVariables hi def link kshStatement shStatement - hi def link shFunctionParen Delimiter endif if !exists("g:sh_no_error") hi def link shCaseError Error hi def link shCondError Error hi def link shCurlyError Error - hi def link shDerefError Error hi def link shDerefOpError Error hi def link shDerefWordError Error hi def link shDoError Error diff --git a/runtime/syntax/tex.vim b/runtime/syntax/tex.vim index d6d5dd81ee..9d91402bc8 100644 --- a/runtime/syntax/tex.vim +++ b/runtime/syntax/tex.vim @@ -1,8 +1,8 @@ " Vim syntax file " Language: TeX " Maintainer: Charles E. Campbell <NdrchipO@ScampbellPfamily.AbizM> -" Last Change: Apr 11, 2016 -" Version: 94 +" Last Change: May 02, 2016 +" Version: 95 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_TEX " " Notes: {{{1 @@ -133,7 +133,7 @@ endif " g:tex_isk if exists("g:tex_isk") exe "setlocal isk=".g:tex_isk -elseif !has("patch-7.4.1141") +elseif !has("patch-7.4.1142") setl isk=48-57,a-z,A-Z,192-255 else syn iskeyword 48-57,a-z,A-Z,192-255 diff --git a/runtime/syntax/tidy.vim b/runtime/syntax/tidy.vim index c24796edd1..6371cb5a86 100644 --- a/runtime/syntax/tidy.vim +++ b/runtime/syntax/tidy.vim @@ -1,145 +1,135 @@ " Vim syntax file " Language: HMTL Tidy configuration file (/etc/tidyrc ~/.tidyrc) " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2013 June 01 +" Last Change: 2016 Apr 24 if exists("b:current_syntax") finish endif -setlocal iskeyword=@,48-57,- +let s:cpo_save = &cpo +set cpo&vim + +syn iskeyword @,48-57,-,_ + +syn case ignore +syn keyword tidyBoolean contained t[rue] f[alse] y[es] n[o] 1 0 +syn keyword tidyAutoBoolean contained t[rue] f[alse] y[es] n[o] 1 0 auto +syn case match +syn keyword tidyDoctype contained html5 omit auto strict loose transitional user +syn keyword tidyEncoding contained raw ascii latin0 latin1 utf8 iso2022 mac win1252 ibm858 utf16le utf16be utf16 big5 shiftjis +syn keyword tidyNewline contained LF CRLF CR +syn match tidyNumber contained "\<\d\+\>" +syn keyword tidyRepeat contained keep-first keep-last +syn keyword tidySorter contained alpha none +syn region tidyString contained start=+"+ skip=+\\\\\|\\"+ end=+"+ oneline +syn region tidyString contained start=+'+ skip=+\\\\\|\\'+ end=+'+ oneline +syn match tidyTags contained "\<\w\+\(\s*,\s*\w\+\)*\>" + +syn keyword tidyBooleanOption add-xml-decl add-xml-pi add-xml-space + \ anchor-as-name ascii-chars assume-xml-procins bare break-before-br + \ clean coerce-endtags decorate-inferred-ul drop-empty-paras + \ drop-empty-elements drop-font-tags drop-proprietary-attributes + \ enclose-block-text enclose-text escape-cdata escape-scripts + \ fix-backslash fix-bad-comments fix-uri force-output gdoc gnu-emacs + \ hide-comments hide-endtags indent-attributes indent-cdata + \ indent-with-tabs input-xml join-classes join-styles keep-time + \ language literal-attributes logical-emphasis lower-literals markup + \ merge-emphasis ncr numeric-entities omit-optional-tags output-html + \ output-xhtml output-xml preserve-entities punctuation-wrap quiet + \ quote-ampersand quote-marks quote-nbsp raw replace-color show-info + \ show-warnings skip-nested split strict-tags-attributes tidy-mark + \ uppercase-attributes uppercase-tags word-2000 wrap-asp + \ wrap-attributes wrap-jste wrap-php wrap-script-literals + \ wrap-sections write-back + \ contained nextgroup=tidyBooleanDelimiter + +syn match tidyBooleanDelimiter ":" nextgroup=tidyBoolean contained skipwhite + +syn keyword tidyAutoBooleanOption indent merge-divs merge-spans output-bom show-body-only vertical-space contained nextgroup=tidyAutoBooleanDelimiter +syn match tidyAutoBooleanDelimiter ":" nextgroup=tidyAutoBoolean contained skipwhite + +syn keyword tidyCSSSelectorOption css-prefix contained nextgroup=tidyCSSSelectorDelimiter +syn match tidyCSSSelectorDelimiter ":" nextgroup=tidyCSSSelector contained skipwhite + +syn keyword tidyDoctypeOption doctype contained nextgroup=tidyDoctypeDelimiter +syn match tidyDoctypeDelimiter ":" nextgroup=tidyDoctype contained skipwhite + +syn keyword tidyEncodingOption char-encoding input-encoding output-encoding contained nextgroup=tidyEncodingDelimiter +syn match tidyEncodingDelimiter ":" nextgroup=tidyEncoding contained skipwhite + +syn keyword tidyIntegerOption accessibility-check doctype-mode indent-spaces show-errors tab-size wrap contained nextgroup=tidyIntegerDelimiter +syn match tidyIntegerDelimiter ":" nextgroup=tidyNumber contained skipwhite + +syn keyword tidyNameOption slide-style contained nextgroup=tidyNameDelimiter +syn match tidyNameDelimiter ":" nextgroup=tidyName contained skipwhite + +syn keyword tidyNewlineOption newline contained nextgroup=tidyNewlineDelimiter +syn match tidyNewlineDelimiter ":" nextgroup=tidyNewline contained skipwhite + +syn keyword tidyTagsOption new-blocklevel-tags new-empty-tags new-inline-tags new-pre-tags contained nextgroup=tidyTagsDelimiter +syn match tidyTagsDelimiter ":" nextgroup=tidyTags contained skipwhite + +syn keyword tidyRepeatOption repeated-attributes contained nextgroup=tidyRepeatDelimiter +syn match tidyRepeatDelimiter ":" nextgroup=tidyRepeat contained skipwhite + +syn keyword tidySorterOption sort-attributes contained nextgroup=tidySorterDelimiter +syn match tidySorterDelimiter ":" nextgroup=tidySorter contained skipwhite + +syn keyword tidyStringOption alt-text error-file gnu-emacs-file output-file contained nextgroup=tidyStringDelimiter +syn match tidyStringDelimiter ":" nextgroup=tidyString contained skipwhite + +syn cluster tidyOptions contains=tidy.*Option + +syn match tidyStart "^" nextgroup=@tidyOptions syn match tidyComment "^\s*//.*$" contains=tidyTodo syn match tidyComment "^\s*#.*$" contains=tidyTodo syn keyword tidyTodo TODO NOTE FIXME XXX contained -syn match tidyAssignment "^[a-z0-9-]\+:\s*.*$" contains=tidyOption,@tidyValue,tidyDelimiter -syn match tidyDelimiter ":" contained +hi def link tidyAutoBooleanOption Identifier +hi def link tidyBooleanOption Identifier +hi def link tidyCSSSelectorOption Identifier +hi def link tidyDoctypeOption Identifier +hi def link tidyEncodingOption Identifier +hi def link tidyIntegerOption Identifier +hi def link tidyNameOption Identifier +hi def link tidyNewlineOption Identifier +hi def link tidyTagsOption Identifier +hi def link tidyRepeatOption Identifier +hi def link tidySorterOption Identifier +hi def link tidyStringOption Identifier -syn match tidyNewTagAssignment "^new-\l\+-tags:\s*.*$" contains=tidyNewTagOption,tidyNewTagDelimiter,tidyNewTagValue,tidyDelimiter -syn match tidyNewTagDelimiter "," contained -syn match tidyNewTagValue "\<\w\+\>" contained +hi def link tidyAutoBooleanDelimiter Special +hi def link tidyBooleanDelimiter Special +hi def link tidyCSSSelectorDelimiter Special +hi def link tidyDoctypeDelimiter Special +hi def link tidyEncodingDelimiter Special +hi def link tidyIntegerDelimiter Special +hi def link tidyNameDelimiter Special +hi def link tidyNewlineDelimiter Special +hi def link tidyTagsDelimiter Special +hi def link tidyRepeatDelimiter Special +hi def link tidySorterDelimiter Special +hi def link tidyStringDelimiter Special -syn case ignore -syn keyword tidyBoolean t[rue] f[alse] y[es] n[o] contained -syn case match -syn match tidyDoctype "\<\%(omit\|auto\|strict\|loose\|transitional\|user\)\>" contained -" NOTE: use match rather than keyword here so that tidyEncoding 'raw' does not -" always have precedence over tidyOption 'raw' -syn match tidyEncoding "\<\%(ascii\|latin0\|latin1\|raw\|utf8\|iso2022\|mac\|utf16le\|utf16be\|utf16\|win1252\|ibm858\|big5\|shiftjis\)\>" contained -syn match tidyNewline "\<\%(LF\|CRLF\|CR\)\>" -syn match tidyNumber "\<\d\+\>" contained -syn match tidyRepeat "\<\%(keep-first\|keep-last\)\>" contained -syn region tidyString start=+"+ skip=+\\\\\|\\"+ end=+"+ contained oneline -syn region tidyString start=+'+ skip=+\\\\\|\\'+ end=+'+ contained oneline -syn cluster tidyValue contains=tidyBoolean,tidyDoctype,tidyEncoding,tidyNewline,tidyNumber,tidyRepeat,tidyString - -syn match tidyOption "^accessibility-check" contained -syn match tidyOption "^add-xml-decl" contained -syn match tidyOption "^add-xml-pi" contained -syn match tidyOption "^add-xml-space" contained -syn match tidyOption "^alt-text" contained -syn match tidyOption "^anchor-as-name" contained -syn match tidyOption "^ascii-chars" contained -syn match tidyOption "^assume-xml-procins" contained -syn match tidyOption "^bare" contained -syn match tidyOption "^break-before-br" contained -syn match tidyOption "^char-encoding" contained -syn match tidyOption "^clean" contained -syn match tidyOption "^css-prefix" contained -syn match tidyOption "^decorate-inferred-ul" contained -syn match tidyOption "^doctype" contained -syn match tidyOption "^doctype-mode" contained -syn match tidyOption "^drop-empty-paras" contained -syn match tidyOption "^drop-font-tags" contained -syn match tidyOption "^drop-proprietary-attributes" contained -syn match tidyOption "^enclose-block-text" contained -syn match tidyOption "^enclose-text" contained -syn match tidyOption "^error-file" contained -syn match tidyOption "^escape-cdata" contained -syn match tidyOption "^fix-backslash" contained -syn match tidyOption "^fix-bad-comments" contained -syn match tidyOption "^fix-uri" contained -syn match tidyOption "^force-output" contained -syn match tidyOption "^gnu-emacs" contained -syn match tidyOption "^gnu-emacs-file" contained -syn match tidyOption "^hide-comments" contained -syn match tidyOption "^hide-endtags" contained -syn match tidyOption "^indent" contained -syn match tidyOption "^indent-attributes" contained -syn match tidyOption "^indent-cdata" contained -syn match tidyOption "^indent-spaces" contained -syn match tidyOption "^input-encoding" contained -syn match tidyOption "^input-xml" contained -syn match tidyOption "^join-classes" contained -syn match tidyOption "^join-styles" contained -syn match tidyOption "^keep-time" contained -syn match tidyOption "^language" contained -syn match tidyOption "^literal-attributes" contained -syn match tidyOption "^logical-emphasis" contained -syn match tidyOption "^lower-literals" contained -syn match tidyOption "^markup" contained -syn match tidyOption "^merge-divs" contained -syn match tidyOption "^merge-spans" contained -syn match tidyOption "^ncr" contained -syn match tidyOption "^newline" contained -syn match tidyOption "^numeric-entities" contained -syn match tidyOption "^output-bom" contained -syn match tidyOption "^output-encoding" contained -syn match tidyOption "^output-file" contained -syn match tidyOption "^output-html" contained -syn match tidyOption "^output-xhtml" contained -syn match tidyOption "^output-xml" contained -syn match tidyOption "^preserve-entities" contained -syn match tidyOption "^punctuation-wrap" contained -syn match tidyOption "^quiet" contained -syn match tidyOption "^quote-ampersand" contained -syn match tidyOption "^quote-marks" contained -syn match tidyOption "^quote-nbsp" contained -syn match tidyOption "^raw" contained -syn match tidyOption "^repeated-attributes" contained -syn match tidyOption "^replace-color" contained -syn match tidyOption "^show-body-only" contained -syn match tidyOption "^show-errors" contained -syn match tidyOption "^show-warnings" contained -syn match tidyOption "^slide-style" contained -syn match tidyOption "^sort-attributes" contained -syn match tidyOption "^split" contained -syn match tidyOption "^tab-size" contained -syn match tidyOption "^tidy-mark" contained -syn match tidyOption "^uppercase-attributes" contained -syn match tidyOption "^uppercase-tags" contained -syn match tidyOption "^word-2000" contained -syn match tidyOption "^wrap" contained -syn match tidyOption "^wrap-asp" contained -syn match tidyOption "^wrap-attributes" contained -syn match tidyOption "^wrap-jste" contained -syn match tidyOption "^wrap-php" contained -syn match tidyOption "^wrap-script-literals" contained -syn match tidyOption "^wrap-sections" contained -syn match tidyOption "^write-back" contained -syn match tidyOption "^vertical-space" contained - -syn match tidyNewTagOption "^new-blocklevel-tags" contained -syn match tidyNewTagOption "^new-empty-tags" contained -syn match tidyNewTagOption "^new-inline-tags" contained -syn match tidyNewTagOption "^new-pre-tags" contained - -hi def link tidyBoolean Boolean -hi def link tidyComment Comment -hi def link tidyDelimiter Special -hi def link tidyDoctype Constant -hi def link tidyEncoding Constant -hi def link tidyNewline Constant -hi def link tidyNewTagDelimiter Special -hi def link tidyNewTagOption Identifier -hi def link tidyNewTagValue Constant -hi def link tidyNumber Number -hi def link tidyOption Identifier -hi def link tidyRepeat Constant -hi def link tidyString String -hi def link tidyTodo Todo +hi def link tidyAutoBoolean Boolean +hi def link tidyBoolean Boolean +hi def link tidyDoctype Constant +hi def link tidyEncoding Constant +hi def link tidyNewline Constant +hi def link tidyTags Constant +hi def link tidyNumber Number +hi def link tidyRepeat Constant +hi def link tidySorter Constant +hi def link tidyString String + +hi def link tidyComment Comment +hi def link tidyTodo Todo let b:current_syntax = "tidy" +let &cpo = s:cpo_save +unlet s:cpo_save + " vim: ts=8 diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim index 34fdae0ffc..32e871ea79 100644 --- a/runtime/syntax/vim.vim +++ b/runtime/syntax/vim.vim @@ -39,8 +39,8 @@ syn keyword vimOnlyOption contained nobiosk nobioskey noconsk noconskey nocp noc " Invertible setting variants syn keyword vimOnlyOption contained invbiosk invbioskey invconsk invconskey invcp invcompatible invguipty invmacatsui invsn invshortname invta invtextauto invtx invtextmode invtf invttyfast invtbi invttybuiltin invwiv invweirdinvert " termcap codes (which can also be set) {{{2 -syn keyword vimTermOption contained t_AB t_al t_bc t_ce t_cl t_Co t_Cs t_CS t_CV t_da t_db t_dl t_DL t_EI t_F1 t_F2 t_F3 t_F4 t_F5 t_F6 t_F7 t_F8 t_F9 t_fs t_IE t_IS t_k1 t_K1 t_k2 t_k3 t_K3 t_k4 t_K4 t_k5 t_K5 t_k6 t_K6 t_k7 t_K7 t_k8 t_K8 t_k9 t_K9 t_KA t_kb t_kB t_KB t_KC t_kd t_kD t_KD t_ke t_KE t_KF t_KG t_kh t_KH t_kI t_KI t_KJ t_KK t_kl t_KL t_kN t_kP t_kr t_ks t_ku t_le t_mb t_md t_me t_mr t_ms t_nd t_op t_RI t_RV t_Sb t_se t_Sf t_SI t_so t_sr t_te t_ti t_ts t_u7 t_ue t_us t_ut t_vb t_ve t_vi t_vs t_WP t_WS t_xs t_ZH t_ZR -syn keyword vimTermOption contained t_AF t_AL t_cd t_Ce t_cm t_cs +syn keyword vimTermOption contained t_8b t_AB t_al t_bc t_ce t_cl t_Co t_Cs t_CV t_db t_DL t_F1 t_F2 t_F3 t_F4 t_F5 t_F6 t_F7 t_F8 t_F9 t_fs t_IE t_IS t_k1 t_K1 t_k2 t_k3 t_K3 t_k4 t_K4 t_k5 t_K5 t_k6 t_K6 t_k7 t_K7 t_k8 t_K8 t_k9 t_K9 t_KA t_kb t_kB t_KB t_KC t_kd t_kD t_KD t_ke t_KE t_KF t_KG t_kh t_KH t_kI t_KI t_KJ t_KK t_kl t_KL t_kN t_kP t_kr t_ks t_ku t_le t_mb t_md t_me t_mr t_ms t_nd t_op t_RB t_RI t_RV t_Sb t_se t_Sf t_SI t_so t_sr t_SR t_te t_ti t_ts t_u7 t_ue t_us t_ut t_vb t_ve t_vi t_vs t_WP t_WS t_xn t_xs t_ZH t_ZR +syn keyword vimTermOption contained t_8f t_AF t_AL t_cd t_Ce t_cm t_cs t_CS t_da t_dl t_EI syn match vimTermOption contained "t_%1" syn match vimTermOption contained "t_#2" syn match vimTermOption contained "t_#4" @@ -177,7 +177,7 @@ syn cluster vimAugroupList contains=vimAugroup,vimIsCommand,vimCommand,vimUserCm if exists("g:vimsyn_folding") && g:vimsyn_folding =~# 'a' syn region vimAugroup fold matchgroup=vimAugroupKey start="\<aug\%[roup]\>\ze\s\+\K\k*" end="\<aug\%[roup]\>\ze\s\+[eE][nN][dD]\>" contains=vimAutoCmd,@vimAugroupList else - syn region vimAugroup matchgroup=vimAugroupKey start="\<aug\%[roup]\>\ze\s\+\K\k*" end="\<aug\%[roup]\>\ze\s\+[eE][nN][dD]\>" contains=vimAutoCmd,@vimAugroupList + syn region vimAugroup matchgroup=vimAugroupKey start="\<aug\%[roup]\>\ze\s\+\K\k*" end="\<aug\%[roup]\>\ze\s\+[eE][nN][dD]\>" contains=vimAutoCmd,@vimAugroupList endif syn match vimAugroup "aug\%[roup]!" contains=vimAugroupKey if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_noaugrouperror") @@ -285,10 +285,11 @@ syn match vimStringCont contained +\(\\\\\|.\)\{-}[^\\]"+ syn cluster vimSubstList contains=vimPatSep,vimPatRegion,vimPatSepErr,vimSubstTwoBS,vimSubstRange,vimNotation syn cluster vimSubstRepList contains=vimSubstSubstr,vimSubstTwoBS,vimNotation syn cluster vimSubstList add=vimCollection -syn match vimSubst "\(:\+\s*\|^\s*\||\s*\)\<\%(s\%[ubstitute]\|sm\%[agic]\|sno\%[magic]\)[:[:alpha:]]\@!" nextgroup=vimSubstPat -syn match vimSubst "\%(^\|[^\\]\)s\%[ubstitute][:#[:alpha:]]\@!" nextgroup=vimSubstPat contained -syn match vimSubst "/\zss\%[ubstitute]\ze/" nextgroup=vimSubstPat -syn match vimSubst1 contained "s\%[ubstitute]\>" nextgroup=vimSubstPat +syn match vimSubst "\(:\+\s*\|^\s*\||\s*\)\<\%(\<s\%[ubstitute]\>\|\<sm\%[agic]\>\|\<sno\%[magic]\>\)[:#[:alpha:]]\@!" nextgroup=vimSubstPat +syn match vimSubst "\%(^\|[^\\]\)\<s\%[ubstitute]\>[:#[:alpha:]]\@!" nextgroup=vimSubstPat contained +syn match vimSubst "/\zs\<s\%[ubstitute]\>\ze/" nextgroup=vimSubstPat +syn match vimSubst "\(:\+\s*\|^\s*\)s\ze#.\{-}#.\{-}#" nextgroup=vimSubstPat +syn match vimSubst1 contained "\<s\%[ubstitute]\>" nextgroup=vimSubstPat syn region vimSubstPat contained matchgroup=vimSubstDelim start="\z([^a-zA-Z( \t[\]&]\)"rs=s+1 skip="\\\\\|\\\z1" end="\z1"re=e-1,me=e-1 contains=@vimSubstList nextgroup=vimSubstRep4 oneline syn region vimSubstRep4 contained matchgroup=vimSubstDelim start="\z(.\)" skip="\\\\\|\\\z1" end="\z1" matchgroup=vimNotation end="<[cC][rR]>" contains=@vimSubstRepList nextgroup=vimSubstFlagErr oneline syn region vimCollection contained transparent start="\\\@<!\[" skip="\\\[" end="\]" contains=vimCollClass diff --git a/scripts/gendispatch.lua b/scripts/gendispatch.lua index 94789e1ef0..397ccc9aaf 100644 --- a/scripts/gendispatch.lua +++ b/scripts/gendispatch.lua @@ -232,8 +232,14 @@ for i = 1, #functions do converted = 'arg_'..j local rt = real_type(param[1]) if rt ~= 'Object' then - output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..') {') - output:write('\n '..converted..' = args.items['..(j - 1)..'].data.'..rt:lower()..';') + if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') then + -- Buffer, Window, and Tabpage have a specific type, but are stored in integer + output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..' && args.items['..(j - 1)..'].data.integer >= 0) {') + output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;') + else + output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..') {') + output:write('\n '..converted..' = args.items['..(j - 1)..'].data.'..rt:lower()..';') + end if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') or rt:match('^Boolean$') then -- accept nonnegative integers for Booleans, Buffers, Windows and Tabpages output:write('\n } else if (args.items['..(j - 1)..'].type == kObjectTypeInteger && args.items['..(j - 1)..'].data.integer >= 0) {') diff --git a/scripts/release.sh b/scripts/release.sh index 5a5b5a6498..93f9fa3d35 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -5,6 +5,7 @@ # Steps: # Create the "release" commit: # - CMakeLists.txt: Unset NVIM_VERSION_PRERELEASE +# - CMakeLists.txt: Unset NVIM_API_PRERELEASE # - Tag the commit. # Create the "version bump" commit: # - CMakeLists.txt: Set NVIM_VERSION_PRERELEASE to "-dev" @@ -34,11 +35,11 @@ __VERSION="${__VERSION_MAJOR}.${__VERSION_MINOR}.${__VERSION_PATCH}" && { echo "ERROR: version parse failed: '${__VERSION}'"; exit 1; } __RELEASE_MSG="NVIM v${__VERSION} -Features: +FEATURES: -Fixes: +FIXES: -Changes: +CHANGES: " __BUMP_MSG="version bump" @@ -46,6 +47,7 @@ __BUMP_MSG="version bump" echo "Most recent tag: ${__LAST_TAG}" echo "Release version: ${__VERSION}" $__sed -i.bk 's/(NVIM_VERSION_PRERELEASE) "-dev"/\1 ""/' CMakeLists.txt +$__sed -i.bk 's/(NVIM_API_PRERELEASE) true/\1 false/' CMakeLists.txt echo "Building changelog since ${__LAST_TAG}..." __CHANGELOG="$(./scripts/git-log-pretty-since.sh "$__LAST_TAG" 'vim-patch:\S')" diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh index c3efb27e3a..de101357db 100755 --- a/scripts/vim-patch.sh +++ b/scripts/vim-patch.sh @@ -124,7 +124,7 @@ assign_commit_details() { patch_file="vim-${vim_version}.patch" } -# Patch surgery: +# Patch surgery preprocess_patch() { local file="$1" local nvim="nvim -u NORC -i NONE --headless" @@ -134,8 +134,8 @@ preprocess_patch() { na_src="$na_src"'\|if_lua\|if_mzsch\|if_olepp\|if_ole\|if_perl\|if_py\|if_ruby\|if_tcl\|if_xcmdsrv' 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/\S*\<\%('${na_src}'\)@norm! d/\v(^diff)|%$
' +w +q "$file" - # Remove todo.txt, version*.txt, tags - local na_doc='todo\.txt\|version\d\.txt\|tags' + # Remove channel.txt, netbeans.txt, os_*.txt, todo.txt, version*.txt, tags + local na_doc='channel\.txt\|netbeans\.txt\|os_\w\+\.txt\|todo\.txt\|version\d\.txt\|tags' 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/doc/\%('${na_doc}'\)@norm! d/\v(^diff)|%$
' +w +q "$file" # Remove some testdir/Make_*.mak files @@ -143,7 +143,12 @@ preprocess_patch() { 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\%('${na_src_testdir}'\)@norm! d/\v(^diff)|%$
' +w +q "$file" # Rename src/ paths to src/nvim/ - LC_ALL=C sed -e 's/\( [ab]\/src\)/\1\/nvim/g' "$file" > "$file".tmp && mv "$file".tmp "$file" + LC_ALL=C sed -e 's/\( [ab]\/src\)/\1\/nvim/g' \ + "$file" > "$file".tmp && mv "$file".tmp "$file" + + # Rename path to matchit plugin. + LC_ALL=C sed -e 's@\( [ab]/runtime\)/pack/dist/opt/matchit/\(plugin/matchit.vim\)@\1/\2@g' \ + "$file" > "$file".tmp && mv "$file".tmp "$file" } get_vim_patch() { diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h index 1d5ecd3071..223aab09dc 100644 --- a/src/nvim/api/private/defs.h +++ b/src/nvim/api/private/defs.h @@ -91,9 +91,6 @@ typedef enum { struct object { ObjectType type; union { - Buffer buffer; - Window window; - Tabpage tabpage; Boolean boolean; Integer integer; Float floating; diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index c0ee735d1a..bd83b1ff1d 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -18,6 +18,7 @@ #include "nvim/map.h" #include "nvim/option.h" #include "nvim/option_defs.h" +#include "nvim/version.h" #include "nvim/eval/typval_encode.h" #include "nvim/lib/kvec.h" @@ -615,13 +616,14 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err) case kObjectTypeWindow: case kObjectTypeTabpage: case kObjectTypeInteger: - if (obj.data.integer > INT_MAX || obj.data.integer < INT_MIN) { + if (obj.data.integer > VARNUMBER_MAX + || obj.data.integer < VARNUMBER_MIN) { api_set_error(err, Validation, _("Integer value outside range")); return false; } tv->v_type = VAR_NUMBER; - tv->vval.v_number = (int)obj.data.integer; + tv->vval.v_number = (varnumber_T)obj.data.integer; break; case kObjectTypeFloat: @@ -763,6 +765,7 @@ Dictionary api_metadata(void) static Dictionary metadata = ARRAY_DICT_INIT; if (!metadata.size) { + PUT(metadata, "version", DICTIONARY_OBJ(version_dict())); init_function_metadata(&metadata); init_error_type_metadata(&metadata); init_type_metadata(&metadata); diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h index a946e35149..9fe8c351cf 100644 --- a/src/nvim/api/private/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -37,15 +37,15 @@ #define BUFFER_OBJ(s) ((Object) { \ .type = kObjectTypeBuffer, \ - .data.buffer = s }) + .data.integer = s }) #define WINDOW_OBJ(s) ((Object) { \ .type = kObjectTypeWindow, \ - .data.window = s }) + .data.integer = s }) #define TABPAGE_OBJ(s) ((Object) { \ .type = kObjectTypeTabpage, \ - .data.tabpage = s }) + .data.integer = s }) #define ARRAY_OBJ(a) ((Object) { \ .type = kObjectTypeArray, \ diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 15ec52ebab..491375bd73 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -34,7 +34,7 @@ #endif /// Executes an ex-command. -/// On VimL error: Returns the VimL error and updates v:errmsg. +/// On VimL error: Returns the VimL error; v:errmsg is not updated. /// /// @param command Ex-command string /// @param[out] err Error details (including actual VimL error), if any diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index ef881fa0eb..1f555a6a05 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -348,7 +348,7 @@ Tabpage nvim_win_get_tabpage(Window window, Error *err) /// @return Window number Integer nvim_win_get_number(Window window, Error *err) { - Integer rv = 0; + int rv = 0; win_T *win = find_window_by_handle(window, err); if (!win) { @@ -356,7 +356,7 @@ Integer nvim_win_get_number(Window window, Error *err) } int tabnr; - win_get_tabwin(window, &tabnr, (int *)&rv); + win_get_tabwin(window, &tabnr, &rv); return rv; } diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 5fb011885e..a66fdc1304 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -323,13 +323,14 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last) wipe_buf = true; } - if (win_valid(win)) { - /* Set b_last_cursor when closing the last window for the buffer. - * Remember the last cursor position and window options of the buffer. - * This used to be only for the current window, but then options like - * 'foldmethod' may be lost with a ":only" command. */ - if (buf->b_nwindows == 1) + if (win_valid_any_tab(win)) { + // Set b_last_cursor when closing the last window for the buffer. + // Remember the last cursor position and window options of the buffer. + // This used to be only for the current window, but then options like + // 'foldmethod' may be lost with a ":only" command. + if (buf->b_nwindows == 1) { set_last_cursor(win); + } buflist_setfpos(buf, win, win->w_cursor.lnum == 1 ? 0 : win->w_cursor.lnum, win->w_cursor.col, TRUE); @@ -402,7 +403,7 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last) buf->b_nwindows = nwindows; buf_freeall(buf, (del_buf ? BFA_DEL : 0) + (wipe_buf ? BFA_WIPE : 0)); - if (win_valid(win) && win->w_buffer == buf) { + if (win_valid_any_tab(win) && win->w_buffer == buf) { win->w_buffer = NULL; // make sure we don't use the buffer now } @@ -478,17 +479,20 @@ void buf_clear_file(buf_T *buf) buf->b_ml.ml_flags = ML_EMPTY; /* empty buffer */ } -/* - * buf_freeall() - free all things allocated for a buffer that are related to - * the file. flags: - * BFA_DEL buffer is going to be deleted - * BFA_WIPE buffer is going to be wiped out - * BFA_KEEP_UNDO do not free undo information - */ +/// buf_freeall() - free all things allocated for a buffer that are related to +/// the file. Careful: get here with "curwin" NULL when exiting. +/// +/// @param flags BFA_DEL buffer is going to be deleted +/// BFA_WIPE buffer is going to be wiped out +/// BFA_KEEP_UNDO do not free undo information void buf_freeall(buf_T *buf, int flags) { bool is_curbuf = (buf == curbuf); + int is_curwin = (curwin != NULL && curwin->w_buffer == buf); + win_T *the_curwin = curwin; + tabpage_T *the_curtab = curtab; + // Make sure the buffer isn't closed by autocommands. buf->b_closing = true; apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, FALSE, buf); if (!buf_valid(buf)) /* autocommands may delete the buffer */ @@ -505,8 +509,18 @@ void buf_freeall(buf_T *buf, int flags) return; } buf->b_closing = false; - if (aborting()) /* autocmds may abort script processing */ + + // If the buffer was in curwin and the window has changed, go back to that + // window, if it still exists. This avoids that ":edit x" triggering a + // "tabnext" BufUnload autocmd leaves a window behind without a buffer. + if (is_curwin && curwin != the_curwin && win_valid_any_tab(the_curwin)) { + block_autocmds(); + goto_tabpage_win(the_curtab, the_curwin); + unblock_autocmds(); + } + if (aborting()) { // autocmds may abort script processing return; + } /* * It's possible that autocommands change curbuf to the one being deleted. @@ -4509,7 +4523,7 @@ chk_modeline ( char_u *e; char_u *linecopy; /* local copy of any modeline found */ int prev; - int vers; + intmax_t vers; int end; int retval = OK; char_u *save_sourcing_name; @@ -4528,7 +4542,10 @@ chk_modeline ( e = s + 4; else e = s + 3; - vers = getdigits_int(&e); + if (getdigits_safe(&e, &vers) != OK) { + continue; + } + if (*e == ':' && (s[0] != 'V' || STRNCMP(skipwhite(e + 1), "set", 3) == 0) @@ -4536,8 +4553,9 @@ chk_modeline ( || (VIM_VERSION_100 >= vers && isdigit(s[3])) || (VIM_VERSION_100 < vers && s[3] == '<') || (VIM_VERSION_100 > vers && s[3] == '>') - || (VIM_VERSION_100 == vers && s[3] == '='))) + || (VIM_VERSION_100 == vers && s[3] == '='))) { break; + } } } prev = *s; diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index ab5987612c..2e6316c74a 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -488,9 +488,9 @@ struct file_buffer { bool file_id_valid; FileID file_id; - bool b_changed; /* 'modified': Set to true if something in the - file has been changed and not written out. */ - int b_changedtick; /* incremented for each change, also for undo */ + int b_changed; // 'modified': Set to true if something in the + // file has been changed and not written out. + int b_changedtick; // incremented for each change, also for undo bool b_saving; /* Set to true if we are in the middle of saving the buffer. */ @@ -655,7 +655,7 @@ struct file_buffer { long b_p_sts; ///< 'softtabstop' long b_p_sts_nopaste; ///< b_p_sts saved for paste mode char_u *b_p_sua; ///< 'suffixesadd' - bool b_p_swf; ///< 'swapfile' + int b_p_swf; ///< 'swapfile' long b_p_smc; ///< 'synmaxcol' char_u *b_p_syn; ///< 'syntax' long b_p_ts; ///< 'tabstop' diff --git a/src/nvim/charset.c b/src/nvim/charset.c index 78f5d96fc7..61c5b10808 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -1732,6 +1732,26 @@ char_u* skiptowhite_esc(char_u *p) { return p; } +/// Get a number from a string and skip over it, signalling overflows +/// +/// @param[out] pp A pointer to a pointer to char_u. +/// It will be advanced past the read number. +/// @param[out] nr Number read from the string. +/// +/// @return OK on success, FAIL on error/overflow +int getdigits_safe(char_u **pp, intmax_t *nr) +{ + errno = 0; + *nr = strtoimax((char *)(*pp), (char **)pp, 10); + + if ((*nr == INTMAX_MIN || *nr == INTMAX_MAX) + && errno == ERANGE) { + return FAIL; + } + + return OK; +} + /// Get a number from a string and skip over it. /// /// @param[out] pp A pointer to a pointer to char_u. @@ -1740,17 +1760,16 @@ char_u* skiptowhite_esc(char_u *p) { /// @return Number read from the string. intmax_t getdigits(char_u **pp) { - errno = 0; - intmax_t number = strtoimax((char *)*pp, (char **)pp, 10); - if (number == INTMAX_MAX || number == INTMAX_MIN) { - assert(errno != ERANGE); - } + intmax_t number; + int ret = getdigits_safe(pp, &number); + + (void)ret; // Avoid "unused variable" warning in Release build + assert(ret == OK); + return number; } -/// Get an int number from a string. -/// -/// A getdigits wrapper restricted to int values. +/// Get an int number from a string. Like getdigits(), but restricted to `int`. int getdigits_int(char_u **pp) { intmax_t number = getdigits(pp); @@ -1760,9 +1779,7 @@ int getdigits_int(char_u **pp) return (int)number; } -/// Get a long number from a string. -/// -/// A getdigits wrapper restricted to long values. +/// Get a long number from a string. Like getdigits(), but restricted to `long`. long getdigits_long(char_u **pp) { intmax_t number = getdigits(pp); diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 76f33e7d8c..5d4241c8af 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -10524,16 +10524,10 @@ static void f_glob2regpat(typval_T *argvars, typval_T *rettv, FunPtr fptr) : file_pat_to_reg_pat(pat, NULL, NULL, false); } -/* - * "has()" function - */ +/// "has()" function static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int i; - char_u *name; - int n = FALSE; - static char *(has_list[]) = - { + static char *(has_list[]) = { #ifdef UNIX "unix", #endif @@ -10646,36 +10640,42 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) NULL }; - name = get_tv_string(&argvars[0]); - for (i = 0; has_list[i] != NULL; ++i) + bool n = false; + char *name = (char *)get_tv_string(&argvars[0]); + + for (int i = 0; has_list[i] != NULL; i++) { if (STRICMP(name, has_list[i]) == 0) { - n = TRUE; + n = true; break; } + } - if (n == FALSE) { + if (!n) { if (STRNICMP(name, "patch", 5) == 0) { if (name[5] == '-' - && STRLEN(name) > 11 + && strlen(name) > 11 && ascii_isdigit(name[6]) && ascii_isdigit(name[8]) && ascii_isdigit(name[10])) { - int major = atoi((char *)name + 6); - int minor = atoi((char *)name + 8); + int major = atoi(name + 6); + int minor = atoi(name + 8); // Expect "patch-9.9.01234". n = (major < VIM_VERSION_MAJOR || (major == VIM_VERSION_MAJOR && (minor < VIM_VERSION_MINOR || (minor == VIM_VERSION_MINOR - && has_patch(atoi((char *)name + 10)))))); + && has_vim_patch(atoi(name + 10)))))); } else { - n = has_patch(atoi((char *)name + 5)); + n = has_vim_patch(atoi(name + 5)); } + } else if (STRNICMP(name, "nvim-", 5) == 0) { + // Expect "nvim-x.y.z" + n = has_nvim_version(name + 5); } else if (STRICMP(name, "vim_starting") == 0) { n = (starting != 0); } else if (STRICMP(name, "multi_byte_encoding") == 0) { - n = has_mbyte; + n = has_mbyte != 0; #if defined(USE_ICONV) && defined(DYNAMIC_ICONV) } else if (STRICMP(name, "iconv") == 0) { n = iconv_enabled(false); @@ -10685,8 +10685,8 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } - if (n == FALSE && eval_has_provider((char *)name)) { - n = TRUE; + if (!n && eval_has_provider(name)) { + n = true; } rettv->vval.v_number = n; @@ -15612,6 +15612,39 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } +// "strgetchar()" function +static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + char_u *str; + int len; + int error = false; + int charidx; + + rettv->vval.v_number = -1; + str = get_tv_string_chk(&argvars[0]); + if (str == NULL) { + return; + } + len = (int)STRLEN(str); + charidx = get_tv_number_chk(&argvars[1], &error); + if (error) { + return; + } + + { + int byteidx = 0; + + while (charidx >= 0 && byteidx < len) { + if (charidx == 0) { + rettv->vval.v_number = mb_ptr2char(str + byteidx); + break; + } + charidx--; + byteidx += mb_cptr2len(str + byteidx); + } + } +} + /* * "stridx()" function */ @@ -15712,6 +15745,64 @@ static void f_strwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = (varnumber_T) mb_string2cells(s); } +// "strcharpart()" function +static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { + char_u *p; + int nchar; + int nbyte = 0; + int charlen; + int len = 0; + int slen; + int error = false; + + p = get_tv_string(&argvars[0]); + slen = (int)STRLEN(p); + + nchar = get_tv_number_chk(&argvars[1], &error); + if (!error) { + if (nchar > 0) { + while (nchar > 0 && nbyte < slen) { + nbyte += mb_cptr2len(p + nbyte); + nchar--; + } + } else { + nbyte = nchar; + } + } + if (argvars[2].v_type != VAR_UNKNOWN) { + charlen = get_tv_number(&argvars[2]); + while (charlen > 0 && nbyte + len < slen) { + int off = nbyte + len; + + if (off < 0) { + len += 1; + } else { + len += mb_cptr2len(p + off); + } + charlen--; + } + } else { + len = slen - nbyte; // default: all bytes that are available. + } + + // Only return the overlap between the specified part and the actual + // string. + if (nbyte < 0) { + len += nbyte; + nbyte = 0; + } else if (nbyte > slen) { + nbyte = slen; + } + if (len < 0) { + len = 0; + } else if (nbyte + len > slen) { + len = slen - nbyte; + } + + rettv->v_type = VAR_STRING; + rettv->vval.v_string = vim_strnsave(p + nbyte, len); +} + /* * "strpart()" function */ diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index eaaee81533..bea25b36f3 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -268,9 +268,11 @@ return { sqrt={args=1, func="float_op_wrapper", data="&sqrt"}, str2float={args=1}, str2nr={args={1, 2}}, + strcharpart={args={2, 3}}, strchars={args={1,2}}, strdisplaywidth={args={1, 2}}, strftime={args={1, 2}}, + strgetchar={args={2, 2}}, stridx={args={2, 3}}, string={args=1}, strlen={args=1}, diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 6205daf0cb..4674460a16 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -2250,28 +2250,28 @@ do_ecmd ( xfree(new_name); goto theend; } - if (buf == curbuf) /* already in new buffer */ - auto_buf = TRUE; - else { - if (curbuf == old_curbuf) + if (buf == curbuf) { // already in new buffer + auto_buf = true; + } else { + win_T *the_curwin = curwin; + + // Set the w_closing flag to avoid that autocommands close the window. + the_curwin->w_closing = true; + if (curbuf == old_curbuf) { buf_copy_options(buf, BCO_ENTER); + } - /* close the link to the current buffer */ - u_sync(FALSE); + // Close the link to the current buffer. This will set + // curwin->w_buffer to NULL. + u_sync(false); close_buffer(oldwin, curbuf, - (flags & ECMD_HIDE) || curbuf->terminal ? 0 : DOBUF_UNLOAD, FALSE); - - /* Autocommands may open a new window and leave oldwin open - * which leads to crashes since the above call sets - * oldwin->w_buffer to NULL. */ - if (curwin != oldwin && oldwin != aucmd_win && win_valid(oldwin)) { - assert(oldwin); - if (oldwin->w_buffer == NULL) { - win_close(oldwin, FALSE); - } - } + (flags & ECMD_HIDE) || curbuf->terminal ? 0 : DOBUF_UNLOAD, + false); + + the_curwin->w_closing = false; - if (aborting()) { /* autocmds may abort script processing */ + // autocmds may abort script processing + if (aborting() && curwin->w_buffer != NULL) { xfree(new_name); goto theend; } @@ -2370,10 +2370,12 @@ do_ecmd ( if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur) { /* Save all the text, so that the reload can be undone. * Sync first so that this is a separate undo-able action. */ - u_sync(FALSE); - if (u_savecommon(0, curbuf->b_ml.ml_line_count + 1, 0, TRUE) - == FAIL) + u_sync(false); + if (u_savecommon(0, curbuf->b_ml.ml_line_count + 1, 0, true) + == FAIL) { + xfree(new_name); goto theend; + } u_unchanged(curbuf); buf_freeall(curbuf, BFA_KEEP_UNDO); @@ -4072,61 +4074,66 @@ void ex_global(exarg_T *eap) vim_regfree(regmatch.regprog); } -/* - * Execute "cmd" on lines marked with ml_setmarked(). - */ +/// Execute `cmd` on lines marked with ml_setmarked(). void global_exe(char_u *cmd) { - linenr_T old_lcount; /* b_ml.ml_line_count before the command */ - buf_T *old_buf = curbuf; /* remember what buffer we started in */ - linenr_T lnum; /* line number according to old situation */ - - /* - * Set current position only once for a global command. - * If global_busy is set, setpcmark() will not do anything. - * If there is an error, global_busy will be incremented. - */ + linenr_T old_lcount; // b_ml.ml_line_count before the command + buf_T *old_buf = curbuf; // remember what buffer we started in + linenr_T lnum; // line number according to old situation + int save_mapped_ctrl_c = mapped_ctrl_c; + + // Set current position only once for a global command. + // If global_busy is set, setpcmark() will not do anything. + // If there is an error, global_busy will be incremented. setpcmark(); - /* When the command writes a message, don't overwrite the command. */ - msg_didout = TRUE; + // When the command writes a message, don't overwrite the command. + msg_didout = true; + // Disable CTRL-C mapping, let it interrupt (potentially long output). + mapped_ctrl_c = 0; sub_nsubs = 0; sub_nlines = 0; - global_need_beginline = FALSE; + global_need_beginline = false; global_busy = 1; old_lcount = curbuf->b_ml.ml_line_count; + while (!got_int && (lnum = ml_firstmarked()) != 0 && global_busy == 1) { curwin->w_cursor.lnum = lnum; curwin->w_cursor.col = 0; - if (*cmd == NUL || *cmd == '\n') + if (*cmd == NUL || *cmd == '\n') { do_cmdline((char_u *)"p", NULL, NULL, DOCMD_NOWAIT); - else + } else { do_cmdline(cmd, NULL, NULL, DOCMD_NOWAIT); + } os_breakcheck(); } + mapped_ctrl_c = save_mapped_ctrl_c; global_busy = 0; - if (global_need_beginline) + if (global_need_beginline) { beginline(BL_WHITE | BL_FIX); - else - check_cursor(); /* cursor may be beyond the end of the line */ + } else { + check_cursor(); // cursor may be beyond the end of the line + } - /* the cursor may not have moved in the text but a change in a previous - * line may move it on the screen */ + // the cursor may not have moved in the text but a change in a previous + // line may move it on the screen changed_line_abv_curs(); - /* If it looks like no message was written, allow overwriting the - * command with the report for number of changes. */ - if (msg_col == 0 && msg_scrolled == 0) - msg_didout = FALSE; + // If it looks like no message was written, allow overwriting the + // command with the report for number of changes. + if (msg_col == 0 && msg_scrolled == 0) { + msg_didout = false; + } - /* If substitutes done, report number of substitutes, otherwise report - * number of extra or deleted lines. - * Don't report extra or deleted lines in the edge case where the buffer - * we are in after execution is different from the buffer we started in. */ - if (!do_sub_msg(false) && curbuf == old_buf) + // If substitutes done, report number of substitutes, otherwise report + // number of extra or deleted lines. + // Don't report extra or deleted lines in the edge case where the buffer + // we are in after execution is different from the buffer we started in. + if (!do_sub_msg(false) && curbuf == old_buf) { msgmore(curbuf->b_ml.ml_line_count - old_lcount); + } } #if defined(EXITFREE) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 9f83688e1e..5e418bf099 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -1302,8 +1302,7 @@ static char_u * do_one_cmd(char_u **cmdlinep, * 2. Handle command modifiers. */ p = ea.cmd; - if (ascii_isdigit(*ea.cmd)) - p = skipwhite(skipdigits(ea.cmd)); + p = skip_range(ea.cmd, NULL); switch (*p) { /* When adding an entry, also modify cmd_exists(). */ case 'a': if (!checkforcmd(&ea.cmd, "aboveleft", 3)) @@ -1406,12 +1405,18 @@ static char_u * do_one_cmd(char_u **cmdlinep, continue; case 't': if (checkforcmd(&p, "tab", 3)) { - if (ascii_isdigit(*ea.cmd)) - cmdmod.tab = atoi((char *)ea.cmd) + 1; - else - cmdmod.tab = tabpage_index(curtab) + 1; - ea.cmd = p; - continue; + long tabnr = get_address(&ea, &ea.cmd, ADDR_TABS, ea.skip, false); + if (tabnr == MAXLNUM) { + cmdmod.tab = tabpage_index(curtab) + 1; + } else { + if (tabnr < 0 || tabnr > LAST_TAB_NR) { + errormsg = (char_u *)_(e_invrange); + goto doend; + } + cmdmod.tab = tabnr + 1; + } + ea.cmd = p; + continue; } if (!checkforcmd(&ea.cmd, "topleft", 2)) break; @@ -1766,11 +1771,8 @@ static char_u * do_one_cmd(char_u **cmdlinep, if (text_locked() && !(ea.argt & CMDWIN) && !IS_USER_CMDIDX(ea.cmdidx)) { - /* Command not allowed when editing the command line. */ - if (cmdwin_type != 0) - errormsg = (char_u *)_(e_cmdwin); - else - errormsg = (char_u *)_(e_secure); + // Command not allowed when editing the command line. + errormsg = get_text_locked_msg(); goto doend; } /* Disallow editing another buffer when "curbuf_lock" is set. diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 7444eb8a38..e525c949bd 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1688,10 +1688,15 @@ int text_locked(void) { */ void text_locked_msg(void) { - if (cmdwin_type != 0) - EMSG(_(e_cmdwin)); - else - EMSG(_(e_secure)); + EMSG(_(get_text_locked_msg())); +} + +char_u * get_text_locked_msg(void) { + if (cmdwin_type != 0) { + return e_cmdwin; + } else { + return e_secure; + } } /* diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c index 14e1c2d978..c3a909692f 100644 --- a/src/nvim/msgpack_rpc/helpers.c +++ b/src/nvim/msgpack_rpc/helpers.c @@ -21,7 +21,8 @@ static msgpack_zone zone; static msgpack_sbuffer sbuffer; #define HANDLE_TYPE_CONVERSION_IMPL(t, lt) \ - bool msgpack_rpc_to_##lt(const msgpack_object *const obj, t *const arg) \ + bool msgpack_rpc_to_##lt(const msgpack_object *const obj, \ + Integer *const arg) \ FUNC_ATTR_NONNULL_ALL \ { \ if (obj->type != MSGPACK_OBJECT_EXT \ @@ -44,12 +45,12 @@ static msgpack_sbuffer sbuffer; return true; \ } \ \ - void msgpack_rpc_from_##lt(t o, msgpack_packer *res) \ + void msgpack_rpc_from_##lt(Integer o, msgpack_packer *res) \ FUNC_ATTR_NONNULL_ARG(2) \ { \ msgpack_packer pac; \ msgpack_packer_init(&pac, &sbuffer, msgpack_sbuffer_write); \ - msgpack_pack_int64(&pac, o); \ + msgpack_pack_int64(&pac, (handle_T)o); \ msgpack_pack_ext(res, sbuffer.size, kObjectType##t); \ msgpack_pack_ext_body(res, sbuffer.data, sbuffer.size); \ msgpack_sbuffer_clear(&sbuffer); \ @@ -213,17 +214,17 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg) switch (cur.mobj->via.ext.type) { case kObjectTypeBuffer: { cur.aobj->type = kObjectTypeBuffer; - ret = msgpack_rpc_to_buffer(cur.mobj, &cur.aobj->data.buffer); + ret = msgpack_rpc_to_buffer(cur.mobj, &cur.aobj->data.integer); break; } case kObjectTypeWindow: { cur.aobj->type = kObjectTypeWindow; - ret = msgpack_rpc_to_window(cur.mobj, &cur.aobj->data.window); + ret = msgpack_rpc_to_window(cur.mobj, &cur.aobj->data.integer); break; } case kObjectTypeTabpage: { cur.aobj->type = kObjectTypeTabpage; - ret = msgpack_rpc_to_tabpage(cur.mobj, &cur.aobj->data.tabpage); + ret = msgpack_rpc_to_tabpage(cur.mobj, &cur.aobj->data.integer); break; } } @@ -369,15 +370,15 @@ void msgpack_rpc_from_object(const Object result, msgpack_packer *const res) break; } case kObjectTypeBuffer: { - msgpack_rpc_from_buffer(cur.aobj->data.buffer, res); + msgpack_rpc_from_buffer(cur.aobj->data.integer, res); break; } case kObjectTypeWindow: { - msgpack_rpc_from_window(cur.aobj->data.window, res); + msgpack_rpc_from_window(cur.aobj->data.integer, res); break; } case kObjectTypeTabpage: { - msgpack_rpc_from_tabpage(cur.aobj->data.tabpage, res); + msgpack_rpc_from_tabpage(cur.aobj->data.integer, res); break; } case kObjectTypeArray: { diff --git a/src/nvim/option.c b/src/nvim/option.c index 81919c00d2..a255165e32 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -2527,7 +2527,7 @@ did_set_string_option ( else if (varp == &p_sbo) { if (check_opt_strings(p_sbo, p_scbopt_values, TRUE) != OK) errmsg = e_invarg; - } else if (varp == &p_ambw || (bool *)varp == &p_emoji) { + } else if (varp == &p_ambw || (int *)varp == &p_emoji) { // 'ambiwidth' if (check_opt_strings(p_ambw, p_ambw_values, false) != OK) { errmsg = e_invarg; @@ -3706,23 +3706,19 @@ set_bool_option ( } } } - } - - /* - * When 'lisp' option changes include/exclude '-' in - * keyword characters. - */ - else if (varp == (char_u *)&(curbuf->b_p_lisp)) { - (void)buf_init_chartab(curbuf, FALSE); /* ignore errors */ - } - /* when 'title' changed, may need to change the title; same for 'icon' */ - else if ((int *)varp == &p_title) { - did_set_title(FALSE); + } else if (varp == (char_u *)&(curbuf->b_p_lisp)) { + // When 'lisp' option changes include/exclude '-' in + // keyword characters. + (void)buf_init_chartab(curbuf, false); // ignore errors + } else if ((int *)varp == &p_title) { + // when 'title' changed, may need to change the title; same for 'icon' + did_set_title(false); } else if ((int *)varp == &p_icon) { - did_set_title(TRUE); - } else if ((bool *)varp == &curbuf->b_changed) { - if (!value) - save_file_ff(curbuf); /* Buffer is unchanged */ + did_set_title(true); + } else if ((int *)varp == &curbuf->b_changed) { + if (!value) { + save_file_ff(curbuf); // Buffer is unchanged + } redraw_titles(); modified_was_set = value; } @@ -3750,11 +3746,12 @@ set_bool_option ( else if ((int *)varp == &curwin->w_p_wrap) { if (curwin->w_p_wrap) curwin->w_leftcol = 0; - } else if ((bool *)varp == &p_ea) { - if (p_ea && !old_value) + } else if ((int *)varp == &p_ea) { + if (p_ea && !old_value) { win_equal(curwin, false, 0); - } else if ((bool *)varp == &p_acd) { - /* Change directories when the 'acd' option is set now. */ + } + } else if ((int *)varp == &p_acd) { + // Change directories when the 'acd' option is set now. do_autochdir(); } /* 'diff' */ @@ -4513,10 +4510,11 @@ get_option_value ( else { /* Special case: 'modified' is b_changed, but we also want to consider * it set when 'ff' or 'fenc' changed. */ - if ((bool *)varp == &curbuf->b_changed) + if ((int *)varp == &curbuf->b_changed) { *numval = curbufIsChanged(); - else + } else { *numval = *(int *)varp; + } } return 1; } @@ -4884,14 +4882,15 @@ showoneopt ( varp = get_varp_scope(p, opt_flags); - /* for 'modified' we also need to check if 'ff' or 'fenc' changed. */ - if ((p->flags & P_BOOL) && ((bool *)varp == &curbuf->b_changed - ? !curbufIsChanged() : !*(bool *)varp)) + // for 'modified' we also need to check if 'ff' or 'fenc' changed. + if ((p->flags & P_BOOL) && ((int *)varp == &curbuf->b_changed + ? !curbufIsChanged() : !*(int *)varp)) { MSG_PUTS("no"); - else if ((p->flags & P_BOOL) && *(int *)varp < 0) + } else if ((p->flags & P_BOOL) && *(int *)varp < 0) { MSG_PUTS("--"); - else + } else { MSG_PUTS(" "); + } MSG_PUTS(p->fullname); if (!(p->flags & P_BOOL)) { msg_putchar('='); diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index e085b973ea..8af6f2194f 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -1,8 +1,6 @@ #ifndef NVIM_OPTION_DEFS_H #define NVIM_OPTION_DEFS_H -#include <stdbool.h> - #include "nvim/types.h" #include "nvim/macros.h" // For EXTERN @@ -296,16 +294,16 @@ enum { * The following are actual variables for the options */ -EXTERN long p_aleph; /* 'aleph' */ -EXTERN bool p_acd; /* 'autochdir' */ -EXTERN char_u *p_ambw; /* 'ambiwidth' */ -EXTERN int p_ar; /* 'autoread' */ -EXTERN int p_aw; /* 'autowrite' */ -EXTERN int p_awa; /* 'autowriteall' */ -EXTERN char_u *p_bs; /* 'backspace' */ -EXTERN char_u *p_bg; /* 'background' */ -EXTERN int p_bk; /* 'backup' */ -EXTERN char_u *p_bkc; /* 'backupcopy' */ +EXTERN long p_aleph; // 'aleph' +EXTERN int p_acd; // 'autochdir' +EXTERN char_u *p_ambw; // 'ambiwidth' +EXTERN int p_ar; // 'autoread' +EXTERN int p_aw; // 'autowrite' +EXTERN int p_awa; // 'autowriteall' +EXTERN char_u *p_bs; // 'backspace' +EXTERN char_u *p_bg; // 'background' +EXTERN int p_bk; // 'backup' +EXTERN char_u *p_bkc; // 'backupcopy' EXTERN unsigned int bkc_flags; ///< flags from 'backupcopy' #ifdef IN_OPTION_C static char *(p_bkc_values[]) = @@ -397,14 +395,15 @@ EXTERN char_u *p_dir; /* 'directory' */ EXTERN char_u *p_dy; /* 'display' */ EXTERN unsigned dy_flags; #ifdef IN_OPTION_C -static char *(p_dy_values[]) = {"lastline", "uhex", NULL}; +static char *(p_dy_values[]) = { "lastline", "truncate", "uhex", NULL }; #endif #define DY_LASTLINE 0x001 -#define DY_UHEX 0x002 +#define DY_TRUNCATE 0x002 +#define DY_UHEX 0x004 EXTERN int p_ed; // 'edcompatible' -EXTERN bool p_emoji; // 'emoji' +EXTERN int p_emoji; // 'emoji' EXTERN char_u *p_ead; // 'eadirection' -EXTERN bool p_ea; // 'equalalways' +EXTERN int p_ea; // 'equalalways' EXTERN char_u *p_ep; // 'equalprg' EXTERN int p_eb; // 'errorbells' EXTERN char_u *p_ef; // 'errorfile' @@ -416,7 +415,7 @@ EXTERN int p_ek; // 'esckeys' EXTERN int p_exrc; // 'exrc' EXTERN char_u *p_fencs; // 'fileencodings' EXTERN char_u *p_ffs; // 'fileformats' -EXTERN bool p_fic; // 'fileignorecase' +EXTERN int p_fic; // 'fileignorecase' EXTERN char_u *p_fcl; // 'foldclose' EXTERN long p_fdls; // 'foldlevelstart' EXTERN char_u *p_fdo; // 'foldopen' @@ -621,7 +620,7 @@ EXTERN long p_titlelen; ///< 'titlelen' EXTERN char_u *p_titleold; ///< 'titleold' EXTERN char_u *p_titlestring; ///< 'titlestring' EXTERN char_u *p_tsr; ///< 'thesaurus' -EXTERN bool p_tgc; ///< 'termguicolors' +EXTERN int p_tgc; ///< 'termguicolors' EXTERN int p_ttimeout; ///< 'ttimeout' EXTERN long p_ttm; ///< 'ttimeoutlen' EXTERN char_u *p_udir; ///< 'undodir' @@ -650,26 +649,26 @@ char_u *p_vfile = (char_u *)""; /* used before options are initialized */ #else extern char_u *p_vfile; /* 'verbosefile' */ #endif -EXTERN int p_warn; /* 'warn' */ -EXTERN char_u *p_wop; /* 'wildoptions' */ -EXTERN long p_window; /* 'window' */ -EXTERN char_u *p_wak; /* 'winaltkeys' */ -EXTERN char_u *p_wig; /* 'wildignore' */ -EXTERN char_u *p_ww; /* 'whichwrap' */ -EXTERN long p_wc; /* 'wildchar' */ -EXTERN long p_wcm; /* 'wildcharm' */ -EXTERN bool p_wic; ///< 'wildignorecase' -EXTERN char_u *p_wim; /* 'wildmode' */ -EXTERN int p_wmnu; /* 'wildmenu' */ -EXTERN long p_wh; /* 'winheight' */ -EXTERN long p_wmh; /* 'winminheight' */ -EXTERN long p_wmw; /* 'winminwidth' */ -EXTERN long p_wiw; /* 'winwidth' */ -EXTERN bool p_ws; /* 'wrapscan' */ -EXTERN int p_write; /* 'write' */ -EXTERN int p_wa; /* 'writeany' */ -EXTERN int p_wb; /* 'writebackup' */ -EXTERN long p_wd; /* 'writedelay' */ +EXTERN int p_warn; // 'warn' +EXTERN char_u *p_wop; // 'wildoptions' +EXTERN long p_window; // 'window' +EXTERN char_u *p_wak; // 'winaltkeys' +EXTERN char_u *p_wig; // 'wildignore' +EXTERN char_u *p_ww; // 'whichwrap' +EXTERN long p_wc; // 'wildchar' +EXTERN long p_wcm; // 'wildcharm' +EXTERN int p_wic; // 'wildignorecase' +EXTERN char_u *p_wim; // 'wildmode' +EXTERN int p_wmnu; // 'wildmenu' +EXTERN long p_wh; // 'winheight' +EXTERN long p_wmh; // 'winminheight' +EXTERN long p_wmw; // 'winminwidth' +EXTERN long p_wiw; // 'winwidth' +EXTERN int p_ws; // 'wrapscan' +EXTERN int p_write; // 'write' +EXTERN int p_wa; // 'writeany' +EXTERN int p_wb; // 'writebackup' +EXTERN long p_wd; // 'writedelay' EXTERN int p_force_on; ///< options that cannot be turned off. EXTERN int p_force_off; ///< options that cannot be turned on. diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 47dd640e59..3e4d016fe7 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -1401,7 +1401,7 @@ static void win_update(win_T *wp) && wp->w_lines[idx].wl_valid && wp->w_lines[idx].wl_lnum == lnum && lnum > wp->w_topline - && !(dy_flags & DY_LASTLINE) + && !(dy_flags & (DY_LASTLINE | DY_TRUNCATE)) && srow + wp->w_lines[idx].wl_size > wp->w_height && diff_check_fill(wp, lnum) == 0 ) { @@ -1484,10 +1484,20 @@ static void win_update(win_T *wp) /* Window ends in filler lines. */ wp->w_botline = lnum; wp->w_filler_rows = wp->w_height - srow; - } else if (dy_flags & DY_LASTLINE) { /* 'display' has "lastline" */ - /* - * Last line isn't finished: Display "@@@" at the end. - */ + } else if (dy_flags & DY_TRUNCATE) { // 'display' has "truncate" + int scr_row = wp->w_winrow + wp->w_height - 1; + + // Last line isn't finished: Display "@@@" in the last screen line. + screen_puts_len((char_u *)"@@", 2, scr_row, wp->w_wincol, + hl_attr(HLF_AT)); + + screen_fill(scr_row, scr_row + 1, + (int)wp->w_wincol + 2, (int)W_ENDCOL(wp), + '@', ' ', hl_attr(HLF_AT)); + set_empty_rows(wp, srow); + wp->w_botline = lnum; + } else if (dy_flags & DY_LASTLINE) { // 'display' has "lastline" + // Last line isn't finished: Display "@@@" at the end. screen_fill(wp->w_winrow + wp->w_height - 1, wp->w_winrow + wp->w_height, W_ENDCOL(wp) - 3, W_ENDCOL(wp), diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 6fd7603629..b49ae9da21 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -5537,7 +5537,7 @@ void ex_ownsyntax(exarg_T *eap) } } -int syntax_present(win_T *win) +bool syntax_present(win_T *win) { return win->w_s->b_syn_patterns.ga_len != 0 || win->w_s->b_syn_clusters.ga_len != 0 diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index 036a4c0470..87c1cd2c58 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -4,6 +4,8 @@ source test_assign.vim source test_cursor_func.vim source test_ex_undo.vim +source test_expr.vim +source test_expr_utf8.vim source test_feedkeys.vim source test_cmdline.vim source test_menu.vim diff --git a/src/nvim/testdir/test_expr.vim b/src/nvim/testdir/test_expr.vim new file mode 100644 index 0000000000..7ea4ebc7df --- /dev/null +++ b/src/nvim/testdir/test_expr.vim @@ -0,0 +1,25 @@ +" Tests for expressions. + +func Test_strgetchar() + call assert_equal(char2nr('a'), strgetchar('axb', 0)) + call assert_equal(char2nr('x'), strgetchar('axb', 1)) + call assert_equal(char2nr('b'), strgetchar('axb', 2)) + + call assert_equal(-1, strgetchar('axb', -1)) + call assert_equal(-1, strgetchar('axb', 3)) + call assert_equal(-1, strgetchar('', 0)) +endfunc + +func Test_strcharpart() + call assert_equal('a', strcharpart('axb', 0, 1)) + call assert_equal('x', strcharpart('axb', 1, 1)) + call assert_equal('b', strcharpart('axb', 2, 1)) + call assert_equal('xb', strcharpart('axb', 1)) + + call assert_equal('', strcharpart('axb', 1, 0)) + call assert_equal('', strcharpart('axb', 1, -1)) + call assert_equal('', strcharpart('axb', -1, 1)) + call assert_equal('', strcharpart('axb', -2, 2)) + + call assert_equal('a', strcharpart('axb', -1, 2)) +endfunc diff --git a/src/nvim/testdir/test_expr_utf8.vim b/src/nvim/testdir/test_expr_utf8.vim new file mode 100644 index 0000000000..7bdcb4f65f --- /dev/null +++ b/src/nvim/testdir/test_expr_utf8.vim @@ -0,0 +1,38 @@ +" Tests for expressions using utf-8. +if !has('multi_byte') + finish +endif +scriptencoding utf-8 + +func Test_strgetchar_utf8() + call assert_equal(char2nr('á'), strgetchar('áxb', 0)) + call assert_equal(char2nr('x'), strgetchar('áxb', 1)) + + call assert_equal(char2nr('a'), strgetchar('àxb', 0)) + call assert_equal(char2nr('̀'), strgetchar('àxb', 1)) + call assert_equal(char2nr('x'), strgetchar('àxb', 2)) + + call assert_equal(char2nr('あ'), strgetchar('あaい', 0)) + call assert_equal(char2nr('a'), strgetchar('あaい', 1)) + call assert_equal(char2nr('い'), strgetchar('あaい', 2)) +endfunc + +func Test_strcharpart_utf8() + call assert_equal('áxb', strcharpart('áxb', 0)) + call assert_equal('á', strcharpart('áxb', 0, 1)) + call assert_equal('x', strcharpart('áxb', 1, 1)) + + call assert_equal('いうeお', strcharpart('あいうeお', 1)) + call assert_equal('い', strcharpart('あいうeお', 1, 1)) + call assert_equal('いう', strcharpart('あいうeお', 1, 2)) + call assert_equal('いうe', strcharpart('あいうeお', 1, 3)) + call assert_equal('いうeお', strcharpart('あいうeお', 1, 4)) + call assert_equal('eお', strcharpart('あいうeお', 3)) + call assert_equal('e', strcharpart('あいうeお', 3, 1)) + + call assert_equal('あ', strcharpart('あいうeお', -3, 4)) + + call assert_equal('a', strcharpart('àxb', 0, 1)) + call assert_equal('̀', strcharpart('àxb', 1, 1)) + call assert_equal('x', strcharpart('àxb', 2, 1)) +endfunc diff --git a/src/nvim/testdir/test_tabpage.vim b/src/nvim/testdir/test_tabpage.vim index e6b85d6e14..0bf7d056de 100644 --- a/src/nvim/testdir/test_tabpage.vim +++ b/src/nvim/testdir/test_tabpage.vim @@ -186,4 +186,62 @@ function Test_tabpage_with_autocmd() bw! endfunction +function Test_tabpage_with_tab_modifier() + for n in range(4) + tabedit + endfor + + function s:check_tab(pre_nr, cmd, post_nr) + exec 'tabnext ' . a:pre_nr + exec a:cmd + call assert_equal(a:post_nr, tabpagenr()) + call assert_equal('help', &filetype) + helpclose + endfunc + + call s:check_tab(1, 'tab help', 2) + call s:check_tab(1, '3tab help', 4) + call s:check_tab(1, '.tab help', 2) + call s:check_tab(1, '.+1tab help', 3) + call s:check_tab(1, '0tab help', 1) + call s:check_tab(2, '+tab help', 4) + call s:check_tab(2, '+2tab help', 5) + call s:check_tab(4, '-tab help', 4) + call s:check_tab(4, '-2tab help', 3) + call s:check_tab(3, '$tab help', 6) + call assert_fails('99tab help', 'E16:') + call assert_fails('+99tab help', 'E16:') + call assert_fails('-99tab help', 'E16:') + + delfunction s:check_tab + tabonly! + bw! +endfunction + +func Test_tabnext_on_buf_unload1() + " This once caused a crash + new + tabedit + tabfirst + au BufUnload <buffer> tabnext + q + + while tabpagenr('$') > 1 + bwipe! + endwhile +endfunc + +func Test_tabnext_on_buf_unload2() + " This once caused a crash + tabedit + autocmd BufUnload <buffer> tabnext + file x + edit y + + while tabpagenr('$') > 1 + bwipe! + endwhile +endfunc + + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index f252b00be2..5e30517c5a 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -611,6 +611,7 @@ static void suspend_event(void **argv) bool enable_mouse = data->mouse_enabled; tui_terminal_stop(ui); data->cont_received = false; + stream_set_blocking(input_global_fd(), true); // normalize stream (#2598) kill(0, SIGTSTP); while (!data->cont_received) { // poll the event loop until SIGCONT is received @@ -620,6 +621,7 @@ static void suspend_event(void **argv) if (enable_mouse) { tui_mouse_on(ui); } + stream_set_blocking(input_global_fd(), false); // libuv expects this // resume the main thread CONTINUE(data->bridge); } diff --git a/src/nvim/version.c b/src/nvim/version.c index 0cb6ea199b..055a997cd4 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -7,6 +7,7 @@ #include <assert.h> #include <limits.h> +#include "nvim/api/private/helpers.h" #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/iconv.h" @@ -129,10 +130,10 @@ static int included_patches[] = { // 2315, // 2314, // 2313, - // 2312, + 2312, // 2311, // 2310 NA - // 2309, + 2309, // 2308 NA // 2307, // 2306, @@ -204,7 +205,7 @@ static int included_patches[] = { // 2240, // 2239, // 2238 NA - // 2237, + 2237, // 2236, // 2235, // 2234 NA @@ -229,7 +230,7 @@ static int included_patches[] = { // 2215, // 2214 NA 2213, - // 2212, + 2212, // 2211 NA // 2210 NA // 2209, @@ -313,7 +314,7 @@ static int included_patches[] = { // 2131 NA // 2130 NA // 2129 NA - // 2128, + 2128, // 2127, // 2126, // 2125, @@ -332,7 +333,7 @@ static int included_patches[] = { 2112, // 2111, // 2110, - // 2109, + 2109, // 2108 NA // 2107, // 2106, @@ -660,10 +661,10 @@ static int included_patches[] = { // 1785, // 1784 NA // 1783, - // 1782, + 1782, // 1781, // 1780, - // 1779, + 1779, // 1778 NA // 1777 NA // 1776 NA @@ -701,19 +702,19 @@ static int included_patches[] = { // 1745 NA // 1744 NA // 1743 NA - // 1742, - // 1741, + 1742, + 1741, 1740, // 1739, // 1738, // 1737 NA // 1736 NA // 1735, - // 1734, + 1734, // 1733 NA 1732, // 1731, - // 1730, + 1730, // 1729 NA 1728, // 1727, @@ -2457,20 +2458,72 @@ static char *(extra_patches[]) = { NULL }; -/// Checks whether patch `n` has been included. +/// Compares a version string to the current Nvim version. /// -/// @param n The patch number. +/// @param version Version string like "1.3.42" /// -/// @return TRUE if patch "n" has been included. -int has_patch(int n) +/// @return true if Nvim is at or above the version. +bool has_nvim_version(char *version_str) + FUNC_ATTR_NONNULL_ALL { - int i; - for (i = 0; included_patches[i] != 0; ++i) { + char *p = version_str; + int major = 0; + int minor = 0; + int patch = 0; + + if (!ascii_isdigit(*p)) { + return false; + } + major = atoi(p); + p = strchr(p, '.'); // Find the next dot. + + if (p) { + p++; // Advance past the dot. + if (!ascii_isdigit(*p)) { + return false; + } + minor = atoi(p); + p = strchr(p, '.'); + if (p) { + p++; + if (!ascii_isdigit(*p)) { + return false; + } + patch = atoi(p); + } + } + + return (major < NVIM_VERSION_MAJOR + || (major == NVIM_VERSION_MAJOR + && (minor < NVIM_VERSION_MINOR + || (minor == NVIM_VERSION_MINOR + && patch <= NVIM_VERSION_PATCH)))); +} + +/// Checks whether a Vim patch has been included. +/// +/// @param n Patch number. +/// +/// @return true if patch `n` has been included. +bool has_vim_patch(int n) +{ + for (int i = 0; included_patches[i] != 0; i++) { if (included_patches[i] == n) { - return TRUE; + return true; } } - return FALSE; + return false; +} + +Dictionary version_dict(void) { + Dictionary d = ARRAY_DICT_INIT; + PUT(d, "major", INTEGER_OBJ(NVIM_VERSION_MAJOR)); + PUT(d, "minor", INTEGER_OBJ(NVIM_VERSION_MINOR)); + PUT(d, "patch", INTEGER_OBJ(NVIM_VERSION_PATCH)); + PUT(d, "api_level", INTEGER_OBJ(NVIM_API_LEVEL)); + PUT(d, "api_compatible", INTEGER_OBJ(NVIM_API_LEVEL_COMPAT)); + PUT(d, "api_prerelease", BOOLEAN_OBJ(NVIM_API_PRERELEASE)); + return d; } void ex_version(exarg_T *eap) @@ -2529,7 +2582,11 @@ static void list_features(void) } } else { while (msg_col % width) { + int old_msg_col = msg_col; msg_putchar(' '); + if (old_msg_col == msg_col) { + break; // XXX: Avoid infinite loop. + } } } } else { diff --git a/src/nvim/window.c b/src/nvim/window.c index 03a2e9a842..9c6a2e26a6 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -1065,6 +1065,23 @@ bool win_valid(win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT return false; } +/// Check if "win" is a pointer to an existing window in any tabpage. +/// +/// @param win window to check +bool win_valid_any_tab(win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (win == NULL) { + return false; + } + + FOR_ALL_TAB_WINDOWS(tp, wp) { + if (wp == win) { + return true; + } + } + return false; +} + /* * Return the number of windows. */ @@ -1918,7 +1935,7 @@ int win_close(win_T *win, int free_buf) if (win->w_buffer != NULL) { win->w_closing = true; close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, true); - if (win_valid(win)) { + if (win_valid_any_tab(win)) { win->w_closing = false; } @@ -1938,11 +1955,19 @@ int win_close(win_T *win, int free_buf) curwin->w_buffer = curbuf; getout(0); } - /* Autocommands may have closed the window already, or closed the only - * other window or moved to another tab page. */ - else if (!win_valid(win) || last_window() || curtab != prev_curtab - || close_last_window_tabpage(win, free_buf, prev_curtab)) + // Autocommands may have moved to another tab page. + if (curtab != prev_curtab && win_valid_any_tab(win) + && win->w_buffer == NULL) { + // Need to close the window anyway, since the buffer is NULL. + win_close_othertab(win, false, prev_curtab); return FAIL; + } + // Autocommands may have closed the window already, or closed the only + // other window or moved to another tab page. + if (!win_valid(win) || last_window() + || close_last_window_tabpage(win, free_buf, prev_curtab)) { + return FAIL; + } // let terminal buffers know that this window dimensions may be ignored win->w_closing = true; @@ -2019,12 +2044,16 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp) tabpage_T *ptp = NULL; int free_tp = FALSE; - assert(win->w_buffer); // to avoid np dereference warning in next line - if (win->w_closing || win->w_buffer->b_closing) - return; /* window is already being closed */ + // Get here with win->w_buffer == NULL when win_close() detects the tab page + // changed. + if (win->w_closing || (win->w_buffer != NULL && win->w_buffer->b_closing)) { + return; // window is already being closed + } - /* Close the link to the buffer. */ - close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, FALSE); + if (win->w_buffer != NULL) { + // Close the link to the buffer. + close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, false); + } /* Careful: Autocommands may have closed the tab page or made it the * current tab page. */ @@ -3213,11 +3242,8 @@ void goto_tabpage(int n) int i; if (text_locked()) { - /* Not allowed when editing the command line. */ - if (cmdwin_type != 0) - EMSG(_(e_cmdwin)); - else - EMSG(_(e_secure)); + // Not allowed when editing the command line. + text_locked_msg(); return; } diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua index 71ec213b97..3d3a2bb046 100644 --- a/test/functional/api/buffer_spec.lua +++ b/test/functional/api/buffer_spec.lua @@ -1,4 +1,3 @@ --- Sanity checks for buffer_* API calls via msgpack-rpc local helpers = require('test.functional.helpers')(after_each) local clear, nvim, buffer = helpers.clear, helpers.nvim, helpers.buffer local curbuf, curwin, eq = helpers.curbuf, helpers.curwin, helpers.eq @@ -6,7 +5,7 @@ local curbufmeths, ok = helpers.curbufmeths, helpers.ok local funcs, request = helpers.funcs, helpers.request local NIL = helpers.NIL -describe('buffer_* functions', function() +describe('api/buf', function() before_each(clear) -- access deprecated functions diff --git a/test/functional/api/server_notifications_spec.lua b/test/functional/api/server_notifications_spec.lua index 88e8c60560..78639d7ed7 100644 --- a/test/functional/api/server_notifications_spec.lua +++ b/test/functional/api/server_notifications_spec.lua @@ -1,4 +1,3 @@ --- Tests for nvim notifications local helpers = require('test.functional.helpers')(after_each) local eq, clear, eval, execute, nvim, next_message = helpers.eq, helpers.clear, helpers.eval, helpers.execute, helpers.nvim, diff --git a/test/functional/api/tabpage_spec.lua b/test/functional/api/tabpage_spec.lua index 90940e9577..e10f30085f 100644 --- a/test/functional/api/tabpage_spec.lua +++ b/test/functional/api/tabpage_spec.lua @@ -1,4 +1,3 @@ --- Sanity checks for tabpage_* API calls via msgpack-rpc local helpers = require('test.functional.helpers')(after_each) local clear, nvim, tabpage, curtab, eq, ok = helpers.clear, helpers.nvim, helpers.tabpage, helpers.curtab, helpers.eq, @@ -8,7 +7,7 @@ local funcs = helpers.funcs local request = helpers.request local NIL = helpers.NIL -describe('tabpage_* functions', function() +describe('api/tabpage', function() before_each(clear) describe('list_wins and get_win', function() diff --git a/test/functional/api/version_spec.lua b/test/functional/api/version_spec.lua new file mode 100644 index 0000000000..3efd00ddbe --- /dev/null +++ b/test/functional/api/version_spec.lua @@ -0,0 +1,71 @@ +local helpers = require('test.functional.helpers')(after_each) +local mpack = require('mpack') +local clear, funcs, eq = helpers.clear, helpers.funcs, helpers.eq + +local function read_mpack_file(fname) + local fd = io.open(fname, 'rb') + local data = fd:read('*a') + fd:close() + local unpack = mpack.Unpacker() + return unpack(data) +end + +-- Remove metadata that is not essential to backwards-compatibility. +local function remove_function_metadata(fspec) + fspec['can_fail'] = nil + fspec['async'] = nil + fspec['method'] = nil + fspec['since'] = nil + fspec['deprecated_since'] = nil + fspec['receives_channel_id'] = nil + for idx, _ in ipairs(fspec['parameters']) do + fspec['parameters'][idx][2] = '' -- Remove parameter name. + end + return fspec +end + +describe("api_info()['version']", function() + before_each(clear) + + it("returns API level", function() + local version = helpers.call('api_info')['version'] + local current = version['api_level'] + local compat = version['api_compatible'] + eq("number", type(current)) + eq("number", type(compat)) + assert(current >= compat) + end) + + it("returns Nvim version", function() + local version = helpers.call('api_info')['version'] + local major = version['major'] + local minor = version['minor'] + local patch = version['patch'] + eq("number", type(major)) + eq("number", type(minor)) + eq("number", type(patch)) + eq(1, funcs.has("nvim-"..major.."."..minor.."."..patch)) + eq(0, funcs.has("nvim-"..major.."."..minor.."."..(patch + 1))) + eq(0, funcs.has("nvim-"..major.."."..(minor + 1).."."..patch)) + eq(0, funcs.has("nvim-"..(major + 1).."."..minor.."."..patch)) + end) + + it("api_compatible level is valid", function() + local api = helpers.call('api_info') + local compat = api['version']['api_compatible'] + local path = 'test/functional/fixtures/api_level_' + ..tostring(compat)..'.mpack' + + -- Verify that the current API function signatures match those of the API + -- level for which we claim compatibility. + local old_api = read_mpack_file(path) + for _, fn_old in ipairs(old_api['functions']) do + for _, fn_new in ipairs(api['functions']) do + if fn_old['name'] == fn_new['name'] then + eq(remove_function_metadata(fn_old), + remove_function_metadata(fn_new)) + end + end + end + end) +end) diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 724d9f1b57..ce6c52e334 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1,4 +1,3 @@ --- Sanity checks for vim_* API calls via msgpack-rpc local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local NIL = helpers.NIL @@ -9,10 +8,10 @@ local meths = helpers.meths local funcs = helpers.funcs local request = helpers.request -describe('vim_* functions', function() +describe('api', function() before_each(clear) - describe('command', function() + describe('nvim_command', function() it('works', function() local fname = helpers.tmpname() nvim('command', 'new') @@ -29,9 +28,18 @@ describe('vim_* functions', function() f:close() os.remove(fname) end) + + it("VimL error: fails (VimL error), does NOT update v:errmsg", function() + -- Most API methods return generic errors (or no error) if a VimL + -- expression fails; nvim_command returns the VimL error details. + local status, rv = pcall(nvim, "command", "bogus_command") + eq(false, status) -- nvim_command() failed. + eq("E492:", string.match(rv, "E%d*:")) -- VimL error was returned. + eq("", nvim("eval", "v:errmsg")) -- v:errmsg was not updated. + end) end) - describe('eval', function() + describe('nvim_eval', function() it('works', function() nvim('command', 'let g:v1 = "a"') nvim('command', 'let g:v2 = [1, 2, {"v3": 3}]') @@ -46,18 +54,41 @@ describe('vim_* functions', function() it('works under deprecated name', function() eq(2, request("vim_eval", "1+1")) end) + + it("VimL error: fails (generic error), does NOT update v:errmsg", function() + local status, rv = pcall(nvim, "eval", "bogus expression") + eq(false, status) -- nvim_eval() failed. + ok(nil ~= string.find(rv, "Failed to evaluate expression")) + eq("", nvim("eval", "v:errmsg")) -- v:errmsg was not updated. + end) end) - describe('call_function', function() + describe('nvim_call_function', function() it('works', function() nvim('call_function', 'setqflist', {{{ filename = 'something', lnum = 17}}, 'r'}) eq(17, nvim('call_function', 'getqflist', {})[1].lnum) eq(17, nvim('call_function', 'eval', {17})) eq('foo', nvim('call_function', 'simplify', {'this/./is//redundant/../../../foo'})) end) + + it("VimL error: fails (generic error), does NOT update v:errmsg", function() + local status, rv = pcall(nvim, "call_function", "bogus function", {"arg1"}) + eq(false, status) -- nvim_call_function() failed. + ok(nil ~= string.find(rv, "Error calling function")) + eq("", nvim("eval", "v:errmsg")) -- v:errmsg was not updated. + end) + end) + + describe('nvim_input', function() + it("VimL error: does NOT fail, updates v:errmsg", function() + local status, _ = pcall(nvim, "input", ":call bogus_fn()<CR>") + local v_errnum = string.match(nvim("eval", "v:errmsg"), "E%d*:") + eq(true, status) -- nvim_input() did not fail. + eq("E117:", v_errnum) -- v:errmsg was updated. + end) end) - describe('strwidth', function() + describe('nvim_strwidth', function() it('works', function() eq(3, nvim('strwidth', 'abc')) -- 6 + (neovim) @@ -70,7 +101,7 @@ describe('vim_* functions', function() end) end) - describe('{get,set}_current_line', function() + describe('nvim_get_current_line, nvim_set_current_line', function() it('works', function() eq('', nvim('get_current_line')) nvim('set_current_line', 'abc') @@ -78,7 +109,7 @@ describe('vim_* functions', function() end) end) - describe('{get,set,del}_var', function() + describe('nvim_get_var, nvim_set_var, nvim_del_var', function() it('works', function() nvim('set_var', 'lua', {1, 2, {['3'] = 1}}) eq({1, 2, {['3'] = 1}}, nvim('get_var', 'lua')) @@ -109,7 +140,7 @@ describe('vim_* functions', function() end) end) - describe('{get,set}_option', function() + describe('nvim_get_option, nvim_set_option', function() it('works', function() ok(nvim('get_option', 'equalalways')) nvim('set_option', 'equalalways', false) @@ -117,7 +148,7 @@ describe('vim_* functions', function() end) end) - describe('{get,set}_current_buf and list_bufs', function() + describe('nvim_{get,set}_current_buf, nvim_list_bufs', function() it('works', function() eq(1, #nvim('list_bufs')) eq(nvim('list_bufs')[1], nvim('get_current_buf')) @@ -129,7 +160,7 @@ describe('vim_* functions', function() end) end) - describe('{get,set}_current_win and list_wins', function() + describe('nvim_{get,set}_current_win, nvim_list_wins', function() it('works', function() eq(1, #nvim('list_wins')) eq(nvim('list_wins')[1], nvim('get_current_win')) @@ -142,7 +173,7 @@ describe('vim_* functions', function() end) end) - describe('{get,set}_current_tabpage and list_tabpages', function() + describe('nvim_{get,set}_current_tabpage, nvim_list_tabpages', function() it('works', function() eq(1, #nvim('list_tabpages')) eq(nvim('list_tabpages')[1], nvim('get_current_tabpage')) @@ -161,7 +192,7 @@ describe('vim_* functions', function() end) end) - describe('replace_termcodes', function() + describe('nvim_replace_termcodes', function() it('escapes K_SPECIAL as K_SPECIAL KS_SPECIAL KE_FILLER', function() eq('\128\254X', helpers.nvim('replace_termcodes', '\128', true, true, true)) end) @@ -183,7 +214,7 @@ describe('vim_* functions', function() end) end) - describe('feedkeys', function() + describe('nvim_feedkeys', function() it('CSI escaping', function() local function on_setup() -- notice the special char(…) \xe2\80\xa6 @@ -210,7 +241,7 @@ describe('vim_* functions', function() end) end) - describe('err_write', function() + describe('nvim_err_write', function() local screen before_each(function() @@ -298,7 +329,7 @@ describe('vim_* functions', function() end) end) - describe('call_atomic', function() + describe('nvim_call_atomic', function() it('works', function() meths.buf_set_lines(0, 0, -1, true, {'first'}) local req = { diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua index bf2bf55fb3..465bda6bc9 100644 --- a/test/functional/api/window_spec.lua +++ b/test/functional/api/window_spec.lua @@ -1,4 +1,3 @@ --- Sanity checks for window_* API calls via msgpack-rpc local helpers = require('test.functional.helpers')(after_each) local clear, nvim, curbuf, curbuf_contents, window, curwin, eq, neq, ok, feed, insert, eval = helpers.clear, helpers.nvim, helpers.curbuf, @@ -29,7 +28,7 @@ local function is_visible(str) return false end -describe('window_* functions', function() +describe('api/win', function() before_each(clear) describe('get_buf', function() diff --git a/test/functional/eval/api_functions_spec.lua b/test/functional/eval/api_functions_spec.lua index 2ef67e7808..21dd228145 100644 --- a/test/functional/eval/api_functions_spec.lua +++ b/test/functional/eval/api_functions_spec.lua @@ -106,7 +106,7 @@ describe('api functions', function() it('have metadata accessible with api_info()', function() local api_keys = eval("sort(keys(api_info()))") - eq({'error_types', 'functions', 'types'}, api_keys) + eq({'error_types', 'functions', 'types', 'version'}, api_keys) end) it('are highlighted by vim.vim syntax file', function() @@ -144,5 +144,4 @@ describe('api functions', function() ]]) screen:detach() end) - end) diff --git a/test/functional/eval/has_spec.lua b/test/functional/eval/has_spec.lua new file mode 100644 index 0000000000..97b3b0e620 --- /dev/null +++ b/test/functional/eval/has_spec.lua @@ -0,0 +1,52 @@ +local helpers = require('test.functional.helpers')(after_each) +local eq = helpers.eq +local clear = helpers.clear +local funcs = helpers.funcs + +describe('has()', function() + before_each(clear) + + it('"nvim-x.y.z"', function() + eq(0, funcs.has("nvim-")) + eq(0, funcs.has("nvim- ")) + eq(0, funcs.has("nvim- \t ")) + eq(0, funcs.has("nvim-0. 1. 1")) + eq(0, funcs.has("nvim-0. 1.1")) + eq(0, funcs.has("nvim-0.1. 1")) + eq(0, funcs.has("nvim-a")) + eq(0, funcs.has("nvim-a.b.c")) + eq(0, funcs.has("nvim-0.b.c")) + eq(0, funcs.has("nvim-0.0.c")) + eq(0, funcs.has("nvim-0.b.0")) + eq(0, funcs.has("nvim-a.b.0")) + eq(0, funcs.has("nvim-.0.0.0")) + eq(0, funcs.has("nvim-.0")) + eq(0, funcs.has("nvim-0.")) + eq(0, funcs.has("nvim-0..")) + eq(0, funcs.has("nvim-.")) + eq(0, funcs.has("nvim-..")) + eq(0, funcs.has("nvim-...")) + eq(0, funcs.has("nvim-42")) + eq(0, funcs.has("nvim-9999")) + eq(0, funcs.has("nvim-99.001.05")) + + eq(1, funcs.has("nvim")) + eq(1, funcs.has("nvim-0")) + eq(1, funcs.has("nvim-0.1")) + eq(1, funcs.has("nvim-0.0.0")) + eq(1, funcs.has("nvim-0.1.1.")) + eq(1, funcs.has("nvim-0.1.1.abc")) + eq(1, funcs.has("nvim-0.1.1..")) + eq(1, funcs.has("nvim-0.1.1.. ..")) + eq(1, funcs.has("nvim-0.1.1.... ")) + eq(1, funcs.has("nvim-0.0.0")) + eq(1, funcs.has("nvim-0.0.1")) + eq(1, funcs.has("nvim-0.1.0")) + eq(1, funcs.has("nvim-0.1.1")) + eq(1, funcs.has("nvim-0.1.5")) + eq(1, funcs.has("nvim-0000.001.05")) + eq(1, funcs.has("nvim-0.01.005")) + eq(1, funcs.has("nvim-00.001.05")) + end) + +end) diff --git a/test/functional/eval/modeline_spec.lua b/test/functional/eval/modeline_spec.lua new file mode 100644 index 0000000000..0be7210a76 --- /dev/null +++ b/test/functional/eval/modeline_spec.lua @@ -0,0 +1,19 @@ +local helpers = require('test.functional.helpers')(after_each) +local clear, execute, write_file = helpers.clear, helpers.execute, helpers.write_file +local eq, eval = helpers.eq, helpers.eval + +describe("modeline", function() + local tempfile = helpers.tmpname() + before_each(clear) + + after_each(function() + os.remove(tempfile) + end) + + it('does not crash with a large version number', function() + write_file(tempfile, 'vim100000000000000000000000') + execute('e! ' .. tempfile) + + eq(2, eval('1+1')) -- Still alive? + end) +end) diff --git a/test/functional/eval/msgpack_functions_spec.lua b/test/functional/eval/msgpack_functions_spec.lua index 5b87b05652..f11c08de05 100644 --- a/test/functional/eval/msgpack_functions_spec.lua +++ b/test/functional/eval/msgpack_functions_spec.lua @@ -460,7 +460,7 @@ describe('msgpackparse() function', function() eval(cmd) eval(cmd) -- do it again (try to force segfault) local api_info = eval(cmd) -- do it again - eq({'error_types', 'functions', 'types'}, api_info) + eq({'error_types', 'functions', 'types', 'version'}, api_info) end) it('fails when called with no arguments', function() diff --git a/test/functional/ex_cmds/global_spec.lua b/test/functional/ex_cmds/global_spec.lua new file mode 100644 index 0000000000..81a0ef3248 --- /dev/null +++ b/test/functional/ex_cmds/global_spec.lua @@ -0,0 +1,74 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local clear, feed, source = helpers.clear, helpers.feed, helpers.source + +if helpers.pending_win32(pending) then return end + +describe(':global', function() + before_each(function() + clear() + end) + + it('is interrupted by mapped CTRL-C', function() + if os.getenv("TRAVIS") and os.getenv("CLANG_SANITIZER") == "ASAN_UBSAN" then + -- XXX: ASAN_UBSAN is too slow to react to the CTRL-C. + pending("", function() end) + return + end + + source([[ + set nomore + set undolevels=-1 + nnoremap <C-C> <NOP> + for i in range(0, 99999) + put ='XXX' + endfor + put ='ZZZ' + 1 + .delete + ]]) + + local screen = Screen.new(52, 6) + screen:attach() + screen:set_default_attr_ids({ + [0] = {foreground = Screen.colors.White, + background = Screen.colors.Red}, + [1] = {bold = true, + foreground = Screen.colors.SeaGreen} + }) + + screen:expect([[ + ^XXX | + XXX | + XXX | + XXX | + XXX | + | + ]]) + + local function test_ctrl_c(ms) + feed(":global/^/p<CR>") + helpers.sleep(ms) + feed("<C-C>") + screen:expect([[ + XXX | + XXX | + XXX | + XXX | + {0:Interrupted} | + Interrupt: {1:Press ENTER or type command to continue}^ | + ]]) + end + + -- The test is time-sensitive. Try with different sleep values. + local ms_values = {10, 50, 100} + for i, ms in ipairs(ms_values) do + if i < #ms_values then + local status, _ = pcall(test_ctrl_c, ms) + if status then break end + else -- Call the last attempt directly. + test_ctrl_c(ms) + end + end + end) +end) diff --git a/test/functional/fixtures/api_level_0.mpack b/test/functional/fixtures/api_level_0.mpack Binary files differnew file mode 100644 index 0000000000..75b236a3c1 --- /dev/null +++ b/test/functional/fixtures/api_level_0.mpack diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index 3598ab5e6e..ff62b4de86 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -136,8 +136,8 @@ local function stop() session:stop() end --- Executes an ex-command. VimL errors will manifest as client (lua) errors, and --- v:errmsg will be updated. +-- Executes an ex-command. VimL errors manifest as client (lua) errors, but +-- v:errmsg will not be updated. local function nvim_command(cmd) request('nvim_command', cmd) end diff --git a/test/functional/plugin/health_spec.lua b/test/functional/plugin/health_spec.lua index 4bcaab009f..5b5e5f9ace 100644 --- a/test/functional/plugin/health_spec.lua +++ b/test/functional/plugin/health_spec.lua @@ -47,7 +47,7 @@ describe('health.vim', function() helpers.expect([[ health#success1#check - ================================================================================ + ======================================================================== ## report 1 - SUCCESS: everything is fine @@ -55,7 +55,7 @@ describe('health.vim', function() - SUCCESS: nothing to see here health#success2#check - ================================================================================ + ======================================================================== ## another 1 - SUCCESS: ok ]]) @@ -66,7 +66,7 @@ describe('health.vim', function() helpers.expect([[ health#broken#check - ================================================================================ + ======================================================================== - ERROR: Failed to run healthcheck for "broken" plugin. Exception: caused an error ]]) @@ -77,7 +77,7 @@ describe('health.vim', function() helpers.expect([[ health#non_existent_healthcheck#check - ================================================================================ + ======================================================================== - ERROR: No healthcheck found for "non_existent_healthcheck" plugin. ]]) end) diff --git a/test/functional/shada/marks_spec.lua b/test/functional/shada/marks_spec.lua index 646b0b692e..05d8cda8e3 100644 --- a/test/functional/shada/marks_spec.lua +++ b/test/functional/shada/marks_spec.lua @@ -102,6 +102,18 @@ describe('ShaDa support code', function() eq(2, nvim_current_line()) end) + it('is able to dump and read back mark " from a closed tab', function() + nvim_command('edit ' .. testfilename) + nvim_command('tabedit ' .. testfilename_2) + nvim_command('2') + nvim_command('q!') + nvim_command('qall') + reset() + nvim_command('edit ' .. testfilename_2) + nvim_command('normal! `"') + eq(2, nvim_current_line()) + end) + it('is able to populate v:oldfiles', function() nvim_command('edit ' .. testfilename) local tf_full = curbufmeths.get_name() |