aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.asan-blacklist1
-rw-r--r--BACKERS.md2
-rw-r--r--CMakeLists.txt105
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--cmake/GenerateHelptags.cmake.in2
-rw-r--r--cmake/GetGitRevisionDescription.cmake8
-rw-r--r--config/config.h.in1
-rw-r--r--config/versiondef.h.in5
-rw-r--r--contrib/YouCompleteMe/README.md4
-rw-r--r--contrib/local.mk.example11
-rw-r--r--man/nvim.116
-rw-r--r--runtime/CMakeLists.txt2
-rw-r--r--runtime/autoload/provider/python.vim2
-rw-r--r--runtime/autoload/provider/python3.vim2
-rw-r--r--runtime/doc/Makefile2
-rw-r--r--runtime/doc/autocmd.txt3
-rw-r--r--runtime/doc/develop.txt19
-rw-r--r--runtime/doc/editing.txt4
-rw-r--r--runtime/doc/eval.txt53
-rw-r--r--runtime/doc/fold.txt4
-rw-r--r--runtime/doc/gui.txt4
-rw-r--r--runtime/doc/help.txt1
-rw-r--r--runtime/doc/index.txt3
-rw-r--r--runtime/doc/insert.txt10
-rw-r--r--runtime/doc/motion.txt4
-rw-r--r--runtime/doc/nvim_terminal_emulator.txt2
-rw-r--r--runtime/doc/options.txt79
-rw-r--r--runtime/doc/os_mac.txt116
-rw-r--r--runtime/doc/repeat.txt6
-rw-r--r--runtime/doc/starting.txt12
-rw-r--r--runtime/doc/todo.txt6
-rw-r--r--runtime/doc/various.txt2
-rw-r--r--runtime/doc/vi_diff.txt37
-rw-r--r--runtime/doc/vim_diff.txt9
-rw-r--r--runtime/doc/windows.txt22
-rw-r--r--runtime/filetype.vim7
-rw-r--r--runtime/ftplugin/kconfig.vim13
-rw-r--r--runtime/ftplugin/spec.vim32
-rw-r--r--runtime/ftplugin/zsh.vim9
-rw-r--r--runtime/indent/javascript.vim6
-rw-r--r--runtime/indent/zsh.vim9
-rw-r--r--runtime/syntax/cpp.vim2
-rw-r--r--runtime/syntax/css.vim127
-rw-r--r--runtime/syntax/debchangelog.vim15
-rw-r--r--runtime/syntax/debcontrol.vim4
-rw-r--r--runtime/syntax/debsources.vim34
-rw-r--r--runtime/syntax/groovy.vim2
-rw-r--r--runtime/syntax/kconfig.vim7
-rw-r--r--runtime/syntax/po.vim8
-rw-r--r--runtime/syntax/rc.vim9
-rw-r--r--runtime/syntax/vhdl.vim49
-rw-r--r--runtime/syntax/vim.vim2
-rw-r--r--runtime/syntax/zsh.vim189
-rwxr-xr-xscripts/vim-patch.sh4
-rw-r--r--src/nvim/auevents.lua8
-rw-r--r--src/nvim/buffer.c1004
-rw-r--r--src/nvim/edit.c8
-rw-r--r--src/nvim/eval.c532
-rw-r--r--src/nvim/eval.h41
-rw-r--r--src/nvim/eval_defs.h2
-rw-r--r--src/nvim/ex_cmds.c1
-rw-r--r--src/nvim/ex_cmds.lua34
-rw-r--r--src/nvim/ex_cmds2.c95
-rw-r--r--src/nvim/ex_docmd.c51
-rw-r--r--src/nvim/globals.h2
-rw-r--r--src/nvim/keymap.c2
-rw-r--r--src/nvim/log.h2
-rw-r--r--src/nvim/main.c7
-rw-r--r--src/nvim/memory.c2
-rw-r--r--src/nvim/misc1.c1
-rw-r--r--src/nvim/normal.c42
-rw-r--r--src/nvim/po/CMakeLists.txt2
-rw-r--r--src/nvim/regexp_nfa.c2
-rw-r--r--src/nvim/terminal.h9
-rw-r--r--src/nvim/testdir/test49.vim2
-rw-r--r--src/nvim/tui/input.c32
-rw-r--r--src/nvim/tui/tui.c12
-rw-r--r--src/nvim/undo.c2
-rw-r--r--src/nvim/version.c139
-rw-r--r--src/nvim/version.h1
-rw-r--r--test/functional/autocmd/termclose_spec.lua28
-rw-r--r--test/functional/dict_notifications_spec.lua257
-rw-r--r--test/functional/ex_cmds/oldfiles_spec.lua97
-rw-r--r--test/functional/ex_cmds/profile_spec.lua51
-rw-r--r--test/functional/ex_cmds/wundo_spec.lua17
-rw-r--r--test/functional/provider/python3_spec.lua1
-rw-r--r--test/functional/provider/python_spec.lua1
-rw-r--r--test/functional/shada/marks_spec.lua2
-rw-r--r--test/functional/terminal/ex_terminal_spec.lua6
-rw-r--r--test/functional/terminal/scrollback_spec.lua2
-rw-r--r--test/functional/terminal/tui_spec.lua28
-rw-r--r--test/unit/buffer_spec.lua97
-rw-r--r--third-party/cmake/BuildLibuv.cmake6
-rw-r--r--third-party/cmake/BuildLuajit.cmake2
94 files changed, 2645 insertions, 1074 deletions
diff --git a/.asan-blacklist b/.asan-blacklist
index bd977dfe17..63558170b3 100644
--- a/.asan-blacklist
+++ b/.asan-blacklist
@@ -1,2 +1,3 @@
# libuv queue.h pointer arithmetic is not accepted by asan
fun:queue_node_data
+fun:dictwatcher_node_data
diff --git a/BACKERS.md b/BACKERS.md
index 10c6f42f27..6cfcb0b407 100644
--- a/BACKERS.md
+++ b/BACKERS.md
@@ -104,7 +104,7 @@ Thank you to everyone who backed our [Bountysource fundraiser](https://www.bount
- Michael Ulm www.mulm.at
- Mikael Jansson http://mikaelj.se
- Mikkel Høgh http://mikkel.hoegh.org/
-- Ming Liu http://www.codingupfengshui.io
+- Ming Liu http://ming.codes
- Holger Peters http://www.holger-peters.de
- Alexander Myshov http://myshov.com/
- Darren Cheng http://sanguinerane.com/
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3db32f1966..f11b9995c0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -38,31 +38,37 @@ endif()
# Set available build types for CMake GUIs.
# A different build type can still be set by -DCMAKE_BUILD_TYPE=...
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
- STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
+ STRINGS "Debug" "Dev" "Release" "MinSizeRel" "RelWithDebInfo")
# Set default build type.
if(NOT CMAKE_BUILD_TYPE)
- message(STATUS "CMAKE_BUILD_TYPE not given; setting to 'RelWithDebInfo'.")
- set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose the type of build." FORCE)
+ message(STATUS "CMAKE_BUILD_TYPE not given, defaulting to 'Dev'.")
+ set(CMAKE_BUILD_TYPE "Dev" CACHE STRING "Choose the type of build." FORCE)
endif()
# Version tokens
-include(GetGitRevisionDescription)
-file(TO_NATIVE_PATH ${CMAKE_CURRENT_LIST_DIR}/.git GIT_DIR)
-get_git_head_revision(GIT_REFSPEC NVIM_VERSION_COMMIT)
-if(NOT NVIM_VERSION_COMMIT)
- set(NVIM_VERSION_COMMIT "?")
-endif()
+# - In a git repo, these tokens are _ignored_.
+# - If the current HEAD is tagged, the tag name is used.
+# - Otherwise the result of `git describe` is used.
+# - If not in a git repo (e.g. a tarball) these tokens set the version string.
set(NVIM_VERSION_MAJOR 0)
-set(NVIM_VERSION_MINOR 0)
+set(NVIM_VERSION_MINOR 1)
set(NVIM_VERSION_PATCH 0)
-set(NVIM_VERSION_PRERELEASE "-alpha")
-# TODO(justinmk): UTC time would be nice here #1071
-git_timestamp(GIT_TIMESTAMP)
-# TODO(justinmk): do not set this for "release" builds #1071
-if(GIT_TIMESTAMP)
- set(NVIM_VERSION_BUILD "+${GIT_TIMESTAMP}")
+set(NVIM_VERSION_PRERELEASE "-dev")
+
+file(TO_CMAKE_PATH ${CMAKE_CURRENT_LIST_DIR}/.git FORCED_GIT_DIR)
+include(GetGitRevisionDescription)
+get_git_head_revision(GIT_REFSPEC NVIM_VERSION_COMMIT)
+if(NVIM_VERSION_COMMIT) # is a git repo
+ git_get_exact_tag(NVIM_VERSION_MEDIUM)
+ if(NVIM_VERSION_MEDIUM) # is a tagged release
+ unset(NVIM_VERSION_COMMIT)
+ else() # is a dev build
+ git_describe(NVIM_VERSION_MEDIUM)
+ get_git_head_revision(GIT_REFSPEC NVIM_VERSION_COMMIT)
+ endif()
endif()
+
set(NVIM_VERSION_BUILD_TYPE "${CMAKE_BUILD_TYPE}")
# NVIM_VERSION_CFLAGS set further below.
@@ -74,6 +80,57 @@ if(CMAKE_C_FLAGS_RELEASE MATCHES "-O3")
string(REPLACE "-O3" "-O2" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
endif()
+# Disable logging for release-type builds.
+if(NOT CMAKE_C_FLAGS_RELEASE MATCHES DDISABLE_LOG)
+ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DDISABLE_LOG")
+endif()
+if(NOT CMAKE_C_FLAGS_MINSIZEREL MATCHES DDISABLE_LOG)
+ set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -DDISABLE_LOG")
+endif()
+if(NOT CMAKE_C_FLAGS_RELWITHDEBINFO MATCHES DDISABLE_LOG)
+ set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -DDISABLE_LOG")
+endif()
+
+# Enable assertions for RelWithDebInfo.
+if(CMAKE_C_FLAGS_RELWITHDEBINFO MATCHES DNDEBUG)
+ string(REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
+endif()
+
+# Set build flags for custom Dev build type.
+# -DNDEBUG purposely omitted because we want assertions.
+if(MSVC)
+ SET(CMAKE_C_FLAGS_DEV ""
+ CACHE STRING "Flags used by the compiler during development (optimized, but with debug info and logging) builds."
+ FORCE)
+else()
+ if(CMAKE_COMPILER_IS_GNUCC)
+ check_c_compiler_flag(-Og HAS_OG_FLAG)
+ else()
+ set(HAS_OG_FLAG 0)
+ endif()
+
+ if(HAS_OG_FLAG)
+ set(CMAKE_C_FLAGS_DEV "-Og -g"
+ CACHE STRING "Flags used by the compiler during development (optimized, but with debug info and logging) builds."
+ FORCE)
+ else()
+ set(CMAKE_C_FLAGS_DEV "-O2 -g"
+ CACHE STRING "Flags used by the compiler during development (optimized, but with debug info and logging) builds."
+ FORCE)
+ endif()
+endif()
+SET(CMAKE_EXE_LINKER_FLAGS_DEV ""
+ CACHE STRING "Flags used for linking binaries during development (optimized, but with debug info and logging) builds."
+ FORCE)
+SET(CMAKE_SHARED_LINKER_FLAGS_DEV ""
+ CACHE STRING "Flags used by the shared libraries linker during development (optimized, but with debug info and logging) builds."
+ FORCE)
+
+MARK_AS_ADVANCED(
+ CMAKE_C_FLAGS_DEV
+ CMAKE_EXE_LINKER_FLAGS_DEV
+ CMAKE_SHARED_LINKER_FLAGS_DEV)
+
# Enable -Wconversion.
if(NOT MSVC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wconversion")
@@ -177,22 +234,6 @@ if(TRAVIS_CI_BUILD)
add_definitions(-Werror)
endif()
-if(CMAKE_COMPILER_IS_GNUCC)
- check_c_compiler_flag(-Og HAS_OG_FLAG)
-else()
- set(HAS_OG_FLAG 0)
-endif()
-
-# Set custom build flags for RelWithDebInfo.
-# -DNDEBUG purposely omitted because we want assertions.
-if(HAS_OG_FLAG)
- set(CMAKE_C_FLAGS_RELWITHDEBINFO "-Og -g"
- CACHE STRING "Flags used by the compiler during release builds with debug info." FORCE)
-elseif(NOT MSVC)
- set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g"
- CACHE STRING "Flags used by the compiler during release builds with debug info." FORCE)
-endif()
-
if(CMAKE_BUILD_TYPE MATCHES Debug)
set(DEBUG 1)
else()
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d50019a532..01105d8379 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -28,7 +28,7 @@ If your issue isn't mentioned there:
- For runtime issues, see
[Troubleshooting#runtime-issues][wiki-troubleshooting-runtime-issues].
If your issue isn't mentioned there, try to reproduce your it using
- `nvim` with the smallest possible `nvimrc` (or none at all via `nvim -u
+ `nvim` with the smallest possible `vimrc` (or none at all via `nvim -u
NONE`), to rule out bugs in plugins you're using.
If you're using a plugin manager, comment out your plugins, then add
them back in one by one.
diff --git a/cmake/GenerateHelptags.cmake.in b/cmake/GenerateHelptags.cmake.in
index 0df10d730e..3ced2c0b17 100644
--- a/cmake/GenerateHelptags.cmake.in
+++ b/cmake/GenerateHelptags.cmake.in
@@ -25,7 +25,7 @@ file(WRITE ${EMPTY_FILE} "")
execute_process(
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/bin/nvim
-u NONE
- -esX
+ -es
-c "helptags ++t ."
-c quit
WORKING_DIRECTORY ${HELPTAGS_WORKING_DIRECTORY}
diff --git a/cmake/GetGitRevisionDescription.cmake b/cmake/GetGitRevisionDescription.cmake
index 1e0968ec3b..5044c682e4 100644
--- a/cmake/GetGitRevisionDescription.cmake
+++ b/cmake/GetGitRevisionDescription.cmake
@@ -42,7 +42,13 @@ set(__get_git_revision_description YES)
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
function(get_git_dir _gitdir)
- # check GIT_DIR in environment first
+ # check FORCED_GIT_DIR first
+ if(FORCED_GIT_DIR)
+ set(${_gitdir} ${FORCED_GIT_DIR} PARENT_SCOPE)
+ return()
+ endif()
+
+ # check GIT_DIR in environment
set(GIT_DIR $ENV{GIT_DIR})
if(NOT GIT_DIR)
set(GIT_PARENT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/config/config.h.in b/config/config.h.in
index f8a795327f..7d901180b4 100644
--- a/config/config.h.in
+++ b/config/config.h.in
@@ -54,7 +54,6 @@
#cmakedefine UNIX
#cmakedefine USE_FNAME_CASE
-#define FEAT_BROWSE
#define FEAT_CSCOPE
#ifndef UNIT_TESTING
diff --git a/config/versiondef.h.in b/config/versiondef.h.in
index a177e599ba..7f37ef72fb 100644
--- a/config/versiondef.h.in
+++ b/config/versiondef.h.in
@@ -5,8 +5,9 @@
#define NVIM_VERSION_MINOR @NVIM_VERSION_MINOR@
#define NVIM_VERSION_PATCH @NVIM_VERSION_PATCH@
#define NVIM_VERSION_PRERELEASE "@NVIM_VERSION_PRERELEASE@"
-#define NVIM_VERSION_BUILD "@NVIM_VERSION_BUILD@"
-#define NVIM_VERSION_COMMIT "@NVIM_VERSION_COMMIT@"
+#cmakedefine NVIM_VERSION_COMMIT "@NVIM_VERSION_COMMIT@"
+#cmakedefine NVIM_VERSION_MEDIUM "@NVIM_VERSION_MEDIUM@"
+
#define NVIM_VERSION_CFLAGS "@NVIM_VERSION_CFLAGS@"
#define NVIM_VERSION_BUILD_TYPE "@NVIM_VERSION_BUILD_TYPE@"
diff --git a/contrib/YouCompleteMe/README.md b/contrib/YouCompleteMe/README.md
index cd6393cd03..0c07440a44 100644
--- a/contrib/YouCompleteMe/README.md
+++ b/contrib/YouCompleteMe/README.md
@@ -2,7 +2,7 @@
## What is this?
-This provides the code necessary to configure vim's YCM plugin to provide C semantic support (completion, go-to-definition, etc) for the Neovim project.
+This provides the code necessary to configure vim's YCM plugin to provide C semantic support (completion, go-to-definition, etc) for developers working on the Neovim project.
## Installation
@@ -17,6 +17,6 @@ cp contrib/YouCompleteMe/ycm_extra_conf.py src/.ycm_extra_conf.py
echo .ycm_extra_conf.py >> .git/info/exclude
make
-(Add the following somewhere in your .nvimrc files)
+(Add the following somewhere in your vimrc)
autocmd FileType c nnoremap <buffer> <silent> <C-]> :YcmCompleter GoTo<cr>
```
diff --git a/contrib/local.mk.example b/contrib/local.mk.example
index 4e7b01a39f..22aac4fda7 100644
--- a/contrib/local.mk.example
+++ b/contrib/local.mk.example
@@ -13,16 +13,19 @@
# Sets the build type; defaults to Debug. Valid values:
#
-# - Debug: Disables optimizations (-O0), enables debug information.
+# - Debug: Disables optimizations (-O0), enables debug information and logging.
#
-# - RelWithDebInfo: Enables all optimizations that do not interfere with
+# - Dev: Enables all optimizations that do not interfere with
# debugging (-Og if available, -O2 and -g if not).
-# Enables debug information.
+# Enables debug information and logging.
+#
+# - RelWithDebInfo: Enables optimizations (-O2) and debug information.
+# Disables logging.
#
# - MinSizeRel: Enables all -O2 optimization that do not typically
# increase code size, and performs further optimizations
# designed to reduce code size (-Os).
-# Disables debug information.
+# Disables debug information and logging.
#
# - Release: Same as RelWithDebInfo, but disables debug information.
#
diff --git a/man/nvim.1 b/man/nvim.1
index 5e109c3145..968da04d52 100644
--- a/man/nvim.1
+++ b/man/nvim.1
@@ -1,4 +1,4 @@
-.Dd October 27, 2015
+.Dd November 11, 2015
.Dt NVIM 1
.Os
.Sh NAME
@@ -173,19 +173,19 @@ See
.It Fl L Op Ar file
Alias for
.Fl r .
-.It Fl u Ar nvimrc
+.It Fl u Ar vimrc
Use
-.Ar nvimrc
+.Ar vimrc
instead of the default of
.Pa ~/.config/nvim/init.vim .
If
-.Ar nvimrc
+.Ar vimrc
is
.Cm NORC ,
do not load any initialization files (excluding plugins),
and do not attempt to parse environment variables.
If
-.Ar nvimrc
+.Ar vimrc
is
.Cm NONE ,
loading plugins is also skipped.
@@ -278,7 +278,7 @@ Like
.Fl c ,
but execute
.Ar command
-before processing any nvimrc.
+before processing any vimrc.
Up to 10 instances of these can be used independently from instances of
.Fl c .
.It Fl S Op Ar session
@@ -395,11 +395,11 @@ configuration directory.
See
.Ev XDG_CONFIG_HOME
above.
-.It Pa /etc/nvim/nvimrc
+.It Pa $VIM/sysinit.vim
The system-global
.Nm
configuration file.
-.It Pa /usr/share/nvim
+.It Pa /usr/local/share/nvim
The system-global
.Nm
runtime directory.
diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt
index 46c5cf8235..ef8e38b553 100644
--- a/runtime/CMakeLists.txt
+++ b/runtime/CMakeLists.txt
@@ -38,7 +38,7 @@ add_custom_command(OUTPUT ${GENERATED_HELP_TAGS}
COMMAND "${PROJECT_BINARY_DIR}/bin/nvim"
-u NONE
-i NONE
- -esX
+ -es
--headless
-c "helptags ++t ."
-c quit
diff --git a/runtime/autoload/provider/python.vim b/runtime/autoload/provider/python.vim
index d4a509864f..b769895357 100644
--- a/runtime/autoload/provider/python.vim
+++ b/runtime/autoload/provider/python.vim
@@ -46,7 +46,7 @@ function! provider#python#Call(method, args)
echohl WarningMsg
echomsg v:exception
echohl None
- finish
+ return
endtry
endif
return call(s:rpcrequest, insert(insert(a:args, 'python_'.a:method), s:host))
diff --git a/runtime/autoload/provider/python3.vim b/runtime/autoload/provider/python3.vim
index f469bf55aa..2952f76b40 100644
--- a/runtime/autoload/provider/python3.vim
+++ b/runtime/autoload/provider/python3.vim
@@ -46,7 +46,7 @@ function! provider#python3#Call(method, args)
echohl WarningMsg
echomsg v:exception
echohl None
- finish
+ return
endtry
endif
return call(s:rpcrequest, insert(insert(a:args, 'python_'.a:method), s:host))
diff --git a/runtime/doc/Makefile b/runtime/doc/Makefile
index 07b4226151..7423e63673 100644
--- a/runtime/doc/Makefile
+++ b/runtime/doc/Makefile
@@ -20,7 +20,7 @@ all: tags html
# Use Vim to generate the tags file. Can only be used when Vim has been
# compiled and installed. Supports multiple languages.
vimtags: $(DOCS)
- $(VIMEXE) -u NONE -esX -c "helptags ++t ." -c quit
+ $(VIMEXE) -u NONE -es -c "helptags ++t ." -c quit
# Use "doctags" to generate the tags file. Only works for English!
tags: doctags $(DOCS)
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index 7b53bd64ca..a0ed91c95d 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -251,6 +251,7 @@ Name triggered by ~
|SwapExists| detected an existing swap file
|TermOpen| when a terminal buffer is starting
+|TermClose| when a terminal buffer ends
Options
|FileType| when the 'filetype' option has been set
@@ -871,6 +872,8 @@ TermChanged After the value of 'term' has changed. Useful
for re-loading the syntax file to update the
colors, fonts and other terminal-dependent
settings. Executed for all loaded buffers.
+ {Nvim} *TermClose*
+TermClose When a terminal buffer ends.
{Nvim} *TermOpen*
TermOpen When a terminal buffer is starting. This can
be used to configure the terminal emulator by
diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt
index 2f96c4c6dc..d0dd741888 100644
--- a/runtime/doc/develop.txt
+++ b/runtime/doc/develop.txt
@@ -140,18 +140,13 @@ such that most users will enjoy using Vim as it is. Commands and options can
be used to adjust Vim to the desire of the user and its environment.
-VIM IS... NOT *design-not*
-
-- Vim is not a shell or an Operating System. You will not be able to run a
- shell inside Vim or use it to control a debugger. This should work the
- other way around: Use Vim as a component from a shell or in an IDE.
- A satirical way to say this: "Unlike Emacs, Vim does not attempt to include
- everything but the kitchen sink, but some people say that you can clean one
- with it. ;-)"
- To use Vim with gdb see: http://www.agide.org and http://clewn.sf.net.
-- Vim is not a fancy GUI editor that tries to look nice at the cost of
- being less consistent over all platforms. But functional GUI features are
- welcomed.
+NVIM IS... NOT *design-not*
+
+Nvim is not an Operating System; instead it should be composed with other
+tools, or hosted as a component. Marvim once said: "Unlike Emacs, Nvim does
+not attempt to include everything but the kitchen sink, but some people use it
+for plumbing."
+
==============================================================================
2. Coding style *coding-style*
diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt
index bb3d89e4ac..ffa3f1d673 100644
--- a/runtime/doc/editing.txt
+++ b/runtime/doc/editing.txt
@@ -1141,8 +1141,8 @@ If you want to always use ":confirm", set the 'confirm' option.
|:mkvimrc|, |:mksession|, |:mkview|, |:split|,
|:vsplit|, |:tabe|, |:tabnew|, |:cfile|, |:cgetfile|,
|:caddfile|, |:lfile|, |:lgetfile|, |:laddfile|,
- |:diffsplit|, |:diffpatch|, |:open|, |:pedit|,
- |:redir|, |:source|, |:update|, |:visual|, |:vsplit|,
+ |:diffsplit|, |:diffpatch|, |:pedit|, |:redir|,
+ |:source|, |:update|, |:visual|, |:vsplit|,
and |:qall| if 'confirm' is set.
{only in Win32, Athena, Motif, GTK and Mac GUI}
When ":browse" is not possible you get an error
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 33ee5b78c1..7b12d2082f 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1763,6 +1763,8 @@ cursor( {lnum}, {col} [, {off}])
cursor( {list}) Number move cursor to position in {list}
deepcopy( {expr} [, {noref}]) any make a full copy of {expr}
delete( {fname}) Number delete file {fname}
+dictwatcheradd({dict}, {pattern}, {callback}) Start watching a dictionary
+dictwatcherdel({dict}, {pattern}, {callback}) Stop watching a dictionary
did_filetype() Number TRUE if FileType autocommand event used
diff_filler( {lnum}) Number diff filler lines about {lnum}
diff_hlID( {lnum}, {col}) Number diff highlighting at {lnum}/{col}
@@ -1870,10 +1872,13 @@ invert( {expr}) Number bitwise invert
isdirectory( {directory}) Number TRUE if {directory} is a directory
islocked( {expr}) Number TRUE if {expr} is locked
items( {dict}) List key-value pairs in {dict}
-job_close({job}) Closes a job with id {job}
-job_send({job}, {data}) Writes {data} to {job}'s stdin
-job_spawn({name}, {prog}[, {argv}])
- Spawns {prog} as a job associated with {name}
+jobclose({job}[, {stream}]) Number Closes a job stream(s)
+jobresize({job}, {width}, {height})
+ Number Resize {job}'s pseudo terminal window
+jobsend({job}, {data}) Number Writes {data} to {job}'s stdin
+jobstart({cmd}[, {opts}]) Number Spawns {cmd} as a job
+jobstop({job}) Number Stops a job
+jobwait({ids}[, {timeout}]) Number Wait for a set of jobs
join( {list} [, {sep}]) String join {list} items into one String
keys( {dict}) List keys in {dict}
len( {expr}) Number the length of {expr}
@@ -2661,6 +2666,44 @@ delete({fname}) *delete()*
To delete a line from the buffer use |:delete|. Use |:exe|
when the line number is in a variable.
+dictwatcheradd({dict}, {pattern}, {callback}) *dictwatcheradd()*
+ Adds a watcher to a dictionary. A dictionary watcher is
+ identified by three components:
+
+ - A dictionary({dict});
+ - A key pattern({pattern}).
+ - A function({callback}).
+
+ After this is called, every change on {dict} and on keys
+ matching {pattern} will result in {callback} being invoked.
+
+ For now {pattern} only accepts very simple patterns that can
+ contain a '*' at the end of the string, in which case it will
+ match every key that begins with the substring before the '*'.
+ That means if '*' is not the last character of {pattern}, only
+ keys that are exactly equal as {pattern} will be matched.
+
+ The {callback} receives three arguments:
+
+ - The dictionary being watched.
+ - The key which changed.
+ - A dictionary containg the new and old values for the key.
+
+ The type of change can be determined by examining the keys
+ present on the third argument:
+
+ - If contains both `old` and `new`, the key was updated.
+ - If it contains only `new`, the key was added.
+ - If it contains only `old`, the key was deleted.
+
+ This function can be used by plugins to implement options with
+ validation and parsing logic.
+
+dictwatcherdel({dict}, {pattern}, {callback}) *dictwatcherdel()*
+ Removes a watcher added with |dictwatcheradd()|. All three
+ arguments must match the ones passed to |dictwatcheradd()| in
+ order for the watcher to be successfully deleted.
+
*did_filetype()*
did_filetype() Returns non-zero when autocommands are being executed and the
FileType event has been triggered at least once. Can be used
@@ -2959,6 +3002,8 @@ extend({expr1}, {expr2} [, {expr3}]) *extend()*
{expr1} is changed when {expr2} is not empty. If necessary
make a copy of {expr1} first.
{expr2} remains unchanged.
+ When {expr1} is locked and {expr2} is not empty the operation
+ fails.
Returns {expr1}.
diff --git a/runtime/doc/fold.txt b/runtime/doc/fold.txt
index ef69835462..03dd6a61ba 100644
--- a/runtime/doc/fold.txt
+++ b/runtime/doc/fold.txt
@@ -362,7 +362,7 @@ zX Undo manually opened and closed folds: re-apply 'foldlevel'.
Also forces recomputing folds, like |zx|.
*zm*
-zm Fold more: Subtract one from 'foldlevel'. If 'foldlevel' was
+zm Fold more: Subtract |v:count1| from 'foldlevel'. If 'foldlevel' was
already zero nothing happens.
'foldenable' will be set.
@@ -371,7 +371,7 @@ zM Close all folds: set 'foldlevel' to 0.
'foldenable' will be set.
*zr*
-zr Reduce folding: Add one to 'foldlevel'.
+zr Reduce folding: Add |v:count1| to 'foldlevel'.
*zR*
zR Open all folds. This sets 'foldlevel' to highest fold level.
diff --git a/runtime/doc/gui.txt b/runtime/doc/gui.txt
index 90f772c46f..c74c31d1fa 100644
--- a/runtime/doc/gui.txt
+++ b/runtime/doc/gui.txt
@@ -61,10 +61,6 @@ When the GUI starts up initializations are carried out, in this order:
~/.config).
The name of the first file found is stored in $MYGVIMRC, unless it was
already set.
-- If the 'exrc' option is set (which is NOT the default) the file ./.ngvimrc
- is sourced, if it exists and isn't the same file as the system or user
- gvimrc file. If this file is not owned by you, some security restrictions
- apply. When ".ngvimrc" is not found, "_ngvimrc" is tried too.
NOTE: All but the first one are not carried out if Vim was started with
"-u NONE" and no "-U" argument was given, or when started with "-U NONE".
diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt
index 76903d50a5..9ca96dfd79 100644
--- a/runtime/doc/help.txt
+++ b/runtime/doc/help.txt
@@ -160,7 +160,6 @@ Versions ~
|vi_diff.txt| Main differences between Vim and Vi
*sys-file-list*
Remarks about specific systems ~
-|os_mac.txt| Macintosh
|os_win32.txt| MS-Windows
*standard-plugin-list*
Standard plugins ~
diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt
index 0238d7cc53..75c986efcd 100644
--- a/runtime/doc/index.txt
+++ b/runtime/doc/index.txt
@@ -1359,8 +1359,7 @@ tag command action ~
|:number| :nu[mber] print lines with line number
|:nunmap| :nun[map] like ":unmap" but for Normal mode
|:nunmenu| :nunme[nu] remove menu for Normal mode
-|:oldfiles| :ol[dfiles] list files that have marks in the ShaDa file
-|:open| :o[pen] start open mode (not implemented)
+|:oldfiles| :o[ldfiles] list files that have marks in the ShaDa file
|:omap| :om[ap] like ":map" but for Operator-pending mode
|:omapclear| :omapc[lear] remove all mappings for Operator-pending mode
|:omenu| :ome[nu] add menu for Operator-pending mode
diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt
index a48ad0185d..013eb6b97b 100644
--- a/runtime/doc/insert.txt
+++ b/runtime/doc/insert.txt
@@ -1,4 +1,4 @@
-*insert.txt* For Vim version 7.4. Last change: 2014 Aug 04
+*insert.txt* For Vim version 7.4. Last change: 2015 May 22
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -77,9 +77,11 @@ CTRL-W Delete the word before the cursor (see |i_backspacing| about
joining lines). See the section "word motions",
|word-motions|, for the definition of a word.
*i_CTRL-U*
-CTRL-U Delete all entered characters in the current line (see
- |i_backspacing| about joining lines).
-
+CTRL-U Delete all entered characters before the cursor in the current
+ line. If there are no newly entereed characters and
+ 'backspace'is not empty, delete all characters before the
+ cursor in the current line.
+ See |i_backspacing| about joining lines.
*i_CTRL-I* *i_<Tab>* *i_Tab*
<Tab> or CTRL-I Insert a tab. If the 'expandtab' option is on, the
equivalent number of spaces is inserted (use CTRL-V <Tab> to
diff --git a/runtime/doc/motion.txt b/runtime/doc/motion.txt
index 5e3fe715ab..7f84f2d2a3 100644
--- a/runtime/doc/motion.txt
+++ b/runtime/doc/motion.txt
@@ -1,4 +1,4 @@
-*motion.txt* For Vim version 7.4. Last change: 2014 Feb 11
+*motion.txt* For Vim version 7.4. Last change: 2015 Jun 06
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -171,6 +171,8 @@ CTRL-H or *CTRL-H* *<BS>*
l or *l*
<Right> or *<Right>* *<Space>*
<Space> [count] characters to the right. |exclusive| motion.
+ See the 'whichwrap' option for adjusting the behavior
+ at end of line
*0*
0 To the first character of the line. |exclusive|
diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt
index 701c6dc274..6ef3aaebaa 100644
--- a/runtime/doc/nvim_terminal_emulator.txt
+++ b/runtime/doc/nvim_terminal_emulator.txt
@@ -105,6 +105,8 @@ The configuration variables are only processed when the terminal starts, which
is why it needs to be done with the |TermOpen| autocmd or setting global
variables before the terminal is started.
+There is also a corresponding |TermClose| event.
+
The terminal cursor can be highlighted via |hl-TermCursor| and
|hl-TermCursorNC|.
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index baafe8cbea..2b1044bead 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -980,60 +980,13 @@ A jump table for the options with a short description can be found at |Q_op|.
the newly created file). Also see 'backupcopy' and |crontab|.
*'balloondelay'* *'bdlay'*
-'balloondelay' 'bdlay' number (default: 600)
- global
- {only available when compiled with the |+balloon_eval|
- feature}
- Delay in milliseconds before a balloon may pop up. See |balloon-eval|.
+'balloondelay' 'bdlay' Removed. {Nvim}
- *'ballooneval'* *'beval'* *'noballooneval'* *'nobeval'*
-'ballooneval' 'beval' boolean (default off)
- global
- {only available when compiled with the |+balloon_eval|
- feature}
- Switch on the |balloon-eval| functionality.
+ *'ballooneval'* *'beval'* *'noballooneval'* *'nobeval'*
+'ballooneval' 'beval' Removed. {Nvim}
- *'balloonexpr'* *'bexpr'*
-'balloonexpr' 'bexpr' string (default "")
- global or local to buffer |global-local|
- {only available when compiled with the |+balloon_eval|
- feature}
- Expression for text to show in evaluation balloon. It is only used
- when 'ballooneval' is on. These variables can be used:
-
- v:beval_bufnr number of the buffer in which balloon is going to show
- v:beval_winnr number of the window
- v:beval_lnum line number
- v:beval_col column number (byte index)
- v:beval_text word under or after the mouse pointer
-
- The evaluation of the expression must not have side effects!
- Example: >
- function! MyBalloonExpr()
- return 'Cursor is at line ' . v:beval_lnum .
- \', column ' . v:beval_col .
- \ ' of file ' . bufname(v:beval_bufnr) .
- \ ' on word "' . v:beval_text . '"'
- endfunction
- set bexpr=MyBalloonExpr()
- set ballooneval
-<
- NOTE: The balloon is displayed only if the cursor is on a text
- character. If the result of evaluating 'balloonexpr' is not empty,
- Vim does not try to send a message to an external debugger (Netbeans
- or Sun Workshop).
-
- The expression will be evaluated in the |sandbox| when set from a
- modeline, see |sandbox-option|.
-
- It is not allowed to change text or jump to another window while
- evaluating 'balloonexpr' |textlock|.
-
- To check whether line breaks in the balloon text work use this check: >
- if has("balloon_multiline")
-< When they are supported "\n" characters will start a new line. If the
- expression evaluates to a |List| this is equal to using each List item
- as a string and putting "\n" in between them.
+ *'balloonexpr'* *'bexpr'*
+'balloonexpr' 'bexpr' Removed. {Nvim}
*'belloff'* *'bo'*
'belloff' 'bo' string (default "")
@@ -1538,14 +1491,6 @@ A jump table for the options with a short description can be found at |Q_op|.
(gzipped files for example). Unloaded buffers are not scanned for
whole-line completion.
- The default is ".,w,b,u,t,i", which means to scan:
- 1. the current buffer
- 2. buffers in other windows
- 3. other loaded buffers
- 4. unloaded buffers
- 5. tags
- 6. included files
-
As you can see, CTRL-N and CTRL-P can be used to do any 'iskeyword'-
based expansion (e.g., dictionary |i_CTRL-X_CTRL-K|, included patterns
|i_CTRL-X_CTRL-I|, tags |i_CTRL-X_CTRL-]| and normal expansions).
@@ -2350,13 +2295,13 @@ A jump table for the options with a short description can be found at |Q_op|.
*'exrc'* *'ex'* *'noexrc'* *'noex'*
'exrc' 'ex' boolean (default off)
global
- Enables the reading of .nvimrc, .exrc and .ngvimrc in the current
- directory. If you switch this option on you should also consider
- setting the 'secure' option (see |initialization|). Using a local
- .exrc, .nvimrc or .ngvimrc is a potential security leak, use with care!
- also see |init.vim| and |gui-init|.
+ Enables the reading of .nvimrc and .exrc in the current directory.
+ If you switch this option on you should also consider setting the
+ 'secure' option (see |initialization|). Using this option comes
+ with a potential security risk, use with care!
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
+ Also see |init.vim| and |gui-init|.
*'fileencoding'* *'fenc'* *E213*
'fileencoding' 'fenc' string (default: "")
@@ -5342,8 +5287,8 @@ A jump table for the options with a short description can be found at |Q_op|.
*'shada'* *'sd'* *E526* *E527* *E528*
'shada' 'sd' string (Vim default for
- Win32: '!,100,<50,s10,h,rA:,rB:
- others: '!,100,<50,s10,h
+ Win32: !,'100,<50,s10,h,rA:,rB:
+ others: !,'100,<50,s10,h
Vi default: "")
global
When non-empty, the shada file is read upon startup and written
diff --git a/runtime/doc/os_mac.txt b/runtime/doc/os_mac.txt
deleted file mode 100644
index 3eebb7ef0d..0000000000
--- a/runtime/doc/os_mac.txt
+++ /dev/null
@@ -1,116 +0,0 @@
-*os_mac.txt* For Vim version 7.4. Last change: 2006 Apr 30
-
-
- VIM REFERENCE MANUAL by Bram Moolenaar et al.
-
-
- *mac* *Mac* *macintosh* *Macintosh*
-
-This file documents the particularities of the Macintosh version of Vim.
-
-NOTE: This file is a bit outdated. You might find more useful info here:
- http://macvim.org/
-
-1. Filename Convention |mac-filename|
-2. .vimrc an .vim files |mac-vimfile|
-3. FAQ |mac-faq|
-4. Known Lack |mac-lack|
-5. Mac Bug Report |mac-bug|
-6. Compiling Vim |mac-compile|
-
-There was a Mac port for version 3.0 of Vim. Here are the first few lines
-from the old file:
-
-VIM Release Notes
-Initial Macintosh release, VIM version 3.0
-19 October 1994
-
-Eric Fischer
-<enf1@midway.uchicago.edu>, <eric@jcp.uchicago.edu>, <etaoin@uchicago.edu>
-5759 N. Guilford Ave
-Indianapolis IN 46220 USA
-
-==============================================================================
-1. Filename Convention *mac-filename*
-
-Starting with Vim version 7 you can just use the unix path separators with
-Vim. In order to determine if the specified filename is relative to the
-current folder or absolute (i.e. relative to the "Desktop"), the following
-algorithm is used:
-
- If the path start by a "/", the path is absolute
- If the path start by a ":", the path is relative
- If the path doesn't start by neither a "/" nor ":",
- and a ":" is found before a "/" then the path is absolute
->
- :e /HD/text
- :e HD:text
-< Edit the file "text" of the disk "HD" >
- :e :src:main.c
- :e src/main.c
-< Edit the file "main.c" in the folder "src" in the current folder >
- :e os_mac.c
-< Edit the file "os_mac.c" in the current folder.
-
-You can use the |$VIM| and |$VIMRUNTIME| variable. >
-
- :so $VIMRUNTIME/syntax/syntax.vim
-
-==============================================================================
-2. .vimrc and .vim files *mac-vimfile*
-
-It is recommended to use Unix style line separators for Vim scripts, thus a
-single newline character.
-
-When starting up Vim will load the $VIMRUNTIME/macmap.vim script to define
-default command-key mappings.
-
-On older systems files starting with a dot "." are discouraged, thus the rc
-files are named "vimrc" or "_vimrc" and "gvimrc" or "_gvimrc". These files
-can be in any format (mac, dos or unix).
-
-==============================================================================
-3. Mac FAQ *mac-faq*
-
-On the internet: http://macvim.org/OSX/index.php#FAQ
-
-Q: I can't enter non-ASCII character in Apple Terminal.
-A: Under Window Settings, Emulation, make sure that "Escape non-ASCII
- characters" is not checked.
-
-Q: How do I start the GUI from the command line?
-A: Assuming that Vim.app is located in /Applications:
- open /Applications/Vim.app
- Or:
- /Applications/Vim.app/Contents/MacOS/Vim -g {arguments}
-
-Q: How can I set $PATH to something reasonable when I start Vim.app from the
- GUI or with open?
-A: The following trick works with most shells. Put it in your vimrc file.
- This is included in the system vimrc file included with the binaries
- distributed at macvim.org . >
- let s:path = system("echo echo VIMPATH'${PATH}' | $SHELL -l")
- let $PATH = matchstr(s:path, 'VIMPATH\zs.\{-}\ze\n')
-
-==============================================================================
-4. Mac Lack *mac-lack*
-
-In a terminal CTRL-^ needs to be entered as Shift-Control-6. CTRL-@ as
-Shift-Control-2.
-
-==============================================================================
-5. Mac Bug Report *mac-bug*
-
-When reporting any Mac specific bug or feature change, please use the vim-mac
-maillist |vim-mac|. However, you need to be subscribed. An alternative is to
-send a message to the current MacVim maintainers:
-
- mac@vim.org
-
-==============================================================================
-6. Compiling Vim *mac-compile*
-
-See the file "src/INSTALLmac.txt" that comes with the source files.
-
-
- vim:tw=78:ts=8:ft=help:norl:
diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt
index 75384832ec..d029391c60 100644
--- a/runtime/doc/repeat.txt
+++ b/runtime/doc/repeat.txt
@@ -586,6 +586,9 @@ For example, to profile the one_script.vim script file: >
If {fname} already exists it will be silently overwritten.
The variable |v:profiling| is set to one.
+:prof[ile] stop
+ Write the logfile and stop profiling.
+
:prof[ile] pause
Don't profile until the following ":profile continue". Can be
used when doing something that should not be counted (e.g., an
@@ -609,6 +612,9 @@ For example, to profile the one_script.vim script file: >
after this command. A :profile command in the script itself
won't work.
+:prof[ile] dump
+ Don't wait until exiting Vim and write the current state of
+ profiling to the log immediately.
:profd[el] ... *:profd* *:profdel*
Stop profiling for the arguments specified. See |:breakdel|
diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt
index 2c630ed958..572823eca9 100644
--- a/runtime/doc/starting.txt
+++ b/runtime/doc/starting.txt
@@ -402,10 +402,9 @@ accordingly. Vim proceeds in this order:
initializations until 4. are skipped. Only the "-u" option is
interpreted.
*system-vimrc*
- a. For Unix, MS-DOS, MS-Windows, and Macintosh, the system vimrc file is
- read for initializations. The path of this file is shown with the
+ a. For Unix, MS-Windows, and Macintosh, the system vimrc file is read for
+ initializations. The path of this file is shown with the
":version" command. Mostly it's "$VIM/vimrc".
- For the Macintosh the $VIMRUNTIME/macmap.vim is read.
*VIMINIT* *EXINIT* *$MYVIMRC*
b. Four places are searched for initializations. The first that exists
@@ -1163,13 +1162,14 @@ running) you have additional options:
*:wv* *:wviminfo*
:wv[iminfo][!] [file] Deprecated alias to |:wshada| command.
- *:ol* *:oldfiles*
-:ol[dfiles] List the files that have marks stored in the ShaDa
+ *:o* *:ol* *:oldfiles*
+:o[ldfiles][!] List the files that have marks stored in the ShaDa
file. This list is read on startup and only changes
afterwards with ":rshada!". Also see |v:oldfiles|.
The number can be used with |c_#<|.
+ Use ! to get a file selection prompt.
-:bro[wse] ol[dfiles][!]
+:bro[wse] o[ldfiles][!]
List file names as with |:oldfiles|, and then prompt
for a number. When the number is valid that file from
the list is edited.
diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt
index 65e69a901b..eeed014fdb 100644
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -1140,9 +1140,6 @@ Now that colnr_T is int instead of unsigned, more type casts can be removed.
'delcombine' does not work for the command line. (Tony Mechelynck, 2009 Jul
20)
-Don't load macmap.vim on startup, turn it into a plugin. (Ron Aaron,
-2009 Apr 7) Reminder Apr 14.
-
Add "no_hlsearch" to winsaveview().
Cursorline highlighting combines with Search ('hlsearch') but not with
@@ -1389,9 +1386,6 @@ The utf class table is missing some entries:
Visual line mode doesn't highlight properly when 'showbreak' is used and the
line doesn't fit. (Dasn, 2008 May 1)
-Mac: Move Carbon todo items to os_mac.txt. Note that this version is frozen,
-try the Cocoa version.
-
Mac: After a ":vsplit" the left scrollbar doesn't appear until 'columns' is
changed or the window is resized.
diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt
index 1b95cfe7d0..117e977e0d 100644
--- a/runtime/doc/various.txt
+++ b/runtime/doc/various.txt
@@ -212,7 +212,7 @@ g8 Print the hex values of the bytes used in the
equivalent to: >
:enew
- :call termopen([&sh, &shcf, '{cmd}'])
+ :call termopen('{cmd}')
:startinsert
<
If no {cmd} is given, 'shellcmdflag' will not be sent
diff --git a/runtime/doc/vi_diff.txt b/runtime/doc/vi_diff.txt
index e76c0163b5..fffb923219 100644
--- a/runtime/doc/vi_diff.txt
+++ b/runtime/doc/vi_diff.txt
@@ -10,33 +10,14 @@ Throughout the help files differences between Vim and Vi/Ex are given in
curly braces, like "{not in Vi}". This file only lists what has not been
mentioned in other files and gives an overview.
-1. Simulated command |simulated-command|
-2. Missing options |missing-options|
-3. Limits |limits|
-4. The most interesting additions |vim-additions|
-5. Other vim features |other-features|
-6. Command-line arguments |cmdline-arguments|
+1. Missing options |missing-options|
+2. Limits |limits|
+3. The most interesting additions |vim-additions|
+4. Other vim features |other-features|
+5. Command-line arguments |cmdline-arguments|
==============================================================================
-1. Simulated command *simulated-command*
-
-This command is in Vi, but Vim only simulates it:
-
- *:o* *:op* *:open*
-:[range]o[pen] Works like |:visual|: end Ex mode.
- {Vi: start editing in open mode}
-
-:[range]o[pen] /pattern/ As above, additionally move the cursor to the
- column where "pattern" matches in the cursor
- line.
-
-Vim does not support open mode, since it's not really useful. For those
-situations where ":open" would start open mode Vim will leave Ex mode, which
-allows executing the same commands, but updates the whole screen instead of
-only one line.
-
-==============================================================================
-2. Missing options *missing-options*
+1. Missing options *missing-options*
These options are in the Unix Vi, but not in Vim.
@@ -58,7 +39,7 @@ w1200 number (default 23) *'w1200'*
w9600 number (default 23) *'w9600'*
==============================================================================
-3. Limits *limits*
+2. Limits *limits*
Vim has only a few limits for the files that can be edited {Vi: can not handle
<Nul> characters and characters above 128, has limited line length, many other
@@ -102,7 +83,7 @@ don't want a swap file at all, set 'updatecount' to 0, or use the "-n"
argument when starting Vim.
==============================================================================
-4. The most interesting additions *vim-additions*
+3. The most interesting additions *vim-additions*
Vi compatibility. |'compatible'|
Although Vim is 99% Vi compatible, some things in Vi can be
@@ -744,7 +725,7 @@ The "No lines in buffer" message is a normal message instead of an error
message, since that may cause a mapping to be aborted.
==============================================================================
-6. Command-line arguments *cmdline-arguments*
+5. Command-line arguments *cmdline-arguments*
Different versions of Vi have different command-line arguments. This can be
confusing. To help you, this section gives an overview of the differences.
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index 6124c36dc9..6cbc2aef59 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -24,7 +24,7 @@ these differences.
- Use `$XDG_CONFIG_HOME/nvim/init.vim` instead of `.vimrc` for storing
configuration.
- Use `$XDG_CONFIG_HOME/nvim` instead of `.vim` to store configuration files.
-- Use `$XDG_DATA_HOME/shada/main.shada` instead of `.viminfo` for persistent
+- Use `$XDG_DATA_HOME/nvim/shada/main.shada` instead of `.viminfo` for persistent
session information.
==============================================================================
@@ -106,6 +106,7 @@ Additional differences:
compatibility reasons.
- |:wviminfo| was renamed to |:wshada|, |:rviminfo| to |:rshada|. Old
commands are still kept.
+- |:oldfiles| supports !.
- When writing (|:wshada| without bang or at exit) it merges much more data,
and does this according to the timestamp. Vim merges only marks.
|shada-merging|
@@ -142,6 +143,8 @@ Events:
|TabNew|
|TabNewEntered|
|TabClosed|
+ |TermOpen|
+ |TermClose|
Highlight groups:
|hl-EndOfBuffer|
@@ -197,7 +200,7 @@ Other options:
'macatsui'
'shelltype'
'shortname'
- 'termencoding'
+ 'termencoding' (Vim 7.4.852 also removed this for Windows)
'textauto'
'textmode'
'toolbar'
@@ -210,12 +213,14 @@ Other commands:
:Print
:fixdel
:mode (no longer accepts an argument)
+ :open
:shell
:tearoff
Other compile-time features:
EBCDIC
Emacs tags support
+ X11 integration (see |x11-selection|)
Nvim does not have a built-in GUI and hence the following aliases have been
removed: gvim, gex, gview, rgvim, rgview
diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt
index 95be125c33..c009bec66e 100644
--- a/runtime/doc/windows.txt
+++ b/runtime/doc/windows.txt
@@ -971,9 +971,10 @@ A buffer can also be unlisted. This means it exists, but it is not in the
list of buffers. |unlisted-buffer|
-:files[!] *:files*
-:buffers[!] *:buffers* *:ls*
-:ls[!] Show all buffers. Example:
+:files[!] [flags] *:files*
+:buffers[!] [flags] *:buffers* *:ls*
+:ls[!] [flags]
+ Show all buffers. Example:
1 #h "/test/text" line 1 ~
2u "asdf" line 0 ~
@@ -999,6 +1000,21 @@ list of buffers. |unlisted-buffer|
+ a modified buffer
x a buffer with read errors
+ [flags] can be a combination of the following characters,
+ which restrict the buffers to be listed:
+ + modified buffers
+ - buffers with 'modifiable' off
+ = readonly buffers
+ a active buffers
+ u unlisted buffers (overrides the "!")
+ h hidden buffers
+ x buffers with a read error
+ % current buffer
+ # alternate buffer
+ Combining flags means they are "and"ed together, e.g.:
+ h+ hidden buffers which are modified
+ a+ active buffers which are modified
+
*:bad* *:badd*
:bad[d] [+lnum] {fname}
Add file name {fname} to the buffer list, without loading it.
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index 9e0e39e3f8..b06e702637 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -495,7 +495,7 @@ au BufNewFile,BufRead *.prg
\ endif
" Clojure
-au BufNewFile,BufRead *.clj,*.cljs setf clojure
+au BufNewFile,BufRead *.clj,*.cljs,*.cljx,*.cljc setf clojure
" Cmake
au BufNewFile,BufRead CMakeLists.txt,*.cmake,*.cmake.in setf cmake
@@ -772,10 +772,9 @@ au BufNewFile,BufRead *.mo,*.gdmo setf gdmo
au BufNewFile,BufRead *.ged,lltxxxxx.txt setf gedcom
" Git
-au BufNewFile,BufRead *.git/COMMIT_EDITMSG setf gitcommit
-au BufNewFile,BufRead *.git/MERGE_MSG setf gitcommit
+au BufNewFile,BufRead COMMIT_EDITMSG setf gitcommit
+au BufNewFile,BufRead MERGE_MSG setf gitcommit
au BufNewFile,BufRead *.git/config,.gitconfig,.gitmodules setf gitconfig
-au BufNewFile,BufRead *.git/modules/*/COMMIT_EDITMSG setf gitcommit
au BufNewFile,BufRead *.git/modules/*/config setf gitconfig
au BufNewFile,BufRead */.config/git/config setf gitconfig
if !empty($XDG_CONFIG_HOME)
diff --git a/runtime/ftplugin/kconfig.vim b/runtime/ftplugin/kconfig.vim
index 1b10c86ae3..940ba7427f 100644
--- a/runtime/ftplugin/kconfig.vim
+++ b/runtime/ftplugin/kconfig.vim
@@ -1,6 +1,10 @@
" Vim filetype plugin file
-" Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2008-07-09
+" Vim syntax file
+" Maintainer: Christian Brabandt <cb@256bit.org>
+" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
+" Latest Revision: 2015-05-29
+" License: Vim (see :h license)
+" Repository: https://github.com/chrisbra/vim-kconfig
if exists("b:did_ftplugin")
finish
@@ -14,5 +18,10 @@ let b:undo_ftplugin = "setl com< cms< fo<"
setlocal comments=:# commentstring=#\ %s formatoptions-=t formatoptions+=croql
+" For matchit.vim
+if exists("loaded_matchit")
+ let b:match_words = '^\<menu\>:\<endmenu\>,^\<if\>:\<endif\>,^\<choice\>:\<endchoice\>'
+endif
+
let &cpo = s:cpo_save
unlet s:cpo_save
diff --git a/runtime/ftplugin/spec.vim b/runtime/ftplugin/spec.vim
index c3af8a9fca..0b6750de94 100644
--- a/runtime/ftplugin/spec.vim
+++ b/runtime/ftplugin/spec.vim
@@ -20,11 +20,36 @@ endif
noremap <buffer> <unique> <script> <Plug>SpecChangelog :call <SID>SpecChangelog("")<CR>
+if !exists("*s:GetRelVer")
+ function! s:GetRelVer()
+ if has('python')
+python << PYEND
+import sys, datetime, shutil, tempfile
+import vim
+
+try:
+ import rpm
+except ImportError:
+ pass
+else:
+ specfile = vim.current.buffer.name
+ if specfile:
+ spec = rpm.spec(specfile)
+ headers = spec.packages[0].header
+ version = headers['Version']
+ release = ".".join(headers['Release'].split(".")[:-1])
+ vim.command("let ver = " + version)
+ vim.command("let rel = " + release)
+PYEND
+ endif
+ endfunction
+endif
+
if !exists("*s:SpecChangelog")
function s:SpecChangelog(format)
if strlen(a:format) == 0
if !exists("g:spec_chglog_format")
- let email = input("Email address: ")
+ let email = input("Name <email address>: ")
let g:spec_chglog_format = "%a %b %d %Y " . l:email
echo "\r"
endif
@@ -69,6 +94,9 @@ if !exists("*s:SpecChangelog")
else
let include_release_info = 0
endif
+
+ call s:GetRelVer()
+
if (chgline == -1)
let option = confirm("Can't find %changelog. Create one? ","&End of file\n&Here\n&Cancel",3)
if (option == 1)
@@ -83,7 +111,7 @@ if !exists("*s:SpecChangelog")
endif
endif
if (chgline != -1)
- let parsed_format = "* ".strftime(format)
+ let parsed_format = "* ".strftime(format)." - ".ver."-".rel
let release_info = "+ ".name."-".ver."-".rel
let wrong_format = 0
let wrong_release = 0
diff --git a/runtime/ftplugin/zsh.vim b/runtime/ftplugin/zsh.vim
index 3970d65cc8..6cbc380dc3 100644
--- a/runtime/ftplugin/zsh.vim
+++ b/runtime/ftplugin/zsh.vim
@@ -1,7 +1,10 @@
" Vim filetype plugin file
-" Language: Zsh shell script
-" Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2011-01-23
+" Language: Zsh shell script
+" Maintainer: Christian Brabandt <cb@256bit.org>
+" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
+" Latest Revision: 2015-05-29
+" License: Vim (see :h license)
+" Repository: https://github.com/chrisbra/vim-zsh
if exists("b:did_ftplugin")
finish
diff --git a/runtime/indent/javascript.vim b/runtime/indent/javascript.vim
index a83d34b110..21c8fff86c 100644
--- a/runtime/indent/javascript.vim
+++ b/runtime/indent/javascript.vim
@@ -1,7 +1,7 @@
" Vim indent file
" Language: Javascript
-" Maintainer: None! Wanna improve this?
-" Last Change: 2007 Jan 22
+" Maintainer: Going to be Darrick Wiebe
+" Last Change: 2015 Jun 09
" Only load this indent file when no other was loaded.
if exists("b:did_indent")
@@ -12,5 +12,7 @@ let b:did_indent = 1
" C indenting is not too bad.
setlocal cindent
setlocal cinoptions+=j1,J1
+setlocal cinkeys-=0#
+setlocal cinkeys+=0]
let b:undo_indent = "setl cin<"
diff --git a/runtime/indent/zsh.vim b/runtime/indent/zsh.vim
index c5580a10b1..8e30c65c18 100644
--- a/runtime/indent/zsh.vim
+++ b/runtime/indent/zsh.vim
@@ -1,7 +1,10 @@
" Vim indent file
-" Language: Zsh Shell Script
-" Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2006-04-19
+" Language: Zsh shell script
+" Maintainer: Christian Brabandt <cb@256bit.org>
+" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
+" Latest Revision: 2015-05-29
+" License: Vim (see :h license)
+" Repository: https://github.com/chrisbra/vim-zsh
if exists("b:did_indent")
finish
diff --git a/runtime/syntax/cpp.vim b/runtime/syntax/cpp.vim
index 04fc73342c..15f0cbb4ff 100644
--- a/runtime/syntax/cpp.vim
+++ b/runtime/syntax/cpp.vim
@@ -63,7 +63,7 @@ if version >= 508 || !exists("did_cpp_syntax_inits")
HiLink cppStructure Structure
HiLink cppBoolean Boolean
HiLink cppConstant Constant
- HiLink cppRawDelimiter Delimiter
+ HiLink cppRawStringDelimiter Delimiter
HiLink cppRawString String
delcommand HiLink
endif
diff --git a/runtime/syntax/css.vim b/runtime/syntax/css.vim
index c6fc6a7ae2..51758ca98f 100644
--- a/runtime/syntax/css.vim
+++ b/runtime/syntax/css.vim
@@ -6,7 +6,7 @@
" Nikolai Weibull (Add CSS2 support)
" Maintainer: Jules Wang <w.jq0722@gmail.com>
" URL: https://github.com/JulesWang/css.vim
-" Last Change: 2013 Nov.27
+" Last Change: 2015 Apr.17
" For version 5.x: Clear all syntax items
" For version 6.x: Quit when a syntax file was already loaded
@@ -26,18 +26,19 @@ set cpo&vim
syn case ignore
-" All HTML4 tags
-syn keyword cssTagName abbr acronym address applet area a b base
-syn keyword cssTagName basefont bdo big blockquote body br button
-syn keyword cssTagName caption center cite code col colgroup dd del
-syn keyword cssTagName dfn dir div dl dt em fieldset font form frame
-syn keyword cssTagName frameset h1 h2 h3 h4 h5 h6 head hr html img i
-syn keyword cssTagName iframe img input ins isindex kbd label legend li
-syn keyword cssTagName link map menu meta noframes noscript ol optgroup
-syn keyword cssTagName option p param pre q s samp script select small
-syn keyword cssTagName span strike strong style sub sup table tbody td
-syn keyword cssTagName textarea tfoot th thead title tr tt ul u var
+" HTML4 tags
+syn keyword cssTagName abbr address area a b base
+syn keyword cssTagName bdo blockquote body br button
+syn keyword cssTagName caption cite code col colgroup dd del
+syn keyword cssTagName dfn div dl dt em fieldset form
+syn keyword cssTagName h1 h2 h3 h4 h5 h6 head hr html img i
+syn keyword cssTagName iframe input ins isindex kbd label legend li
+syn keyword cssTagName link map menu meta noscript ol optgroup
+syn keyword cssTagName option p param pre q s samp script small
+syn keyword cssTagName span strong sub sup tbody td
+syn keyword cssTagName textarea tfoot th thead title tr ul u var
syn keyword cssTagName object svg
+syn match cssTagName /\<select\>\|\<style\>\|\<table\>/
" 34 HTML5 tags
syn keyword cssTagName article aside audio bdi canvas command data
@@ -47,8 +48,8 @@ syn keyword cssTagName output progress rt rp ruby section
syn keyword cssTagName source summary time track video wbr
" Tags not supported in HTML5
-syn keyword cssDeprecated acronym applet basefont big center dir
-syn keyword cssDeprecated font frame frameset noframes strike tt
+" acronym applet basefont big center dir
+" font frame frameset noframes strike tt
syn match cssTagName "\*"
@@ -70,13 +71,13 @@ endtry
" digits
syn match cssValueInteger contained "[-+]\=\d\+" contains=cssUnitDecorators
syn match cssValueNumber contained "[-+]\=\d\+\(\.\d*\)\=" contains=cssUnitDecorators
-syn match cssValueLength contained "[-+]\=\d\+\(\.\d*\)\=\(%\|mm\|cm\|in\|pt\|pc\|em\|ex\|px\|rem\|dpi\|dppx\|dpcm\)" contains=cssUnitDecorators
-syn match cssValueAngle contained "[-+]\=\d\+\(\.\d*\)\=\(deg\|grad\|rad\)" contains=cssUnitDecorators
-syn match cssValueTime contained "+\=\d\+\(\.\d*\)\=\(ms\|s\)" contains=cssUnitDecorators
-syn match cssValueFrequency contained "+\=\d\+\(\.\d*\)\=\(Hz\|kHz\)" contains=cssUnitDecorators
+syn match cssValueLength contained "[-+]\=\d\+\(\.\d*\)\=\(%\|mm\|cm\|in\|pt\|pc\|em\|ex\|px\|rem\|dpi\|dppx\|dpcm\)\>" contains=cssUnitDecorators
+syn match cssValueAngle contained "[-+]\=\d\+\(\.\d*\)\=\(deg\|grad\|rad\)\>" contains=cssUnitDecorators
+syn match cssValueTime contained "+\=\d\+\(\.\d*\)\=\(ms\|s\)\>" contains=cssUnitDecorators
+syn match cssValueFrequency contained "+\=\d\+\(\.\d*\)\=\(Hz\|kHz\)\>" contains=cssUnitDecorators
-syn match cssIncludeKeyword /@\(-[a-z]+-\)\=\(media\|keyframes\|import\|charset\|namespace\|page\)/ contained
+syn match cssIncludeKeyword /@\(-[a-z]\+-\)\=\(media\|keyframes\|import\|charset\|namespace\|page\)/ contained
" @media
syn region cssInclude start=/@media\>/ end=/\ze{/ skipwhite skipnl contains=cssMediaProp,cssValueLength,cssMediaKeyword,cssValueInteger,cssMediaAttr,cssVendor,cssMediaType,cssIncludeKeyword,cssMediaComma,cssComment nextgroup=cssMediaBlock
syn keyword cssMediaType contained screen print aural braille embossed handheld projection tty tv speech all contained skipwhite skipnl
@@ -86,7 +87,7 @@ syn match cssMediaComma "," skipwhite skipnl contained
" Reference: http://www.w3.org/TR/css3-mediaqueries/
syn keyword cssMediaProp contained width height orientation scan grid
-syn match cssMediaProp contained /\(\(device\)-\)\=aspect-ratio/
+syn match cssMediaProp contained /\(\(max\|min\)-\)\=\(\(device\)-\)\=aspect-ratio/
syn match cssMediaProp contained /\(\(max\|min\)-\)\=device-pixel-ratio/
syn match cssMediaProp contained /\(\(max\|min\)-\)\=device-\(height\|width\)/
syn match cssMediaProp contained /\(\(max\|min\)-\)\=\(height\|width\|resolution\|monochrome\|color\(-index\)\=\)/
@@ -104,7 +105,7 @@ syn keyword cssPageProp contained orphans widows
" @keyframe
" http://www.w3.org/TR/css3-animations/#keyframes
-syn match cssKeyFrame "@\(-[a-z]+-\)\=keyframes\>[^{]*{\@=" nextgroup=cssKeyFrameWrap contains=cssVendor,cssIncludeKeyword skipwhite skipnl transparent
+syn match cssKeyFrame "@\(-[a-z]\+-\)\=keyframes\>[^{]*{\@=" nextgroup=cssKeyFrameWrap contains=cssVendor,cssIncludeKeyword skipwhite skipnl transparent
syn region cssKeyFrameWrap contained transparent matchgroup=cssBraces start="{" end="}" contains=cssKeyFrameSelector
syn match cssKeyFrameSelector /\(\d*%\|from\|to\)\=/ contained skipwhite skipnl nextgroup=cssDefinition
@@ -116,15 +117,27 @@ syn region cssInclude start=/@namespace\>/ end=/\ze;/ transparent contains=cssSt
" @font-face
" http://www.w3.org/TR/css3-fonts/#at-font-face-rule
syn match cssFontDescriptor "@font-face\>" nextgroup=cssFontDescriptorBlock skipwhite skipnl
-syn region cssFontDescriptorBlock contained transparent matchgroup=cssBraces start="{" end="}" contains=cssComment,cssError,cssUnicodeEscape,cssFontProp,cssFontAttr,cssCommonAttr,cssStringQ,cssStringQQ,cssFontDescriptorProp,cssValue.*,cssFontDescriptorFunction,cssUnicodeRange,cssFontDescriptorAttr
-"syn match cssFontDescriptorProp contained "\<\(unicode-range\|unit-per-em\|panose-1\|cap-height\|x-height\|definition-src\)\>"
-"syn keyword cssFontDescriptorProp contained src stemv stemh slope ascent descent widths bbox baseline centerline mathline topline
+syn region cssFontDescriptorBlock contained transparent matchgroup=cssBraces start="{" end="}" contains=cssComment,cssError,cssUnicodeEscape,cssCommonAttr,cssFontDescriptorProp,cssValue.*,cssFontDescriptorFunction,cssFontDescriptorAttr,cssNoise
+
+syn match cssFontDescriptorProp contained "\<font-family\>"
syn keyword cssFontDescriptorProp contained src
+syn match cssFontDescriptorProp contained "\<font-\(style\|weight\|stretch\)\>"
syn match cssFontDescriptorProp contained "\<unicode-range\>"
-syn keyword cssFontDescriptorAttr contained all
+syn match cssFontDescriptorProp contained "\<font-\(variant\|feature-settings\)\>"
+
+" src functions
syn region cssFontDescriptorFunction contained matchgroup=cssFunctionName start="\<\(uri\|url\|local\|format\)\s*(" end=")" contains=cssStringQ,cssStringQQ oneline keepend
-syn match cssUnicodeRange contained "U+[0-9A-Fa-f?]\+"
-syn match cssUnicodeRange contained "U+\x\+-\x\+"
+" font-sytle and font-weight attributes
+syn keyword cssFontDescriptorAttr contained normal italic oblique bold
+" font-stretch attributes
+syn match cssFontDescriptorAttr contained "\<\(\(ultra\|extra\|semi\)-\)\=\(condensed\|expanded\)\>"
+" unicode-range attributes
+syn match cssFontDescriptorAttr contained "U+[0-9A-Fa-f?]\+"
+syn match cssFontDescriptorAttr contained "U+\x\+-\x\+"
+" font-feature-settings attributes
+syn keyword cssFontDescriptorAttr contained on off
+
+
" The 16 basic color names
syn keyword cssColor contained aqua black blue fuchsia gray green lime maroon navy olive purple red silver teal yellow
@@ -133,23 +146,23 @@ syn keyword cssColor contained aqua black blue fuchsia gray green lime maroon na
syn keyword cssColor contained aliceblue antiquewhite aquamarine azure
syn keyword cssColor contained beige bisque blanchedalmond blueviolet brown burlywood
syn keyword cssColor contained cadetblue chartreuse chocolate coral cornflowerblue cornsilk crimson cyan
-syn match cssColor contained /dark\(blue\|cyan\|goldenrod\|gray\|green\|grey\|khaki\)/
-syn match cssColor contained /dark\(magenta\|olivegreen\|orange\|orchid\|red\|salmon\|seagreen\)/
-syn match cssColor contained /darkslate\(blue\|gray\|grey\)/
-syn match cssColor contained /dark\(turquoise\|violet\)/
+syn match cssColor contained /\<dark\(blue\|cyan\|goldenrod\|gray\|green\|grey\|khaki\)\>/
+syn match cssColor contained /\<dark\(magenta\|olivegreen\|orange\|orchid\|red\|salmon\|seagreen\)\>/
+syn match cssColor contained /\<darkslate\(blue\|gray\|grey\)\>/
+syn match cssColor contained /\<dark\(turquoise\|violet\)\>/
syn keyword cssColor contained deeppink deepskyblue dimgray dimgrey dodgerblue firebrick
syn keyword cssColor contained floralwhite forestgreen gainsboro ghostwhite gold
syn keyword cssColor contained goldenrod greenyellow grey honeydew hotpink
syn keyword cssColor contained indianred indigo ivory khaki lavender lavenderblush lawngreen
syn keyword cssColor contained lemonchiffon limegreen linen magenta
-syn match cssColor contained /light\(blue\|coral\|cyan\|goldenrodyellow\|gray\|green\)/
-syn match cssColor contained /light\(grey\|pink\|salmon\|seagreen\|skyblue\|yellow\)/
-syn match cssColor contained /light\(slategray\|slategrey\|steelblue\)/
-syn match cssColor contained /medium\(aquamarine\|blue\|orchid\|purple\|seagreen\)/
-syn match cssColor contained /medium\(slateblue\|springgreen\|turquoise\|violetred\)/
+syn match cssColor contained /\<light\(blue\|coral\|cyan\|goldenrodyellow\|gray\|green\)\>/
+syn match cssColor contained /\<light\(grey\|pink\|salmon\|seagreen\|skyblue\|yellow\)\>/
+syn match cssColor contained /\<light\(slategray\|slategrey\|steelblue\)\>/
+syn match cssColor contained /\<medium\(aquamarine\|blue\|orchid\|purple\|seagreen\)\>/
+syn match cssColor contained /\<medium\(slateblue\|springgreen\|turquoise\|violetred\)\>/
syn keyword cssColor contained midnightblue mintcream mistyrose moccasin navajowhite
syn keyword cssColor contained oldlace olivedrab orange orangered orchid
-syn match cssColor contained /pale\(goldenrod\|green\|turquoise\|violetred\)/
+syn match cssColor contained /\<pale\(goldenrod\|green\|turquoise\|violetred\)\>/
syn keyword cssColor contained papayawhip peachpuff peru pink plum powderblue
syn keyword cssColor contained rosybrown royalblue saddlebrown salmon sandybrown
syn keyword cssColor contained seagreen seashell sienna skyblue slateblue
@@ -167,11 +180,12 @@ syn case ignore
syn match cssImportant contained "!\s*important\>"
syn match cssColor contained "\<transparent\>"
+syn match cssColor contained "\<currentColor\>"
syn match cssColor contained "\<white\>"
syn match cssColor contained "#[0-9A-Fa-f]\{3\}\>" contains=cssUnitDecorators
syn match cssColor contained "#[0-9A-Fa-f]\{6\}\>" contains=cssUnitDecorators
-syn region cssURL contained matchgroup=cssFunctionName start="\<url\s*(" end=")" oneline extend
+syn region cssURL contained matchgroup=cssFunctionName start="\<url\s*(" end=")" contains=cssStringQ,cssStringQQ oneline
syn region cssFunction contained matchgroup=cssFunctionName start="\<\(rgb\|clip\|attr\|counter\|rect\|cubic-bezier\|steps\)\s*(" end=")" oneline contains=cssValueInteger,cssValueNumber,cssValueLength,cssFunctionComma
syn region cssFunction contained matchgroup=cssFunctionName start="\<\(rgba\|hsl\|hsla\|color-stop\|from\|to\)\s*(" end=")" oneline contains=cssColor,cssValueInteger,cssValueNumber,cssValueLength,cssFunctionComma,cssFunction
syn region cssFunction contained matchgroup=cssFunctionName start="\<\(linear-\|radial-\)\=\gradient\s*(" end=")" oneline contains=cssColor,cssValueInteger,cssValueNumber,cssValueLength,cssFunction,cssGradientAttr,cssFunctionComma
@@ -196,6 +210,9 @@ syn keyword cssAnimationAttr contained forwards backwards both
" animation-play-state attributes
syn keyword cssAnimationAttr contained running paused
+
+" animation-iteration-count attributes
+syn keyword cssAnimationAttr contained infinite
"------------------------------------------------
" CSS Backgrounds and Borders Module Level 3
" http://www.w3.org/TR/css3-background/
@@ -253,7 +270,7 @@ syn keyword cssDimensionProp contained width
syn match cssFlexibleBoxProp contained "\<box-\(align\|direction\|flex\|ordinal-group\|orient\|pack\|shadow\|sizing\)\>"
syn keyword cssFlexibleBoxAttr contained start end baseline
syn keyword cssFlexibleBoxAttr contained reverse
-syn keyword cssFlexibleBoxAttr contained single mulitple
+syn keyword cssFlexibleBoxAttr contained single multiple
syn keyword cssFlexibleBoxAttr contained horizontal
syn match cssFlexibleBoxAttr contained "\<vertical\(-align\)\@!\>" "escape vertical-align
syn match cssFlexibleBoxAttr contained "\<\(inline\|block\)-axis\>"
@@ -261,6 +278,7 @@ syn match cssFlexibleBoxAttr contained "\<\(inline\|block\)-axis\>"
" CSS Fonts Module Level 3
" http://www.w3.org/TR/css-fonts-3/
syn match cssFontProp contained "\<font\(-\(family\|\|feature-settings\|kerning\|language-override\|size\(-adjust\)\=\|stretch\|style\|synthesis\|variant\(-\(alternates\|caps\|east-asian\|ligatures\|numeric\|position\)\)\=\|weight\)\)\=\>"
+
" font attributes
syn keyword cssFontAttr contained icon menu caption
syn match cssFontAttr contained "\<small-\(caps\|caption\)\>"
@@ -268,27 +286,21 @@ syn match cssFontAttr contained "\<message-box\>"
syn match cssFontAttr contained "\<status-bar\>"
syn keyword cssFontAttr contained larger smaller
syn match cssFontAttr contained "\<\(x\{1,2\}-\)\=\(large\|small\)\>"
-
" font-family attributes
syn match cssFontAttr contained "\<\(sans-\)\=serif\>"
-syn keyword cssFontAttr contained Antiqua Arial Black Book Charcoal Comic Courier Dingbats Gadget Geneva Georgia Grande Helvetica Impact Linotype Lucida MS Monaco Neue New Palatino Roboto Roman Symbol Tahoma Times Trebuchet Unicode Verdana Webdings Wingdings York Zapf
+syn keyword cssFontAttr contained Antiqua Arial Black Book Charcoal Comic Courier Dingbats Gadget Geneva Georgia Grande Helvetica Impact Linotype Lucida MS Monaco Neue New Palatino Roboto Roman Symbol Tahoma Times Trebuchet Verdana Webdings Wingdings York Zapf
syn keyword cssFontAttr contained cursive fantasy monospace
-
" font-feature-settings attributes
syn keyword cssFontAttr contained on off
-
" font-stretch attributes
syn match cssFontAttr contained "\<\(\(ultra\|extra\|semi\)-\)\=\(condensed\|expanded\)\>"
-
" font-style attributes
syn keyword cssFontAttr contained italic oblique
-
-" font-variant-caps attributes
-syn match cssFontAttr contained "\<\(all-\)\=\(small-\|petite-\|titling-\)caps\>"
-syn keyword cssFontAttr contained unicase
-
+" font-synthesis attributes
+syn keyword cssFontAttr contained weight style
" font-weight attributes
syn keyword cssFontAttr contained bold bolder lighter
+" TODO: font-variant-* attributes
"------------------------------------------------
" Webkit specific property/attributes
@@ -448,7 +460,7 @@ syn match cssMobileTextProp contained "\<text-size-adjust\>"
syn match cssBraces contained "[{}]"
syn match cssError contained "{@<>"
-syn region cssDefinition transparent matchgroup=cssBraces start='{' end='}' contains=cssAttrRegion,css.*Prop,cssComment,cssValue.*,cssColor,cssURL,cssImportant,cssError,cssStringQ,cssStringQQ,cssFunction,cssUnicodeEscape,cssVendor,cssDefinition,cssHacks keepend fold
+syn region cssDefinition transparent matchgroup=cssBraces start='{' end='}' contains=cssAttrRegion,css.*Prop,cssComment,cssValue.*,cssColor,cssURL,cssImportant,cssError,cssStringQ,cssStringQQ,cssFunction,cssUnicodeEscape,cssVendor,cssDefinition,cssHacks,cssNoise fold
syn match cssBraceError "}"
syn match cssAttrComma ","
@@ -466,6 +478,9 @@ syn match cssPseudoClassId contained "\<selection\>"
syn match cssPseudoClassId contained "\<focus\(-inner\)\=\>"
syn match cssPseudoClassId contained "\<\(input-\)\=placeholder\>"
+" Misc highlight groups
+syntax match cssUnitDecorators /\(#\|-\|%\|mm\|cm\|in\|pt\|pc\|em\|ex\|px\|ch\|rem\|vh\|vw\|vmin\|vmax\|dpi\|dppx\|dpcm\|Hz\|kHz\|s\|ms\|deg\|grad\|rad\)/ contained
+syntax match cssNoise contained /\(:\|;\|\/\)/
" Comment
syn region cssComment start="/\*" end="\*/" contains=@Spell fold
@@ -487,17 +502,13 @@ syn match cssVendor contained "\(-\(webkit\|moz\|o\|ms\)-\)"
" http://www.paulirish.com/2009/browser-specific-css-hacks/
syn match cssHacks contained /\(_\|*\)/
-" Misc highlight groups
-syntax match cssUnitDecorators /\(#\|-\|%\|mm\|cm\|in\|pt\|pc\|em\|ex\|px\|rem\|dpi\|dppx\|dpcm\|Hz\|kHz\|s\|ms\|deg\|grad\|rad\)/ contained
-syntax match cssNoise contained /\(:\|;\|\/\)/
-
" Attr Enhance
" Some keywords are both Prop and Attr, so we have to handle them
-syn region cssAttrRegion start=/:/ end=/;/ contained keepend contains=css.*Attr,cssColor,cssImportant,cssValue.*,cssFunction,cssString.*,cssURL,cssComment,cssUnicodeEscape,cssVendor,cssError,cssAttrComma,cssNoise
+syn region cssAttrRegion start=/:/ end=/\ze\(;\|)\|}\)/ contained contains=css.*Attr,cssColor,cssImportant,cssValue.*,cssFunction,cssString.*,cssURL,cssComment,cssUnicodeEscape,cssVendor,cssError,cssAttrComma,cssNoise
" Hack for transition
-" The 'transition' Prop has Props after ':'.
-syn region cssAttrRegion start=/transition\s*:/ end=/;/ contained keepend contains=css.*Prop,css.*Attr,cssColor,cssImportant,cssValue.*,cssFunction,cssString.*,cssURL,cssComment,cssUnicodeEscape,cssVendor,cssError,cssAttrComma,cssNoise
+" 'transition' has Props after ':'.
+syn region cssAttrRegion start=/transition\s*:/ end=/\ze\(;\|)\|}\)/ contained contains=css.*Prop,css.*Attr,cssColor,cssImportant,cssValue.*,cssFunction,cssString.*,cssURL,cssComment,cssUnicodeEscape,cssVendor,cssError,cssAttrComma,cssNoise
if main_syntax == "css"
@@ -635,7 +646,7 @@ if version >= 508 || !exists("did_css_syn_inits")
HiLink cssAttr Constant
HiLink cssUnitDecorators Number
HiLink cssNoise Noise
- HiLink atKeyword Comment
+ HiLink atKeyword PreProc
delcommand HiLink
endif
diff --git a/runtime/syntax/debchangelog.vim b/runtime/syntax/debchangelog.vim
index 6206fa388c..ed3d024499 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: 2014 Jul 11
+" Last Change: 2015 Apr 30
" URL: http://anonscm.debian.org/hg/pkg-vim/vim/raw-file/unstable/runtime/syntax/debchangelog.vim
" Standard syntax initialization
@@ -16,10 +16,14 @@ endif
" Case doesn't matter for us
syn case ignore
+let urgency='urgency=\(low\|medium\|high\|critical\)\( [^[:space:],][^,]*\)\='
+let binNMU='binary-only=yes'
+
" Define some common expressions we can use later on
syn match debchangelogName contained "^[[:alnum:]][[:alnum:].+-]\+ "
-syn match debchangelogUrgency contained "; urgency=\(low\|medium\|high\|critical\|emergency\)\( \S.*\)\="
-syn match debchangelogTarget contained "\v %(frozen|unstable|%(testing|%(old)=stable)%(-proposed-updates|-security)=|experimental|squeeze-%(backports%(-sloppy)=|volatile)|wheezy-backports|%(devel|lucid|precise|trusty|utopic)%(-%(security|proposed|updates|backports|commercial|partner))=)+"
+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|lucid|precise|trusty|utopic)%(-%(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\+\)*"
@@ -27,7 +31,7 @@ syn match debchangelogEmail contained "[_=[:alnum:].+-]\+@[[:alnum:]./\-]\+"
syn match debchangelogEmail contained "<.\{-}>"
" Define the entries that make up the changelog
-syn region debchangelogHeader start="^[^ ]" end="$" contains=debchangelogName,debchangelogUrgency,debchangelogTarget,debchangelogVersion oneline
+syn region debchangelogHeader start="^[^ ]" end="$" contains=debchangelogName,debchangelogFirstKV,debchangelogOtherKV,debchangelogTarget,debchangelogVersion,debchangelogBinNMU oneline
syn region debchangelogFooter start="^ [^ ]" end="$" contains=debchangelogEmail oneline
syn region debchangelogEntry start="^ " end="$" contains=debchangelogCloses,debchangelogLP oneline
@@ -45,7 +49,8 @@ if version >= 508 || !exists("did_debchangelog_syn_inits")
HiLink debchangelogEntry Normal
HiLink debchangelogCloses Statement
HiLink debchangelogLP Statement
- HiLink debchangelogUrgency Identifier
+ HiLink debchangelogFirstKV Identifier
+ HiLink debchangelogOtherKV Identifier
HiLink debchangelogName Comment
HiLink debchangelogVersion Identifier
HiLink debchangelogTarget Identifier
diff --git a/runtime/syntax/debcontrol.vim b/runtime/syntax/debcontrol.vim
index 5d9d45d025..6d140d9bd9 100644
--- a/runtime/syntax/debcontrol.vim
+++ b/runtime/syntax/debcontrol.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: 2014 May 01
+" Last Change: 2014 Oct 08
" URL: http://anonscm.debian.org/hg/pkg-vim/vim/raw-file/unstable/runtime/syntax/debcontrol.vim
" Standard syntax initialization
@@ -50,7 +50,7 @@ syn match debcontrolDmUpload contained "\cyes"
syn match debcontrolHTTPUrl contained "\vhttps?://[[:alnum:]][-[:alnum:]]*[[:alnum:]]?(\.[[:alnum:]][-[:alnum:]]*[[:alnum:]]?)*\.[[:alpha:]][-[:alnum:]]*[[:alpha:]]?(:\d+)?(/[^[:space:]]*)?$"
syn match debcontrolVcsSvn contained "\vsvn%(\+ssh)?://[[:alnum:]][-[:alnum:]]*[[:alnum:]]?(\.[[:alnum:]][-[:alnum:]]*[[:alnum:]]?)*\.[[:alpha:]][-[:alnum:]]*[[:alpha:]]?(:\d+)?(/[^[:space:]]*)?$"
syn match debcontrolVcsCvs contained "\v%(\-d *)?:pserver:[^@]+\@[[:alnum:]][-[:alnum:]]*[[:alnum:]]?(\.[[:alnum:]][-[:alnum:]]*[[:alnum:]]?)*\.[[:alpha:]][-[:alnum:]]*[[:alpha:]]?:/[^[:space:]]*%( [^[:space:]]+)?$"
-syn match debcontrolVcsGit contained "\v%(git|http)://[[:alnum:]][-[:alnum:]]*[[:alnum:]]?(\.[[:alnum:]][-[:alnum:]]*[[:alnum:]]?)*\.[[:alpha:]][-[:alnum:]]*[[:alpha:]]?(:\d+)?(/[^[:space:]]*)?%(\s+-b\s+[^ ~^:?*[\\]+)?$"
+syn match debcontrolVcsGit contained "\v%(git|https?)://[[:alnum:]][-[:alnum:]]*[[:alnum:]]?(\.[[:alnum:]][-[:alnum:]]*[[:alnum:]]?)*\.[[:alpha:]][-[:alnum:]]*[[:alpha:]]?(:\d+)?(/[^[:space:]]*)?%(\s+-b\s+[^ ~^:?*[\\]+)?$"
" An email address
syn match debcontrolEmail "[_=[:alnum:]\.+-]\+@[[:alnum:]\./\-]\+"
diff --git a/runtime/syntax/debsources.vim b/runtime/syntax/debsources.vim
index e877b06ae4..c8d110c77b 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: 2014 Jul 11
+" Last Change: 2015 May 25
" URL: http://anonscm.debian.org/hg/pkg-vim/vim/raw-file/unstable/runtime/syntax/debsources.vim
" Standard syntax initialization
@@ -21,15 +21,35 @@ syn match debsourcesKeyword /\(deb-src\|deb\|main\|contrib\|non-free\|res
" Match comments
syn match debsourcesComment /#.*/ contains=@Spell
+let s:cpo = &cpo
+set cpo-=C
+let s:supported = [
+ \ 'oldstable', 'stable', 'testing', 'unstable', 'experimental',
+ \ 'squeeze', 'wheezy', 'jessie', 'stretch', 'sid', 'rc-buggy',
+ \
+ \ 'precise', 'trusty', 'utopic', 'vivid', 'wily', 'devel'
+ \ ]
+let s:unsupported = [
+ \ 'buzz', 'rex', 'bo', 'hamm', 'slink', 'potato',
+ \ 'woody', 'sarge', 'etch', 'lenny',
+ \
+ \ 'warty', 'hoary', 'breezy', 'dapper', 'edgy', 'feisty',
+ \ 'gutsy', 'hardy', 'intrepid', 'jaunty', 'karmic', 'lucid',
+ \ 'maverick', 'natty', 'oneiric', 'quantal', 'raring', 'saucy'
+ \ ]
+let &cpo=s:cpo
+
" Match uri's
syn match debsourcesUri +\(http://\|ftp://\|[rs]sh://\|debtorrent://\|\(cdrom\|copy\|file\):\)[^' <>"]\++
-syn match debsourcesDistrKeyword +\([[:alnum:]_./]*\)\(squeeze\|wheezy\|jessie\|\(old\)\=stable\|testing\|unstable\|sid\|rc-buggy\|experimental\|devel\|lucid\|precise\|trusty\|utopic\)\([-[:alnum:]_./]*\)+
+exe 'syn match debsourcesDistrKeyword +\([[:alnum:]_./]*\)\('. join(s:supported, '\|'). '\)\([-[:alnum:]_./]*\)+'
+exe 'syn match debsourcesUnsupportedDistrKeyword +\([[:alnum:]_./]*\)\('. join(s:unsupported, '\|') .'\)\([-[:alnum:]_./]*\)+'
" Associate our matches and regions with pretty colours
-hi def link debsourcesLine Error
-hi def link debsourcesKeyword Statement
-hi def link debsourcesDistrKeyword Type
-hi def link debsourcesComment Comment
-hi def link debsourcesUri Constant
+hi def link debsourcesLine Error
+hi def link debsourcesKeyword Statement
+hi def link debsourcesDistrKeyword Type
+hi def link debsourcesUnsupportedDistrKeyword WarningMsg
+hi def link debsourcesComment Comment
+hi def link debsourcesUri Constant
let b:current_syntax = "debsources"
diff --git a/runtime/syntax/groovy.vim b/runtime/syntax/groovy.vim
index 2056bd16d0..c745960bd5 100644
--- a/runtime/syntax/groovy.vim
+++ b/runtime/syntax/groovy.vim
@@ -157,7 +157,7 @@ syn match groovyOperator "\.\."
syn match groovyOperator "<\{2,3}"
syn match groovyOperator ">\{2,3}"
syn match groovyOperator "->"
-syn match groovyExternal '^#!.*[/\\]groovy\>'
+syn match groovyLineComment '^\%1l#!.*' " Shebang line
syn match groovyExceptions "\<Exception\>\|\<[A-Z]\{1,}[a-zA-Z0-9]*Exception\>"
" Groovy JDK stuff
diff --git a/runtime/syntax/kconfig.vim b/runtime/syntax/kconfig.vim
index a6ceb1712a..c7a305b73c 100644
--- a/runtime/syntax/kconfig.vim
+++ b/runtime/syntax/kconfig.vim
@@ -1,6 +1,9 @@
" Vim syntax file
-" Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2009-05-25
+" Maintainer: Christian Brabandt <cb@256bit.org>
+" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
+" Latest Revision: 2015-05-29
+" License: Vim (see :h license)
+" Repository: https://github.com/chrisbra/vim-kconfig
if exists("b:current_syntax")
finish
diff --git a/runtime/syntax/po.vim b/runtime/syntax/po.vim
index c09b960357..2ab13ac0b1 100644
--- a/runtime/syntax/po.vim
+++ b/runtime/syntax/po.vim
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: po (gettext)
" Maintainer: Dwayne Bailey <dwayne@translate.org.za>
-" Last Change: 2012 Apr 30
+" Last Change: 2015 Jun 07
" Contributors: Dwayne Bailey (Most advanced syntax highlighting)
" Leonardo Fontenelle (Spell checking)
" Nam SungHyun <namsh@kldp.org> (Original maintainer)
@@ -52,6 +52,9 @@ syn match poCommentTranslator "^# .*$" contains=poCopyrightUnset
syn match poCommentAutomatic "^#\..*$"
syn match poCommentSources "^#:.*$"
syn match poCommentFlags "^#,.*$" contains=poFlagFuzzy
+syn match poDiffOld '\(^#| "[^{]*+}\|{+[^}]*+}\|{+[^}]*\|"$\)' contained
+syn match poDiffNew '\(^#| "[^{]*-}\|{-[^}]*-}\|{-[^}]*\|"$\)' contained
+syn match poCommentDiff "^#|.*$" contains=poDiffOld,poDiffNew
" Translations (also includes header fields as they appear in a translation msgstr)
syn region poCommentKDE start=+"_: +ms=s+1 end="\\n" end="\"\n^msgstr"me=s-1 contained
@@ -94,8 +97,11 @@ if version >= 508 || !exists("did_po_syn_inits")
HiLink poCommentAutomatic Comment
HiLink poCommentTranslator Comment
HiLink poCommentFlags Special
+ HiLink poCommentDiff Comment
HiLink poCopyrightUnset Todo
HiLink poFlagFuzzy Todo
+ HiLink poDiffOld Todo
+ HiLink poDiffNew Special
HiLink poObsolete Comment
HiLink poStatementMsgid Statement
diff --git a/runtime/syntax/rc.vim b/runtime/syntax/rc.vim
index c3feb97816..a2d5824d3e 100644
--- a/runtime/syntax/rc.vim
+++ b/runtime/syntax/rc.vim
@@ -1,7 +1,10 @@
" Vim syntax file
" Language: M$ Resource files (*.rc)
-" Maintainer: Heiko Erhardt <Heiko.Erhardt@munich.netsurf.de>
-" Last Change: 2001 May 09
+" Maintainer: Christian Brabandt
+" Last Change: 2015-05-29
+" Repository: https://github.com/chrisbra/vim-rc-syntax
+" License: Vim (see :h license)
+" Previous Maintainer: Heiko Erhardt <Heiko.Erhardt@munich.netsurf.de>
" This file is based on the c.vim
@@ -21,7 +24,7 @@ syn keyword rcMainObject MENU ACCELERATORS TOOLBAR DIALOG
syn keyword rcMainObject STRINGTABLE MESSAGETABLE RCDATA DLGINIT DESIGNINFO
syn keyword rcSubObject POPUP MENUITEM SEPARATOR
-syn keyword rcSubObject CONTROL LTEXT CTEXT EDITTEXT
+syn keyword rcSubObject CONTROL LTEXT CTEXT RTEXT EDITTEXT
syn keyword rcSubObject BUTTON PUSHBUTTON DEFPUSHBUTTON GROUPBOX LISTBOX COMBOBOX
syn keyword rcSubObject FILEVERSION PRODUCTVERSION FILEFLAGSMASK FILEFLAGS FILEOS
syn keyword rcSubObject FILETYPE FILESUBTYPE
diff --git a/runtime/syntax/vhdl.vim b/runtime/syntax/vhdl.vim
index db51fa5034..c76b046d8c 100644
--- a/runtime/syntax/vhdl.vim
+++ b/runtime/syntax/vhdl.vim
@@ -3,7 +3,7 @@
" Maintainer: Daniel Kho <daniel.kho@tauhop.com>
" Previous Maintainer: Czo <Olivier.Sirol@lip6.fr>
" Credits: Stephan Hegel <stephan.hegel@snc.siemens.com.cn>
-" Last Changed: 2012 Feb 03 by Thilo Six
+" Last Changed: 2015 Apr 25 by Daniel Kho
" $Id: vhdl.vim,v 1.1 2004/06/13 15:34:56 vimboss Exp $
" VHSIC (Very High Speed Integrated Circuit) Hardware Description Language
@@ -160,10 +160,20 @@ syn match vhdlSpecial "[().,;]"
syn match vhdlTime "\<\d\+\s\+\(\([fpnum]s\)\|\(sec\)\|\(min\)\|\(hr\)\)\>"
syn match vhdlTime "\<\d\+\.\d\+\s\+\(\([fpnum]s\)\|\(sec\)\|\(min\)\|\(hr\)\)\>"
-syn keyword vhdlTodo contained TODO FIXME
-
-syn region vhdlComment start="/\*" end="\*/" contains=vhdlTodo,@Spell
-syn match vhdlComment "--.*" contains=vhdlTodo,@Spell
+syn keyword vhdlTodo contained TODO NOTE
+syn keyword vhdlFixme contained FIXME
+
+" Regex for space is '\s'
+" Any number of spaces: \s*
+" At least one space: \s+
+syn region vhdlComment start="/\*" end="\*/" contains=vhdlTodo,vhdlFixme,@Spell
+syn match vhdlComment "--.*" contains=vhdlTodo,vhdlFixme,@Spell
+syn match vhdlPreProc "/\* synthesis .* \*/"
+syn match vhdlPreProc "/\* pragma .* \*/"
+syn match vhdlPreProc "/\* synopsys .* \*/"
+syn match vhdlPreProc "--\s*synthesis .*"
+syn match vhdlPreProc "--\s*pragma .*"
+syn match vhdlPreProc "--\s*synopsys .*"
" syn match vhdlGlobal "[\'$#~!%@?\^\[\]{}\\]"
"Modify the following as needed. The trade-off is performance versus functionality.
@@ -180,21 +190,22 @@ if version >= 508 || !exists("did_vhdl_syntax_inits")
command -nargs=+ HiLink hi def link <args>
endif
-" HiLink cDefine PreProc
- HiLink vhdlSpecial Special
- HiLink vhdlStatement Statement
- HiLink vhdlCharacter Character
- HiLink vhdlString String
- HiLink vhdlVector Number
- HiLink vhdlBoolean Number
- HiLink vhdlTodo Todo
- HiLink vhdlComment Comment
- HiLink vhdlNumber Number
- HiLink vhdlTime Number
- HiLink vhdlType Type
- HiLink vhdlOperator Special
+ HiLink vhdlSpecial Special
+ HiLink vhdlStatement Statement
+ HiLink vhdlCharacter Character
+ HiLink vhdlString String
+ HiLink vhdlVector Number
+ HiLink vhdlBoolean Number
+ HiLink vhdlTodo Todo
+ HiLink vhdlFixme Fixme
+ HiLink vhdlComment Comment
+ HiLink vhdlNumber Number
+ HiLink vhdlTime Number
+ HiLink vhdlType Type
+ HiLink vhdlOperator Operator
" HiLink vhdlGlobal Error
- HiLink vhdlAttribute Type
+ HiLink vhdlAttribute Special
+ HiLink vhdlPreProc PreProc
delcommand HiLink
endif
diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim
index e23232bbbe..cf51830b68 100644
--- a/runtime/syntax/vim.vim
+++ b/runtime/syntax/vim.vim
@@ -19,7 +19,7 @@ syn cluster vimCommentGroup contains=vimTodo,@Spell
" Special and plugin vim commands {{{2
syn match vimCommand contained "\<z[-+^.=]\="
-syn keyword vimOnlyCommand contained fix[del] sh[ell] P[rint]
+syn keyword vimOnlyCommand contained fix[del] op[en] sh[ell] P[rint]
syn keyword vimStdPlugin contained DiffOrig Man N[ext] S TOhtml XMLent XMLns
" Vim-specific options {{{2
diff --git a/runtime/syntax/zsh.vim b/runtime/syntax/zsh.vim
index 79fd017ee8..5e588e7d6c 100644
--- a/runtime/syntax/zsh.vim
+++ b/runtime/syntax/zsh.vim
@@ -1,7 +1,10 @@
" Vim syntax file
-" Language: Zsh shell script
-" Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2010-01-23
+" Language: Zsh shell script
+" Maintainer: Christian Brabandt <cb@256bit.org>
+" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
+" Latest Revision: 2015-05-29
+" License: Vim (see :h license)
+" Repository: https://github.com/chrisbra/vim-zsh
if exists("b:current_syntax")
finish
@@ -14,7 +17,7 @@ setlocal iskeyword+=-
syn keyword zshTodo contained TODO FIXME XXX NOTE
-syn region zshComment oneline start='\%(^\|\s\)#' end='$'
+syn region zshComment oneline start='\%(^\|\s*\)#' end='$'
\ contains=zshTodo,@Spell
syn match zshPreProc '^\%1l#\%(!\|compdef\|autoload\).*$'
@@ -30,7 +33,7 @@ syn match zshJobSpec '%\(\d\+\|?\=\w\+\|[%+-]\)'
syn keyword zshPrecommand noglob nocorrect exec command builtin - time
-syn keyword zshDelimiter do done
+syn keyword zshDelimiter do done end
syn keyword zshConditional if then elif else fi case in esac select
@@ -64,7 +67,7 @@ syn region zshHereDoc matchgroup=zshRedir
\ end='^\s*\z1\>'
\ contains=@zshSubst
syn region zshHereDoc matchgroup=zshRedir
- \ start=+<\@<!<<\s*\(["']\)\z(\S\+\)\1+
+ \ start=+<\@<!<<\s*\(["']\)\z(\S\+\)\1+
\ end='^\z1\>'
syn region zshHereDoc matchgroup=zshRedir
\ start=+<\@<!<<-\s*\(["']\)\z(\S\+\)\1+
@@ -121,6 +124,165 @@ syn keyword zshCommands alias autoload bg bindkey break bye cap cd
\ zmodload zparseopts zprof zpty zregexparse
\ zsocket zstyle ztcp
+" Options, generated by: echo ${(j:\n:)options[(I)*]} | sort
+syn case ignore
+syn keyword zshOptions aliases allexport all_export alwayslastprompt
+ \ always_lastprompt alwaystoend always_to_end
+ \ appendhistory append_history autocd autocontinue
+ \ auto_continue autolist auto_list
+ \ automenu auto_menu autonamedirs auto_name_dirs
+ \ autoparamkeys auto_param_keys autoparamslash
+ \ auto_param_slash autopushd auto_pushd autoremoveslash
+ \ auto_remove_slash autoresume auto_resume badpattern
+ \ banghist bang_hist bareglobqual bare_glob_qual
+ \ bashautolist bash_auto_list bashrematch bash_rematch
+ \ beep bgnice braceccl brace_ccl braceexpand brace_expand
+ \ bsdecho bsd_echo caseglob case_glob casematch case_match
+ \ cbases cdablevars cd_able_vars chasedots chase_dots
+ \ chaselinks chase_links checkjobs check_jobs
+ \ clobber combiningchars combining_chars completealiases
+ \ complete_aliases completeinword complete_in_word
+ \ continueonerror continue_on_error correct
+ \ correctall correct_all cprecedences c_precedences
+ \ cshjunkiehistory csh_junkie_history cshjunkieloops
+ \ csh_junkie_loops cshjunkiequotes csh_junkie_quotes
+ \ cshnullcmd csh_null_cmd cshnullglob csh_null_glob
+ \ debugbeforecmd debug_before_cmd dotglob dot_glob dvorak
+ \ emacs equals errexit err_exit errreturn err_return evallineno
+ \ eval_lineno exec extendedglob extended_glob extendedhistory
+ \ extended_history flowcontrol flow_control forcefloat
+ \ force_float functionargzero function_arg_zero glob globalexport
+ \ global_export globalrcs global_rcs globassign glob_assign
+ \ globcomplete glob_complete globdots glob_dots glob_subst
+ \ globsubst hashall hash_all hashcmds hash_cmds hashdirs
+ \ hash_dirs hashexecutablesonly hash_executables_only hashlistall
+ \ hash_list_all histallowclobber hist_allow_clobber histappend
+ \ hist_append histbeep hist_beep hist_expand hist_expire_dups_first
+ \ histexpand histexpiredupsfirst histfcntllock hist_fcntl_lock
+ \ histfindnodups hist_find_no_dups histignorealldups
+ \ hist_ignore_all_dups histignoredups hist_ignore_dups
+ \ histignorespace hist_ignore_space histlexwords hist_lex_words
+ \ histnofunctions hist_no_functions histnostore hist_no_store
+ \ histreduceblanks hist_reduce_blanks histsavebycopy
+ \ hist_save_by_copy histsavenodups hist_save_no_dups
+ \ histsubstpattern hist_subst_pattern histverify hist_verify
+ \ hup ignorebraces ignore_braces ignoreclosebraces ignore_close_braces
+ \ ignoreeof ignore_eof incappendhistory inc_append_history
+ \ incappendhistorytime inc_append_history_time interactive
+ \ interactivecomments interactive_comments ksharrays ksh_arrays
+ \ kshautoload ksh_autoload kshglob ksh_glob kshoptionprint
+ \ ksh_option_print kshtypeset ksh_typeset kshzerosubscript
+ \ ksh_zero_subscript listambiguous list_ambiguous listbeep
+ \ list_beep listpacked list_packed listrowsfirst list_rows_first
+ \ listtypes list_types localloops local_loops localoptions
+ \ local_options localpatterns local_patterns localtraps
+ \ local_traps log login longlistjobs long_list_jobs magicequalsubst
+ \ magic_equal_subst mailwarn mail_warn mail_warning mark_dirs
+ \ mailwarning markdirs menucomplete menu_complete monitor
+ \ multibyte multi_byte multifuncdef multi_func_def multios
+ \ multi_os nomatch no_match notify nullglob null_glob numericglobsort
+ \ numeric_glob_sort octalzeroes octal_zeroes onecmd one_cmd
+ \ overstrike over_strike pathdirs path_dirs pathscript
+ \ path_script physical pipefail pipe_fail posixaliases
+ \ posix_aliases posixargzero posix_arg_zero posixbuiltins
+ \ posix_builtins posixcd posix_cd posixidentifiers posix_identifiers
+ \ posixjobs posix_jobs posixstrings posix_strings posixtraps
+ \ posix_traps printeightbit print_eight_bit printexitvalue
+ \ print_exit_value privileged promptbang prompt_bang promptcr
+ \ prompt_cr promptpercent prompt_percent promptsp prompt_sp
+ \ promptsubst prompt_subst promptvars prompt_vars pushdignoredups
+ \ pushd_ignore_dups pushdminus pushd_minus pushdsilent pushd_silent
+ \ pushdtohome pushd_to_home rcexpandparam rc_expandparam rcquotes
+ \ rc_quotes rcs recexact rec_exact rematchpcre re_match_pcre
+ \ restricted rmstarsilent rm_star_silent rmstarwait rm_star_wait
+ \ sharehistory share_history shfileexpansion sh_file_expansion
+ \ shglob sh_glob shinstdin shin_stdin shnullcmd sh_nullcmd
+ \ shoptionletters sh_option_letters shortloops short_loops shwordsplit
+ \ sh_word_split singlecommand single_command singlelinezle single_line_zle
+ \ sourcetrace source_trace stdin sunkeyboardhack sun_keyboard_hack
+ \ trackall track_all transientrprompt transient_rprompt
+ \ trapsasync trapasync typesetsilent type_set_silent unset verbose vi
+ \ warncreateglobal warn_create_global xtrace zle
+
+syn keyword zshOptions noaliases no_aliases noallexport no_allexport noall_export no_all_export noalwayslastprompt no_alwayslastprompt
+ \ noalways_lastprompt no_always_lastprompt noalwaystoend no_alwaystoend noalways_to_end no_always_to_end
+ \ noappendhistory no_appendhistory noappend_history no_append_history noautocd no_autocd noautocontinue no_autocontinue
+ \ noauto_continue no_auto_continue noautolist no_autolist noauto_list no_auto_list
+ \ noautomenu no_automenu noauto_menu no_auto_menu noautonamedirs no_autonamedirs noauto_name_dirs no_auto_name_dirs
+ \ noautoparamkeys no_autoparamkeys noauto_param_keys no_auto_param_keys noautoparamslash no_autoparamslash
+ \ noauto_param_slash no_auto_param_slash noautopushd no_autopushd noauto_pushd no_auto_pushd noautoremoveslash no_autoremoveslash
+ \ noauto_remove_slash no_auto_remove_slash noautoresume no_autoresume noauto_resume no_auto_resume nobadpattern no_badpattern
+ \ nobanghist no_banghist nobang_hist no_bang_hist nobareglobqual no_bareglobqual nobare_glob_qual no_bare_glob_qual
+ \ nobashautolist no_bashautolist nobash_auto_list no_bash_auto_list nobashrematch no_bashrematch nobash_rematch no_bash_rematch
+ \ nobeep no_beep nobgnice no_bgnice nobraceccl no_braceccl nobrace_ccl no_brace_ccl nobraceexpand no_braceexpand nobrace_expand no_brace_expand
+ \ nobsdecho no_bsdecho nobsd_echo no_bsd_echo nocaseglob no_caseglob nocase_glob no_case_glob nocasematch no_casematch nocase_match no_case_match
+ \ nocbases no_cbases nocdablevars no_cdablevars nocd_able_vars no_cd_able_vars nochasedots no_chasedots nochase_dots no_chase_dots
+ \ nochaselinks no_chaselinks nochase_links no_chase_links nocheckjobs no_checkjobs nocheck_jobs no_check_jobs
+ \ noclobber no_clobber nocombiningchars no_combiningchars nocombining_chars no_combining_chars nocompletealiases no_completealiases
+ \ nocomplete_aliases no_complete_aliases nocompleteinword no_completeinword nocomplete_in_word no_complete_in_word
+ \ nocontinueonerror no_continueonerror nocontinue_on_error no_continue_on_error nocorrect no_correct
+ \ nocorrectall no_correctall nocorrect_all no_correct_all nocprecedences no_cprecedences noc_precedences no_c_precedences
+ \ nocshjunkiehistory no_cshjunkiehistory nocsh_junkie_history no_csh_junkie_history nocshjunkieloops no_cshjunkieloops
+ \ nocsh_junkie_loops no_csh_junkie_loops nocshjunkiequotes no_cshjunkiequotes nocsh_junkie_quotes no_csh_junkie_quotes
+ \ nocshnullcmd no_cshnullcmd nocsh_null_cmd no_csh_null_cmd nocshnullglob no_cshnullglob nocsh_null_glob no_csh_null_glob
+ \ nodebugbeforecmd no_debugbeforecmd nodebug_before_cmd no_debug_before_cmd nodotglob no_dotglob nodot_glob no_dot_glob nodvorak no_dvorak
+ \ noemacs no_emacs noequals no_equals noerrexit no_errexit noerr_exit no_err_exit noerrreturn no_errreturn noerr_return no_err_return noevallineno no_evallineno
+ \ noeval_lineno no_eval_lineno noexec no_exec noextendedglob no_extendedglob noextended_glob no_extended_glob noextendedhistory no_extendedhistory
+ \ noextended_history no_extended_history noflowcontrol no_flowcontrol noflow_control no_flow_control noforcefloat no_forcefloat
+ \ noforce_float no_force_float nofunctionargzero no_functionargzero nofunction_arg_zero no_function_arg_zero noglob no_glob noglobalexport no_globalexport
+ \ noglobal_export no_global_export noglobalrcs no_globalrcs noglobal_rcs no_global_rcs noglobassign no_globassign noglob_assign no_glob_assign
+ \ noglobcomplete no_globcomplete noglob_complete no_glob_complete noglobdots no_globdots noglob_dots no_glob_dots noglob_subst no_glob_subst
+ \ noglobsubst no_globsubst nohashall no_hashall nohash_all no_hash_all nohashcmds no_hashcmds nohash_cmds no_hash_cmds nohashdirs no_hashdirs
+ \ nohash_dirs no_hash_dirs nohashexecutablesonly no_hashexecutablesonly nohash_executables_only no_hash_executables_only nohashlistall no_hashlistall
+ \ nohash_list_all no_hash_list_all nohistallowclobber no_histallowclobber nohist_allow_clobber no_hist_allow_clobber nohistappend no_histappend
+ \ nohist_append no_hist_append nohistbeep no_histbeep nohist_beep no_hist_beep nohist_expand no_hist_expand nohist_expire_dups_first no_hist_expire_dups_first
+ \ nohistexpand no_histexpand nohistexpiredupsfirst no_histexpiredupsfirst nohistfcntllock no_histfcntllock nohist_fcntl_lock no_hist_fcntl_lock
+ \ nohistfindnodups no_histfindnodups nohist_find_no_dups no_hist_find_no_dups nohistignorealldups no_histignorealldups
+ \ nohist_ignore_all_dups no_hist_ignore_all_dups nohistignoredups no_histignoredups nohist_ignore_dups no_hist_ignore_dups
+ \ nohistignorespace no_histignorespace nohist_ignore_space no_hist_ignore_space nohistlexwords no_histlexwords nohist_lex_words no_hist_lex_words
+ \ nohistnofunctions no_histnofunctions nohist_no_functions no_hist_no_functions nohistnostore no_histnostore nohist_no_store no_hist_no_store
+ \ nohistreduceblanks no_histreduceblanks nohist_reduce_blanks no_hist_reduce_blanks nohistsavebycopy no_histsavebycopy
+ \ nohist_save_by_copy no_hist_save_by_copy nohistsavenodups no_histsavenodups nohist_save_no_dups no_hist_save_no_dups
+ \ nohistsubstpattern no_histsubstpattern nohist_subst_pattern no_hist_subst_pattern nohistverify no_histverify nohist_verify no_hist_verify
+ \ nohup no_hup noignorebraces no_ignorebraces noignore_braces no_ignore_braces noignoreclosebraces no_ignoreclosebraces noignore_close_braces no_ignore_close_braces
+ \ noignoreeof no_ignoreeof noignore_eof no_ignore_eof noincappendhistory no_incappendhistory noinc_append_history no_inc_append_history
+ \ noincappendhistorytime no_incappendhistorytime noinc_append_history_time no_inc_append_history_time nointeractive no_interactive
+ \ nointeractivecomments no_interactivecomments nointeractive_comments no_interactive_comments noksharrays no_ksharrays noksh_arrays no_ksh_arrays
+ \ nokshautoload no_kshautoload noksh_autoload no_ksh_autoload nokshglob no_kshglob noksh_glob no_ksh_glob nokshoptionprint no_kshoptionprint
+ \ noksh_option_print no_ksh_option_print nokshtypeset no_kshtypeset noksh_typeset no_ksh_typeset nokshzerosubscript no_kshzerosubscript
+ \ noksh_zero_subscript no_ksh_zero_subscript nolistambiguous no_listambiguous nolist_ambiguous no_list_ambiguous nolistbeep no_listbeep
+ \ nolist_beep no_list_beep nolistpacked no_listpacked nolist_packed no_list_packed nolistrowsfirst no_listrowsfirst nolist_rows_first no_list_rows_first
+ \ nolisttypes no_listtypes nolist_types no_list_types nolocalloops no_localloops nolocal_loops no_local_loops nolocaloptions no_localoptions
+ \ nolocal_options no_local_options nolocalpatterns no_localpatterns nolocal_patterns no_local_patterns nolocaltraps no_localtraps
+ \ nolocal_traps no_local_traps nolog no_log nologin no_login nolonglistjobs no_longlistjobs nolong_list_jobs no_long_list_jobs nomagicequalsubst no_magicequalsubst
+ \ nomagic_equal_subst no_magic_equal_subst nomailwarn no_mailwarn nomail_warn no_mail_warn nomail_warning no_mail_warning nomark_dirs no_mark_dirs
+ \ nomailwarning no_mailwarning nomarkdirs no_markdirs nomenucomplete no_menucomplete nomenu_complete no_menu_complete nomonitor no_monitor
+ \ nomultibyte no_multibyte nomulti_byte no_multi_byte nomultifuncdef no_multifuncdef nomulti_func_def no_multi_func_def nomultios no_multios
+ \ nomulti_os no_multi_os nonomatch no_nomatch nono_match no_no_match nonotify no_notify nonullglob no_nullglob nonull_glob no_null_glob nonumericglobsort no_numericglobsort
+ \ nonumeric_glob_sort no_numeric_glob_sort nooctalzeroes no_octalzeroes nooctal_zeroes no_octal_zeroes noonecmd no_onecmd noone_cmd no_one_cmd
+ \ nooverstrike no_overstrike noover_strike no_over_strike nopathdirs no_pathdirs nopath_dirs no_path_dirs nopathscript no_pathscript
+ \ nopath_script no_path_script nophysical no_physical nopipefail no_pipefail nopipe_fail no_pipe_fail noposixaliases no_posixaliases
+ \ noposix_aliases no_posix_aliases noposixargzero no_posixargzero noposix_arg_zero no_posix_arg_zero noposixbuiltins no_posixbuiltins
+ \ noposix_builtins no_posix_builtins noposixcd no_posixcd noposix_cd no_posix_cd noposixidentifiers no_posixidentifiers noposix_identifiers no_posix_identifiers
+ \ noposixjobs no_posixjobs noposix_jobs no_posix_jobs noposixstrings no_posixstrings noposix_strings no_posix_strings noposixtraps no_posixtraps
+ \ noposix_traps no_posix_traps noprinteightbit no_printeightbit noprint_eight_bit no_print_eight_bit noprintexitvalue no_printexitvalue
+ \ noprint_exit_value no_print_exit_value noprivileged no_privileged nopromptbang no_promptbang noprompt_bang no_prompt_bang nopromptcr no_promptcr
+ \ noprompt_cr no_prompt_cr nopromptpercent no_promptpercent noprompt_percent no_prompt_percent nopromptsp no_promptsp noprompt_sp no_prompt_sp
+ \ nopromptsubst no_promptsubst noprompt_subst no_prompt_subst nopromptvars no_promptvars noprompt_vars no_prompt_vars nopushdignoredups no_pushdignoredups
+ \ nopushd_ignore_dups no_pushd_ignore_dups nopushdminus no_pushdminus nopushd_minus no_pushd_minus nopushdsilent no_pushdsilent nopushd_silent no_pushd_silent
+ \ nopushdtohome no_pushdtohome nopushd_to_home no_pushd_to_home norcexpandparam no_rcexpandparam norc_expandparam no_rc_expandparam norcquotes no_rcquotes
+ \ norc_quotes no_rc_quotes norcs no_rcs norecexact no_recexact norec_exact no_rec_exact norematchpcre no_rematchpcre nore_match_pcre no_re_match_pcre
+ \ norestricted no_restricted normstarsilent no_rmstarsilent norm_star_silent no_rm_star_silent normstarwait no_rmstarwait norm_star_wait no_rm_star_wait
+ \ nosharehistory no_sharehistory noshare_history no_share_history noshfileexpansion no_shfileexpansion nosh_file_expansion no_sh_file_expansion
+ \ noshglob no_shglob nosh_glob no_sh_glob noshinstdin no_shinstdin noshin_stdin no_shin_stdin noshnullcmd no_shnullcmd nosh_nullcmd no_sh_nullcmd
+ \ noshoptionletters no_shoptionletters nosh_option_letters no_sh_option_letters noshortloops no_shortloops noshort_loops no_short_loops noshwordsplit no_shwordsplit
+ \ nosh_word_split no_sh_word_split nosinglecommand no_singlecommand nosingle_command no_single_command nosinglelinezle no_singlelinezle nosingle_line_zle no_single_line_zle
+ \ nosourcetrace no_sourcetrace nosource_trace no_source_trace nostdin no_stdin nosunkeyboardhack no_sunkeyboardhack nosun_keyboard_hack no_sun_keyboard_hack
+ \ notrackall no_trackall notrack_all no_track_all notransientrprompt no_transientrprompt notransient_rprompt no_transient_rprompt
+ \ notrapsasync no_trapsasync notrapasync no_trapasync notypesetsilent no_typesetsilent notype_set_silent no_type_set_silent nounset no_unset noverbose no_verbose novi no_vi
+ \ nowarncreateglobal no_warncreateglobal nowarn_create_global no_warn_create_global noxtrace no_xtrace nozle no_zle
+syn case match
+
syn keyword zshTypes float integer local typeset declare
" XXX: this may be too much
@@ -149,7 +311,7 @@ syn region zshSubst matchgroup=zshSubstDelim start='\${' skip='\\}'
syn region zshOldSubst matchgroup=zshSubstDelim start=+`+ skip=+\\`+
\ end=+`+ contains=TOP,zshOldSubst
-syn sync minlines=50
+syn sync minlines=50 maxlines=90
syn sync match zshHereDocSync grouphere NONE '<<-\=\s*\%(\\\=\S\+\|\(["']\)\S\+\1\)'
syn sync match zshHereDocEndSync groupthere NONE '^\s*EO\a\+\>'
@@ -170,16 +332,8 @@ hi def link zshKeyword Keyword
hi def link zshFunction None
hi def link zshKSHFunction zshFunction
hi def link zshHereDoc String
-if 0
- hi def link zshOperator Operator
-else
- hi def link zshOperator None
-endif
-if 1
- hi def link zshRedir Operator
-else
- hi def link zshRedir None
-endif
+hi def link zshOperator None
+hi def link zshRedir Operator
hi def link zshVariable None
hi def link zshVariableDef zshVariable
hi def link zshDereferencing PreProc
@@ -199,6 +353,7 @@ else
hi def link zshDeref None
endif
hi def link zshCommands Keyword
+hi def link zshOptions Constant
hi def link zshTypes Type
hi def link zshSwitches Special
hi def link zshNumber Number
diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index a1b58c7c91..4a567727d8 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -205,8 +205,8 @@ list_vim_patches() {
echo " To port one of the above patches to Neovim, execute"
echo " this script with the patch revision as argument."
echo
- echo " Examples: '${BASENAME} 7.4.487'"
- echo " '${BASENAME} 1e8ebf870720e7b671f98f22d653009826304c4f'"
+ echo " Examples: '${BASENAME} -p 7.4.487'"
+ echo " '${BASENAME} -p 1e8ebf870720e7b671f98f22d653009826304c4f'"
}
review_pr() {
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua
index 3d8a75febd..7624dd2303 100644
--- a/src/nvim/auevents.lua
+++ b/src/nvim/auevents.lua
@@ -77,8 +77,9 @@ return {
'TabNew', -- when creating a new tab
'TabNewEntered', -- after entering a new tab
'TermChanged', -- after changing 'term'
- 'TermResponse', -- after setting "v:termresponse"
+ 'TermClose', -- after the processs exits
'TermOpen', -- after opening a terminal buffer
+ 'TermResponse', -- after setting "v:termresponse"
'TextChanged', -- text was modified
'TextChangedI', -- text was modified in Insert mode
'User', -- user defined autocommand
@@ -98,9 +99,10 @@ return {
-- List of neovim-specific events or aliases for the purpose of generating
-- syntax file
neovim_specific = {
+ TabClosed=true,
TabNew=true,
TabNewEntered=true,
- TabClosed=true,
- TermEnter=true,
+ TermClose=true,
+ TermOpen=true,
},
}
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index b3eba4f5f6..6fc08643af 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -2159,9 +2159,23 @@ void buflist_list(exarg_T *eap)
int i;
for (buf = firstbuf; buf != NULL && !got_int; buf = buf->b_next) {
- /* skip unlisted buffers, unless ! was used */
- if (!buf->b_p_bl && !eap->forceit)
+ // skip unspecified buffers
+ if ((!buf->b_p_bl && !eap->forceit && !strchr((char *)eap->arg, 'u'))
+ || (strchr((char *)eap->arg, 'u') && buf->b_p_bl)
+ || (strchr((char *)eap->arg, '+')
+ && ((buf->b_flags & BF_READERR) || !bufIsChanged(buf)))
+ || (strchr((char *)eap->arg, 'a')
+ && (buf->b_ml.ml_mfp == NULL || buf->b_nwindows == 0))
+ || (strchr((char *)eap->arg, 'h')
+ && (buf->b_ml.ml_mfp == NULL || buf->b_nwindows != 0))
+ || (strchr((char *)eap->arg, '-') && buf->b_p_ma)
+ || (strchr((char *)eap->arg, '=') && !buf->b_p_ro)
+ || (strchr((char *)eap->arg, 'x') && !(buf->b_flags & BF_READERR))
+ || (strchr((char *)eap->arg, '%') && buf != curbuf)
+ || (strchr((char *)eap->arg, '#')
+ && (buf == curbuf || curwin->w_alt_fnum != buf->b_fnum))) {
continue;
+ }
msg_putchar('\n');
if (buf_spname(buf) != NULL)
STRLCPY(NameBuff, buf_spname(buf), MAXPATHL);
@@ -2789,58 +2803,59 @@ void free_titles(void)
# endif
+/// Enumeration specifying the valid numeric bases that can
+/// be used when printing numbers in the status line.
+typedef enum {
+ kNumBaseDecimal = 10,
+ kNumBaseOctal = 8,
+ kNumBaseHexadecimal = 16
+} NumberBase;
-/*
- * Build a string from the status line items in "fmt".
- * Return length of string in screen cells.
- *
- * Normally works for window "wp", except when working for 'tabline' then it
- * is "curwin".
- *
- * Items are drawn interspersed with the text that surrounds it
- * Specials: %-<wid>(xxx%) => group, %= => middle marker, %< => truncation
- * Item: %-<minwid>.<maxwid><itemch> All but <itemch> are optional
- *
- * If maxwidth is not zero, the string will be filled at any middle marker
- * or truncated if too long, fillchar is used for all whitespace.
- */
-int
-build_stl_str_hl (
+
+/// Build a string from the status line items in "fmt".
+/// Return length of string in screen cells.
+///
+/// Normally works for window "wp", except when working for 'tabline' then it
+/// is "curwin".
+///
+/// Items are drawn interspersed with the text that surrounds it
+/// Specials: %-<wid>(xxx%) => group, %= => middle marker, %< => truncation
+/// Item: %-<minwid>.<maxwid><itemch> All but <itemch> are optional
+///
+/// If maxwidth is not zero, the string will be filled at any middle marker
+/// or truncated if too long, fillchar is used for all whitespace.
+///
+/// @param wp The window to build a statusline for
+/// @param out The output buffer to write the statusline to
+/// Note: This should not be NameBuff
+/// @param outlen The length of the output buffer
+/// @param fmt The statusline format string
+/// @param use_sandbox Use a sandboxed environment when evaluating fmt
+/// @param fillchar Character to use when filling empty space in the statusline
+/// @param maxwidth The maximum width to make the statusline
+/// @param hltab HL attributes (can be NULL)
+/// @param tabtab tab page nrs (can be NULL)
+///
+/// @return The final width of the statusline
+int build_stl_str_hl(
win_T *wp,
- char_u *out, /* buffer to write into != NameBuff */
- size_t outlen, /* length of out[] */
+ char_u *out,
+ size_t outlen,
char_u *fmt,
- int use_sandbox, /* "fmt" was set insecurely, use sandbox */
+ int use_sandbox,
int fillchar,
int maxwidth,
- struct stl_hlrec *hltab, /* return: HL attributes (can be NULL) */
- struct stl_hlrec *tabtab /* return: tab page nrs (can be NULL) */
+ struct stl_hlrec *hltab,
+ struct stl_hlrec *tabtab
)
{
- char_u *p;
- char_u *s;
- char_u *t;
- int byteval;
- win_T *o_curwin;
- buf_T *o_curbuf;
- int empty_line;
- colnr_T virtcol;
- long l;
- long n;
- int prevchar_isflag;
- int prevchar_isitem;
- int itemisflag;
- int fillable;
- char_u *str;
- long num;
- int width;
- int itemcnt;
- int curitem;
int groupitem[STL_MAX_ITEM];
- int groupdepth;
struct stl_item {
+ // Where the item starts in the status line output buffer
char_u *start;
+ // The minimum width of the item
int minwid;
+ // The maximum width of the item
int maxwid;
enum {
Normal,
@@ -2852,20 +2867,13 @@ build_stl_str_hl (
Trunc
} type;
} item[STL_MAX_ITEM];
- int minwid;
- int maxwid;
- int zeropad;
- char_u base;
- char_u opt;
+
#define TMPLEN 70
char_u tmp[TMPLEN];
char_u *usefmt = fmt;
- struct stl_hlrec *sp;
- /*
- * When the format starts with "%!" then evaluate it as an expression and
- * use the result as the actual format string.
- */
+ // When the format starts with "%!" then evaluate it as an expression and
+ // use the result as the actual format string.
if (fmt[0] == '%' && fmt[1] == '!') {
usefmt = eval_to_string_safe(fmt + 2, NULL, use_sandbox);
if (usefmt == NULL)
@@ -2874,175 +2882,280 @@ build_stl_str_hl (
if (fillchar == 0)
fillchar = ' ';
- /* Can't handle a multi-byte fill character yet. */
+ // Can't handle a multi-byte fill character yet.
else if (mb_char2len(fillchar) > 1)
fillchar = '-';
- /* Get line & check if empty (cursorpos will show "0-1"). Note that
- * p will become invalid when getting another buffer line. */
- p = ml_get_buf(wp->w_buffer, wp->w_cursor.lnum, FALSE);
- empty_line = (*p == NUL);
+ // Get line & check if empty (cursorpos will show "0-1").
+ char_u *line_ptr = ml_get_buf(wp->w_buffer, wp->w_cursor.lnum, false);
+ bool empty_line = (*line_ptr == NUL);
- /* Get the byte value now, in case we need it below. This is more
- * efficient than making a copy of the line. */
- if (wp->w_cursor.col > (colnr_T)STRLEN(p))
+ // Get the byte value now, in case we need it below. This is more
+ // efficient than making a copy of the line.
+ int byteval;
+ if (wp->w_cursor.col > (colnr_T)STRLEN(line_ptr))
byteval = 0;
else
- byteval = (*mb_ptr2char)(p + wp->w_cursor.col);
-
- groupdepth = 0;
- p = out;
- curitem = 0;
- prevchar_isflag = TRUE;
- prevchar_isitem = FALSE;
- for (s = usefmt; *s; ) {
+ byteval = (*mb_ptr2char)(line_ptr + wp->w_cursor.col);
+
+ int groupdepth = 0;
+
+ int curitem = 0;
+ bool prevchar_isflag = true;
+ bool prevchar_isitem = false;
+
+ // out_p is the current position in the output buffer
+ char_u *out_p = out;
+
+ // out_end_p is the last valid character in the output buffer
+ // Note: The null termination character must occur here or earlier,
+ // so any user-visible characters must occur before here.
+ char_u *out_end_p = (out + outlen) - 1;
+
+
+ // Proceed character by character through the statusline format string
+ // fmt_p is the current positon in the input buffer
+ for (char_u *fmt_p = usefmt; *fmt_p; ) {
if (curitem == STL_MAX_ITEM) {
- /* There are too many items. Add the error code to the statusline
- * to give the user a hint about what went wrong. */
- if (p + 6 < out + outlen) {
- memmove(p, " E541", (size_t)5);
- p += 5;
+ // There are too many items. Add the error code to the statusline
+ // to give the user a hint about what went wrong.
+ if (out_p + 5 < out_end_p) {
+ memmove(out_p, " E541", (size_t)5);
+ out_p += 5;
}
break;
}
- if (*s != NUL && *s != '%')
- prevchar_isflag = prevchar_isitem = FALSE;
+ if (*fmt_p != NUL && *fmt_p != '%') {
+ prevchar_isflag = prevchar_isitem = false;
+ }
- /*
- * Handle up to the next '%' or the end.
- */
- while (*s != NUL && *s != '%' && p + 1 < out + outlen)
- *p++ = *s++;
- if (*s == NUL || p + 1 >= out + outlen)
+ // Copy the formatting verbatim until we reach the end of the string
+ // or find a formatting item (denoted by `%`)
+ // or run out of room in our output buffer.
+ while (*fmt_p != NUL && *fmt_p != '%' && out_p < out_end_p)
+ *out_p++ = *fmt_p++;
+
+ // If we have processed the entire format string or run out of
+ // room in our output buffer, exit the loop.
+ if (*fmt_p == NUL || out_p >= out_end_p)
break;
- /*
- * Handle one '%' item.
- */
- s++;
- if (*s == NUL) /* ignore trailing % */
+ // The rest of this loop will handle a single `%` item.
+ // Note: We increment here to skip over the `%` character we are currently
+ // on so we can process the item's contents.
+ fmt_p++;
+
+ // Ignore `%` at the end of the format string
+ if (*fmt_p == NUL) {
break;
- if (*s == '%') {
- if (p + 1 >= out + outlen)
+ }
+
+ // Two `%` in a row is the escape sequence to print a
+ // single `%` in the output buffer.
+ if (*fmt_p == '%') {
+ // Ignore the character if we're out of room in the output buffer.
+ if (out_p >= out_end_p)
break;
- *p++ = *s++;
- prevchar_isflag = prevchar_isitem = FALSE;
+ *out_p++ = *fmt_p++;
+ prevchar_isflag = prevchar_isitem = false;
continue;
}
- if (*s == STL_MIDDLEMARK) {
- s++;
- if (groupdepth > 0)
+
+ // STL_MIDDLEMARK: Separation place between left and right aligned items.
+ if (*fmt_p == STL_MIDDLEMARK) {
+ fmt_p++;
+ // Ignored when we are inside of a grouping
+ if (groupdepth > 0) {
continue;
+ }
item[curitem].type = Middle;
- item[curitem++].start = p;
+ item[curitem++].start = out_p;
continue;
}
- if (*s == STL_TRUNCMARK) {
- s++;
+
+ // STL_TRUNCMARK: Where to begin truncating if the statusline is too long.
+ if (*fmt_p == STL_TRUNCMARK) {
+ fmt_p++;
item[curitem].type = Trunc;
- item[curitem++].start = p;
+ item[curitem++].start = out_p;
continue;
}
- if (*s == ')') {
- s++;
- if (groupdepth < 1)
+
+ // The end of a grouping
+ if (*fmt_p == ')') {
+ fmt_p++;
+ // Ignore if we are not actually inside a group currently
+ if (groupdepth < 1) {
continue;
+ }
groupdepth--;
- t = item[groupitem[groupdepth]].start;
- *p = NUL;
- l = vim_strsize(t);
+ // Determine how long the group is.
+ // Note: We set the current output position to null
+ // so `vim_strsize` will work.
+ char_u *t = item[groupitem[groupdepth]].start;
+ *out_p = NUL;
+ long group_len = vim_strsize(t);
+
+ // If the group contained internal items
+ // and the group did not have a minimum width,
+ // and if there were no normal items in the group,
+ // move the output pointer back to where the group started.
+ // Note: This erases any non-item characters that were in the group.
+ // Otherwise there would be no reason to do this step.
if (curitem > groupitem[groupdepth] + 1
&& item[groupitem[groupdepth]].minwid == 0) {
- /* remove group if all items are empty */
- for (n = groupitem[groupdepth] + 1; n < curitem; n++)
- if (item[n].type == Normal)
+ bool has_normal_items = false;
+ for (long n = groupitem[groupdepth] + 1; n < curitem; n++) {
+ if (item[n].type == Normal) {
+ has_normal_items = true;
break;
- if (n == curitem) {
- p = t;
- l = 0;
+ }
+ }
+
+ if (!has_normal_items) {
+ out_p = t;
+ group_len = 0;
}
}
- if (l > item[groupitem[groupdepth]].maxwid) {
- /* truncate, remove n bytes of text at the start */
+
+ // If the group is longer than it is allowed to be
+ // truncate by removing bytes from the start of the group text.
+ if (group_len > item[groupitem[groupdepth]].maxwid) {
+ // { Determine the number of bytes to remove
+ long n;
if (has_mbyte) {
/* Find the first character that should be included. */
n = 0;
- while (l >= item[groupitem[groupdepth]].maxwid) {
- l -= ptr2cells(t + n);
+ while (group_len >= item[groupitem[groupdepth]].maxwid) {
+ group_len -= ptr2cells(t + n);
n += (*mb_ptr2len)(t + n);
}
- } else
- n = (long)(p - t) - item[groupitem[groupdepth]].maxwid + 1;
+ } else {
+ n = (long)(out_p - t) - item[groupitem[groupdepth]].maxwid + 1;
+ }
+ // }
+ // Prepend the `<` to indicate that the output was truncated.
*t = '<';
- memmove(t + 1, t + n, (size_t)(p - (t + n)));
- p = p - n + 1;
+
+ // { Move the truncated output
+ memmove(t + 1, t + n, (size_t)(out_p - (t + n)));
+ out_p = out_p - n + 1;
/* Fill up space left over by half a double-wide char. */
- while (++l < item[groupitem[groupdepth]].minwid)
- *p++ = fillchar;
+ while (++group_len < item[groupitem[groupdepth]].minwid)
+ *out_p++ = fillchar;
+ // }
/* correct the start of the items for the truncation */
- for (l = groupitem[groupdepth] + 1; l < curitem; l++) {
- item[l].start -= n;
- if (item[l].start < t)
- item[l].start = t;
+ for (int idx = groupitem[groupdepth] + 1; idx < curitem; idx++) {
+ // Shift everything back by the number of removed bytes
+ item[idx].start -= n;
+
+ // If the item was partially or completely truncated, set its
+ // start to the start of the group
+ if (item[idx].start < t) {
+ item[idx].start = t;
+ }
}
- } else if (abs(item[groupitem[groupdepth]].minwid) > l) {
- /* fill */
- n = item[groupitem[groupdepth]].minwid;
- if (n < 0) {
- /* fill by appending characters */
- n = 0 - n;
- while (l++ < n && p + 1 < out + outlen)
- *p++ = fillchar;
+ // If the group is shorter than the minimum width, add padding characters.
+ } else if (abs(item[groupitem[groupdepth]].minwid) > group_len) {
+ long min_group_width = item[groupitem[groupdepth]].minwid;
+ // If the group is left-aligned, add characters to the right.
+ if (min_group_width < 0) {
+ min_group_width = 0 - min_group_width;
+ while (group_len++ < min_group_width && out_p < out_end_p)
+ *out_p++ = fillchar;
+ // If the group is right-aligned, shift everything to the right and
+ // prepend with filler characters.
} else {
- /* fill by inserting characters */
- memmove(t + n - l, t, (size_t)(p - t));
- l = n - l;
- if (p + l >= out + outlen)
- l = (long)((out + outlen) - p - 1);
- p += l;
- for (n = groupitem[groupdepth] + 1; n < curitem; n++)
- item[n].start += l;
- for (; l > 0; l--)
+ // { Move the group to the right
+ memmove(t + min_group_width - group_len, t, (size_t)(out_p - t));
+ group_len = min_group_width - group_len;
+ if (out_p + group_len >= (out_end_p + 1)) {
+ group_len = (long)(out_end_p - out_p);
+ }
+ out_p += group_len;
+ // }
+
+ // Adjust item start positions
+ for (int n = groupitem[groupdepth] + 1; n < curitem; n++) {
+ item[n].start += group_len;
+ }
+
+ // Prepend the fill characters
+ for (; group_len > 0; group_len--) {
*t++ = fillchar;
+ }
}
}
continue;
}
- minwid = 0;
- maxwid = 9999;
- zeropad = FALSE;
- l = 1;
- if (*s == '0') {
- s++;
- zeropad = TRUE;
+ int minwid = 0;
+ int maxwid = 9999;
+ bool left_align = false;
+
+ // Denotes that numbers should be left-padded with zeros
+ bool zeropad = (*fmt_p == '0');
+ if (zeropad) {
+ fmt_p++;
}
- if (*s == '-') {
- s++;
- l = -1;
+
+ // Denotes that the item should be left-aligned.
+ // This is tracked by using a negative length.
+ if (*fmt_p == '-') {
+ fmt_p++;
+ left_align = true;
}
- if (ascii_isdigit(*s)) {
- minwid = getdigits_int(&s);
+
+ // The first digit group is the item's min width
+ if (ascii_isdigit(*fmt_p)) {
+ minwid = getdigits_int(&fmt_p);
if (minwid < 0) /* overflow */
minwid = 0;
}
- if (*s == STL_USER_HL) {
+
+ // User highlight groups override the min width field
+ // to denote the styling to use.
+ if (*fmt_p == STL_USER_HL) {
item[curitem].type = Highlight;
- item[curitem].start = p;
+ item[curitem].start = out_p;
item[curitem].minwid = minwid > 9 ? 1 : minwid;
- s++;
+ fmt_p++;
curitem++;
continue;
}
- if (*s == STL_TABPAGENR || *s == STL_TABCLOSENR) {
- if (*s == STL_TABCLOSENR) {
+
+ // TABPAGE pairs are used to denote a region that when clicked will
+ // either switch to or close a tab.
+ //
+ // Ex: tabline=%0Ttab\ zero%X
+ // This tabline has a TABPAGENR item with minwid `0`,
+ // which is then closed with a TABCLOSENR item.
+ // Clicking on this region with mouse enabled will switch to tab 0.
+ // Setting the minwid to a different value will switch
+ // to that tab, if it exists
+ //
+ // Ex: tabline=%1Xtab\ one%X
+ // This tabline has a TABCLOSENR item with minwid `1`,
+ // which is then closed with a TABCLOSENR item.
+ // Clicking on this region with mouse enabled will close tab 0.
+ // This is determined by the following formula:
+ // tab to close = (1 - minwid)
+ // This is because for TABPAGENR we use `minwid` = `tab number`.
+ // For TABCLOSENR we store the tab number as a negative value.
+ // Because 0 is a valid TABPAGENR value, we have to
+ // start our numbering at `-1`.
+ // So, `-1` corresponds to us wanting to close tab `0`
+ //
+ // Note: These options are only valid when creating a tabline.
+ if (*fmt_p == STL_TABPAGENR || *fmt_p == STL_TABCLOSENR) {
+ if (*fmt_p == STL_TABCLOSENR) {
if (minwid == 0) {
/* %X ends the close label, go back to the previously
* define tab label nr. */
- for (n = curitem - 1; n >= 0; --n)
+ for (long n = curitem - 1; n >= 0; --n)
if (item[n].type == TabPage && item[n].minwid >= 0) {
minwid = item[n].minwid;
break;
@@ -3052,54 +3165,70 @@ build_stl_str_hl (
minwid = -minwid;
}
item[curitem].type = TabPage;
- item[curitem].start = p;
+ item[curitem].start = out_p;
item[curitem].minwid = minwid;
- s++;
+ fmt_p++;
curitem++;
continue;
}
- if (*s == '.') {
- s++;
- if (ascii_isdigit(*s)) {
- maxwid = getdigits_int(&s);
+
+ // Denotes the end of the minwid
+ // the maxwid may follow immediately after
+ if (*fmt_p == '.') {
+ fmt_p++;
+ if (ascii_isdigit(*fmt_p)) {
+ maxwid = getdigits_int(&fmt_p);
if (maxwid <= 0) /* overflow */
maxwid = 50;
}
}
- minwid = (minwid > 50 ? 50 : minwid) * l;
- if (*s == '(') {
+
+ // Bound the minimum width at 50.
+ // Make the number negative to denote left alignment of the item
+ minwid = (minwid > 50 ? 50 : minwid) * (left_align ? -1 : 1);
+
+ // Denotes the start of a new group
+ if (*fmt_p == '(') {
groupitem[groupdepth++] = curitem;
item[curitem].type = Group;
- item[curitem].start = p;
+ item[curitem].start = out_p;
item[curitem].minwid = minwid;
item[curitem].maxwid = maxwid;
- s++;
+ fmt_p++;
curitem++;
continue;
}
- if (vim_strchr(STL_ALL, *s) == NULL) {
- s++;
+
+ // An invalid item was specified.
+ // Continue processing on the next character of the format string.
+ if (vim_strchr(STL_ALL, *fmt_p) == NULL) {
+ fmt_p++;
continue;
}
- opt = *s++;
-
- /* OK - now for the real work */
- base = 'D';
- itemisflag = FALSE;
- fillable = TRUE;
- num = -1;
- str = NULL;
+
+ // The status line item type
+ char_u opt = *fmt_p++;
+
+ // OK - now for the real work
+ NumberBase base = kNumBaseDecimal;
+ bool itemisflag = false;
+ bool fillable = true;
+ long num = -1;
+ char_u *str = NULL;
switch (opt) {
case STL_FILEPATH:
case STL_FULLPATH:
case STL_FILENAME:
- fillable = FALSE; /* don't change ' ' to fillchar */
- if (buf_spname(wp->w_buffer) != NULL)
+ {
+ // Set fillable to false to that ' ' in the filename will not
+ // get replaced with the fillchar
+ fillable = false;
+ if (buf_spname(wp->w_buffer) != NULL) {
STRLCPY(NameBuff, buf_spname(wp->w_buffer), MAXPATHL);
- else {
- t = (opt == STL_FULLPATH) ? wp->w_buffer->b_ffname
- : wp->w_buffer->b_fname;
- home_replace(wp->w_buffer, t, NameBuff, MAXPATHL, TRUE);
+ } else {
+ char_u *t = (opt == STL_FULLPATH) ? wp->w_buffer->b_ffname
+ : wp->w_buffer->b_fname;
+ home_replace(wp->w_buffer, t, NameBuff, MAXPATHL, true);
}
trans_characters(NameBuff, MAXPATHL);
if (opt != STL_FILENAME)
@@ -3107,42 +3236,59 @@ build_stl_str_hl (
else
str = path_tail(NameBuff);
break;
-
+ }
case STL_VIM_EXPR: /* '{' */
- itemisflag = TRUE;
- t = p;
- while (*s != '}' && *s != NUL && p + 1 < out + outlen)
- *p++ = *s++;
- if (*s != '}') /* missing '}' or out of space */
+ {
+ itemisflag = true;
+
+ // Attempt to copy the expression to evaluate into
+ // the output buffer as a null-terminated string.
+ char_u *t = out_p;
+ while (*fmt_p != '}' && *fmt_p != NUL && out_p < out_end_p)
+ *out_p++ = *fmt_p++;
+ if (*fmt_p != '}') /* missing '}' or out of space */
break;
- s++;
- *p = 0;
- p = t;
+ fmt_p++;
+ *out_p = 0;
+
+ // Move our position in the output buffer
+ // to the beginning of the expression
+ out_p = t;
+
+ // { Evaluate the expression
+ // Store the current buffer number as a string variable
vim_snprintf((char *)tmp, sizeof(tmp), "%d", curbuf->b_fnum);
set_internal_string_var((char_u *)"actual_curbuf", tmp);
- o_curbuf = curbuf;
- o_curwin = curwin;
+ buf_T *o_curbuf = curbuf;
+ win_T *o_curwin = curwin;
curwin = wp;
curbuf = wp->w_buffer;
- str = eval_to_string_safe(p, &t, use_sandbox);
+ // Note: The result stored in `t` is unused.
+ str = eval_to_string_safe(out_p, &t, use_sandbox);
curwin = o_curwin;
curbuf = o_curbuf;
- do_unlet((char_u *)"g:actual_curbuf", TRUE);
+ // Remove the variable we just stored
+ do_unlet((char_u *)"g:actual_curbuf", true);
+
+ // }
+
+ // Check if the evaluated result is a number.
+ // If so, convert the number to an int and free the string.
if (str != NULL && *str != 0) {
if (*skipdigits(str) == NUL) {
num = atoi((char *)str);
xfree(str);
str = NULL;
- itemisflag = FALSE;
+ itemisflag = false;
}
}
break;
-
+ }
case STL_LINE:
num = (wp->w_buffer->b_ml.ml_flags & ML_EMPTY)
? 0L : (long)(wp->w_cursor.lnum);
@@ -3159,21 +3305,23 @@ build_stl_str_hl (
case STL_VIRTCOL:
case STL_VIRTCOL_ALT:
- /* In list mode virtcol needs to be recomputed */
- virtcol = wp->w_virtcol;
+ {
+ // In list mode virtcol needs to be recomputed
+ colnr_T virtcol = wp->w_virtcol;
if (wp->w_p_list && lcs_tab1 == NUL) {
wp->w_p_list = FALSE;
getvcol(wp, &wp->w_cursor, NULL, &virtcol, NULL);
wp->w_p_list = TRUE;
}
++virtcol;
- /* Don't display %V if it's the same as %c. */
+ // Don't display %V if it's the same as %c.
if (opt == STL_VIRTCOL_ALT
&& (virtcol == (colnr_T)(!(State & INSERT) && empty_line
? 0 : (int)wp->w_cursor.col + 1)))
break;
num = (long)virtcol;
break;
+ }
case STL_PERCENTAGE:
num = (int)(((long)wp->w_cursor.lnum * 100L) /
@@ -3181,19 +3329,31 @@ build_stl_str_hl (
break;
case STL_ALTPERCENT:
+ // Store the position percentage in our temporary buffer.
+ // Note: We cannot store the value in `num` because
+ // `get_rel_pos` can return a named position. Ex: "Top"
+ get_rel_pos(wp, tmp, TMPLEN);
str = tmp;
- get_rel_pos(wp, str, TMPLEN);
break;
case STL_ARGLISTSTAT:
- fillable = FALSE;
+ fillable = false;
+
+ // Note: This is important because `append_arg_number` starts appending
+ // at the end of the null-terminated string.
+ // Setting the first byte to null means it will place the argument
+ // number string at the beginning of the buffer.
tmp[0] = 0;
- if (append_arg_number(wp, tmp, (int)sizeof(tmp), FALSE))
+
+ // Note: The call will only return true if it actually
+ // appended data to the `tmp` buffer.
+ if (append_arg_number(wp, tmp, (int)sizeof(tmp), false)) {
str = tmp;
+ }
break;
case STL_KEYMAP:
- fillable = FALSE;
+ fillable = false;
if (get_keymap_str(wp, tmp, TMPLEN))
str = tmp;
break;
@@ -3206,16 +3366,17 @@ build_stl_str_hl (
break;
case STL_OFFSET_X:
- base = 'X';
+ base = kNumBaseHexadecimal;
case STL_OFFSET:
- l = ml_find_line_or_offset(wp->w_buffer, wp->w_cursor.lnum, NULL);
+ {
+ long l = ml_find_line_or_offset(wp->w_buffer, wp->w_cursor.lnum, NULL);
num = (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) || l < 0 ?
0L : l + 1 + (!(State & INSERT) && empty_line ?
0 : (int)wp->w_cursor.col);
break;
-
+ }
case STL_BYTEVAL_X:
- base = 'X';
+ base = kNumBaseHexadecimal;
case STL_BYTEVAL:
num = byteval;
if (num == NL)
@@ -3226,20 +3387,23 @@ build_stl_str_hl (
case STL_ROFLAG:
case STL_ROFLAG_ALT:
- itemisflag = TRUE;
+ itemisflag = true;
if (wp->w_buffer->b_p_ro)
str = (char_u *)((opt == STL_ROFLAG_ALT) ? ",RO" : _("[RO]"));
break;
case STL_HELPFLAG:
case STL_HELPFLAG_ALT:
- itemisflag = TRUE;
+ itemisflag = true;
if (wp->w_buffer->b_help)
str = (char_u *)((opt == STL_HELPFLAG_ALT) ? ",HLP"
: _("[Help]"));
break;
case STL_FILETYPE:
+ // Copy the filetype if it is not null and the formatted string will fit
+ // in the temporary buffer
+ // (including the brackets and null terminating character)
if (*wp->w_buffer->b_p_ft != NUL
&& STRLEN(wp->w_buffer->b_p_ft) < TMPLEN - 3) {
vim_snprintf((char *)tmp, sizeof(tmp), "[%s]",
@@ -3249,20 +3413,26 @@ build_stl_str_hl (
break;
case STL_FILETYPE_ALT:
- itemisflag = TRUE;
+ {
+ itemisflag = true;
+ // Copy the filetype if it is not null and the formatted string will fit
+ // in the temporary buffer
+ // (including the comma and null terminating character)
if (*wp->w_buffer->b_p_ft != NUL
&& STRLEN(wp->w_buffer->b_p_ft) < TMPLEN - 2) {
vim_snprintf((char *)tmp, sizeof(tmp), ",%s",
wp->w_buffer->b_p_ft);
- for (t = tmp; *t != 0; t++)
+ // Uppercase the file extension
+ for (char_u *t = tmp; *t != 0; t++) {
*t = TOUPPER_LOC(*t);
+ }
str = tmp;
}
break;
-
+ }
case STL_PREVIEWFLAG:
case STL_PREVIEWFLAG_ALT:
- itemisflag = TRUE;
+ itemisflag = true;
if (wp->w_p_pvw)
str = (char_u *)((opt == STL_PREVIEWFLAG_ALT) ? ",PRV"
: _("[Preview]"));
@@ -3277,7 +3447,7 @@ build_stl_str_hl (
case STL_MODIFIED:
case STL_MODIFIED_ALT:
- itemisflag = TRUE;
+ itemisflag = true;
switch ((opt == STL_MODIFIED_ALT)
+ bufIsChanged(wp->w_buffer) * 2
+ (!MODIFIABLE(wp->w_buffer)) * 4) {
@@ -3291,212 +3461,360 @@ build_stl_str_hl (
break;
case STL_HIGHLIGHT:
- t = s;
- while (*s != '#' && *s != NUL)
- ++s;
- if (*s == '#') {
+ {
+ // { The name of the highlight is surrounded by `#`
+ char_u *t = fmt_p;
+ while (*fmt_p != '#' && *fmt_p != NUL) {
+ ++fmt_p;
+ }
+ // }
+
+ // Create a highlight item based on the name
+ if (*fmt_p == '#') {
item[curitem].type = Highlight;
- item[curitem].start = p;
- item[curitem].minwid = -syn_namen2id(t, (int)(s - t));
+ item[curitem].start = out_p;
+ item[curitem].minwid = -syn_namen2id(t, (int)(fmt_p - t));
curitem++;
+ fmt_p++;
}
- if (*s != NUL)
- ++s;
continue;
}
+ }
- item[curitem].start = p;
+ // If we made it this far, the item is normal and starts at
+ // our current position in the output buffer.
+ // Non-normal items would have `continued`.
+ item[curitem].start = out_p;
item[curitem].type = Normal;
+
+ // Copy the item string into the output buffer
if (str != NULL && *str) {
- t = str;
+ // { Skip the leading `,` or ` ` if the item is a flag
+ // and the proper conditions are met
+ char_u *t = str;
if (itemisflag) {
if ((t[0] && t[1])
&& ((!prevchar_isitem && *t == ',')
|| (prevchar_isflag && *t == ' ')))
t++;
- prevchar_isflag = TRUE;
+ prevchar_isflag = true;
+ }
+ // }
+
+ long l = vim_strsize(t);
+
+ // If this item is non-empty, record that the last thing
+ // we put in the output buffer was an item
+ if (l > 0) {
+ prevchar_isitem = true;
}
- l = vim_strsize(t);
- if (l > 0)
- prevchar_isitem = TRUE;
+
+ // If the item is too wide, truncate it from the beginning
if (l > maxwid) {
while (l >= maxwid)
if (has_mbyte) {
l -= ptr2cells(t);
t += (*mb_ptr2len)(t);
- } else
+ } else {
l -= byte2cells(*t++);
- if (p + 1 >= out + outlen)
+ }
+
+ // Early out if there isn't enough room for the truncation marker
+ if (out_p >= out_end_p)
break;
- *p++ = '<';
+
+ // Add the truncation marker
+ *out_p++ = '<';
}
+
+ // If the item is right aligned and not wide enough,
+ // pad with fill characters.
if (minwid > 0) {
- for (; l < minwid && p + 1 < out + outlen; l++) {
- /* Don't put a "-" in front of a digit. */
+ for (; l < minwid && out_p < out_end_p; l++) {
+ // Don't put a "-" in front of a digit.
if (l + 1 == minwid && fillchar == '-' && ascii_isdigit(*t))
- *p++ = ' ';
+ *out_p++ = ' ';
else
- *p++ = fillchar;
+ *out_p++ = fillchar;
}
minwid = 0;
- } else
+ } else {
+ // Note: The negative value denotes a left aligned item.
+ // Here we switch the minimum width back to a positive value.
minwid *= -1;
- while (*t && p + 1 < out + outlen) {
- *p++ = *t++;
- /* Change a space by fillchar, unless fillchar is '-' and a
- * digit follows. */
- if (fillable && p[-1] == ' '
+ }
+
+ // { Copy the string text into the output buffer
+ while (*t && out_p < out_end_p) {
+ *out_p++ = *t++;
+ // Change a space by fillchar, unless fillchar is '-' and a
+ // digit follows.
+ if (fillable && out_p[-1] == ' '
&& (!ascii_isdigit(*t) || fillchar != '-'))
- p[-1] = fillchar;
+ out_p[-1] = fillchar;
+ }
+ // }
+
+ // For left-aligned items, fill any remaining space with the fillchar
+ for (; l < minwid && out_p < out_end_p; l++) {
+ *out_p++ = fillchar;
}
- for (; l < minwid && p + 1 < out + outlen; l++)
- *p++ = fillchar;
- } else if (num >= 0) {
- int nbase = (base == 'D' ? 10 : (base == 'O' ? 8 : 16));
- char_u nstr[20];
- if (p + 20 >= out + outlen)
+ // Otherwise if the item is a number, copy that to the output buffer.
+ } else if (num >= 0) {
+ if (out_p + 20 > out_end_p)
break; /* not sufficient space */
- prevchar_isitem = TRUE;
- t = nstr;
+ prevchar_isitem = true;
+
+ // { Build the formatting string
+ char_u nstr[20];
+ char_u *t = nstr;
if (opt == STL_VIRTCOL_ALT) {
*t++ = '-';
minwid--;
}
*t++ = '%';
- if (zeropad)
+ if (zeropad) {
*t++ = '0';
+ }
+
+ // Note: The `*` means we take the width as one of the arguments
*t++ = '*';
- *t++ = nbase == 16 ? base : (char_u)(nbase == 8 ? 'o' : 'd');
+ *t++ = (char_u) (base == kNumBaseHexadecimal ? 'X'
+ : (base == kNumBaseOctal ? 'o'
+ : 'd'));
*t = 0;
+ // }
+
+ // { Determine how many characters the number will take up when printed
+ // Note: We have to cast the base because the compiler uses
+ // unsigned ints for the enum values.
+ long num_chars = 1;
+ for (long n = num; n >= (int) base; n /= (int) base) {
+ num_chars++;
+ }
- for (n = num, l = 1; n >= nbase; n /= nbase)
- l++;
- if (opt == STL_VIRTCOL_ALT)
- l++;
- if (l > maxwid) {
- l += 2;
- n = l - maxwid;
- while (l-- > maxwid)
- num /= nbase;
+ // VIRTCOL_ALT takes up an extra character because
+ // of the `-` we added above.
+ if (opt == STL_VIRTCOL_ALT) {
+ num_chars++;
+ }
+ // }
+
+ size_t remaining_buf_len = (out_end_p - out_p) + 1;
+
+ // If the number is going to take up too much room
+ // Figure out the approximate number in "scientific" type notation.
+ // Ex: 14532 with maxwid of 4 -> '14>3'
+ if (num_chars > maxwid) {
+ // Add two to the width because the power piece will take
+ // two extra characters
+ num_chars += 2;
+
+ // How many extra characters there are
+ long n = num_chars - maxwid;
+
+ // { Reduce the number by base^n
+ while (num_chars-- > maxwid) {
+ num /= base;
+ }
+ // }
+
+ // { Add the format string for the exponent bit
*t++ = '>';
*t++ = '%';
+ // Use the same base as the first number
*t = t[-3];
*++t = 0;
- vim_snprintf((char *)p, outlen - (p - out), (char *)nstr,
+ // }
+
+ vim_snprintf((char *)out_p, remaining_buf_len, (char *)nstr,
0, num, n);
- } else
- vim_snprintf((char *)p, outlen - (p - out), (char *)nstr,
+ } else {
+ vim_snprintf((char *)out_p, remaining_buf_len, (char *)nstr,
minwid, num);
- p += STRLEN(p);
- } else
+ }
+
+ // Advance the output buffer position to the end of the
+ // number we just printed
+ out_p += STRLEN(out_p);
+
+ // Otherwise, there was nothing to print so mark the item as empty
+ } else {
item[curitem].type = Empty;
+ }
- if (opt == STL_VIM_EXPR)
+ // Only free the string buffer if we allocated it.
+ // Note: This is not needed if `str` is pointing at `tmp`
+ if (opt == STL_VIM_EXPR) {
xfree(str);
+ }
if (num >= 0 || (!itemisflag && str && *str))
- prevchar_isflag = FALSE; /* Item not NULL, but not a flag */
+ prevchar_isflag = false; /* Item not NULL, but not a flag */
+
+ // Item processed, move to the next
curitem++;
}
- *p = NUL;
- itemcnt = curitem;
- if (usefmt != fmt)
+ *out_p = NUL;
+ int itemcnt = curitem;
+
+ // Free the format buffer if we allocated it internally
+ if (usefmt != fmt) {
xfree(usefmt);
+ }
+
+ // We have now processed the entire statusline format string.
+ // What follows is post-processing to handle alignment and
+ // highlighting factors.
- width = vim_strsize(out);
+ int width = vim_strsize(out);
if (maxwidth > 0 && width > maxwidth) {
- /* Result is too long, must truncate somewhere. */
- l = 0;
- if (itemcnt == 0)
- s = out;
- else {
- for (; l < itemcnt; l++)
- if (item[l].type == Trunc) {
- /* Truncate at %< item. */
- s = item[l].start;
+ // Result is too long, must truncate somewhere.
+ int item_idx = 0;
+ char_u *trunc_p;
+
+ // If there are no items, truncate from beginning
+ if (itemcnt == 0) {
+ trunc_p = out;
+
+ // Otherwise, look for the truncation item
+ } else {
+ // Default to truncating at the first item
+ trunc_p = item[0].start;
+ item_idx = 0;
+
+ for (int i = 0; i < itemcnt; i++)
+ if (item[i].type == Trunc) {
+ // Truncate at %< item.
+ trunc_p = item[i].start;
+ item_idx = i;
break;
}
- if (l == itemcnt) {
- /* No %< item, truncate first item. */
- s = item[0].start;
- l = 0;
- }
}
- if (width - vim_strsize(s) >= maxwidth) {
- /* Truncation mark is beyond max length */
+ // If the truncation point we found is beyond the maximum
+ // length of the string, truncate the end of the string.
+ if (width - vim_strsize(trunc_p) >= maxwidth) {
+ // If we are using a multi-byte encoding, walk from the beginning of the
+ // string to find the last character that will fit.
if (has_mbyte) {
- s = out;
+ trunc_p = out;
width = 0;
for (;; ) {
- width += ptr2cells(s);
+ width += ptr2cells(trunc_p);
if (width >= maxwidth)
break;
- s += (*mb_ptr2len)(s);
+
+ // Note: Only advance the pointer if the next
+ // character will fit in the available output space
+ trunc_p += (*mb_ptr2len)(trunc_p);
}
- /* Fill up for half a double-wide character. */
- while (++width < maxwidth)
- *s++ = fillchar;
- } else
- s = out + maxwidth - 1;
- for (l = 0; l < itemcnt; l++)
- if (item[l].start > s)
+
+ // Otherwise put the truncation point at the end, leaving enough room
+ // for a single-character truncation marker
+ } else {
+ trunc_p = out + maxwidth - 1;
+ }
+
+ // Ignore any items in the statusline that occur after
+ // the truncation point
+ for (int i = 0; i < itemcnt; i++) {
+ if (item[i].start > trunc_p) {
+ itemcnt = i;
break;
- itemcnt = l;
- *s++ = '>';
- *s = 0;
+ }
+ }
+
+ // Truncate the output
+ *trunc_p++ = '>';
+ *trunc_p = 0;
+
+ // Truncate at the truncation point we found
} else {
+ // { Determine how many bytes to remove
+ long trunc_len;
if (has_mbyte) {
- n = 0;
+ trunc_len = 0;
while (width >= maxwidth) {
- width -= ptr2cells(s + n);
- n += (*mb_ptr2len)(s + n);
+ width -= ptr2cells(trunc_p + trunc_len);
+ trunc_len += (*mb_ptr2len)(trunc_p + trunc_len);
}
- } else
- n = width - maxwidth + 1;
- p = s + n;
- STRMOVE(s + 1, p);
- *s = '<';
+ } else {
+ // Truncate an extra character so we can insert our `<`.
+ trunc_len = (width - maxwidth) + 1;
+ }
+ // }
- /* Fill up for half a double-wide character. */
+ // { Truncate the string
+ char_u *trunc_end_p = trunc_p + trunc_len;
+ STRMOVE(trunc_p + 1, trunc_end_p);
+
+ // Put a `<` to mark where we truncated at
+ *trunc_p = '<';
+
+ // Advance the pointer to the end of the string
+ trunc_p = trunc_p + STRLEN(trunc_p);
+
+ // Fill up for half a double-wide character.
while (++width < maxwidth) {
- s = s + STRLEN(s);
- *s++ = fillchar;
- *s = NUL;
+ *trunc_p++ = fillchar;
+ *trunc_p = NUL;
}
-
- --n; /* count the '<' */
- for (; l < itemcnt; l++) {
- if (item[l].start - n >= s)
- item[l].start -= n;
- else
- item[l].start = s;
+ // }
+
+ // { Change the start point for items based on
+ // their position relative to our truncation point
+
+ // Note: The offset is one less than the truncation length because
+ // the truncation marker `<` is not counted.
+ long item_offset = trunc_len - 1;
+
+ for (int i = item_idx; i < itemcnt; i++) {
+ // Items starting at or after the end of the truncated section need
+ // to be moved backwards.
+ if (item[i].start >= trunc_end_p) {
+ item[i].start -= item_offset;
+ // Anything inside the truncated area is set to start
+ // at the `<` truncation character.
+ } else {
+ item[i].start = trunc_p;
+ }
}
+ // }
}
width = maxwidth;
- } else if (width < maxwidth && STRLEN(out) + maxwidth - width + 1 <
- outlen) {
- /* Apply STL_MIDDLE if any */
- for (l = 0; l < itemcnt; l++)
- if (item[l].type == Middle)
+
+ // If there is room left in our statusline, and room left in our buffer,
+ // add characters at the middle marker (if there is one) to
+ // fill up the available space.
+ } else if (width < maxwidth
+ && STRLEN(out) + maxwidth - width + 1 < outlen) {
+ for (int item_idx = 0; item_idx < itemcnt; item_idx++) {
+ if (item[item_idx].type == Middle) {
+ // Move the statusline to make room for the middle characters
+ char_u *middle_end = item[item_idx].start + (maxwidth - width);
+ STRMOVE(middle_end, item[item_idx].start);
+
+ // Fill the middle section with our fill character
+ for (char_u *s = item[item_idx].start; s < middle_end; s++)
+ *s = fillchar;
+
+ // Adjust the offset of any items after the middle
+ for (item_idx++; item_idx < itemcnt; item_idx++)
+ item[item_idx].start += maxwidth - width;
+
+ width = maxwidth;
break;
- if (l < itemcnt) {
- p = item[l].start + maxwidth - width;
- STRMOVE(p, item[l].start);
- for (s = item[l].start; s < p; s++)
- *s = fillchar;
- for (l++; l < itemcnt; l++)
- item[l].start += maxwidth - width;
- width = maxwidth;
+ }
}
}
- /* Store the info about highlighting. */
+ // Store the info about highlighting.
if (hltab != NULL) {
- sp = hltab;
- for (l = 0; l < itemcnt; l++) {
+ struct stl_hlrec *sp = hltab;
+ for (long l = 0; l < itemcnt; l++) {
if (item[l].type == Highlight) {
sp->start = item[l].start;
sp->userhl = item[l].minwid;
@@ -3507,10 +3825,10 @@ build_stl_str_hl (
sp->userhl = 0;
}
- /* Store the info about tab pages labels. */
+ // Store the info about tab pages labels.
if (tabtab != NULL) {
- sp = tabtab;
- for (l = 0; l < itemcnt; l++) {
+ struct stl_hlrec *sp = tabtab;
+ for (long l = 0; l < itemcnt; l++) {
if (item[l].type == TabPage) {
sp->start = item[l].start;
sp->userhl = item[l].minwid;
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index abd16e57ae..208e41946b 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -977,6 +977,14 @@ static int insert_handle_key(InsertState *s)
queue_process_events(loop.events);
break;
+ case K_FOCUSGAINED: // Neovim has been given focus
+ apply_autocmds(EVENT_FOCUSGAINED, NULL, NULL, false, curbuf);
+ break;
+
+ case K_FOCUSLOST: // Neovim has lost focus
+ apply_autocmds(EVENT_FOCUSLOST, NULL, NULL, false, curbuf);
+ break;
+
case K_HOME: // <Home>
case K_KHOME:
case K_S_HOME:
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 7685e422fc..9581b81456 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -98,6 +98,7 @@
#include "nvim/os/input.h"
#include "nvim/event/loop.h"
#include "nvim/lib/kvec.h"
+#include "nvim/lib/queue.h"
#define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */
@@ -228,50 +229,11 @@ static int echo_attr = 0; /* attributes used for ":echo" */
#define GLV_QUIET TFN_QUIET /* no error messages */
#define GLV_NO_AUTOLOAD TFN_NO_AUTOLOAD /* do not use script autoloading */
-/*
- * Structure to hold info for a user function.
- */
-typedef struct ufunc ufunc_T;
-
-struct ufunc {
- int uf_varargs; /* variable nr of arguments */
- int uf_flags;
- int uf_calls; /* nr of active calls */
- garray_T uf_args; /* arguments */
- garray_T uf_lines; /* function lines */
- int uf_profiling; /* TRUE when func is being profiled */
- /* profiling the function as a whole */
- int uf_tm_count; /* nr of calls */
- proftime_T uf_tm_total; /* time spent in function + children */
- proftime_T uf_tm_self; /* time spent in function itself */
- proftime_T uf_tm_children; /* time spent in children this call */
- /* profiling the function per line */
- int *uf_tml_count; /* nr of times line was executed */
- proftime_T *uf_tml_total; /* time spent in a line + children */
- proftime_T *uf_tml_self; /* time spent in a line itself */
- proftime_T uf_tml_start; /* start time for current line */
- proftime_T uf_tml_children; /* time spent in children for this line */
- proftime_T uf_tml_wait; /* start wait time for current line */
- int uf_tml_idx; /* index of line being timed; -1 if none */
- int uf_tml_execed; /* line being timed was executed */
- scid_T uf_script_ID; /* ID of script where function was defined,
- used for s: variables */
- int uf_refcount; /* for numbered function: reference count */
- char_u uf_name[1]; /* name of function (actually longer); can
- start with <SNR>123_ (<SNR> is K_SPECIAL
- KS_EXTRA KE_SNR) */
-};
-
/* function flags */
#define FC_ABORT 1 /* abort function on error */
#define FC_RANGE 2 /* function accepts range */
#define FC_DICT 4 /* Dict function, uses "self" */
-/*
- * All user-defined functions are found in this hashtable.
- */
-static hashtab_T func_hashtab;
-
/* The names of packages that once were loaded are remembered. */
static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL};
@@ -279,12 +241,6 @@ static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL};
static dict_T *first_dict = NULL; /* list of all dicts */
static list_T *first_list = NULL; /* list of all lists */
-/* From user function to hashitem and back. */
-static ufunc_T dumuf;
-#define UF2HIKEY(fp) ((fp)->uf_name)
-#define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf)))
-#define HI2UF(hi) HIKEY2UF((hi)->hi_key)
-
#define FUNCARG(fp, j) ((char_u **)(fp->uf_args.ga_data))[j]
#define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j]
@@ -459,6 +415,13 @@ typedef struct {
Queue *events;
} TerminalJobData;
+typedef struct dict_watcher {
+ ufunc_T *callback;
+ char *key_pattern;
+ QUEUE node;
+ bool busy; // prevent recursion if the dict is changed in the callback
+} DictWatcher;
+
/// Structure representing current VimL to messagepack conversion state
typedef struct {
enum {
@@ -2376,6 +2339,14 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, ch
: lp->ll_n1 != lp->ll_n2)
EMSG(_("E711: List value has not enough items"));
} else {
+ typval_T oldtv;
+ dict_T *dict = lp->ll_dict;
+ bool watched = is_watched(dict);
+
+ if (watched) {
+ init_tv(&oldtv);
+ }
+
/*
* Assign to a List or Dictionary item.
*/
@@ -2392,22 +2363,38 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, ch
return;
}
lp->ll_tv = &di->di_tv;
- } else if (op != NULL && *op != '=') {
- tv_op(lp->ll_tv, rettv, op);
- return;
- } else
- clear_tv(lp->ll_tv);
+ } else {
+ if (watched) {
+ copy_tv(lp->ll_tv, &oldtv);
+ }
- /*
- * Assign the value to the variable or list item.
- */
- if (copy)
+ if (op != NULL && *op != '=') {
+ tv_op(lp->ll_tv, rettv, op);
+ goto notify;
+ } else {
+ clear_tv(lp->ll_tv);
+ }
+ }
+
+ // Assign the value to the variable or list item.
+ if (copy) {
copy_tv(rettv, lp->ll_tv);
- else {
+ } else {
*lp->ll_tv = *rettv;
lp->ll_tv->v_lock = 0;
init_tv(rettv);
}
+
+notify:
+ if (watched) {
+ if (oldtv.v_type == VAR_UNKNOWN) {
+ dictwatcher_notify(dict, (char *)lp->ll_newkey, lp->ll_tv, NULL);
+ } else {
+ dictitem_T *di = lp->ll_di;
+ dictwatcher_notify(dict, (char *)di->di_key, lp->ll_tv, &oldtv);
+ clear_tv(&oldtv);
+ }
+ }
}
}
@@ -2932,12 +2919,31 @@ static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit)
++lp->ll_n1;
}
} else {
- if (lp->ll_list != NULL)
- /* unlet a List item. */
+ if (lp->ll_list != NULL) {
+ // unlet a List item.
listitem_remove(lp->ll_list, lp->ll_li);
- else
- /* unlet a Dictionary item. */
- dictitem_remove(lp->ll_dict, lp->ll_di);
+ } else {
+ // unlet a Dictionary item.
+ dict_T *d = lp->ll_dict;
+ dictitem_T *di = lp->ll_di;
+ bool watched = is_watched(d);
+ char *key = NULL;
+ typval_T oldtv;
+
+ if (watched) {
+ copy_tv(&di->di_tv, &oldtv);
+ // need to save key because dictitem_remove will free it
+ key = xstrdup((char *)di->di_key);
+ }
+
+ dictitem_remove(d, di);
+
+ if (watched) {
+ dictwatcher_notify(d, key, NULL, &oldtv);
+ clear_tv(&oldtv);
+ xfree(key);
+ }
+ }
}
return ret;
@@ -2953,8 +2959,9 @@ int do_unlet(char_u *name, int forceit)
hashitem_T *hi;
char_u *varname;
dictitem_T *di;
+ dict_T *dict;
+ ht = find_var_ht_dict(name, &varname, &dict);
- ht = find_var_ht(name, &varname);
if (ht != NULL && *varname != NUL) {
hi = hash_find(ht, varname);
if (!HASHITEM_EMPTY(hi)) {
@@ -2962,7 +2969,19 @@ int do_unlet(char_u *name, int forceit)
if (var_check_fixed(di->di_flags, name)
|| var_check_ro(di->di_flags, name))
return FAIL;
+ typval_T oldtv;
+ bool watched = is_watched(dict);
+
+ if (watched) {
+ copy_tv(&di->di_tv, &oldtv);
+ }
+
delete_var(ht, hi);
+
+ if (watched) {
+ dictwatcher_notify(dict, (char *)varname, NULL, &oldtv);
+ clear_tv(&oldtv);
+ }
return OK;
}
}
@@ -5959,6 +5978,7 @@ dict_T *dict_alloc(void) FUNC_ATTR_NONNULL_RET
d->dv_refcount = 0;
d->dv_copyID = 0;
d->internal_refcount = 0;
+ QUEUE_INIT(&d->watchers);
return d;
}
@@ -6025,6 +6045,14 @@ dict_free (
--todo;
}
}
+
+ while (!QUEUE_EMPTY(&d->watchers)) {
+ QUEUE *w = QUEUE_HEAD(&d->watchers);
+ DictWatcher *watcher = dictwatcher_node_data(w);
+ dictwatcher_free(watcher);
+ QUEUE_REMOVE(w);
+ }
+
hash_clear(&d->dv_hashtab);
xfree(d);
}
@@ -6066,10 +6094,11 @@ static void dictitem_remove(dict_T *dict, dictitem_T *item)
hashitem_T *hi;
hi = hash_find(&dict->dv_hashtab, item->di_key);
- if (HASHITEM_EMPTY(hi))
+ if (HASHITEM_EMPTY(hi)) {
EMSG2(_(e_intern2), "dictitem_remove()");
- else
+ } else {
hash_remove(&dict->dv_hashtab, hi);
+ }
dictitem_free(item);
}
@@ -6264,7 +6293,16 @@ static bool get_dict_callback(dict_T *d, char *key, ufunc_T **result)
return false;
}
- uint8_t *name = di->di_tv.vval.v_string;
+ if ((*result = find_ufunc(di->di_tv.vval.v_string)) == NULL) {
+ return false;
+ }
+
+ (*result)->uf_refcount++;
+ return true;
+}
+
+static ufunc_T *find_ufunc(uint8_t *name)
+{
uint8_t *n = name;
ufunc_T *rv = NULL;
if (*n > '9' || *n < '0') {
@@ -6279,13 +6317,10 @@ static bool get_dict_callback(dict_T *d, char *key, ufunc_T **result)
if (!rv) {
EMSG2(_("Function %s doesn't exist"), name);
- *result = NULL;
- return false;
+ return NULL;
}
- rv->uf_refcount++;
- *result = rv;
- return true;
+ return rv;
}
/*
@@ -7098,6 +7133,8 @@ static struct fst {
{"cursor", 1, 3, f_cursor},
{"deepcopy", 1, 2, f_deepcopy},
{"delete", 1, 1, f_delete},
+ {"dictwatcheradd", 3, 3, f_dictwatcheradd},
+ {"dictwatcherdel", 3, 3, f_dictwatcherdel},
{"did_filetype", 0, 0, f_did_filetype},
{"diff_filler", 1, 1, f_diff_filler},
{"diff_hlID", 2, 2, f_diff_hlID},
@@ -8666,6 +8703,110 @@ static void f_delete(typval_T *argvars, typval_T *rettv)
rettv->vval.v_number = os_remove((char *)get_tv_string(&argvars[0]));
}
+// dictwatcheradd(dict, key, funcref) function
+static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv)
+{
+ if (check_restricted() || check_secure()) {
+ return;
+ }
+
+ if (argvars[0].v_type != VAR_DICT) {
+ EMSG2(e_invarg2, "dict");
+ return;
+ }
+
+ if (argvars[1].v_type != VAR_STRING && argvars[1].v_type != VAR_NUMBER) {
+ EMSG2(e_invarg2, "key");
+ return;
+ }
+
+ if (argvars[2].v_type != VAR_FUNC && argvars[2].v_type != VAR_STRING) {
+ EMSG2(e_invarg2, "funcref");
+ return;
+ }
+
+ char *key_pattern = (char *)get_tv_string_chk(argvars + 1);
+ assert(key_pattern);
+ const size_t key_len = STRLEN(argvars[1].vval.v_string);
+
+ if (key_len == 0) {
+ EMSG(_(e_emptykey));
+ return;
+ }
+
+ ufunc_T *func = find_ufunc(argvars[2].vval.v_string);
+ if (!func) {
+ // Invalid function name. Error already reported by `find_ufunc`.
+ return;
+ }
+
+ func->uf_refcount++;
+ DictWatcher *watcher = xmalloc(sizeof(DictWatcher));
+ watcher->key_pattern = xmemdupz(key_pattern, key_len);
+ watcher->callback = func;
+ watcher->busy = false;
+ QUEUE_INSERT_TAIL(&argvars[0].vval.v_dict->watchers, &watcher->node);
+}
+
+// dictwatcherdel(dict, key, funcref) function
+static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv)
+{
+ if (check_restricted() || check_secure()) {
+ return;
+ }
+
+ if (argvars[0].v_type != VAR_DICT) {
+ EMSG2(e_invarg2, "dict");
+ return;
+ }
+
+ if (argvars[1].v_type != VAR_STRING && argvars[1].v_type != VAR_NUMBER) {
+ EMSG2(e_invarg2, "key");
+ return;
+ }
+
+ if (argvars[2].v_type != VAR_FUNC && argvars[2].v_type != VAR_STRING) {
+ EMSG2(e_invarg2, "funcref");
+ return;
+ }
+
+ char *key_pattern = (char *)get_tv_string_chk(argvars + 1);
+ assert(key_pattern);
+ const size_t key_len = STRLEN(argvars[1].vval.v_string);
+
+ if (key_len == 0) {
+ EMSG(_(e_emptykey));
+ return;
+ }
+
+ ufunc_T *func = find_ufunc(argvars[2].vval.v_string);
+ if (!func) {
+ // Invalid function name. Error already reported by `find_ufunc`.
+ return;
+ }
+
+ dict_T *dict = argvars[0].vval.v_dict;
+ QUEUE *w = NULL;
+ DictWatcher *watcher = NULL;
+ bool matched = false;
+ QUEUE_FOREACH(w, &dict->watchers) {
+ watcher = dictwatcher_node_data(w);
+ if (func == watcher->callback
+ && !strcmp(watcher->key_pattern, key_pattern)) {
+ matched = true;
+ break;
+ }
+ }
+
+ if (!matched) {
+ EMSG("Couldn't find a watcher matching key and callback");
+ return;
+ }
+
+ QUEUE_REMOVE(w);
+ dictwatcher_free(watcher);
+}
+
/*
* "did_filetype()" function
*/
@@ -8972,6 +9113,7 @@ void dict_extend(dict_T *d1, dict_T *d2, char_u *action)
dictitem_T *di1;
hashitem_T *hi2;
int todo;
+ bool watched = is_watched(d1);
todo = (int)d2->dv_hashtab.ht_used;
for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2) {
@@ -8992,14 +9134,30 @@ void dict_extend(dict_T *d1, dict_T *d2, char_u *action)
}
if (di1 == NULL) {
di1 = dictitem_copy(HI2DI(hi2));
- if (dict_add(d1, di1) == FAIL)
+ if (dict_add(d1, di1) == FAIL) {
dictitem_free(di1);
+ }
+
+ if (watched) {
+ dictwatcher_notify(d1, (char *)di1->di_key, &di1->di_tv, NULL);
+ }
} else if (*action == 'e') {
EMSG2(_("E737: Key already exists: %s"), hi2->hi_key);
break;
} else if (*action == 'f' && HI2DI(hi2) != di1) {
+ typval_T oldtv;
+
+ if (watched) {
+ copy_tv(&di1->di_tv, &oldtv);
+ }
+
clear_tv(&di1->di_tv);
copy_tv(&HI2DI(hi2)->di_tv, &di1->di_tv);
+
+ if (watched) {
+ dictwatcher_notify(d1, (char *)di1->di_key, &di1->di_tv, &oldtv);
+ clear_tv(&oldtv);
+ }
}
}
}
@@ -10556,9 +10714,7 @@ static void f_has(typval_T *argvars, typval_T *rettv)
#endif
"arabic",
"autocmd",
-#ifdef FEAT_BROWSE
"browsefilter",
-#endif
"byte_offset",
"cindent",
"cmdline_compl",
@@ -13519,6 +13675,9 @@ static void f_remove(typval_T *argvars, typval_T *rettv)
*rettv = di->di_tv;
init_tv(&di->di_tv);
dictitem_remove(d, di);
+ if (is_watched(d)) {
+ dictwatcher_notify(d, (char *)key, NULL, rettv);
+ }
}
}
}
@@ -18111,53 +18270,67 @@ static dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, in
return HI2DI(hi);
}
-/*
- * Find the hashtab used for a variable name.
- * Set "varname" to the start of name without ':'.
- */
-static hashtab_T *find_var_ht(char_u *name, char_u **varname)
+// Find the dict and hashtable used for a variable name. Set "varname" to the
+// start of name without ':'.
+static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d)
{
hashitem_T *hi;
+ *d = NULL;
if (name[1] != ':') {
- /* The name must not start with a colon or #. */
- if (name[0] == ':' || name[0] == AUTOLOAD_CHAR)
+ // name has implicit scope
+ if (name[0] == ':' || name[0] == AUTOLOAD_CHAR) {
+ // The name must not start with a colon or #.
return NULL;
+ }
*varname = name;
- /* "version" is "v:version" in all scopes */
+ // "version" is "v:version" in all scopes
hi = hash_find(&compat_hashtab, name);
- if (!HASHITEM_EMPTY(hi))
+ if (!HASHITEM_EMPTY(hi)) {
return &compat_hashtab;
+ }
- if (current_funccal == NULL)
- return &globvarht; /* global variable */
- return &current_funccal->l_vars.dv_hashtab; /* l: variable */
+ *d = current_funccal ? &current_funccal->l_vars : &globvardict;
+ goto end;
}
+
*varname = name + 2;
- if (*name == 'g') /* global variable */
- return &globvarht;
- /* There must be no ':' or '#' in the rest of the name, unless g: is used
- */
- if (vim_strchr(name + 2, ':') != NULL
- || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL)
+ if (*name == 'g') { // global variable
+ *d = &globvardict;
+ } else if (vim_strchr(name + 2, ':') != NULL
+ || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL) {
+ // There must be no ':' or '#' in the rest of the name if g: was not used
return NULL;
- if (*name == 'b') /* buffer variable */
- return &curbuf->b_vars->dv_hashtab;
- if (*name == 'w') /* window variable */
- return &curwin->w_vars->dv_hashtab;
- if (*name == 't') /* tab page variable */
- return &curtab->tp_vars->dv_hashtab;
- if (*name == 'v') /* v: variable */
- return &vimvarht;
- if (*name == 'a' && current_funccal != NULL) /* function argument */
- return &current_funccal->l_avars.dv_hashtab;
- if (*name == 'l' && current_funccal != NULL) /* local function variable */
- return &current_funccal->l_vars.dv_hashtab;
- if (*name == 's' /* script variable */
- && current_SID > 0 && current_SID <= ga_scripts.ga_len)
- return &SCRIPT_VARS(current_SID);
- return NULL;
+ }
+
+ if (*name == 'b') { // buffer variable
+ *d = curbuf->b_vars;
+ } else if (*name == 'w') { // window variable
+ *d = curwin->w_vars;
+ } else if (*name == 't') { // tab page variable
+ *d = curtab->tp_vars;
+ } else if (*name == 'v') { // v: variable
+ *d = &vimvardict;
+ } else if (*name == 'a' && current_funccal != NULL) { // function argument
+ *d = &current_funccal->l_avars;
+ } else if (*name == 'l' && current_funccal != NULL) { // local variable
+ *d = &current_funccal->l_vars;
+ } else if (*name == 's' // script variable
+ && current_SID > 0 && current_SID <= ga_scripts.ga_len) {
+ *d = &SCRIPT_SV(current_SID)->sv_dict;
+ }
+
+end:
+ return *d ? &(*d)->dv_hashtab : NULL;
+}
+
+// Find the hashtab used for a variable name.
+// Set "varname" to the start of name without ':'.
+static hashtab_T *find_var_ht(uint8_t *name, uint8_t **varname)
+{
+ dict_T *d;
+ return find_var_ht_dict(name, varname, &d);
}
/*
@@ -18221,6 +18394,7 @@ void init_var_dict(dict_T *dict, dictitem_T *dict_var, int scope)
dict_var->di_tv.v_lock = VAR_FIXED;
dict_var->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
dict_var->di_key[0] = NUL;
+ QUEUE_INIT(&dict->watchers);
}
/*
@@ -18353,8 +18527,16 @@ set_var (
dictitem_T *v;
char_u *varname;
hashtab_T *ht;
+ typval_T oldtv;
+ dict_T *dict;
+
+ ht = find_var_ht_dict(name, &varname, &dict);
+ bool watched = is_watched(dict);
+
+ if (watched) {
+ init_tv(&oldtv);
+ }
- ht = find_var_ht(name, &varname);
if (ht == NULL || *varname == NUL) {
EMSG2(_(e_illvar), name);
return;
@@ -18411,6 +18593,9 @@ set_var (
return;
}
+ if (watched) {
+ copy_tv(&v->di_tv, &oldtv);
+ }
clear_tv(&v->di_tv);
} else { /* add a new variable */
/* Can't add "v:" variable. */
@@ -18432,13 +18617,22 @@ set_var (
v->di_flags = 0;
}
- if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT)
+ if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT) {
copy_tv(tv, &v->di_tv);
- else {
+ } else {
v->di_tv = *tv;
v->di_tv.v_lock = 0;
init_tv(tv);
}
+
+ if (watched) {
+ if (oldtv.v_type == VAR_UNKNOWN) {
+ dictwatcher_notify(dict, (char *)v->di_key, &v->di_tv, NULL);
+ } else {
+ dictwatcher_notify(dict, (char *)v->di_key, &v->di_tv, &oldtv);
+ clear_tv(&oldtv);
+ }
+ }
}
/*
@@ -21014,9 +21208,9 @@ void last_set_msg(scid_T scriptID)
*/
void ex_oldfiles(exarg_T *eap)
{
- list_T *l = vimvars[VV_OLDFILES].vv_list;
+ list_T *l = get_vim_var_list(VV_OLDFILES);
listitem_T *li;
- int nr = 0;
+ long nr = 0;
if (l == NULL)
msg((char_u *)_("No old files"));
@@ -21024,7 +21218,7 @@ void ex_oldfiles(exarg_T *eap)
msg_start();
msg_scroll = TRUE;
for (li = l->lv_first; li != NULL && !got_int; li = li->li_next) {
- msg_outnum((long)++nr);
+ msg_outnum(++nr);
MSG_PUTS(": ");
msg_outtrans(get_tv_string(&li->li_tv));
msg_putchar('\n');
@@ -21034,6 +21228,23 @@ void ex_oldfiles(exarg_T *eap)
/* Assume "got_int" was set to truncate the listing. */
got_int = FALSE;
+ // File selection prompt on ":oldfiles!"
+ if (eap->forceit) {
+ quit_more = false;
+ nr = prompt_for_number(false);
+ msg_starthere();
+ if (nr > 0 && nr <= l->lv_len) {
+ char_u *p = list_find_str(l, nr);
+ if (p == NULL) {
+ return;
+ }
+ p = expand_env_save(p);
+ eap->arg = p;
+ eap->cmdidx = CMD_edit;
+ do_exedit(eap, NULL);
+ xfree(p);
+ }
+ }
}
}
@@ -21570,8 +21781,10 @@ static void on_process_exit(Process *proc, int status, void *d)
TerminalJobData *data = d;
if (data->term && !data->exited) {
data->exited = true;
- terminal_close(data->term,
- _("\r\n[Program exited, press any key to close]"));
+ char msg[22];
+ snprintf(msg, sizeof msg, "\r\n[Process exited %d]", proc->status);
+ terminal_close(data->term, msg);
+ apply_autocmds(EVENT_TERMCLOSE, NULL, NULL, false, curbuf);
}
if (data->status_ptr) {
@@ -21759,3 +21972,94 @@ bool eval_has_provider(char *name)
return false;
}
+
+// Compute the `DictWatcher` address from a QUEUE node. This only exists because
+// ASAN doesn't handle `QUEUE_DATA` pointer arithmetic, and we blacklist this
+// function on .asan-blacklist.
+static DictWatcher *dictwatcher_node_data(QUEUE *q)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
+{
+ return QUEUE_DATA(q, DictWatcher, node);
+}
+
+// Send a change notification to all `dict` watchers that match `key`.
+static void dictwatcher_notify(dict_T *dict, const char *key, typval_T *newtv,
+ typval_T *oldtv)
+ FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_NONNULL_ARG(2)
+{
+ typval_T argv[3];
+ for (size_t i = 0; i < ARRAY_SIZE(argv); i++) {
+ init_tv(argv + i);
+ }
+
+ argv[0].v_type = VAR_DICT;
+ argv[0].vval.v_dict = dict;
+ argv[1].v_type = VAR_STRING;
+ argv[1].vval.v_string = (char_u *)xstrdup(key);
+ argv[2].v_type = VAR_DICT;
+ argv[2].vval.v_dict = dict_alloc();
+ argv[2].vval.v_dict->dv_refcount++;
+
+ if (newtv) {
+ dictitem_T *v = dictitem_alloc((char_u *)"new");
+ copy_tv(newtv, &v->di_tv);
+ dict_add(argv[2].vval.v_dict, v);
+ }
+
+ if (oldtv) {
+ dictitem_T *v = dictitem_alloc((char_u *)"old");
+ copy_tv(oldtv, &v->di_tv);
+ dict_add(argv[2].vval.v_dict, v);
+ }
+
+ typval_T rettv;
+
+ QUEUE *w;
+ QUEUE_FOREACH(w, &dict->watchers) {
+ DictWatcher *watcher = dictwatcher_node_data(w);
+ if (!watcher->busy && dictwatcher_matches(watcher, key)) {
+ init_tv(&rettv);
+ watcher->busy = true;
+ call_user_func(watcher->callback, ARRAY_SIZE(argv), argv, &rettv,
+ curwin->w_cursor.lnum, curwin->w_cursor.lnum, NULL);
+ watcher->busy = false;
+ clear_tv(&rettv);
+ }
+ }
+
+ for (size_t i = 1; i < ARRAY_SIZE(argv); i++) {
+ clear_tv(argv + i);
+ }
+}
+
+// Test if `key` matches with with `watcher->key_pattern`
+static bool dictwatcher_matches(DictWatcher *watcher, const char *key)
+ FUNC_ATTR_NONNULL_ALL
+{
+ // For now only allow very simple globbing in key patterns: a '*' at the end
+ // of the string means it should match everything up to the '*' instead of the
+ // whole string.
+ char *nul = strchr(watcher->key_pattern, NUL);
+ size_t len = nul - watcher->key_pattern;
+ if (*(nul - 1) == '*') {
+ return !strncmp(key, watcher->key_pattern, len - 1);
+ } else {
+ return !strcmp(key, watcher->key_pattern);
+ }
+}
+
+// Perform all necessary cleanup for a `DictWatcher` instance.
+static void dictwatcher_free(DictWatcher *watcher)
+ FUNC_ATTR_NONNULL_ALL
+{
+ user_func_unref(watcher->callback);
+ xfree(watcher->key_pattern);
+ xfree(watcher);
+}
+
+// Check if `d` has at least one watcher.
+static bool is_watched(dict_T *d)
+{
+ return d && !QUEUE_EMPTY(&d->watchers);
+}
+
diff --git a/src/nvim/eval.h b/src/nvim/eval.h
index 864daed716..8ccf71068c 100644
--- a/src/nvim/eval.h
+++ b/src/nvim/eval.h
@@ -5,6 +5,47 @@
#include "nvim/profile.h"
+// All user-defined functions are found in this hashtable.
+EXTERN hashtab_T func_hashtab;
+
+// Structure to hold info for a user function.
+typedef struct ufunc ufunc_T;
+
+struct ufunc {
+ int uf_varargs; ///< variable nr of arguments
+ int uf_flags;
+ int uf_calls; ///< nr of active calls
+ garray_T uf_args; ///< arguments
+ garray_T uf_lines; ///< function lines
+ int uf_profiling; ///< true when func is being profiled
+ // Profiling the function as a whole.
+ int uf_tm_count; ///< nr of calls
+ proftime_T uf_tm_total; ///< time spent in function + children
+ proftime_T uf_tm_self; ///< time spent in function itself
+ proftime_T uf_tm_children; ///< time spent in children this call
+ // Profiling the function per line.
+ int *uf_tml_count; ///< nr of times line was executed
+ proftime_T *uf_tml_total; ///< time spent in a line + children
+ proftime_T *uf_tml_self; ///< time spent in a line itself
+ proftime_T uf_tml_start; ///< start time for current line
+ proftime_T uf_tml_children; ///< time spent in children for this line
+ proftime_T uf_tml_wait; ///< start wait time for current line
+ int uf_tml_idx; ///< index of line being timed; -1 if none
+ int uf_tml_execed; ///< line being timed was executed
+ scid_T uf_script_ID; ///< ID of script where function was defined,
+ // used for s: variables
+ int uf_refcount; ///< for numbered function: reference count
+ char_u uf_name[1]; ///< name of function (actually longer); can
+ // start with <SNR>123_ (<SNR> is K_SPECIAL
+ // KS_EXTRA KE_SNR)
+};
+
+// From user function to hashitem and back.
+EXTERN ufunc_T dumuf;
+#define UF2HIKEY(fp) ((fp)->uf_name)
+#define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf)))
+#define HI2UF(hi) HIKEY2UF((hi)->hi_key)
+
/* Defines for Vim variables. These must match vimvars[] in eval.c! */
enum {
VV_COUNT,
diff --git a/src/nvim/eval_defs.h b/src/nvim/eval_defs.h
index 373f1e6278..bd50d6b829 100644
--- a/src/nvim/eval_defs.h
+++ b/src/nvim/eval_defs.h
@@ -5,6 +5,7 @@
#include <stddef.h>
#include "nvim/hashtab.h"
+#include "nvim/lib/queue.h"
typedef int varnumber_T;
typedef double float_T;
@@ -119,6 +120,7 @@ struct dictvar_S {
dict_T *dv_used_prev; /* previous dict in used dicts list */
int internal_refcount; // number of internal references to
// prevent garbage collection
+ QUEUE watchers; // dictionary key watchers set by user code
};
// structure used for explicit stack while garbage collecting hash tables
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 5db3880026..c4fffcda71 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -62,7 +62,6 @@
#include "nvim/tempfile.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
-#include "nvim/version.h"
#include "nvim/window.h"
#include "nvim/os/os.h"
#include "nvim/os/shell.h"
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index 77f7dba81b..b7a3505c99 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -267,7 +267,7 @@ return {
},
{
command='buffers',
- flags=bit.bor(BANG, TRLBAR, CMDWIN),
+ flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
addr_type=ADDR_LINES,
func='buflist_list',
},
@@ -885,7 +885,7 @@ return {
},
{
command='files',
- flags=bit.bor(BANG, TRLBAR, CMDWIN),
+ flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
addr_type=ADDR_LINES,
func='buflist_list',
},
@@ -989,13 +989,13 @@ return {
command='gui',
flags=bit.bor(BANG, FILES, EDITCMD, ARGOPT, TRLBAR, CMDWIN),
addr_type=ADDR_LINES,
- func='ex_gui',
+ func='ex_nogui',
},
{
command='gvim',
flags=bit.bor(BANG, FILES, EDITCMD, ARGOPT, TRLBAR, CMDWIN),
addr_type=ADDR_LINES,
- func='ex_gui',
+ func='ex_nogui',
},
{
command='help',
@@ -1013,7 +1013,7 @@ return {
command='helpfind',
flags=bit.bor(EXTRA, NOTRLCOM),
addr_type=ADDR_LINES,
- func='ex_helpfind',
+ func='ex_ni',
},
{
command='helpgrep',
@@ -1521,7 +1521,7 @@ return {
},
{
command='ls',
- flags=bit.bor(BANG, TRLBAR, CMDWIN),
+ flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
addr_type=ADDR_LINES,
func='buflist_list',
},
@@ -1643,19 +1643,19 @@ return {
command='nbkey',
flags=bit.bor(EXTRA, NOTADR, NEEDARG),
addr_type=ADDR_LINES,
- func='ex_nbkey',
+ func='ex_ni',
},
{
command='nbclose',
flags=bit.bor(TRLBAR, CMDWIN),
addr_type=ADDR_LINES,
- func='ex_nbclose',
+ func='ex_ni',
},
{
command='nbstart',
flags=bit.bor(WORD1, TRLBAR, CMDWIN),
addr_type=ADDR_LINES,
- func='ex_nbstart',
+ func='ex_ni',
},
{
command='new',
@@ -1754,12 +1754,6 @@ return {
func='ex_menu',
},
{
- command='open',
- flags=bit.bor(RANGE, BANG, EXTRA),
- addr_type=ADDR_LINES,
- func='ex_open',
- },
- {
command='oldfiles',
flags=bit.bor(BANG, TRLBAR, SBOXOK, CMDWIN),
addr_type=ADDR_LINES,
@@ -1865,7 +1859,7 @@ return {
command='popup',
flags=bit.bor(NEEDARG, EXTRA, BANG, TRLBAR, NOTRLCOM, CMDWIN),
addr_type=ADDR_LINES,
- func='ex_popup',
+ func='ex_ni',
},
{
command='ppop',
@@ -1889,13 +1883,13 @@ return {
command='promptfind',
flags=bit.bor(EXTRA, NOTRLCOM, CMDWIN),
addr_type=ADDR_LINES,
- func='gui_mch_find_dialog',
+ func='ex_ni',
},
{
command='promptrepl',
flags=bit.bor(EXTRA, NOTRLCOM, CMDWIN),
addr_type=ADDR_LINES,
- func='gui_mch_replace_dialog',
+ func='ex_ni',
},
{
command='profile',
@@ -2309,7 +2303,7 @@ return {
command='simalt',
flags=bit.bor(NEEDARG, WORD1, TRLBAR, CMDWIN),
addr_type=ADDR_LINES,
- func='ex_simalt',
+ func='ex_ni',
},
{
command='sign',
@@ -3035,7 +3029,7 @@ return {
command='wsverb',
flags=bit.bor(EXTRA, NOTADR, NEEDARG),
addr_type=ADDR_LINES,
- func='ex_wsverb',
+ func='ex_ni',
},
{
command='wshada',
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index f172ea54c2..a632a3cce4 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -21,7 +21,6 @@
#ifdef HAVE_LOCALE_H
# include <locale.h>
#endif
-#include "nvim/version.h"
#include "nvim/ex_cmds2.h"
#include "nvim/buffer.h"
#include "nvim/charset.h"
@@ -762,9 +761,14 @@ void ex_profile(exarg_T *eap)
do_profiling = PROF_YES;
profile_set_wait(profile_zero());
set_vim_var_nr(VV_PROFILING, 1L);
- } else if (do_profiling == PROF_NONE)
+ } else if (do_profiling == PROF_NONE) {
EMSG(_("E750: First use \":profile start {fname}\""));
- else if (STRCMP(eap->arg, "pause") == 0) {
+ } else if (STRCMP(eap->arg, "stop") == 0) {
+ profile_dump();
+ do_profiling = PROF_NONE;
+ set_vim_var_nr(VV_PROFILING, 0L);
+ profile_reset();
+ } else if (STRCMP(eap->arg, "pause") == 0) {
if (do_profiling == PROF_YES)
pause_time = profile_start();
do_profiling = PROF_PAUSED;
@@ -774,6 +778,8 @@ void ex_profile(exarg_T *eap)
profile_set_wait(profile_add(profile_get_wait(), pause_time));
}
do_profiling = PROF_YES;
+ } else if (STRCMP(eap->arg, "dump") == 0) {
+ profile_dump();
} else {
/* The rest is similar to ":breakadd". */
ex_breakadd(eap);
@@ -817,18 +823,14 @@ static enum {
} pexpand_what;
static char *pexpand_cmds[] = {
- "start",
-#define PROFCMD_START 0
- "pause",
-#define PROFCMD_PAUSE 1
"continue",
-#define PROFCMD_CONTINUE 2
- "func",
-#define PROFCMD_FUNC 3
+ "dump",
"file",
-#define PROFCMD_FILE 4
+ "func",
+ "pause",
+ "start",
+ "stop",
NULL
-#define PROFCMD_LAST 5
};
/*
@@ -891,10 +893,63 @@ void profile_dump(void)
}
}
-/*
- * Start profiling script "fp".
- */
-static void script_do_profile(scriptitem_T *si)
+/// Reset all profiling information.
+static void profile_reset(void)
+{
+ // Reset sourced files.
+ for (int id = 1; id <= script_items.ga_len; id++) {
+ scriptitem_T *si = &SCRIPT_ITEM(id);
+ if (si->sn_prof_on) {
+ si->sn_prof_on = 0;
+ si->sn_pr_force = 0;
+ si->sn_pr_child = profile_zero();
+ si->sn_pr_nest = 0;
+ si->sn_pr_count = 0;
+ si->sn_pr_total = profile_zero();
+ si->sn_pr_self = profile_zero();
+ si->sn_pr_start = profile_zero();
+ si->sn_pr_children = profile_zero();
+ ga_clear(&si->sn_prl_ga);
+ si->sn_prl_start = profile_zero();
+ si->sn_prl_children = profile_zero();
+ si->sn_prl_wait = profile_zero();
+ si->sn_prl_idx = -1;
+ si->sn_prl_execed = 0;
+ }
+ }
+
+ // Reset functions.
+ size_t n = func_hashtab.ht_used;
+ hashitem_T *hi = func_hashtab.ht_array;
+
+ for (; n > (size_t)0; hi++) {
+ if (!HASHITEM_EMPTY(hi)) {
+ n--;
+ ufunc_T *uf = HI2UF(hi);
+ if (uf->uf_profiling) {
+ uf->uf_profiling = 0;
+ uf->uf_tm_count = 0;
+ uf->uf_tm_total = profile_zero();
+ uf->uf_tm_self = profile_zero();
+ uf->uf_tm_children = profile_zero();
+ uf->uf_tml_count = NULL;
+ uf->uf_tml_total = NULL;
+ uf->uf_tml_self = NULL;
+ uf->uf_tml_start = profile_zero();
+ uf->uf_tml_children = profile_zero();
+ uf->uf_tml_wait = profile_zero();
+ uf->uf_tml_idx = -1;
+ uf->uf_tml_execed = 0;
+ }
+ }
+ }
+
+ xfree(profile_fname);
+ profile_fname = NULL;
+}
+
+/// Start profiling a script.
+static void profile_init(scriptitem_T *si)
{
si->sn_pr_count = 0;
si->sn_pr_total = profile_zero();
@@ -2357,9 +2412,7 @@ do_source (
*/
p = path_tail(fname_exp);
if ((*p == '.' || *p == '_')
- && (STRICMP(p + 1, "nvimrc") == 0
- || STRICMP(p + 1, "ngvimrc") == 0
- || STRICMP(p + 1, "exrc") == 0)) {
+ && (STRICMP(p + 1, "nvimrc") == 0 || STRICMP(p + 1, "exrc") == 0)) {
if (*p == '_')
*p = '.';
else
@@ -2510,8 +2563,8 @@ do_source (
int forceit;
/* Check if we do profiling for this script. */
- if (!si->sn_prof_on && has_profiling(TRUE, si->sn_name, &forceit)) {
- script_do_profile(si);
+ if (!si->sn_prof_on && has_profiling(true, si->sn_name, &forceit)) {
+ profile_init(si);
si->sn_pr_force = forceit;
}
if (si->sn_prof_on) {
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 70cf5fd029..4d9f8b5769 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -80,6 +80,9 @@
static int quitmore = 0;
static int ex_pressedreturn = FALSE;
+/* whether ":lcd" was produced for a session */
+static int did_lcd;
+
typedef struct ucmd {
char_u *uc_name; /* The command name */
uint32_t uc_argt; /* The argument type */
@@ -144,23 +147,9 @@ struct dbg_stuff {
# include "ex_docmd.c.generated.h"
#endif
-# define ex_gui ex_nogui
-# define ex_popup ex_ni
-# define ex_simalt ex_ni
-# define gui_mch_find_dialog ex_ni
-# define gui_mch_replace_dialog ex_ni
-# define ex_helpfind ex_ni
-static int did_lcd; /* whether ":lcd" was produced for a session */
#ifndef HAVE_WORKING_LIBINTL
# define ex_language ex_ni
#endif
-# define ex_wsverb ex_ni
-# define ex_nbclose ex_ni
-# define ex_nbkey ex_ni
-# define ex_nbstart ex_ni
-
-
-
/*
* Declare cmdnames[].
@@ -6467,40 +6456,6 @@ static void ex_find(exarg_T *eap)
}
/*
- * ":open" simulation: for now just work like ":visual".
- */
-static void ex_open(exarg_T *eap)
-{
- regmatch_T regmatch;
- char_u *p;
-
- curwin->w_cursor.lnum = eap->line2;
- beginline(BL_SOL | BL_FIX);
- if (*eap->arg == '/') {
- /* ":open /pattern/": put cursor in column found with pattern */
- ++eap->arg;
- p = skip_regexp(eap->arg, '/', p_magic, NULL);
- *p = NUL;
- regmatch.regprog = vim_regcomp(eap->arg, p_magic ? RE_MAGIC : 0);
- if (regmatch.regprog != NULL) {
- regmatch.rm_ic = p_ic;
- p = get_cursor_line_ptr();
- if (vim_regexec(&regmatch, p, (colnr_T)0))
- curwin->w_cursor.col = (colnr_T)(regmatch.startp[0] - p);
- else
- EMSG(_(e_nomatch));
- vim_regfree(regmatch.regprog);
- }
- /* Move to the NUL, ignore any other arguments. */
- eap->arg += STRLEN(eap->arg);
- }
- check_cursor();
-
- eap->cmdidx = CMD_visual;
- do_exedit(eap, NULL);
-}
-
-/*
* ":edit", ":badd", ":visual".
*/
static void ex_edit(exarg_T *eap)
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 0ef0a12889..7c42238d20 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -633,7 +633,7 @@ EXTERN int silent_mode INIT(= FALSE);
/* set to TRUE when "-s" commandline argument
* used for ex */
-// Set to true when sourcing of startup scripts (nvimrc) is done.
+// Set to true when sourcing of startup scripts (init.vim) is done.
// Used for options that cannot be changed after startup scripts.
EXTERN bool did_source_startup_scripts INIT(= false);
diff --git a/src/nvim/keymap.c b/src/nvim/keymap.c
index 9d656276ec..85380ba173 100644
--- a/src/nvim/keymap.c
+++ b/src/nvim/keymap.c
@@ -284,6 +284,8 @@ static struct key_name_entry {
{K_SNR, (char_u *)"SNR"},
{K_PLUG, (char_u *)"Plug"},
{K_PASTE, (char_u *)"Paste"},
+ {K_FOCUSGAINED, (char_u *)"FocusGained"},
+ {K_FOCUSLOST, (char_u *)"FocusLost"},
{0, NULL}
};
diff --git a/src/nvim/log.h b/src/nvim/log.h
index 152e90760e..32b7276f14 100644
--- a/src/nvim/log.h
+++ b/src/nvim/log.h
@@ -19,7 +19,7 @@
#define ELOGN(...)
// Logging is disabled if NDEBUG or DISABLE_LOG is defined.
-#ifdef NDEBUG
+#if !defined(DISABLE_LOG) && defined(NDEBUG)
# define DISABLE_LOG
#endif
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 43723ff363..83fe32cccb 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -935,9 +935,6 @@ static void command_line_scan(mparm_T *parmp)
want_argument = TRUE;
break;
- case 'X': /* "-X" don't connect to X server */
- break;
-
case 'Z': /* "-Z" restricted mode */
restricted = TRUE;
break;
@@ -1833,7 +1830,7 @@ static void usage(void)
mch_msg(_(" -n No swap file, use memory only\n"));
mch_msg(_(" -r, -L List swap files and exit\n"));
mch_msg(_(" -r <file> Recover crashed session\n"));
- mch_msg(_(" -u <nvimrc> Use <nvimrc> instead of the default\n"));
+ mch_msg(_(" -u <vimrc> Use <vimrc> instead of the default\n"));
mch_msg(_(" -i <shada> Use <shada> instead of the default\n"));
mch_msg(_(" --noplugin Don't load plugin scripts\n"));
mch_msg(_(" -o[N] Open N windows (default: one for each file)\n"));
@@ -1842,7 +1839,7 @@ static void usage(void)
mch_msg(_(" + Start at end of file\n"));
mch_msg(_(" +<linenum> Start at line <linenum>\n"));
mch_msg(_(" +/<pattern> Start at first occurrence of <pattern>\n"));
- mch_msg(_(" --cmd <command> Execute <command> before loading any nvimrc\n"));
+ mch_msg(_(" --cmd <command> Execute <command> before loading any vimrc\n"));
mch_msg(_(" -c <command> Execute <command> after loading the first file\n"));
mch_msg(_(" -S <session> Source <session> after loading the first file\n"));
mch_msg(_(" -s <scriptin> Read Normal mode commands from <scriptin>\n"));
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index d25dc7c941..6d386f3599 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -42,8 +42,6 @@ void try_to_free_memory(void)
clear_sb_text();
// Try to save all buffers and release as many blocks as possible
mf_release_all();
- // cleanup recursive lists/dicts
- garbage_collect();
trying_to_free = false;
}
diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c
index 6829e4988c..5097255880 100644
--- a/src/nvim/misc1.c
+++ b/src/nvim/misc1.c
@@ -19,7 +19,6 @@
#include "nvim/vim.h"
#include "nvim/ascii.h"
-#include "nvim/version.h"
#include "nvim/misc1.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index de575c0234..78df4ea7ea 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -349,6 +349,8 @@ static const struct nv_cmd {
{K_F8, farsi_fkey, 0, 0},
{K_F9, farsi_fkey, 0, 0},
{K_EVENT, nv_event, NV_KEEPREG, 0},
+ {K_FOCUSGAINED, nv_focusgained, NV_KEEPREG, 0},
+ {K_FOCUSLOST, nv_focuslost, NV_KEEPREG, 0},
};
/* Number of commands in nv_cmds[]. */
@@ -4253,8 +4255,13 @@ dozet:
break;
/* "zm": fold more */
- case 'm': if (curwin->w_p_fdl > 0)
- --curwin->w_p_fdl;
+ case 'm':
+ if (curwin->w_p_fdl > 0) {
+ curwin->w_p_fdl -= cap->count1;
+ if (curwin->w_p_fdl < 0) {
+ curwin->w_p_fdl = 0;
+ }
+ }
old_fdl = -1; /* force an update */
curwin->w_p_fen = true;
break;
@@ -4266,7 +4273,14 @@ dozet:
break;
/* "zr": reduce folding */
- case 'r': ++curwin->w_p_fdl;
+ case 'r':
+ curwin->w_p_fdl += cap->count1;
+ {
+ int d = getDeepestNesting();
+ if (curwin->w_p_fdl >= d) {
+ curwin->w_p_fdl = d;
+ }
+ }
break;
/* "zR": open all folds */
@@ -7689,10 +7703,32 @@ static void nv_open(cmdarg_T *cap)
// Handle an arbitrary event in normal mode
static void nv_event(cmdarg_T *cap)
{
+ // Garbage collection should have been executed before blocking for events in
+ // the `os_inchar` in `state_enter`, but we also disable it here in case the
+ // `os_inchar` branch was not executed(!queue_empty(loop.events), which could
+ // have `may_garbage_collect` set to true in `normal_check`).
+ //
+ // That is because here we may run code that calls `os_inchar`
+ // later(`f_confirm` or `get_keystroke` for example), but in these cases it is
+ // not safe to perform garbage collection because there could be unreferenced
+ // lists or dicts being used.
+ may_garbage_collect = false;
queue_process_events(loop.events);
cap->retval |= CA_COMMAND_BUSY; // don't call edit() now
}
+/// Trigger FocusGained event.
+static void nv_focusgained(cmdarg_T *cap)
+{
+ apply_autocmds(EVENT_FOCUSGAINED, NULL, NULL, false, curbuf);
+}
+
+/// Trigger FocusLost event.
+static void nv_focuslost(cmdarg_T *cap)
+{
+ apply_autocmds(EVENT_FOCUSLOST, NULL, NULL, false, curbuf);
+}
+
/*
* Return TRUE when 'mousemodel' is set to "popup" or "popup_setpos".
*/
diff --git a/src/nvim/po/CMakeLists.txt b/src/nvim/po/CMakeLists.txt
index 243ac19b33..6687918df4 100644
--- a/src/nvim/po/CMakeLists.txt
+++ b/src/nvim/po/CMakeLists.txt
@@ -82,7 +82,7 @@ if(HAVE_WORKING_LIBINTL AND GETTEXT_FOUND AND XGETTEXT_PRG AND ICONV_PRG)
set(poFile ${CMAKE_CURRENT_SOURCE_DIR}/${name}.po)
add_custom_target(check-po-${name}
- COMMAND $<TARGET_FILE:nvim> -u NONE -n -e -X
+ COMMAND $<TARGET_FILE:nvim> -u NONE -n -e
-S ${CMAKE_CURRENT_SOURCE_DIR}/check.vim
-c "if error == 0 | q | endif" -c cq ${poFile} ||
${CMAKE_COMMAND} -E echo "${name}.po failed the check."
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c
index 4cd422400f..fa356da5b9 100644
--- a/src/nvim/regexp_nfa.c
+++ b/src/nvim/regexp_nfa.c
@@ -5761,7 +5761,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
// Bail out quickly when there can't be a match, avoid the overhead of
// win_linetabsize() on long lines.
- if (op != 1 && col > t->state->val) {
+ if (op != 1 && col > t->state->val * (has_mbyte ? MB_MAXBYTES : 1)) {
break;
}
diff --git a/src/nvim/terminal.h b/src/nvim/terminal.h
index 6e0b062fbd..25e609fb68 100644
--- a/src/nvim/terminal.h
+++ b/src/nvim/terminal.h
@@ -18,15 +18,6 @@ typedef struct {
terminal_close_cb close_cb;
} TerminalOptions;
-#define TERMINAL_OPTIONS_INIT ((TerminalOptions) { \
- .data = NULL, \
- .width = 80, \
- .height = 24, \
- .write_cb = NULL, \
- .resize_cb = NULL, \
- .close_cb = NULL \
- })
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "terminal.h.generated.h"
#endif
diff --git a/src/nvim/testdir/test49.vim b/src/nvim/testdir/test49.vim
index 4cb500292d..afee9d882c 100644
--- a/src/nvim/testdir/test49.vim
+++ b/src/nvim/testdir/test49.vim
@@ -456,7 +456,7 @@ function! ExtraVim(...)
" messing up the user's viminfo file.
let redirect = a:0 ?
\ " -c 'au VimLeave * redir END' -c 'redir\\! >" . a:1 . "'" : ""
- exec "!echo '" . debug_quits . "q' | ../../../build/bin/nvim -u NONE -N -Xes" . redirect .
+ exec "!echo '" . debug_quits . "q' | ../../../build/bin/nvim -u NONE -N -es" . redirect .
\ " -c 'debuggreedy|set viminfo+=nviminfo'" .
\ " -c 'let ExtraVimBegin = " . extra_begin . "'" .
\ " -c 'let ExtraVimResult = \"" . resultfile . "\"'" . breakpoints .
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index 654b857301..b41e4d2fba 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -10,6 +10,8 @@
#include "nvim/event/rstream.h"
#define PASTETOGGLE_KEY "<Paste>"
+#define FOCUSGAINED_KEY "<FocusGained>"
+#define FOCUSLOST_KEY "<FocusLost>"
#define KEY_BUFFER_SIZE 0xfff
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -252,6 +254,32 @@ static void timer_cb(TimeWatcher *watcher, void *data)
flush_input(data, true);
}
+/// Handle focus events.
+///
+/// If the upcoming sequence of bytes in the input stream matches either the
+/// escape code for focus gained `<ESC>[I` or focus lost `<ESC>[O` then consume
+/// that sequence and push the appropriate event into the input queue
+///
+/// @param input the input stream
+/// @return true iff handle_focus_event consumed some input
+static bool handle_focus_event(TermInput *input)
+{
+ if (rbuffer_size(input->read_stream.buffer) > 2
+ && (!rbuffer_cmp(input->read_stream.buffer, "\x1b[I", 3)
+ || !rbuffer_cmp(input->read_stream.buffer, "\x1b[O", 3))) {
+ // Advance past the sequence
+ bool focus_gained = *rbuffer_get(input->read_stream.buffer, 2) == 'I';
+ rbuffer_consumed(input->read_stream.buffer, 3);
+ if (focus_gained) {
+ enqueue_input(input, FOCUSGAINED_KEY, sizeof(FOCUSGAINED_KEY) - 1);
+ } else {
+ enqueue_input(input, FOCUSLOST_KEY, sizeof(FOCUSLOST_KEY) - 1);
+ }
+ return true;
+ }
+ return false;
+}
+
static bool handle_bracketed_paste(TermInput *input)
{
if (rbuffer_size(input->read_stream.buffer) > 5 &&
@@ -314,7 +342,9 @@ static void read_cb(Stream *stream, RBuffer *buf, size_t c, void *data,
}
do {
- if (handle_bracketed_paste(input) || handle_forced_escape(input)) {
+ if (handle_focus_event(input)
+ || handle_bracketed_paste(input)
+ || handle_forced_escape(input)) {
continue;
}
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 02efa1f8df..7f7d138358 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -66,6 +66,7 @@ typedef struct {
int enable_bracketed_paste, disable_bracketed_paste;
int enter_insert_mode, enter_replace_mode, exit_insert_mode;
int set_rgb_foreground, set_rgb_background;
+ int enable_focus_reporting, disable_focus_reporting;
} unibi_ext;
} TUIData;
@@ -120,6 +121,8 @@ static void terminfo_start(UI *ui)
data->unibi_ext.enter_insert_mode = -1;
data->unibi_ext.enter_replace_mode = -1;
data->unibi_ext.exit_insert_mode = -1;
+ data->unibi_ext.enable_focus_reporting = -1;
+ data->unibi_ext.disable_focus_reporting = -1;
data->out_fd = 1;
data->out_isatty = os_isatty(data->out_fd);
// setup unibilium
@@ -135,6 +138,8 @@ static void terminfo_start(UI *ui)
unibi_out(ui, unibi_clear_screen);
// Enable bracketed paste
unibi_out(ui, data->unibi_ext.enable_bracketed_paste);
+ // Enable focus reporting
+ unibi_out(ui, data->unibi_ext.enable_focus_reporting);
uv_loop_init(&data->write_loop);
if (data->out_isatty) {
uv_tty_init(&data->write_loop, &data->output_handle.tty, data->out_fd, 0);
@@ -157,6 +162,8 @@ static void terminfo_stop(UI *ui)
unibi_out(ui, unibi_exit_ca_mode);
// Disable bracketed paste
unibi_out(ui, data->unibi_ext.disable_bracketed_paste);
+ // Disable focus reporting
+ unibi_out(ui, data->unibi_ext.disable_focus_reporting);
flush_buf(ui);
uv_tty_reset_mode();
uv_close((uv_handle_t *)&data->output_handle, NULL);
@@ -807,6 +814,11 @@ static void fix_terminfo(TUIData *data)
data->unibi_ext.disable_bracketed_paste = (int)unibi_add_ext_str(ut, NULL,
"\x1b[?2004l");
+ data->unibi_ext.enable_focus_reporting = (int)unibi_add_ext_str(ut, NULL,
+ "\x1b[?1004h");
+ data->unibi_ext.disable_focus_reporting = (int)unibi_add_ext_str(ut, NULL,
+ "\x1b[?1004l");
+
#define XTERM_SETAF \
"\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m"
#define XTERM_SETAB \
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index d8158bf7cd..b0c49cbf8e 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -650,7 +650,7 @@ void u_compute_hash(char_u *hash)
///
/// @return [allocated] File name to read from/write to or NULL.
char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+ FUNC_ATTR_WARN_UNUSED_RESULT
{
char *dirp;
char dir_name[MAXPATHL + 1];
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 7cc72705b6..d5bbd734f4 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -25,18 +25,21 @@
#define STR_(x) #x
#define STR(x) STR_(x)
-// for the startup-screen ( ":intro" command )
-#define NVIM_VERSION_MEDIUM STR(NVIM_VERSION_MAJOR) "." STR(NVIM_VERSION_MINOR)
-
-// for the ":version" command and "nvim --version"
-#define NVIM_VERSION_LONG "NVIM " NVIM_VERSION_MEDIUM "." STR(NVIM_VERSION_PATCH) NVIM_VERSION_PRERELEASE NVIM_VERSION_BUILD
+// for ":version", ":intro", and "nvim --version"
+#ifndef NVIM_VERSION_MEDIUM
+#define NVIM_VERSION_MEDIUM STR(NVIM_VERSION_MAJOR) "." STR(NVIM_VERSION_MINOR)\
+ "." STR(NVIM_VERSION_PATCH) NVIM_VERSION_PRERELEASE
+#endif
+#define NVIM_VERSION_LONG "NVIM " NVIM_VERSION_MEDIUM
char *Version = VIM_VERSION_SHORT;
char *longVersion = NVIM_VERSION_LONG;
-char *longVersionWithDate = NVIM_VERSION_LONG " (compiled " __DATE__ " " __TIME__ ")";
-char *mediumVersion = NVIM_VERSION_MEDIUM;
+char *longVersionWithDate = NVIM_VERSION_LONG \
+ " (compiled " __DATE__ " " __TIME__ ")";
+#ifdef NVIM_VERSION_COMMIT
char *version_commit = "Commit: " NVIM_VERSION_COMMIT;
+#endif
char *version_buildtype = "Build type: " NVIM_VERSION_BUILD_TYPE;
char *version_cflags = "Compilation: " NVIM_VERSION_CFLAGS;
@@ -71,20 +74,92 @@ static char *features[] = {
// clang-format off
static int included_patches[] = {
- // 850,
- 849,
+ // 922,
+ // 921 NA
+ // 920 NA
+ // 919 NA
+ // 918 NA
+ // 917 NA
+ 916,
+ // 915,
+ // 914,
+ // 913 NA
+ // 912,
+ // 911 NA
+ // 910 NA
+ // 909,
+ // 908 NA
+ // 907 NA
+ // 906 NA
+ // 905,
+ // 904,
+ // 903,
+ // 902 NA
+ // 901,
+ // 900 NA
+ // 899 NA
+ // 898,
+ // 897,
+ // 896,
+ // 895,
+ // 894 NA
+ // 893,
+ // 892,
+ // 891,
+ // 890 NA
+ // 889,
+ // 888,
+ // 887,
+ // 886 NA
+ // 885,
+ // 884 NA
+ // 883,
+ // 882,
+ // 881,
+ // 880 NA
+ // 879,
+ // 878,
+ // 877,
+ // 876 NA
+ // 875 NA
+ // 874 NA
+ // 873,
+ // 872 NA
+ // 871,
+ // 870,
+ // 869 NA
+ // 868,
+ // 867 NA
+ // 866,
+ // 865,
+ // 864,
+ // 863,
+ // 862 NA
+ // 861 NA
+ // 860,
+ // 859,
+ // 858,
+ // 857,
+ // 856,
+ // 855 NA
+ // 854,
+ // 853,
+ // 852 NA
+ // 851 NA
+ // 850 NA
+ 849,
// 848,
// 847,
- // 846,
+ // 846 NA
// 845,
// 844,
// 843,
// 842,
// 841,
- // 840,
+ // 840 NA
// 839,
// 838,
- // 837,
+ // 837 NA
836,
// 835,
// 834,
@@ -92,7 +167,7 @@ static int included_patches[] = {
// 832,
// 831,
// 830,
- // 829,
+ // 829 NA
// 828,
// 827,
826,
@@ -112,14 +187,14 @@ static int included_patches[] = {
// 812,
// 811,
// 810,
- // 809,
+ 809,
// 808,
// 807,
// 806,
// 805,
// 804,
// 803,
- // 802,
+ 802,
// 801,
// 800,
799,
@@ -130,7 +205,7 @@ static int included_patches[] = {
// 794 NA
793,
// 792,
- // 791,
+ 791,
// 790,
// 789,
// 788 NA
@@ -149,35 +224,35 @@ static int included_patches[] = {
775,
774,
773,
- // 772,
+ // 772 NA
// 771,
- // 770,
+ // 770 NA
// 769,
// 768,
// 767,
- // 766,
+ // 766 NA
// 765,
// 764,
- // 763,
- // 762,
- // 761,
+ // 763 NA
+ // 762 NA
+ // 761 NA
// 760,
- // 759,
+ // 759 NA
// 758,
- // 757,
- // 756,
+ // 757 NA
+ // 756 NA
// 755,
// 754,
// 753,
// 752,
- // 751,
- // 750,
+ // 751 NA
+ // 750 NA
// 749,
// 748,
// 747,
// 746,
// 745,
- // 744,
+ // 744 NA
// 743,
// 742,
// 741,
@@ -235,7 +310,7 @@ static int included_patches[] = {
// 689,
// 688,
// 687 NA
- // 686,
+ 686,
// 685,
// 684,
// 683 NA
@@ -269,8 +344,8 @@ static int included_patches[] = {
// 655,
// 654,
653,
- // 652,
- // 651,
+ // 652 NA
+ 651,
// 650 NA
// 649,
// 648 NA
@@ -1024,7 +1099,9 @@ void list_version(void)
// When adding features here, don't forget to update the list of
// internal variables in eval.c!
MSG(longVersionWithDate);
+#ifdef NVIM_VERSION_COMMIT
MSG(version_commit);
+#endif
MSG(version_buildtype);
MSG(version_cflags);
diff --git a/src/nvim/version.h b/src/nvim/version.h
index c1881250f1..1de809e539 100644
--- a/src/nvim/version.h
+++ b/src/nvim/version.h
@@ -3,7 +3,6 @@
// defined in version.c
extern char* Version;
-extern char* mediumVersion;
extern char* longVersion;
//
diff --git a/test/functional/autocmd/termclose_spec.lua b/test/functional/autocmd/termclose_spec.lua
new file mode 100644
index 0000000000..265d857a42
--- /dev/null
+++ b/test/functional/autocmd/termclose_spec.lua
@@ -0,0 +1,28 @@
+local helpers = require('test.functional.helpers')
+local Screen = require('test.functional.ui.screen')
+
+local clear, eval, execute, feed, nvim, nvim_dir = helpers.clear, helpers.eval,
+helpers.execute, helpers.feed, helpers.nvim, helpers.nvim_dir
+local wait = helpers.wait
+
+describe('TermClose event', function()
+ before_each(function()
+ clear()
+ nvim('set_option', 'shell', nvim_dir .. '/shell-test')
+ nvim('set_option', 'shellcmdflag', 'EXE')
+ screen = Screen.new(20, 4)
+ screen:attach(false)
+ end)
+
+ it('works as expected', function()
+ execute('autocmd TermClose * echomsg "TermClose works!"')
+ execute('terminal')
+ feed('<c-\\><c-n>')
+ screen:expect([[
+ ready $ |
+ [Process exited 0] |
+ ^ |
+ TermClose works! |
+ ]])
+ end)
+end)
diff --git a/test/functional/dict_notifications_spec.lua b/test/functional/dict_notifications_spec.lua
new file mode 100644
index 0000000000..2540929126
--- /dev/null
+++ b/test/functional/dict_notifications_spec.lua
@@ -0,0 +1,257 @@
+local helpers = require('test.functional.helpers')
+local clear, nvim, source = helpers.clear, helpers.nvim, helpers.source
+local eq, next_msg = helpers.eq, helpers.next_message
+local exc_exec = helpers.exc_exec
+
+
+describe('dictionary change notifications', function()
+ local channel
+
+ setup(function()
+ clear()
+ channel = nvim('get_api_info')[1]
+ nvim('set_var', 'channel', channel)
+ end)
+
+ -- the same set of tests are applied to top-level dictionaries(g:, b:, w: and
+ -- t:) and a dictionary variable, so we generate them in the following
+ -- function.
+ local function gentests(dict_expr, dict_expr_suffix, dict_init)
+ if not dict_expr_suffix then
+ dict_expr_suffix = ''
+ end
+
+ local function update(opval, key)
+ if not key then
+ key = 'watched'
+ end
+ if opval == '' then
+ nvim('command', "unlet "..dict_expr..dict_expr_suffix..key)
+ else
+ nvim('command', "let "..dict_expr..dict_expr_suffix..key.." "..opval)
+ end
+ end
+
+ local function verify_echo()
+ -- helper to verify that no notifications are sent after certain change
+ -- to a dict
+ nvim('command', "call rpcnotify(g:channel, 'echo')")
+ eq({'notification', 'echo', {}}, next_msg())
+ end
+
+ local function verify_value(vals, key)
+ if not key then
+ key = 'watched'
+ end
+ eq({'notification', 'values', {key, vals}}, next_msg())
+ end
+
+ describe('watcher', function()
+ if dict_init then
+ setup(function()
+ source(dict_init)
+ end)
+ end
+
+ before_each(function()
+ source([[
+ function! g:Changed(dict, key, value)
+ if a:dict != ]]..dict_expr..[[ |
+ throw 'invalid dict'
+ endif
+ call rpcnotify(g:channel, 'values', a:key, a:value)
+ endfunction
+ call dictwatcheradd(]]..dict_expr..[[, "watched", "g:Changed")
+ call dictwatcheradd(]]..dict_expr..[[, "watched2", "g:Changed")
+ ]])
+ end)
+
+ after_each(function()
+ source([[
+ call dictwatcherdel(]]..dict_expr..[[, "watched", "g:Changed")
+ call dictwatcherdel(]]..dict_expr..[[, "watched2", "g:Changed")
+ ]])
+ update('= "test"')
+ update('= "test2"', 'watched2')
+ update('', 'watched2')
+ update('')
+ verify_echo()
+ end)
+
+ it('is not triggered when unwatched keys are updated', function()
+ update('= "noop"', 'unwatched')
+ update('.= "noop2"', 'unwatched')
+ update('', 'unwatched')
+ verify_echo()
+ end)
+
+ it('is triggered by remove()', function()
+ update('= "test"')
+ verify_value({new = 'test'})
+ nvim('command', 'call remove('..dict_expr..', "watched")')
+ verify_value({old = 'test'})
+ end)
+
+ it('is triggered by extend()', function()
+ update('= "xtend"')
+ verify_value({new = 'xtend'})
+ nvim('command', [[
+ call extend(]]..dict_expr..[[, {'watched': 'xtend2', 'watched2': 5, 'watched3': 'a'})
+ ]])
+ verify_value({old = 'xtend', new = 'xtend2'})
+ verify_value({new = 5}, 'watched2')
+ update('')
+ verify_value({old = 'xtend2'})
+ update('', 'watched2')
+ verify_value({old = 5}, 'watched2')
+ update('', 'watched3')
+ verify_echo()
+ end)
+
+ it('is triggered with key patterns', function()
+ source([[
+ call dictwatcheradd(]]..dict_expr..[[, "wat*", "g:Changed")
+ ]])
+ update('= 1')
+ verify_value({new = 1})
+ verify_value({new = 1})
+ update('= 3', 'watched2')
+ verify_value({new = 3}, 'watched2')
+ verify_value({new = 3}, 'watched2')
+ verify_echo()
+ source([[
+ call dictwatcherdel(]]..dict_expr..[[, "wat*", "g:Changed")
+ ]])
+ -- watch every key pattern
+ source([[
+ call dictwatcheradd(]]..dict_expr..[[, "*", "g:Changed")
+ ]])
+ update('= 3', 'another_key')
+ update('= 4', 'another_key')
+ update('', 'another_key')
+ update('= 2')
+ verify_value({new = 3}, 'another_key')
+ verify_value({old = 3, new = 4}, 'another_key')
+ verify_value({old = 4}, 'another_key')
+ verify_value({old = 1, new = 2})
+ verify_value({old = 1, new = 2})
+ verify_echo()
+ source([[
+ call dictwatcherdel(]]..dict_expr..[[, "*", "g:Changed")
+ ]])
+ end)
+
+ -- test a sequence of updates of different types to ensure proper memory
+ -- management(with ASAN)
+ local function test_updates(tests)
+ it('test change sequence', function()
+ local input, output
+ for i = 1, #tests do
+ input, output = unpack(tests[i])
+ update(input)
+ verify_value(output)
+ end
+ end)
+ end
+
+ test_updates({
+ {'= 3', {new = 3}},
+ {'= 6', {old = 3, new = 6}},
+ {'+= 3', {old = 6, new = 9}},
+ {'', {old = 9}}
+ })
+
+ test_updates({
+ {'= "str"', {new = 'str'}},
+ {'= "str2"', {old = 'str', new = 'str2'}},
+ {'.= "2str"', {old = 'str2', new = 'str22str'}},
+ {'', {old = 'str22str'}}
+ })
+
+ test_updates({
+ {'= [1, 2]', {new = {1, 2}}},
+ {'= [1, 2, 3]', {old = {1, 2}, new = {1, 2, 3}}},
+ -- the += will update the list in place, so old and new are the same
+ {'+= [4, 5]', {old = {1, 2, 3, 4, 5}, new = {1, 2, 3, 4, 5}}},
+ {'', {old = {1, 2, 3, 4 ,5}}}
+ })
+
+ test_updates({
+ {'= {"k": "v"}', {new = {k = 'v'}}},
+ {'= {"k1": 2}', {old = {k = 'v'}, new = {k1 = 2}}},
+ {'', {old = {k1 = 2}}},
+ })
+ end)
+ end
+
+ gentests('g:')
+ gentests('b:')
+ gentests('w:')
+ gentests('t:')
+ gentests('g:dict_var', '.', 'let g:dict_var = {}')
+
+ describe('multiple watchers on the same dict/key', function()
+ setup(function()
+ source([[
+ function! g:Watcher1(dict, key, value)
+ call rpcnotify(g:channel, '1', a:key, a:value)
+ endfunction
+ function! g:Watcher2(dict, key, value)
+ call rpcnotify(g:channel, '2', a:key, a:value)
+ endfunction
+ call dictwatcheradd(g:, "key", "g:Watcher1")
+ call dictwatcheradd(g:, "key", "g:Watcher2")
+ ]])
+ end)
+
+ it('invokes all callbacks when the key is changed', function()
+ nvim('command', 'let g:key = "value"')
+ eq({'notification', '1', {'key', {new = 'value'}}}, next_msg())
+ eq({'notification', '2', {'key', {new = 'value'}}}, next_msg())
+ end)
+
+ it('only removes watchers that fully match dict, key and callback', function()
+ nvim('command', 'call dictwatcherdel(g:, "key", "g:Watcher1")')
+ nvim('command', 'let g:key = "v2"')
+ eq({'notification', '2', {'key', {old = 'value', new = 'v2'}}}, next_msg())
+ end)
+ end)
+
+ describe('errors', function()
+ -- WARNING: This suite depends on the above tests
+ it('fails to remove if no watcher with matching callback is found', function()
+ eq("Vim(call):Couldn't find a watcher matching key and callback",
+ exc_exec('call dictwatcherdel(g:, "key", "g:Watcher1")'))
+ end)
+
+ it('fails to remove if no watcher with matching key is found', function()
+ eq("Vim(call):Couldn't find a watcher matching key and callback",
+ exc_exec('call dictwatcherdel(g:, "invalid_key", "g:Watcher2")'))
+ end)
+
+ it("fails to add/remove if the callback doesn't exist", function()
+ eq("Vim(call):Function g:InvalidCb doesn't exist",
+ exc_exec('call dictwatcheradd(g:, "key", "g:InvalidCb")'))
+ eq("Vim(call):Function g:InvalidCb doesn't exist",
+ exc_exec('call dictwatcherdel(g:, "key", "g:InvalidCb")'))
+ end)
+
+ it('fails with empty keys', function()
+ eq("Vim(call):E713: Cannot use empty key for Dictionary",
+ exc_exec('call dictwatcheradd(g:, "", "g:Watcher1")'))
+ eq("Vim(call):E713: Cannot use empty key for Dictionary",
+ exc_exec('call dictwatcherdel(g:, "", "g:Watcher1")'))
+ end)
+
+ it('fails to replace a watcher function', function()
+ source([[
+ function! g:ReplaceWatcher2()
+ function! g:Watcher2()
+ endfunction
+ endfunction
+ ]])
+ eq("Vim(function):E127: Cannot redefine function Watcher2: It is in use",
+ exc_exec('call g:ReplaceWatcher2()'))
+ end)
+ end)
+end)
diff --git a/test/functional/ex_cmds/oldfiles_spec.lua b/test/functional/ex_cmds/oldfiles_spec.lua
new file mode 100644
index 0000000000..e02f42cd12
--- /dev/null
+++ b/test/functional/ex_cmds/oldfiles_spec.lua
@@ -0,0 +1,97 @@
+local Screen = require('test.functional.ui.screen')
+local helpers = require('test.functional.helpers')
+
+local buf, eq, execute = helpers.curbufmeths, helpers.eq, helpers.execute
+local feed, nvim, nvim_prog = helpers.feed, helpers.nvim, helpers.nvim_prog
+local ok, set_session, spawn = helpers.ok, helpers.set_session, helpers.spawn
+
+local shada_file = 'test.shada'
+
+--
+-- helpers.clear() uses "-i NONE", which is not useful for this test.
+--
+local function _clear()
+ if session then
+ session:exit(0)
+ end
+ set_session(spawn({nvim_prog,
+ '-u', 'NONE',
+ '--cmd', 'set noswapfile undodir=. directory=. viewdir=. backupdir=.',
+ '--embed'}))
+end
+
+describe(':oldfiles', function()
+ before_each(_clear)
+
+ after_each(function()
+ os.remove(shada_file)
+ end)
+
+ local function add_padding(s)
+ return s .. string.rep(' ', 96 - string.len(s))
+ end
+
+ it('shows most recently used files', function()
+ screen = Screen.new(100, 5)
+ screen:attach()
+ execute('edit testfile1')
+ execute('edit testfile2')
+ execute('wshada ' .. shada_file)
+ execute('rshada! ' .. shada_file)
+ local oldfiles = helpers.meths.get_vvar('oldfiles')
+ execute('oldfiles')
+ screen:expect([[
+ testfile2 |
+ 1: ]].. add_padding(oldfiles[1]) ..[[ |
+ 2: ]].. add_padding(oldfiles[2]) ..[[ |
+ |
+ Press ENTER or type command to continue^ |
+ ]])
+ end)
+end)
+
+describe(':oldfiles!', function()
+ local filename
+ local filename2
+ local oldfiles
+
+ before_each(function()
+ _clear()
+ execute('edit testfile1')
+ filename = buf.get_name()
+ execute('edit testfile2')
+ filename2 = buf.get_name()
+ execute('wshada ' .. shada_file)
+ _clear()
+ execute('rshada! ' .. shada_file)
+
+ -- Ensure v:oldfiles isn't busted. Since things happen so fast,
+ -- the ordering of v:oldfiles is unstable (it uses qsort() under-the-hood).
+ -- Let's verify the contents and the length of v:oldfiles before moving on.
+ oldfiles = helpers.meths.get_vvar('oldfiles')
+ eq(2, #oldfiles)
+ ok(filename == oldfiles[1] or filename == oldfiles[2])
+ ok(filename2 == oldfiles[1] or filename2 == oldfiles[2])
+
+ execute('oldfiles!')
+ end)
+
+ after_each(function()
+ os.remove(shada_file)
+ end)
+
+ it('provides a prompt and edits the chosen file', function()
+ feed('2<cr>')
+ eq(oldfiles[2], buf.get_name())
+ end)
+
+ it('provides a prompt and does nothing on <cr>', function()
+ feed('<cr>')
+ eq('', buf.get_name())
+ end)
+
+ it('provides a prompt and does nothing if choice is out-of-bounds', function()
+ feed('3<cr>')
+ eq('', buf.get_name())
+ end)
+end)
diff --git a/test/functional/ex_cmds/profile_spec.lua b/test/functional/ex_cmds/profile_spec.lua
new file mode 100644
index 0000000000..721669e73b
--- /dev/null
+++ b/test/functional/ex_cmds/profile_spec.lua
@@ -0,0 +1,51 @@
+require('os')
+require('lfs')
+
+local helpers = require('test.functional.helpers')
+local eval = helpers.eval
+local command = helpers.command
+local eq, neq = helpers.eq, helpers.neq
+local tempfile = os.tmpname()
+
+-- os.tmpname() also creates the file on POSIX systems. Remove it again.
+-- We just need the name, ignoring any race conditions.
+if lfs.attributes(tempfile, 'uid') then
+ os.remove(tempfile)
+end
+
+local function assert_file_exists(filepath)
+ -- Use 2-argument lfs.attributes() so no extra table gets created.
+ -- We don't really care for the uid.
+ neq(nil, lfs.attributes(filepath, 'uid'))
+end
+
+local function assert_file_exists_not(filepath)
+ eq(nil, lfs.attributes(filepath, 'uid'))
+end
+
+describe(':profile', function()
+ before_each(helpers.clear)
+
+ after_each(function()
+ if lfs.attributes(tempfile, 'uid') ~= nil then
+ os.remove(tempfile)
+ end
+ end)
+
+ it('dump', function()
+ eq(0, eval('v:profiling'))
+ command('profile start ' .. tempfile)
+ eq(1, eval('v:profiling'))
+ assert_file_exists_not(tempfile)
+ command('profile dump')
+ assert_file_exists(tempfile)
+ end)
+
+ it('stop', function()
+ command('profile start ' .. tempfile)
+ assert_file_exists_not(tempfile)
+ command('profile stop')
+ assert_file_exists(tempfile)
+ eq(0, eval('v:profiling'))
+ end)
+end)
diff --git a/test/functional/ex_cmds/wundo_spec.lua b/test/functional/ex_cmds/wundo_spec.lua
index d8bd8a7031..c3147e1c0f 100644
--- a/test/functional/ex_cmds/wundo_spec.lua
+++ b/test/functional/ex_cmds/wundo_spec.lua
@@ -1,9 +1,9 @@
--- Specs for
--- :wundo
+-- Specs for :wundo and underlying functions
local helpers = require('test.functional.helpers')
-local execute, eq, clear, eval, feed =
- helpers.execute, helpers.eq, helpers.clear, helpers.eval, helpers.feed
+local execute, clear, eval, feed, spawn, nvim_prog, set_session =
+ helpers.execute, helpers.clear, helpers.eval, helpers.feed, helpers.spawn,
+ helpers.nvim_prog, helpers.set_session
describe(':wundo', function()
@@ -16,5 +16,14 @@ describe(':wundo', function()
os.remove(eval('getcwd()') .. '/foo') --cleanup
end)
+end)
+describe('u_* functions', function()
+ it('safely fail on new, non-empty buffer', function()
+ local session = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed',
+ '-c', 'set undodir=. undofile'})
+ set_session(session)
+ execute('echo "True"') -- Should not error out due to crashed Neovim
+ session:exit(0)
+ end)
end)
diff --git a/test/functional/provider/python3_spec.lua b/test/functional/provider/python3_spec.lua
index 5ecc1a0a91..a94880d4a2 100644
--- a/test/functional/provider/python3_spec.lua
+++ b/test/functional/provider/python3_spec.lua
@@ -4,6 +4,7 @@ local eq, clear, insert = helpers.eq, helpers.clear, helpers.insert
local expect, write_file = helpers.expect, helpers.write_file
do
+ clear()
command('let [g:interp, g:errors] = provider#pythonx#Detect(3)')
local errors = eval('g:errors')
if errors ~= '' then
diff --git a/test/functional/provider/python_spec.lua b/test/functional/provider/python_spec.lua
index f37c16a26a..da45d6aa00 100644
--- a/test/functional/provider/python_spec.lua
+++ b/test/functional/provider/python_spec.lua
@@ -4,6 +4,7 @@ local eq, clear, insert = helpers.eq, helpers.clear, helpers.insert
local expect, write_file = helpers.expect, helpers.write_file
do
+ clear()
command('let [g:interp, g:errors] = provider#pythonx#Detect(2)')
local errors = eval('g:errors')
if errors ~= '' then
diff --git a/test/functional/shada/marks_spec.lua b/test/functional/shada/marks_spec.lua
index f03b330fb5..6818844ebd 100644
--- a/test/functional/shada/marks_spec.lua
+++ b/test/functional/shada/marks_spec.lua
@@ -108,6 +108,7 @@ describe('ShaDa support code', function()
nvim_command('qall')
reset()
local oldfiles = meths.get_vvar('oldfiles')
+ table.sort(oldfiles)
eq(2, #oldfiles)
eq(testfilename, oldfiles[1]:sub(-#testfilename))
eq(testfilename_2, oldfiles[2]:sub(-#testfilename_2))
@@ -115,6 +116,7 @@ describe('ShaDa support code', function()
eq(tf_full_2, oldfiles[2])
nvim_command('rshada!')
local oldfiles = meths.get_vvar('oldfiles')
+ table.sort(oldfiles)
eq(2, #oldfiles)
eq(testfilename, oldfiles[1]:sub(-#testfilename))
eq(testfilename_2, oldfiles[2]:sub(-#testfilename_2))
diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua
index 3855cf4b65..611ba55793 100644
--- a/test/functional/terminal/ex_terminal_spec.lua
+++ b/test/functional/terminal/ex_terminal_spec.lua
@@ -22,7 +22,7 @@ describe(':terminal', function()
wait()
screen:expect([[
ready $ |
- [Program exited, press any key to close] |
+ [Process exited 0] |
|
|
|
@@ -37,7 +37,7 @@ describe(':terminal', function()
screen:expect([[
ready $ echo hi |
|
- [Program exited, press any key to close] |
+ [Process exited 0] |
|
|
|
@@ -51,7 +51,7 @@ describe(':terminal', function()
screen:expect([[
ready $ echo 'hello' \ "world" |
|
- [Program exited, press any key to close] |
+ [Process exited 0] |
|
|
|
diff --git a/test/functional/terminal/scrollback_spec.lua b/test/functional/terminal/scrollback_spec.lua
index 87cc9a8266..4b56698520 100644
--- a/test/functional/terminal/scrollback_spec.lua
+++ b/test/functional/terminal/scrollback_spec.lua
@@ -340,7 +340,7 @@ describe('terminal prints more lines than the screen height and exits', function
line8 |
line9 |
|
- [Program exited, press any key to close] |
+ [Process exited 0] |
-- TERMINAL -- |
]])
feed('<cr>')
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index 0c4b80fdd2..9a1fdfca55 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -148,6 +148,32 @@ describe('tui', function()
-- TERMINAL -- |
]])
end)
+
+ it('can handle focus events', function()
+ execute('autocmd FocusGained * echo "gained"')
+ execute('autocmd FocusLost * echo "lost"')
+ feed('\x1b[I')
+ screen:expect([[
+ {1: } |
+ ~ |
+ ~ |
+ ~ |
+ [No Name] |
+ gained |
+ -- TERMINAL -- |
+ ]])
+
+ feed('\x1b[O')
+ screen:expect([[
+ {1: } |
+ ~ |
+ ~ |
+ ~ |
+ [No Name] |
+ lost |
+ -- TERMINAL -- |
+ ]])
+ end)
end)
describe('tui with non-tty file descriptors', function()
@@ -167,7 +193,7 @@ describe('tui with non-tty file descriptors', function()
:q |
abc |
|
- [Program exited, press any key to close] |
+ [Process exited 0] |
|
-- TERMINAL -- |
]])
diff --git a/test/unit/buffer_spec.lua b/test/unit/buffer_spec.lua
index e0e2b827e9..05fba684d6 100644
--- a/test/unit/buffer_spec.lua
+++ b/test/unit/buffer_spec.lua
@@ -1,9 +1,15 @@
+
+local assert = require("luassert")
local helpers = require("test.unit.helpers")
local to_cstr = helpers.to_cstr
local eq = helpers.eq
+local neq = helpers.neq
+local globals = helpers.cimport("./src/nvim/globals.h")
local buffer = helpers.cimport("./src/nvim/buffer.h")
+local fileio = helpers.cimport("./src/nvim/fileio.h")
+local ex_docmd = helpers.cimport("./src/nvim/ex_docmd.h")
local window = helpers.cimport("./src/nvim/window.h")
local option = helpers.cimport("./src/nvim/option.h")
@@ -206,4 +212,95 @@ describe('buffer functions', function()
close_buffer(NULL, buf2, buffer.DOBUF_WIPE, 0)
end)
end)
+
+ describe('build_stl_str_hl', function()
+
+ output_buffer = to_cstr(string.rep(" ", 100))
+
+ local build_stl_str_hl = function(pat)
+ return buffer.build_stl_str_hl(globals.curwin,
+ output_buffer,
+ 100,
+ to_cstr(pat),
+ false,
+ 32,
+ 80,
+ NULL,
+ NULL)
+ end
+
+ it('should copy plain text', function()
+ local width = build_stl_str_hl("this is a test")
+
+ eq(14, width)
+ eq("this is a test", helpers.ffi.string(output_buffer, width))
+
+ end)
+
+ it('should print no file name', function()
+ local width = build_stl_str_hl("%f")
+
+ eq(9, width)
+ eq("[No Name]", helpers.ffi.string(output_buffer, width))
+
+ end)
+
+ it('should print the relative file name', function()
+ buffer.setfname(globals.curbuf, to_cstr("Makefile"), NULL, 1)
+ local width = build_stl_str_hl("%f")
+
+ eq(8, width)
+ eq("Makefile", helpers.ffi.string(output_buffer, width))
+
+ end)
+
+ it('should print the full file name', function()
+ buffer.setfname(globals.curbuf, to_cstr("Makefile"), NULL, 1)
+
+ local width = build_stl_str_hl("%F")
+
+ assert.is_true(8 < width)
+ neq(NULL, string.find(helpers.ffi.string(output_buffer, width), "Makefile"))
+
+ end)
+
+ it('should print the tail file name', function()
+ buffer.setfname(globals.curbuf, to_cstr("src/nvim/buffer.c"), NULL, 1)
+
+ local width = build_stl_str_hl("%t")
+
+ eq(8, width)
+ eq("buffer.c", helpers.ffi.string(output_buffer, width))
+
+ end)
+
+ it('should print the buffer number', function()
+ buffer.setfname(globals.curbuf, to_cstr("src/nvim/buffer.c"), NULL, 1)
+
+ local width = build_stl_str_hl("%n")
+
+ eq(1, width)
+ eq("1", helpers.ffi.string(output_buffer, width))
+ end)
+
+ it('should print the current line number in the buffer', function()
+ buffer.setfname(globals.curbuf, to_cstr("test/unit/buffer_spec.lua"), NULL, 1)
+
+ local width = build_stl_str_hl("%l")
+
+ eq(1, width)
+ eq("0", helpers.ffi.string(output_buffer, width))
+
+ end)
+
+ it('should print the number of lines in the buffer', function()
+ buffer.setfname(globals.curbuf, to_cstr("test/unit/buffer_spec.lua"), NULL, 1)
+
+ local width = build_stl_str_hl("%L")
+
+ eq(1, width)
+ eq("1", helpers.ffi.string(output_buffer, width))
+
+ end)
+ end)
end)
diff --git a/third-party/cmake/BuildLibuv.cmake b/third-party/cmake/BuildLibuv.cmake
index 2919d289cc..5debe5c071 100644
--- a/third-party/cmake/BuildLibuv.cmake
+++ b/third-party/cmake/BuildLibuv.cmake
@@ -43,18 +43,18 @@ set(UNIX_CFGCMD sh ${DEPS_BUILD_DIR}/src/libuv/autogen.sh &&
if(UNIX)
BuildLibUv(
CONFIGURE_COMMAND ${UNIX_CFGCMD}
- INSTALL_COMMAND ${MAKE_PRG} install)
+ INSTALL_COMMAND ${MAKE_PRG} V=1 install)
elseif(MINGW AND CMAKE_CROSSCOMPILING)
# Build libuv for the host
BuildLibUv(TARGET libuv_host
CONFIGURE_COMMAND sh ${DEPS_BUILD_DIR}/src/libuv_host/autogen.sh && ${DEPS_BUILD_DIR}/src/libuv_host/configure --with-pic --disable-shared --prefix=${HOSTDEPS_INSTALL_DIR} CC=${HOST_C_COMPILER}
- INSTALL_COMMAND ${MAKE_PRG} install)
+ INSTALL_COMMAND ${MAKE_PRG} V=1 install)
# Build libuv for the target
BuildLibUv(
CONFIGURE_COMMAND ${UNIX_CFGCMD} --host=${CROSS_TARGET}
- INSTALL_COMMAND ${MAKE_PRG} install)
+ INSTALL_COMMAND ${MAKE_PRG} V=1 install)
elseif(WIN32 AND MSVC)
diff --git a/third-party/cmake/BuildLuajit.cmake b/third-party/cmake/BuildLuajit.cmake
index 3598b00c04..83aceecb59 100644
--- a/third-party/cmake/BuildLuajit.cmake
+++ b/third-party/cmake/BuildLuajit.cmake
@@ -41,6 +41,7 @@ set(INSTALLCMD_UNIX ${MAKE_PRG} CFLAGS=-fPIC
CFLAGS+=-DLUA_USE_ASSERT
CCDEBUG+=-g
BUILDMODE=static
+ Q=
install)
if(UNIX)
@@ -67,6 +68,7 @@ elseif(MINGW AND CMAKE_CROSSCOMPILING)
HOST_CC=${HOST_C_COMPILER} HOST_CFLAGS=${HOST_C_FLAGS}
HOST_LDFLAGS=${HOST_EXE_LINKER_FLAGS}
FILE_T=luajit.exe
+ Q=
INSTALL_TSYMNAME=luajit.exe)
elseif(WIN32 AND MSVC)